MFC:Microsoft Foundation Classes,它封装了WIN32/WIN64功能,在MFC应用程序中,可以使用一组标准类,它们把我们与Windows API隔离开。
Windows API称为WINAPI或WIN32/WIN64。直接使用WINAPI是最费力的开发应用程序的方法。
任何Windows应用程序与Windows本身之间的所有通信,都要使用Windows应用程序编程接口,称作WindowsAPI。
Windows程序是事件驱动的,因此Windows程序要等待某个事件发生。
WndProc()或WindowProc(),Windows消息处理函数。
Windows数据类型
变量前缀
窗口,左上角(0,0),水平向右是x+,垂直向下是y-。
最简单仅使用Windows API的Windows程序而言,需要编写两个函数。
WinMain function (winbase.h) - Win32 apps | Microsoft DocsThe user-provided entry point for a graphical Windows-based application.https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
hInstance | 是一种称为“实例句柄”或“模块句柄”的东西。操作系统在将可执行文件 (EXE) 加载到内存时使用此值来识别它。某些 Windows 功能需要实例句柄,例如,加载图标或位图。 |
hPrevInstance | 没有任何意义。它曾在 16 位 Windows 中使用,但现在始终为零。 |
pCmdLine | 包含作为 Unicode 字符串的命令行参数。 |
nCmdShow | 是一个标志,它表明主应用程序窗口是最小化、最大化还是正常显示。 |
WNDCLASSEXA (winuser.h) - Win32 apps | Microsoft DocsContains window class information.https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa
typedef struct tagWNDCLASSEXA {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCSTR lpszMenuName;
LPCSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEXA, *PWNDCLASSEXA, *NPWNDCLASSEXA, *LPWNDCLASSEXA;
cbSize | 此结构的大小(以字节为单位)。 将此成员设置为 sizeof(WNDCLASSEX)。 请务必在调用 GetClassInfoEx 函数之前设置此成员。 |
style | 窗口行为风格。 该成员可以是类样式的任意组合。每个选项都是以CS_开头,可以用 | 组合。 |
lpfnWndProc | 指向窗口消息处理函数的指针,必须使用 CallWindowProc 函数来调用Windows消息处理函数。 有关详细信息,请参阅 WindowProc。 |
cbClsExtra | 按照窗口类结构分配的额外字节数。 系统将字节初始化为零。 |
cbWndExtra | 在窗口实例之后分配的额外字节数。 系统将字节初始化为零。 如果应用程序使用 WNDCLASSEX 在资源文件中注册使用 CLASS 指令创建的对话框,则必须将此成员设置为 DLGWINDOWEXTRA。 |
hInstance | 包含当前应用程序实例的句柄。 |
hIcon | 类图标的句柄。 此成员必须是图标资源的句柄。 如果此成员为 NULL,则系统提供默认图标。 |
hCursor | 类游标的句柄。 此成员必须是游标资源的句柄。 如果此成员为 NULL,则应用程序必须在鼠标移入应用程序窗口时显式设置光标形状。 |
hbrBackground | 类背景画笔的句柄。 该成员可以是用于绘制背景的画笔的句柄,也可以是颜色值。 颜色值必须是以下标准系统颜色之一(必须将值 1 添加到所选颜色)。 如果给定了颜色值,则必须将其转换为以下 HBRUSH 类型之一(j见下文)。 使用 UnregisterClass 注销Class时,系统会自动删除班级背景画笔。 应用程序不应删除这些画笔。 当此成员为 NULL 时,每当请求在其客户区中绘制时,应用程序都必须绘制自己的背景。 要确定是否必须绘制背景,应用程序可以处理 WM_ERASEBKGND 消息或测试由 BeginPaint 函数填充的 PAINTSTRUCT 结构的 fErase 成员。 |
lpszMenuName | 指向以空字符结尾的字符串的指针,该字符串指定类菜单的资源名称,因为该名称出现在资源文件中。 如果您使用整数来标识菜单,请使用 MAKEINTRESOURCE 宏。 如果此成员为 NULL,则属于此类的窗口没有默认菜单。 |
lpszClassName | 窗口名,指向以 null 结尾的字符串的指针,或者是一个原子。 如果 lpszClassName 是一个字符串,它指定窗口类名。 lpszClassName 的最大长度为 256。如果 lpszClassName 大于最大长度, RegisterClassEx函数将失败。 |
hIconSm | 与窗口类关联的小图标的句柄。 如果该成员为NULL,则系统在hIcon成员指定的图标资源中搜索合适大小的图标作为小图标使用。 |
Window Class Styles
常数/值 | 描述 |
---|---|
CS_BYTEALIGNCLIENT 0x1000 |
在字节边界上对齐窗口的客户区(在 x 方向)。 此样式会影响窗口的宽度及其在显示器上的水平位置。 |
CS_BYTEALIGNWINDOW 0x2000 |
在字节边界上对齐窗口(在 x 方向上)。 此样式会影响窗口的宽度及其在显示器上的水平位置。 |
CS_CLASSDC 0x0040 |
分配一个设备上下文以供类中的所有窗口共享。 因为窗口类是特定于进程的,所以一个应用程序的多个线程可以创建同一个类的窗口。 线程也有可能同时尝试使用设备上下文。 发生这种情况时,系统只允许一个线程成功完成其绘图操作。 |
CS_DBLCLKS 0x0008 |
当光标在属于该类的窗口内时,当用户双击鼠标时,向窗口过程发送双击消息。 |
CS_DROPSHADOW 0x00020000 |
在窗口上启用阴影效果。 效果通过 SPI_SETDROPSHADOW 打开和关闭。 通常,这对小型、短存活期的窗口(例如菜单)启用,以强调它们与其他窗口的 Z 顺序关系。 从具有这种样式的类创建的窗口必须是顶级窗口; 它们可能不是子窗口。 |
CS_GLOBALCLASS 0x4000 |
指示窗口类是应用程序全局类。 详细信息, 见 About Window Classes的"Application Global Classes"部分。 |
CS_HREDRAW 0x0002 |
如果移动或大小调整改变了客户区的宽度,则重绘整个窗口。 |
CS_NOCLOSE 0x0200 |
在窗口菜单上禁用关闭。 |
CS_OWNDC 0x0020 |
为类中的每个窗口分配一个唯一的设备上下文。 |
CS_PARENTDC 0x0080 |
将子窗口的剪切矩形设置为父窗口的剪切矩形,以便子窗口可以在父窗口上绘图。 具有 CS_PARENTDC 样式位的窗口从系统的设备上下文缓存中接收常规设备上下文。 它不会给子类 父设备上下文或设备上下文设置。 指定 CS_PARENTDC 可提高应用程序的性能。 |
CS_SAVEBITS 0x0800 |
将屏幕图像中被此类窗口遮挡的部分保存为位图。 当窗口被移除时,系统使用保存的位图来恢复屏幕图像,包括其他被遮挡的窗口。 因此,如果位图使用的内存没有被丢弃并且其他屏幕操作没有使存储的图像无效,系统不会向被遮挡的窗口发送 WM_PAINT 消息。 这种风格对于短暂显示且在其他屏幕活动发生之前删除的小窗口(例如,菜单或对话框)很有用。 这种样式增加了显示窗口所需的时间,因为系统必须首先分配内存来存储位图。 |
CS_VREDRAW 0x0001 |
如果移动或大小调整改变了客户区的高度,则重绘整个窗口。 |
HBRUSH 类型
注册窗口类
RegisterClassExA function (winuser.h) - Win32 apps | Microsoft DocsRegisters a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclassexa
ATOM RegisterClassExW(
[in] const WNDCLASSEXW *unnamedParam1
);
ATOM RegisterClassExA(
[in] const WNDCLASSEXA *unnamedParam1
);
[in] unnamedParam1 | 指向 WNDCLASSEX 结构的指针。 在将结构传递给函数之前,您必须使用适当的类属性填充结构。 |
返回值
如果函数成功,则返回值是唯一标识正在注册的类的类原子。
该原子只能由 CreateWindow, CreateWindowEx, GetClassInfo, GetClassInfoEx, FindWindow, FindWindowEx, 和UnregisterClass 函数和 IActiveIMMap::FilterClientWindows 方法使用。
如果函数失败,则返回值为零。 要获取扩展错误信息,请调用 GetLastError。
创建窗口
CreateWindowA macro (winuser.h) - Win32 apps | Microsoft DocsCreates an overlapped, pop-up, or child window.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowa
HWND CreateWindowW(
[in, optional] lpClassName,
[in, optional] lpWindowName,
[in] dwStyle,
[in] x,
[in] y,
[in] nWidth,
[in] nHeight,
[in, optional] hWndParent,
[in, optional] hMenu,
[in, optional] hInstance,
[in, optional] lpParam
);
void CreateWindowA(
[in, optional] lpClassName,
[in, optional] lpWindowName,
[in] dwStyle,
[in] x,
[in] y,
[in] nWidth,
[in] nHeight,
[in, optional] hWndParent,
[in, optional] hMenu,
[in, optional] hInstance,
[in, optional] lpParam
);
CreateWindowExA function (winuser.h) - Win32 apps | Microsoft DocsCreates an overlapped, pop-up, or child window with an extended window style; otherwise, this function is identical to the CreateWindow function.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa
HWND CreateWindowExW(
[in] DWORD dwExStyle,
[in, optional] LPCWSTR lpClassName,
[in, optional] LPCWSTR lpWindowName,
[in] DWORD dwStyle,
[in] int X,
[in] int Y,
[in] int nWidth,
[in] int nHeight,
[in, optional] HWND hWndParent,
[in, optional] HMENU hMenu,
[in, optional] HINSTANCE hInstance,
[in, optional] LPVOID lpParam
);
HWND CreateWindowExA(
[in] DWORD dwExStyle,
[in, optional] LPCSTR lpClassName,
[in, optional] LPCSTR lpWindowName,
[in] DWORD dwStyle,
[in] int X,
[in] int Y,
[in] int nWidth,
[in] int nHeight,
[in, optional] HWND hWndParent,
[in, optional] HMENU hMenu,
[in, optional] HINSTANCE hInstance,
[in, optional] LPVOID lpParam
);
[in] dwExStyle | 正在创建的窗口的扩展窗口样式。 有关可能值的列表,请参阅Extended Window Styles。 |
[in, optional] lpClassName | 由先前调用 RegisterClass 或 RegisterClassEx 函数创建的以 null 结尾的字符串或类原子。 原子必须在 lpClassName 的低位字中; 高位字必须为零。 如果 lpClassName 是一个字符串,它指定窗口类名。 类名可以是通过RegisterClass 或RegisterClassEx 注册的任何名称,前提是注册类的模块也是创建窗口的模块。类名也可以是任何预定义的系统类名。 |
[in, optional] lpWindowName | 窗口名称。 如果窗口样式指定了标题栏,则 lpWindowName 指向的窗口标题显示在标题栏中。 使用 CreateWindow 创建控件时,例如按钮、复选框和静态控件,使用 lpWindowName 来指定控件的文本。 当使用 SS_ICON 样式创建静态控件时,使用 lpWindowName 来指定图标名称或标识符。 要指定标识符,请使用语法“#num”。 |
[in] dwStyle | 正在创建的窗口的样式。 此参数可以是window style values组合值,以及备注部分中指示的控件样式的组合。 |
[in] X | 窗口的初始水平位置。 对于重叠或弹出窗口,x 参数是窗口左上角的初始 x 坐标,以屏幕坐标表示。 对于子窗口,x 是窗口左上角相对于父窗口客户区左上角的 x 坐标。 如果 x 设置为 CW_USEDEFAULT,则系统选择窗口左上角的默认位置并忽略 y 参数。 CW_USEDEFAULT 仅对重叠窗口有效; 如果为弹出窗口或子窗口指定,则 x 和 y 参数设置为零。 |
[in] Y | 窗口的初始垂直位置。 对于重叠或弹出窗口,y 参数是窗口左上角的初始 y 坐标,以屏幕坐标表示。 对于子窗口,y 是子窗口左上角相对于父窗口客户区左上角的初始 y 坐标。 对于列表框,y 是列表框客户区左上角相对于父窗口客户区左上角的初始 y 坐标。 如果创建重叠窗口时设置了 WS_VISIBLE 样式位并且 x 参数设置为 CW_USEDEFAULT,则 y 参数确定窗口的显示方式。 如果 y 参数是 CW_USEDEFAULT,则窗口管理器在创建窗口后调用带有 SW_SHOW 标志的 ShowWindow 。 如果 y 参数是其他值,则窗口管理器调用 ShowWindow 并将该值作为 nCmdShow 参数。 |
[in] nWidth | 窗口的宽度(以设备为单位)。 CW_USEDEFAULT 仅对重叠窗口有效; 如果为弹出窗口或子窗口指定了 CW_USEDEFAULT,则 nWidth 和 nHeight 参数设置为零。 |
[in] nHeight | 窗口的高度(以设备为单位)。 对于重叠的窗口,nHeight 是窗口的高度,以屏幕坐标表示。 如果 nWidth 参数设置为 CW_USEDEFAULT,系统将忽略 nHeight。 |
[in, optional] hWndParent | 正在创建的窗口的父窗口或所有者窗口的句柄。 要创建子窗口或拥有的窗口,请提供有效的窗口句柄。 该参数对于弹出窗口是可选的。 要创建 message-only window,请提供 HWND_MESSAGE 或现有仅消息窗口的句柄。 |
[in, optional] hMenu | 菜单句柄,或指定子窗口标识符,具体取决于窗口样式。 对于重叠或弹出窗口,hMenu 标识要与窗口一起使用的菜单; 如果要使用类菜单,它可以为 NULL。 对于子窗口,hMenu 指定子窗口标识符,一个整数值,对话框控件用于通知其父级事件。 应用程序确定子窗口标识符; 对于具有相同父窗口的所有子窗口,它必须是唯一的。 |
[in, optional] hInstance | 要与窗口关联的模块实例的句柄。 |
[in, optional] lpParam | 指向要通过 WM_CREATE 消息的 lParam 参数指向的 CREATESTRUCT 结构(lpCreateParams 成员)传递给窗口的值的指针。 此消息在返回之前由该函数发送到创建的窗口。 如果应用程序调用 CreateWindow 来创建 MDI 客户端窗口,lpParam 应该指向 CLIENTCREATESTRUCT 结构。 如果一个 MDI 客户窗口调用 CreateWindow 来创建一个 MDI 子窗口,lpParam 应该指向一个MDICREATESTRUCT 结构。 如果不需要其他数据,lpParam 可能为 NULL。 |
Return value
如果函数成功,则返回值是新窗口的句柄。
如果函数失败,则返回值为 NULL。 要获取扩展错误信息,请调用 GetLastError。
此功能通常由于以下原因之一失败:
显示窗口
ShowWindow function (winuser.h) - Win32 apps | Microsoft DocsSets the specified window's show state.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
BOOL ShowWindow(
[in] HWND hWnd,
[in] int nCmdShow
);
[in] hWnd | 窗口的句柄。 |
[in] nCmdShow | 控制窗口的显示方式。 如果启动应用程序的程序提供 STARTUPINFO 结构,则该参数在应用程序第一次调用 ShowWindow 时将被忽略。 否则,第一次调用 ShowWindow 时,该值应该是 WinMain函数在其 nCmdShow 参数中获取的值。 在后续调用中,此参数可以是以下值之一。 |
值 | 意义 |
---|---|
SW_HIDE 0 |
隐藏窗口并激活另一个窗口 |
SW_SHOWNORMAL SW_NORMAL 1 |
激活并显示一个窗口。 如果窗口被最小化或最大化,系统会将其恢复到原来的大小和位置。 应用程序应在第一次显示窗口时指定此标志。 |
SW_SHOWMINIMIZED 2 |
激活窗口并将其显示为最小化窗口。 |
SW_SHOWMAXIMIZED SW_MAXIMIZE 3 |
激活窗口并将其显示为最大化窗口。 |
SW_SHOWNOACTIVATE 4 |
以最近的大小和位置显示窗口。 该值与 SW_SHOWNORMAL 类似,只是窗口未激活。 |
SW_SHOW 5 |
激活窗口并以其当前大小和位置显示它。 |
SW_MINIMIZE 6 |
最小化指定窗口并激活 Z 顺序中的下一个顶级窗口。 |
SW_SHOWMINNOACTIVE 7 |
将窗口显示为最小化窗口。 此值类似于 SW_SHOWMINIMIZED,但未激活窗口。 |
SW_SHOWNA 8 |
以当前大小和位置显示窗口。 该值与 SW_SHOW 类似,只是窗口未激活。 |
SW_RESTORE 9 |
激活并显示窗口。 如果窗口被最小化或最大化,系统会将其恢复到原来的大小和位置。应用程序在恢复最小化窗口时应指定此标志。 |
SW_SHOWDEFAULT 10 |
根据启动应用程序的程序传递给 CreateProcess函数的 STARTUPINFO结构中指定的 SW_ 值设置显示状态。 |
SW_FORCEMINIMIZE 11 |
最小化一个窗口,即使拥有该窗口的线程没有响应。 只有在最小化来自不同线程的窗口时才应使用此标志。 |
返回值
类型:布尔
如果窗口先前可见,则返回值非零。
如果窗口先前被隐藏,则返回值为零。
重画窗口工作区
UpdateWindow function (winuser.h) - Win32 apps | Microsoft DocsThe UpdateWindow function updates the client area of the specified window by sending a WM_PAINT message to the window if the window's update region is not empty.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow
BOOL UpdateWindow(
[in] HWND hWnd
);
[in] hWnd | 处理要更新的窗口。 |
返回值
如果函数成功,则返回值非零。如果函数失败,则返回值为零。
包含来自线程的消息队列的消息信息
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
DWORD lPrivate;
} MSG, *PMSG, *NPMSG, *LPMSG;
//包含来自线程的消息队列的消息信息。
hwnd | 窗口过程接收消息的窗口句柄。 当消息是线程消息时,此成员为 NULL。 |
message | 消息标识符。 应用程序只能使用低位字; 高位字由系统保留。 |
wParam | 有关消息的附加信息。 确切的含义取决于消息成员的ID值。 |
lParam | 有关消息的附加信息。 确切的含义取决于消息成员的ID值 |
time | 发布消息的时间。 |
pt | 发布消息时的光标位置,以屏幕坐标表示。 |
lPrivate |
消息ID
从调用线程的消息队列中检索消息。该函数分派传入的已发送消息,直到发布的消息可用于检索。
BOOL GetMessage(
[out] LPMSG lpMsg,
[in, optional] HWND hWnd,
[in] UINT wMsgFilterMin,
[in] UINT wMsgFilterMax
);
[out] lpMsg | 指向从线程的消息队列接收消息信息的 MSG 结构的指针。 |
[in, optional] hWnd | 要检索其消息的窗口的句柄。 窗口必须属于当前线程。 如果 hWnd 为 NULL,GetMessage 检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中 hwnd 值为 NULL 的任何消息(参见 MSG结构)。 因此,如果 hWnd 为 NULL,则窗口消息和线程消息都会被处理。 如果 hWnd 为 -1,GetMessage 只检索当前线程的消息队列中 hwnd 值为 NULL 的消息,即 PostMessage(当 hWnd 参数为 NULL 时)或 PostThreadMessage发布的线程消息。 |
[in] wMsgFilterMin | 要检索的最低消息值的整数值。 使用 WM_KEYFIRST (0x0100) 指定第一条键盘消息或 WM_MOUSEFIRST (0x0200) 指定第一条鼠标消息。 在此处和 wMsgFilterMax 中使用 WM_INPUT仅指定 WM_INPUT 消息。 如果 wMsgFilterMin 和 wMsgFilterMax 都为零,则 GetMessage 返回所有可用消息(即不执行范围过滤)。 |
[in] wMsgFilterMax | 要检索的最高消息值的整数值。 使用 WM_KEYLAST 指定最后一个键盘消息或 WM_MOUSELAST 指定最后一个鼠标消息。 在此处和 wMsgFilterMin 中使用 WM_INPUT仅指定 WM_INPUT 消息。 如果 wMsgFilterMin 和 wMsgFilterMax 都为零,则 GetMessage 返回所有可用消息(即不执行范围过滤)。 |
返回值
如果函数检索 WM_QUIT以外的消息,则返回值非零。如果函数检索到 WM_QUIT消息,则返回值为零。
如果有错误,返回值为-1。 例如,如果 hWnd 是无效的窗口句柄或 lpMsg 是无效的指针,则函数将失败。 要获取扩展错误信息,请调用 GetLastError。
因为返回值可以是非零、零或 -1,所以避免使用这样的代码:
while (GetMessage( lpMsg, hWnd, 0, 0)) ...
在 hWnd 是无效参数的情况下(例如引用已经被销毁的窗口)可能返回 -1 值,这意味着此类代码可能导致致命的应用程序错误。 相反,使用这样的代码:
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//创建窗口的种类
tagWNDCLASSEXW wcex; //决定窗口种类的结构
wcex.cbSize = sizeof(tagWNDCLASSEXW); //结构大小(单位字节)
wcex.style = CS_HREDRAW | CS_VREDRAW; //窗口风格
wcex.lpfnWndProc = WindowProc; //消息处理函数
wcex.cbClsExtra = 0; //窗口结构的额外字节
wcex.cbWndExtra = 0; //窗口实例的额外字节
wcex.hInstance = hInstance; //当前应用程序实例的句柄(wWinMaind的_In_ HINSTANCE hInstance)
wcex.hIcon = LoadIcon(nullptr,IDI_APPLICATION); //图标的句柄
wcex.hCursor = LoadCursorW(nullptr,IDC_ARROW); //游标的句柄
wcex.hbrBackground = static_cast(GetStockObject(GRAY_BRUSH)); //背景画笔的句柄
wcex.lpszMenuName = nullptr; //窗口菜单
static LPCTSTR szAppName{ _T("WndClsName") }; //窗口名
wcex.lpszClassName = szAppName; //窗口类名称
wcex.hIconSm = nullptr; //与窗口类关联的小图标的句柄。
//注册窗口
RegisterClassEx(&wcex);
//创建窗口
HWND hWnd; //Window handle
hWnd = CreateWindowEx(WS_EX_STATICEDGE, //窗口的扩展窗口样式
szAppName, //窗口类名称
_T("WinTitle"), //窗口名称
WS_OVERLAPPEDWINDOW, //正在创建的窗口的样式
CW_USEDEFAULT, //X
CW_USEDEFAULT, //Y
CW_USEDEFAULT, //nWidth
CW_USEDEFAULT, //nHeight
nullptr, //所有者窗口的句柄
nullptr, //菜单句柄
hInstance, //要与窗口关联的模块实例的句柄。(wWinMaind的_In_ HINSTANCE hInstance)
nullptr //指向要通过 WM_CREATE 消息的 lParam 参数指向的 CREATESTRUCT 结构(lpCreateParams 成员)传递给窗口的值的指针。如果不需要其他数据,lpParam 可能为 NULL。
);
//显示窗口
ShowWindow(hWnd,nCmdShow); //nCmdShow:wWinMain的_In_ int nCmdShow
//重画窗口工作区
UpdateWindow(hWnd);
//包含来自线程的消息队列的消息信息
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0)) // 如果函数检索 WM_QUIT以外的消息,则返回值非零。如果函数检索到 WM_QUIT消息,则返回值为零。
{
TranslateMessage(&msg); //对检索的消息执行任何必要的转换
DispatchMessage(&msg); //使Windows调用应用程序的WindowProc()函数来处理消息
}
return static_cast(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
返回类型LRESULT是一个Windows类型,通常等价于long类型。
该函数是Windows通过指针(该指针是在WinMain()函数的WNDCLASSEX结构中用WindowProc()函数的地址设置的)调用的,所以需要将该函数限定为CALLBACK。
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
BeginPaint BeginPaint function (winuser.h) - Win32 apps | Microsoft Docshttps://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-beginpaintBeginPaint 函数准备指定的窗口进行绘画,并用有关绘画的信息填充 PAINTSTRUCT 结构。
HDC BeginPaint(
[in] HWND hWnd,
[out] LPPAINTSTRUCT lpPaint
);
[in] hWnd | 处理要重绘的窗口。 |
[out] lpPaint | 指向将接收绘画信息的 PAINTSTRUCT结构的指针。 |
返回值
如果函数成功,则返回值是指定窗口的显示设备上下文的句柄。如果函数失败,返回值为NULL,表示没有可用的显示设备上下文。
PAINTSTRUCT
PAINTSTRUCT (winuser.h) - Win32 apps | Microsoft DocsThe PAINTSTRUCT structure contains information for an application. This information can be used to paint the client area of a window owned by that application.https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-paintstructPAINTSTRUCT 结构包含应用程序的信息。 此信息可用于绘制该应用程序拥有的窗口的客户区。
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT;
hdc | 用于绘画的显示 DC 的句柄。 |
fErase | 指示是否必须删除背景。 如果应用程序应该擦除背景,则此值非零。 如果在没有背景画笔的情况下创建窗口类,则应用程序负责擦除背景。 有关详细信息,请参阅 WNDCLASS结构的 hbrBackground 成员的说明。 |
rcPaint | 一个 RECT结构,它指定请求绘画的矩形的左上角和右下角,以相对于客户区左上角的设备单位表示。 |
|
预留的; 系统内部使用。 |
fIncUpdate | 预留的; 系统内部使用。 |
rgbReserved | 预留的; 系统内部使用。 |
RECTRECT (windef.h) - Win32 apps | Microsoft DocsThe RECT structure defines a rectangle by the coordinates of its upper-left and lower-right corners.https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rectRECT 结构通过其左上角和右下角的坐标定义一个矩形。
typedef struct tagRECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;
left | 指定矩形左上角的 x 坐标。 |
top | 指定矩形左上角的 y 坐标。 |
right | 指定矩形右下角的 x 坐标。 |
bottom | 指定矩形右下角的 y 坐标。 |
GetClientRectGetClientRect function (winuser.h) - Win32 apps | Microsoft Docshttps://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect检索窗口客户区的坐标。 客户坐标指定客户区的左上角和右下角。 因为客户坐标是相对于窗口客户区的左上角的,所以左上角的坐标是(0,0)。
BOOL GetClientRect(
[in] HWND hWnd,
[out] LPRECT lpRect
);
[in] hWnd | 处理要重绘的窗口。 |
[out] lpPaint | 指向接收客户端坐标的RECT 结构的指针。 左侧和顶部成员为零。 右侧和底部成员包含窗口的宽度和高度。 |
返回值
如果函数成功,则返回值非零。如果函数失败,则返回值为零。 要获取扩展错误信息,请调用 GetLastError。
SetBkModeSetBkMode function (wingdi.h) - Win32 apps | Microsoft DocsThe SetBkMode function sets the background mix mode of the specified device context. The background mix mode is used with text, hatched brushes, and pen styles that are not solid lines.https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setbkmodeSetBkMode 函数设置指定设备上下文的背景混合模式。 背景混合模式用于文本、阴影画笔和非实线的笔样式。
int SetBkMode(
[in] HDC hdc,
[in] int mode
);
[in] hdc | 设备上下文的句柄。 | ||||||
[in] mode | 背景模式。 此参数可以是以下值之一。
|
返回值
如果函数成功,返回值指定之前的后台模式。如果函数失败,则返回值为零。
DrawText & DrawTextExDrawText function (winuser.h) - Win32 apps | Microsoft DocsThe DrawText function draws formatted text in the specified rectangle. It formats the text according to the specified method (expanding tabs, justifying characters, breaking lines, and so forth).https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtextDrawTextExA function (winuser.h) - Win32 apps | Microsoft DocsThe DrawTextEx function draws formatted text in the specified rectangle.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtextexaDrawText 函数在指定的矩形中绘制格式化文本。 它根据指定的方法(扩展制表符、对齐字符、换行等)格式化文本。
要指定其他格式选项,请使用 DrawTextEx 函数。
int DrawText(
[in] HDC hdc,
[in, out] LPCTSTR lpchText,
[in] int cchText,
[in, out] LPRECT lprc,
[in] UINT format
);
DrawTextEx 函数在指定的矩形中绘制格式化文本。
int DrawTextExA(
[in] HDC hdc,
[in, out] LPSTR lpchText,
[in] int cchText,
[in, out] LPRECT lprc,
[in] UINT format,
[in] LPDRAWTEXTPARAMS lpdtp
);
[in] hdc | 设备上下文的句柄。 |
[in, out] lpchText | 指向指定要绘制的文本的字符串的指针。 如果 nCount 参数为 -1,则字符串必须以 null 结尾。 如果 uFormat 包含 DT_MODIFYSTRING,该函数最多可以向该字符串添加四个附加字符。 包含字符串的缓冲区应该足够大以容纳这些额外的字符。 |
[in] cchText | 字符串的长度(以字符为单位)。 如果 nCount 为 -1,则假定 lpchText 参数是指向以 null 结尾的字符串的指针,并且 DrawText 会自动计算字符数。 |
[in, out] lprc | 指向 RECT 结构的指针,该结构包含要在其中格式化文本的矩形(在逻辑坐标中) |
[in] format | 格式化文本的方法。 该参数可以是以下一个或多个值。 |
format
值 | 含义 |
---|---|
DT_BOTTOM |
将文本对齐到矩形的底部。 此值仅与 DT_SINGLELINE 值一起使用。. |
DT_CALCRECT |
确定矩形的宽度和高度。 如果有多行文本,DrawText 使用 lpRect 参数指向的矩形的宽度,并扩展矩形的底部以绑定最后一行文本。 如果最大的单词比矩形宽,则宽度会扩大。 如果文本小于矩形的宽度,则宽度会减小。 如果只有一行文本,DrawText 会修改矩形的右侧,使其与行中的最后一个字符相接。 无论哪种情况,DrawText 都会返回格式化文本的高度,但不会绘制文本。 |
DT_CENTER |
在矩形中水平居中文本。 |
DT_EDITCONTROL |
复制多行编辑控件的文本显示特征。 具体来说,平均字符宽度的计算方式与编辑控件相同,并且该函数不显示部分可见的最后一行。 |
DT_END_ELLIPSIS |
对于显示的文本,如果字符串的结尾不适合矩形,则会将其截断并添加省略号。 如果不在字符串末尾的单词超出了矩形的范围,则将其截断而没有省略号。 与 DT_PATH_ELLIPSIS 和 DT_WORD_ELLIPSIS 进行比较。 |
DT_EXPANDTABS |
扩展制表符。 每个制表符的默认字符数为 8。 DT_WORD_ELLIPSIS、DT_PATH_ELLIPSIS 和 DT_END_ELLIPSIS 值不能与 DT_EXPANDTABS 值一起使用。 |
DT_EXTERNALLEADING |
包括字体外部行高前导。 通常,外部行距不包括在一行文本的高度中。 |
DT_HIDEPREFIX |
忽略文本中的 & 前缀字符。 后面的字母不会加下划线,但仍会处理其他助记符前缀字符。 输入字符串:“A&bc&&d” 正常:“Abc&d” DT_HIDEPREFIX: "Abc&d"与 DT_NOPREFIX 和 DT_PREFIXONLY 进行比较。 |
DT_INTERNAL |
使用系统字体来计算文本度量。 |
DT_LEFT |
将文本左对齐。 |
DT_MODIFYSTRING |
修改指定的字符串以匹配显示的文本。 除非指定 DT_END_ELLIPSIS 或 DT_PATH_ELLIPSIS,否则此值无效。 |
DT_NOCLIP |
无需剪裁即可绘制。 使用 DT_NOCLIP 时,DrawText 会更快一些。 |
DT_NOFULLWIDTHCHARBREAK |
防止在 DBCS(双宽字符串)处换行,因此换行规则等同于 SBCS 字符串。 例如,这可以在韩语窗口中使用,以提高图标标签的可读性。 除非指定 DT_WORDBREAK,否则此值无效。 |
DT_NOPREFIX |
关闭前缀字符的处理。 通常,DrawText 将助记符前缀字符 & 解释为下划线字符的指令,并将助记符前缀字符 && 解释为打印单个 & 的指令。 通过指定 DT_NOPREFIX,此处理被关闭。 输入字符串:“A&bc&&d” 正常:“Abc&d” DT_NOPREFIX: "A&bc&&d" 与 DT_HIDEPREFIX 和 DT_PREFIXONLY 进行比较。 |
DT_PATH_ELLIPSIS |
对于显示的文本,用省略号替换字符串中间的字符,以便结果适合指定的矩形。 如果字符串包含反斜杠 (\\) 字符,DT_PATH_ELLIPSIS 会尽可能多地保留最后一个反斜杠之后的文本。 除非指定 DT_MODIFYSTRING 标志,否则不会修改字符串。 与 DT_END_ELLIPSIS 和 DT_WORD_ELLIPSIS 进行比较。 |
DT_PREFIXONLY |
仅在与号 (&) 前缀字符之后的字符位置绘制下划线。 不在字符串中绘制任何其他字符。 例如, 输入字符串:“A&bc&&d”n 正常:“Abc&d” DT_PREFIXONLY:“_” 与 DT_HIDEPREFIX 和 DT_NOPREFIX 进行比较。 |
DT_RIGHT |
将文本右对齐。 |
DT_RTLREADING |
当在 hdc 中选择的字体是希伯来语或阿拉伯语字体时,双向文本按从右到左的阅读顺序布局。 所有文本的默认阅读顺序是从左到右。 |
DT_SINGLELINE |
仅在单行上显示文本。 回车和换行不会中断行。 |
DT_TABSTOP |
设置制表位。 uFormat 参数的第 15-8 位(低位字的高位字节)指定每个制表符的字符数。 每个制表符的默认字符数为 8。 DT_CALCRECT、DT_EXTERNALEADING、DT_INTERNAL、DT_NOCLIP 和 DT_NOPREFIX 值不能与 DT_TABSTOP 值一起使用。 |
DT_TOP |
将文本对齐到矩形的顶部。 |
DT_VCENTER |
垂直居中文本。 此值仅与 DT_SINGLELINE 值一起使用。 |
DT_WORDBREAK |
Breaks words。 如果单词超出 lpRect 参数指定的矩形边缘,则单词之间会自动换行。 回车换行序列也会换行。 |
DT_WORD_ELLIPSIS |
截断任何不适合矩形的单词并添加省略号。 与 DT_END_ELLIPSIS 和 DT_PATH_ELLIPSIS 进行比较。 |
返回值
如果函数成功,则返回值是以逻辑单位表示的文本高度。 如果指定了 DT_VCENTER 或 DT_BOTTOM,则返回值是从 lpRect->top 到绘制文本底部的偏移量。如果函数失败,则返回值为零。
EndPaintEndPaint function (winuser.h) - Win32 apps | Microsoft DocsThe EndPaint function marks the end of painting in the specified window. This function is required for each call to the BeginPaint function, but only after painting is complete.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-endpaintEndPaint 函数标记指定窗口中绘画的结束。 每次调用 BeginPaint函数时都需要此函数,但仅在绘制完成之后。
BOOL EndPaint(
[in] HWND hWnd,
[in] const PAINTSTRUCT *lpPaint
);
[in] hWnd | 处理已重绘的窗口。 |
[in] lpPaint | 指向包含由 BeginPaint检索的绘画信息的 PAINTSTRUCT结构的指针。 |
返回值
返回值始终为非零。
结束程序
向系统指示线程已请求终止(退出)。 它通常用于响应 WM_DESTROY消息。
void PostQuitMessage(
[in] int nExitCode
);
[in] nExitCode | 应用程序退出代码。 该值用作 WM_QUIT 消息的 wParam 参数。 |
返回值
无
DefWindowProc
DefWindowProcA
DefWindowProcA function (winuser.h) - Win32 apps | Microsoft Docshttps://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca调用默认窗口过程为应用程序未处理的任何窗口消息提供默认处理。 此功能可确保处理每条消息。 DefWindowProc 使用与窗口过程接收的相同参数调用。
LRESULT DefWindowProcW(
[in] HWND hWnd,
[in] UINT Msg,
[in] WPARAM wParam,
[in] LPARAM lParam
);
DefWindowProcW
调用默认窗口过程为应用程序未处理的任何窗口消息提供默认处理。 此功能可确保处理每条消息。 DefWindowProc 使用与窗口过程接收的相同参数调用。
LRESULT DefWindowProcW(
[in] HWND hWnd,
[in] UINT Msg,
[in] WPARAM wParam,
[in] LPARAM lParam
);
[in] hWnd | 接收消息的窗口过程的句柄。 |
[in] Msg | 消息。 |
[in] wParam | 附加消息信息。 该参数的内容取决于 Msg 参数的值。 |
[in] lParam | 附加消息信息。 该参数的内容取决于 Msg 参数的值。 |
返回值
返回值是消息处理的结果,取决于消息。
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT: //当系统或其他应用程序发出绘制应用程序窗口部分的请求时,将发送 WM_PAINT 消息。
HDC hDC; //处理将与新的Graphics::Graphics对象关联的设备上下文。
PAINTSTRUCT PaintSt; //此信息可用于绘制该应用程序拥有的窗口的客户区。
RECT aRect; //RECT 结构通过其左上角和右下角的坐标定义一个矩形。
hDC = BeginPaint(hWnd,&PaintSt); //准备指定的窗口进行绘画,并用有关绘画的信息填充 PAINTSTRUCT 结构。
GetClientRect(hWnd,&aRect); //检索窗口客户区的坐标。
SetBkMode(hDC, TRANSPARENT); //指定设备上下文的背景混合模式。TRANSPARENT 背景保持不变。
//函数在指定的矩形中绘制格式化文本。
DrawText( hDC,
_T("DrawText lpchText"), //指向指定要绘制的文本的字符串的指针。
-1, //表示以空字符结尾的字符串
&aRect, //该结构包含要在其中格式化文本的矩形(在逻辑坐标中)
DT_SINGLELINE | DT_CENTER | DT_VCENTER); //格式化文本的方法。
EndPaint(hWnd, &PaintSt); //标记指定窗口中绘画的结束。
return 0;
case WM_DESTROY: //此消息在窗口被销毁时发送
PostQuitMessage(WM_QUIT); //向系统指示线程已请求终止(退出)。
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
#include "pch.h"
#include "framework.h"
#include "WNDAPP.h"
#define MAX_LOADSTRING 100 //字符串长度
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance); //UNREFERENCED_PARAMETER 展开传递的参数或表达式。其目的是避免编译器关于未引用参数的警告。
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此处放置代码。
// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); //LoadStringW:从与指定模块关联的可执行文件中加载字符串资源,并将字符串复制到带有终止空字符的缓冲区中,或者返回指向字符串资源本身的只读指针。
LoadStringW(hInstance, IDC_WNDAPP, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); //注册窗口类
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WNDAPP)); //加载指定的快捷键表。
MSG msg; //包含来自线程的消息队列的消息信息
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0)) // 如果函数检索 WM_QUIT以外的消息,则返回值非
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) //处理菜单命令的accelerator keys。
{
TranslateMessage(&msg); //对检索的消息执行任何必要的转换
DispatchMessage(&msg); //使Windows调用应用程序的WindowProc()函数来处理消息
}
}
return (int) msg.wParam;
}
// 函数: MyRegisterClass()
// 目标: 注册窗口类。
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex; //决定窗口种类的结构
wcex.cbSize = sizeof(WNDCLASSEX); //结构大小(单位字节)
wcex.style = CS_HREDRAW | CS_VREDRAW; //窗口风格
wcex.lpfnWndProc = WndProc; //消息处理函数
wcex.cbClsExtra = 0; //窗口结构的额外字节
wcex.cbWndExtra = 0; //窗口实例的额外字节
wcex.hInstance = hInstance; //当前应用程序实例的句柄(wWinMaind的_In_ HINSTANCE hInstance)
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WNDAPP)); //图标的句柄
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); //游标的句柄
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //背景画笔的句柄
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WNDAPP); //窗口菜单
wcex.lpszClassName = szWindowClass; //窗口类名称
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));//与窗口类关联的小图标的句柄。
return RegisterClassExW(&wcex); //注册窗口
}
// 函数: InitInstance(HINSTANCE, int)
// 目标: 保存实例句柄并创建主窗口
// 注释: 在此函数中,我们在全局变量中保存实例句柄并创建和显示主程序窗口。
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW( //创建窗口,hInst,Window handle
szWindowClass, //窗口类名称
szTitle, //窗口名称
WS_OVERLAPPEDWINDOW, //正在创建的窗口的样式
CW_USEDEFAULT, //X
0, //Y
CW_USEDEFAULT, //nWidth
0, //nHeight
nullptr, //所有者窗口的句柄
nullptr, //菜单句柄
hInstance, //要与窗口关联的模块实例的句柄。(wWinMaind的_In_ HINSTANCE hInstance)
nullptr); //指向要通过 WM_CREATE 消息的 lParam 参数指向的
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow); //显示窗口
UpdateWindow(hWnd); //重画窗口工作区
return TRUE;
}
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
// 目标: 处理主窗口的消息。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND: // WM_COMMAND - 处理应用程序菜单
{
int wmId = LOWORD(wParam); //该宏从指定的 32 位值中检索低位字。
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); //此函数从对话框模板资源创建模式对话框。
break;
case IDM_EXIT:
DestroyWindow(hWnd); //该函数销毁指定的窗口。
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT: // WM_PAINT - 绘制主窗口
{
PAINTSTRUCT ps; //此信息可用于绘制该应用程序拥有的窗口的客户区。
HDC hdc = BeginPaint(hWnd, &ps); //准备指定的窗口进行绘画,并用有关绘画的信息填充 PAINTSTRUCT 结构。
// TODO: 在此处添加使用 hdc 的任何绘图代码...
EndPaint(hWnd, &ps); //标记指定窗口中绘画的结束。
}
break;
case WM_DESTROY: // WM_DESTROY - 发送退出消息并返回
PostQuitMessage(0); //向系统指示线程已请求终止(退出)。
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam); //UNREFERENCED_PARAMETER 展开传递的参数或表达式。其目的是避免编译器关于未引用参数的警告。
switch (message)
{
case WM_INITDIALOG: //在显示对话框之前立即发送到对话框过程
return (INT_PTR)TRUE; //INT_PTR(其实也就是 typedef了一把)
case WM_COMMAND: // WM_COMMAND - 处理应用程序菜单
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam)); //销毁模态对话框,导致系统结束对对话框的任何处理。
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}