消息

1、WM_NCCREATE:调用CreateWindow函数的时候,会首先发送WM_NCCREATE消息给窗口过程函数,即NC,也就是No-Client(标题栏、窗体边框、最大化按钮、最小化按钮、滚动条等输入No-Client区域)。如果应用程序需要处理这个消息,那么需要返回TRUE来继续往下创建窗口。如果WM_NCCREATE返回FALSE的话,窗口创建将被终止,直接返回一个NULL句柄。

#define WM NCCREATE Ox0081

wParam中 此参数未使用。

lParam的 指向CREATESTRUCT结构的指针,其中包含有关正在创建的窗口的信息。

2、WM_CREATE:创建窗口的消息,发送完WM_NCCREATE消息并返回TRUE的情况下,会发送WM_CREATE消息给窗口过程函数。在窗口对用户可见之前,窗口过程函数会接收到消息。所以说,可以在这里创建控件、子窗口、初始化滚动条等操作

#define WM_CREATE                       0x0001

wParam:此参数未使用。
lParam的指向CREATESTRUCT结构的指针,其中包含有关正在创建的窗口的信息。

CREATESTRUCT结构体的定义如下:

typedef struct tagCREATESTRUCTW {
    LPVOID      lpCreateParams;//创建窗口的基本参数
    HINSTANCE   hInstance;//拥有将创建窗口的模块实例句柄
    HMENU       hMenu;//新窗口的菜单句柄
    HWND        hwndParent;//新窗口的父窗口句柄
    int         cy;//新窗口的高度
    int         cx;//新窗口的宽度
    int         y;//新窗口的左上角y坐标
    int         x;//新窗口的右上角x坐标
    LONG        style;//新窗口的样式
    LPCWSTR     lpszName;//窗口标题名称
    LPCWSTR     lpszClass;//窗口类名称
    DWORD       dwExStyle;//窗口扩展样式
} CREATESTRUCTW, *LPCREATESTRUCTW;

以下为WM_NCCREATE和WM_CREATE消息具体案例,WM_NCCREATE返回TRUE。

case WM_NCCREATE:
{
	CREATESTRUCT* p = (CREATESTRUCT*)lParam;
	return TRUE;
}

case WM_CREATE:
{
	CREATESTRUCT* p = (CREATESTRUCT*)lParam;
	return 0;
}

3、WM_CLOSE:用户点击关闭按钮的时候依次发送WM_CLOSE、WM_DESTROY和WM_NCDESTROY消息来销毁窗口。此刻窗口消息并未退出,为了使程序彻底退出,应该在WM_DESTROY调用PostQuitMessage(0)函数来发送WM_QUIT消息并退出消息循环,具体可参考如下代码:

case WM_CLOSE:
{
	WriteFile("WM_CLOSE");
	return DefWindowProc(hwnd, message, wParam, lParam);
}
case WM_NCDESTROY:
{
	WriteFile("WM_NCDESTROY");
	return DefWindowProc(hwnd, message, wParam, lParam);
}
case WM_DESTROY:
{
	WriteFile("WM_DESTROY");
	PostQuitMessage(0);
	break;
}

4、WM_PAINT:以下操作会触发操作系统的重绘消息

4.1、程序启动时,UpdateWindow函数会发送一个WM_PAINT消息来更新指定窗口的客户区域。

4.2、鼠标调整窗口大小的时候,会连续触发。

4.3、最小化的时候不会触发,但是从最小化到正常化的时候,会触发。

4.4、最大化的时候会触发。

4.5、当向屏幕外面拖拽的时候不会触发,但是当从屏幕外面拖拽到屏幕里面的时候,会连续触发。

4.6、调用InvalidateRect函数的时候会触发。

注意:仅仅覆盖或者移动窗口的是 不会触发,因为窗口的大小并未发生变化。

case WM_PAINT:
{
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(hwnd, &ps);//使窗口无效区域变得有效,从而不在发送WM_PAINT消息。
	EndPaint(hwnd, &ps);//和BeginPaint成双结对使用,必须同时调用。
	return 0;
}
typedef struct tagPAINTSTRUCT {
    HDC         hdc;//用于绘图的显示器DC
    BOOL        fErase;//是否擦除背景
    RECT        rcPaint;//指定客户区的矩形
    BOOL        fRestore;//系统保留
    BOOL        fIncUpdate;//系统保留
    BYTE        rgbReserved[32];//系统保留
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;

5、WM_ERASEBKGND:当窗体大小发生变化,必须擦除背景的时候,发送WM_ERASEBKGND消息。默认情况下,windows使用WNDCLASS中hbrBackground对背景进行擦除。如果程序处理WM_ERASEBKGND返回非0值表示不需要进一步擦除。返回0代表需要进一步擦除,PAINTSTRUCT结构体中的fErase将会编程true。

7、UpdateWindow、InvalidateRect、RedrawWindow三个函数的区别

UpdateWindow:如果窗口的更新区域不是空的,则UpdateWindow函数立即向窗口发送。WM_PAINT消息来更新指定窗口的客户区。

InvalidateRect:只增加一个无效区域在更新区域中,并不立刻进行重绘,直到发生下一个WM_PAINT消息时处理该区域是才重绘。如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow。

RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。