在上一章的基础上,一样一样地学习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 //分配给窗口类结构之后的额外字节数,一般为0int
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; }