最近更新于 2024-05-05 14:18
环境
Windows 11 专业工作站版 22H2
Visual Studio 2022 专业版
使用 Unicode 字符集,C17 标准编译,64 位编译
添加对话框资源
先添加一个资源文件,再给它添加对话框资源
在设计界面有工具箱可以添加组件,这里主要是演示代码的调用,所以就用默认的就行
模式对话框
模式对话框会阻塞调用者,即弹出模式对话框后,原来的窗口就暂停了,也无法操作
#include <Windows.h>
#include "resource.h" // 引入对话框资源
HINSTANCE g_hInstance = {0}; // 用于保存当前实例句柄
/**
* @brief 对话框过程函数
* @param hWndDlg 对话框的窗口句柄
* @param msg 消息代码
* @param wParam 消息参数
* @param lParam 消息参数
* @return 返回 FALSE 调用内部默认处理
*/
INT_PTR CALLBACK DlgProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) // 和普通窗口的消息过程函数使用类似
{
switch (msg)
{
case WM_INITDIALOG: // 相当于普通窗口的 WM_CREATE 消息
{
MessageBox(NULL, L"对话框初始化操作可以在这里执行", L"提醒", MB_OK);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
{
MessageBox(NULL, L"点击确定1", L"消息", MB_OK);
break;
}
case IDCANCEL:
{
MessageBox(NULL, L"点击取消1", L"消息", MB_OK);
break;
}
default:
{
break;
}
}
}
case WM_CLOSE:
{
// 销毁对话框窗口,同时解除阻塞
EndDialog(hWndDlg,
LOWORD(wParam)); // DialogBox 的返回值,这里就将对话框按键状态传回去
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONUP: // 在窗口中点击鼠标打开对话框
{
// 创建对话框
INT_PTR db = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProc);
if (db == IDOK)
{
MessageBox(NULL, L"点击确定2", L"消息", MB_OK);
}
else if (db == IDCANCEL)
{
MessageBox(NULL, L"点击取消2", L"消息", MB_OK);
}
else
{
MessageBox(NULL, L"点击关闭2", L"消息", MB_OK);
}
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
return 0;
}
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPreInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
g_hInstance = hInstance;
PCWSTR szClassName = L"Desktop";
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"注册窗口失败!", L"错误", MB_OK);
return 1;
}
HWND hWnd = CreateWindowEx(0, szClassName, L"简单程序", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL, L"创建窗口失败!", L"错误", MB_OK);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
运行程序
在窗口空白处点以下左键触发弹出模式对话框
此时,“简单程序”框就无法操作了,分别点击确定和取消都会弹出两次消息框,一个消息框是在对话框过程函数中产生的,另一个消息框是根据创建对话框函数传出的返回值产生的。
非模式对话框
相比于模式对话框,主要区别就在弹出对话框后,原来的窗口依然在运行,在上面做操作也会有响应。比如可以调出多个同样的对话框,当然这里的代码做了禁止重复弹出的措施。将对话框句柄变量设为全局的,在创建对话框之前先判断这个句柄是否已经是一个窗口句柄了,不是才创建,是就不创建,避免弹出多个同样对话框的情况。
#include <Windows.h>
#include "resource.h" // 引入对话框资源
HINSTANCE g_hInstance = {0}; // 用于保存当前实例句柄
HWND g_hWndDlg = NULL; // 用于保存对话框句柄
/**
* @brief 对话框过程函数
* @param hWndDlg 对话框的窗口句柄
* @param msg 消息代码
* @param wParam 消息参数
* @param lParam 消息参数
* @return 返回 FALSE 执行内部默认操作
*/
INT_PTR CALLBACK DlgProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) // 和普通窗口的消息过程函数使用类似
{
switch (msg)
{
case WM_INITDIALOG: // 相当于普通窗口的 WM_CREATE 消息
{
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
{
MessageBox(hWndDlg, L"点击确定", L"消息", MB_OK);
break;
}
case IDCANCEL:
{
MessageBox(hWndDlg, L"点击取消", L"消息", MB_OK);
break;
}
default:
{
break;
}
}
}
case WM_CLOSE:
{
// 销毁对话框窗口
DestroyWindow(hWndDlg);
break;
}
default:
{
return FALSE;
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONUP: // 在窗口中点击鼠标打开对话框
{
if (!IsWindow(g_hWndDlg)) // 防止重复弹出对话框
{
g_hWndDlg = CreateDialog(g_hInstance, // 当前实例句柄
MAKEINTRESOURCE(IDD_DIALOG1), // 对话框资源
hWnd, // 父窗口句柄
DlgProc); // 对话框过程函数
ShowWindow(g_hWndDlg, SW_SHOW); // 需要手动设置显示
}
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
return 0;
}
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPreInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
g_hInstance = hInstance;
PCWSTR szClassName = L"Desktop";
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"注册窗口失败!", L"错误", MB_OK);
return 1;
}
HWND hWnd = CreateWindowEx(0, szClassName, L"简单程序", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL, L"创建窗口失败!", L"错误", MB_OK);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
现在可以直接点击主窗口的关闭停止程序,而模式对话框弹出时,主窗口无法操作,只能先关闭对话框后才能操作主窗口。
桌面程序添加对话框 – Windows API