提问人:CristhianDev 提问时间:11/7/2023 最后编辑:CristhianDev 更新时间:11/7/2023 访问量:129
如何在使用 CreateWindow 创建的窗口中设置默认按钮,而不是在 Windows 中设置对话框资源?
How can I set a default button in a window created with CreateWindow instead of a dialog resource in Windows?
问:
我正在开发一个 Windows 应用程序,我需要使用该函数创建一个自定义窗口。但是,我注意到当我使用对话框资源时,我可以设置默认按钮,但是当我使用 动态创建窗口时,我不确定如何做到这一点。CreateWindow
CreateWindow
有没有办法在不依赖对话框资源的情况下在使用 CreateWindow 创建的窗口中设置默认按钮?如果是这样,实现这一目标的最佳方法是什么?我想确保默认按钮突出显示,并且可以在窗口处于焦点时通过“Enter”键激活。
我一直在网上进行广泛的研究,但我无法找到任何关于如何处理这种特定情况的明确信息。以下是我的代码摘录:main.cpp
#include <Windows.h>
#include <CommCtrl.h>
#define IDC_BUTTON1 1001
#define IDC_BUTTON2 1002
LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
WNDCLASSEXA wcex = { };
wcex.cbSize = sizeof(WNDCLASSEXA);
wcex.lpfnWndProc = MainWindowProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIconA(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursorA(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszClassName = "MainWindowClass";
RegisterClassExA(&wcex);
HWND hWnd = CreateWindowExA(0, "MainWindowClass", "", WS_OVERLAPPEDWINDOW, 0, 0, 416, 228, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_NORMAL);
MSG msg = { };
while (GetMessageA(&msg, NULL, 0, 0) > 0)
{
if (!IsDialogMessageA(hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
return 0;
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
HFONT hFont = CreateFontA(13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "MS Shell Dlg 2");
HWND hWndEdit1 = CreateWindowExA(WS_EX_CLIENTEDGE, WC_EDIT, "", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 100, 20, 200, 21, hWnd, NULL, NULL, NULL);
HWND hWndEdit2 = CreateWindowExA(WS_EX_CLIENTEDGE, WC_EDIT, "", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 100, 60, 200, 21, hWnd, NULL, NULL, NULL);
HWND hWndButton1 = CreateWindowExA(0, WC_BUTTON, "Button 1", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 122, 120, 75, 23, hWnd, (HMENU)IDC_BUTTON1, NULL, NULL);
HWND hWndButton2 = CreateWindowExA(0, WC_BUTTON, "Button 2", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 203, 120, 75, 23, hWnd, (HMENU)IDC_BUTTON2, NULL, NULL);
SendMessageA(hWndEdit1, WM_SETFONT, (WPARAM)hFont, (LPARAM)FALSE);
SendMessageA(hWndEdit2, WM_SETFONT, (WPARAM)hFont, (LPARAM)FALSE);
SendMessageA(hWndButton1, WM_SETFONT, (WPARAM)hFont, (LPARAM)FALSE);
SendMessageA(hWndButton2, WM_SETFONT, (WPARAM)hFont, (LPARAM)FALSE);
SendMessageA(hWndEdit1, EM_SETMARGINS, (WPARAM)EC_LEFTMARGIN, (LPARAM)0);
SendMessageA(hWndEdit2, EM_SETMARGINS, (WPARAM)EC_LEFTMARGIN, (LPARAM)0);
SendMessageA(hWnd, DM_SETDEFID, (WPARAM)IDC_BUTTON1, (LPARAM)0);
SetFocus(hWndEdit1); // Need focus edit control, no default button
} break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
{
MessageBoxA(hWnd, "OK", "Title", MB_OK);
} break;
case IDCANCEL:
{
MessageBoxA(hWnd, "Cancel", "Title", MB_OK);
} break;
case IDC_BUTTON1:
{
MessageBoxA(hWnd, "BUTTON 1", "Title", MB_OK);
} break;
case IDC_BUTTON2:
{
MessageBoxA(hWnd, "BUTTON 2", "Title", MB_OK);
} break;
}
} break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
return 0;
}
我尝试使用 ,但我找不到使它按预期工作的方法。似乎我可能需要手动处理 和 事件,但我不确定如何进行此操作以确保功能正常。DM_SETDEFID
DM_SETDEFID
DM_GETDEFID
我正在寻找有关如何有效管理 和 事件或任何其他推荐技术的指导,这些技术将使我能够在 Windows 应用程序中为使用 CreateWindow 创建的自定义窗口设置默认按钮。DM_SETDEFID
DM_GETDEFID
答:
将BS_DEFPUSHBUTTON
窗口样式指定给默认按钮:
创建一个按钮,其行为类似于BS_PUSHBUTTON样式的按钮,但具有独特的外观。如果按钮位于对话框中,则用户可以通过按 Enter 键选择该按钮,即使该按钮没有输入焦点也是如此。此样式可用于使用户能够快速选择最可能(默认)选项。
此外,请确保在显示窗口时,默认按钮具有初始输入焦点。而且,您可能需要向窗口发送一条消息,以便知道按下时要发送哪个控件 ID,否则它将根据 MSDN 的对话框键盘界面文档发送:DM_SETDEFID
IsDialogMessageA()
EnterIDOK
系统为对话框提供了一个特殊的键盘界面,该界面对多个键进行特殊处理。该接口生成与对话框中的某些按钮相对应的消息,或将输入焦点从一个控件更改为另一个控件。以下是此接口中使用的键及其各自的操作。
钥匙 行动 ... ... 进入 向对话框过程发送消息。该参数设置为默认按钮的控制标识符。 WM_COMMAND
wParam
IDOK
... ... 系统会自动为所有模式对话框提供键盘界面。它不提供无模式对话框的接口,除非应用程序调用
IsDialogMessage
函数来筛选其主消息循环中的消息。这意味着应用程序必须在从消息队列中检索消息后立即将消息传递到。如果该函数用于对话框,则该函数处理消息,并返回一个非零值,以指示消息已处理,不得传递给 or 函数。IsDialogMessage
TranslateMessage
DispatchMessage
评论
Enter
IDOK
BUTTON 1
Tab
IsDialogMessage()
DM_SETDEFID
DM_SETDEFID
TAB
default button
TAB
DM_SETDEFID
DM_GETDEFID
IDOK
DM_SETDEFID
评论
DefDlgProc
DefWindowProc
WNDCLASS
的cbWndExtra
成员必须至少设置为DLGWINDOWEXTRA
。DWLP_MSGRESULT
DefDlgProc