《Windows32 SDK教程》02章 创建一个简单窗口


在上一章的基础上,一样一样地学习SDK编程的内容,大家只要跟着教程多动手,多看帮助。这三章攻克之后,后面就不难了。

一、注册窗口类

“ATOM MyRegisterClass(HINSTANCE hInstance)”中的ATOM是无符号整数类型,参数hInstance是当前窗口的句柄,这里的关键是API函数RegisterClassEx(&wc),先看一下这个函数的原型。

ATOM RegisterClassEx(
    CONST WNDCLASSEX *lpwcx
);

这个函数的参数是一个结构体,你想要申请一个什么样的窗口,要事先设置好,然后传给这个函数。下面再看一下WNDCLASSEX的结构。

typedef struct {
    UINT cbSize            //这个结构体的长度,一般用sizeof(WNDCLASSEX)设置
    UINT style             //窗口式样
    WNDPROC lpfnWndProc    //窗口消息处理的函数名
    int cbClsExtra         //分配给窗口类结构之后的额外字节数,一般为0
    int cbWndExtra         //分配给窗口实例之后的额外字节数,一般为0
    HINSTANCE hInstance    //想要申请的窗口实例句柄
    HICON hIcon            //运行时的图标,NULL时取系统缺省图标
    HCURSOR hCursor        //光标
    HBRUSH hbrBackground   //背景
    LPCTStr lpszMenuName   //菜单
    LPCTStr lpszClassName  //窗口名
    HICON hIconSm;         //缩小时的图标,NULL时取系统缺省图标
} WNDCLASSEX, *PWNDCLASSEX;

窗口式样style的值可用下表的值组合起来设置,窗口处理函数名lpfnWndProc和hInstance不能设置错。光标有2个hIcon和hIconSm,当取不到值时自动分配一个系统缺省值。光标hCursor可选择下面的光标ID设置到结构体中去。关于图标、背景、菜单后面有专门章节介绍。下面在上一章的基础之上,修改部分数据,看看有什么变化。

设置值 解说
CS_HREDRAW 窗口客户区宽度发生改变时重绘窗口
CS_VREDRAW 窗口客户区高度发生改变时重绘窗口
CS_DBLCLKS 鼠标双击时系统所发的消息
CS_NOCLOSE 禁用系统菜单中的“关闭”命令
CS_OWNDC 为该窗口类的各窗口分配各自独立的设备环境
CS_CLASSDC 为该窗口类的各窗口分配一个共享的设备环境
CS_PARENtdC 指定子窗口继承其父窗口的设备环境
CS_SAVEBITS 把被窗口覆盖的屏幕部分作为位图保存起来。 当窗口被刷新时,系统使用被保存的位图来重画窗口。
CS_BYTEALIGNCLIENT Aligns the window's client area on a byte boundary (in the x direction). This style affects the width of the window and its horizontal placement on the display.
CS_BYTEALIGNWINDOW Aligns the window on a byte boundary (in the x direction). This style affects the width of the window and its horizontal placement on the display.
CS_GLOBALCLASS Specifies that the window class is an application global class. For more information, see Application Global Classes.


ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(wc));  //与memset()函数功能相当

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = (WNDPROC)WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(hInstance, (LPCTSTR)IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_SIZEALL);  //光标
    wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);           //背景
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = szWindowClass;
    wc.hIconSm       = LoadIcon(wc.hInstance, (LPCTSTR)IDI_APPLICATION);

    return RegisterClassEx(&wc);
}

二、初始化窗口

InitInstance()函数中,CreateWindow()函数创建一个窗口,这儿说的窗口是广义的窗口,事实上按钮也是窗口,也是由这个函数创建的。其中最关键的是第三个参数,先看一下函数原型。

HWND CreateWindow(
    LPCTSTR lpClassName,      //窗口名
    LPCTSTR lpWindowName,     //窗口标题
    DWORD dwStyle,            //窗口式样
    int x,                    //窗口左上角的x坐标
    int y,                    //窗口左上角的y坐标
    int nWidth,               //窗口的宽度
    int nHeight,              //窗口的高度
    HWND hWndParent,          //父窗口句柄
    HMENU hMenu,              //菜单句柄
    HINSTANCE hInstance,      //实例句柄
    LPVOID lpParam            //创建参数
);

窗口式样有以下几种,先用简单易懂的值试一试,然后再逐步深入。动手做是学习的关键。下面我们在上一个例子的基础上修改2个地方,看看有什么变化。运行之后窗口变成了最小化。

设置值 解说
WS_OVERLAPPEDWINDOW 层叠式窗口,有边框、标题栏、系统菜单、最大最小化按钮,是以下几种风格的集合:WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX
WS_POPUPWINDOW 弹出式窗口,是以下几种风格的集合: WS_BORDER,WS_POPUP,WS_SYSMENU。WS_CAPTION与WS_POPUPWINDOW风格一起使用时窗口菜单才能可见
WS_OVERLAPPED 层叠式窗口,有标题栏和边框,与WS_TILED风格类似
WS_POPUP 弹出式窗口,与WS_CHILD不能同时使用
WS_BORDER 窗口有单线边框
WS_CAPTION 窗口有标题栏
WS_CHILD 子窗口,不能与WS_POPUP同时使用
WS_DISABLED 为无效窗口
WS_HSCROLL 水平滚动条
WS_ICONIC 初始化为最小化
WS_MAXIMIZE 初始化为最大化
WS_MAXIMIZEBOX 有最大化按钮
WS_MINIMIZE 与WS_MAXIMIZE一样
WS_MINIMIZEBOX 窗口有最小化按钮
WS_SIZEBOX 边框可进行大小控制的窗口
WS_SYSMENU 创建一个有系统菜单的窗口,必须与WS_CAPTION风格同时使用
WS_THICKFRAME 创建一个大小可控制的窗口,与WS_SIZEBOX风格一样.
WS_TILED 创建一个层叠式窗口,有标题栏
WS_VISIBLE 窗口为可见
WS_VSCROLL 窗口有垂直滚动条

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   //创建一个有滚动条的层叠式窗口
   hWnd = CreateWindow( szWindowClass,
                        szTitle,
                        WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,
                        100,
                        100,
                        220,
                        120,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
   if (!hWnd)
   {
      return FALSE;
   }
   ShowWindow(hWnd, SW_MINIMIZE);  //最小化窗口
   UpdateWindow(hWnd);

   return TRUE;
}