在无模式对话框中阻止 ESC 和 Enter 键(Win32,非 MFC) [英] Block ESC and Enter keys in modeless dialog box (Win32, non-MFC)
问题描述
有一些关于这个主题的文章,但没有一篇对我有用.我正在使用 Win32(无 MFC)编写以下内容.目标是防止 ESC
或 ENTER
键关闭无模式对话框.
There're some articles written on this subject, but none of them worked in my case. I'm writing the following using Win32 (no MFC). The goal is to prevent ESC
or ENTER
keys from closing the modeless dialog box.
这是对话框模板:
IDD_DIALOG_1 DIALOGEX 0, 0, 345, 179
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION ""
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "New Pt",IDC_CHECK_NEW_PT,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,7,3,39,12
CONTROL "Lines",IDC_CHECK_LINES,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,54,3,39,12
CONTROL "Curves",IDC_CHECK_CURVES,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,94,3,39,12
CONTROL "Ellipses",IDC_CHECK_ELLIPSE,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,134,3,39,12
CONTROL "Circles",IDC_CHECK_CIRCLE,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,174,3,39,12
LTEXT "Pen Size:",IDC_STATIC,242,7,30,8
EDITTEXT IDC_EDIT_PEN_SIZE,275,3,40,14,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_SPIN_PEN_SIZE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,316,3,11,14
EDITTEXT IDC_EDIT_SRC,7,19,331,106,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
END
为了捕获这两个键,我将消息循环更改为:
To trap those two keys, I change the message loop to this:
MSG msg;
// Main message loop:
for(int nR;;)
{
nR = ::GetMessage(&msg, nullptr, 0, 0);
if(!nR)
{
break;
}
else if(nR == -1)
{
//Error
ASSERT(NULL);
break;
}
if(ghActiveModelessDlg)
{
BOOL bProcessAsDlgMsg = TRUE;
if(msg.message == WM_KEYDOWN ||
msg.message == WM_KEYUP)
{
//Try to trap ESC & Enter keys
if(msg.wParam == VK_ESCAPE)
{
//Do not process
bProcessAsDlgMsg = FALSE;
}
else if(msg.wParam == VK_RETURN)
goto lbl_check_enter;
}
else if(msg.message == WM_CHAR)
{
//Try to trap ESC & Enter key
if(msg.wParam == 27)
{
//ESC - Do not process
bProcessAsDlgMsg = FALSE;
}
else if(msg.wParam == '\r')
{
lbl_check_enter:
//See what window is it
WCHAR buffClass[256];
if(::GetClassName(msg.hwnd, buffClass, _countof(buffClass)) &&
lstrcmpi(buffClass, L"edit") == 0 &&
(::GetWindowLongPtr(msg.hwnd, GWL_STYLE) & ES_WANTRETURN))
{
//This is edit ctrl that can handle its own Enter keystroke
}
else
{
//Do not process
bProcessAsDlgMsg = FALSE;
}
}
}
if(bProcessAsDlgMsg)
{
if(::IsDialogMessage(ghActiveModelessDlg, &msg))
{
continue;
}
}
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
并且 ghActiveModelessDlg
是从 DlgProc
中为无模式对话框设置的:
And ghActiveModelessDlg
is set from within DlgProc
for the modeless dialog as such:
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(hDlg)
{
//...
case WM_ACTIVATE:
{
//Needed to ensure that keyboard shortcuts are properly processed in the message loop
ghActiveModelessDlg = wParam != WA_INACTIVE ? hDlg : NULL;
}
break;
}
return 0;
}
这有效......在大多数情况下.除了这个.
This works ... in most cases. Except this one.
这是顺序.将焦点放入多行编辑框中,然后按任意字母/数字键,然后按 ESC
:
Here's the sequence. Put the focus into the multi-line edit box, then hit any letter/number key and then ESC
:
然后它会关闭对话框.
知道它如何传递我上面的覆盖代码吗?
Any idea how can it pass my override code above?
附注.有趣的观察.
1) 如果我先点击 ESC
,我的代码就会捕获它.只有当我按下其他键然后 ESC
时它才会失败.
1) If I just hit ESC
first, my code traps it. It's only when I hit some other key and then ESC
it fails.
2) 如果我注释掉调用 IsDialogMessage
(以及随后的 continue
)的那行,它将停止接受 ESC
.所以我的猜测是,它不是执行此操作的编辑控件.
2) If I comment out the line that calls IsDialogMessage
(and a subsequent continue
) it stops accepting ESC
. So my guess is that it's not the edit control that does this.
推荐答案
如果我们只想通过点击系统菜单中的关闭 X
按钮(或通过 ALT+F4
code>) 并通过 ESC
和 ENTER
键禁用关闭 - 所有我们需要的 - 在处理 (WM_SYSCOMMAND, SC_CLOSE) 时调用
DestroyWindow
并且不对 (WM_COMMAND, IDCANCEL, IDOK)
做任何事情.我们不需要特殊的消息循环或子类任何控件.并且对话框中没有带有 IDOK/IDCANCEL id 的按钮
if we want let close dialog only by clicking close X
button in system menu (or by ALT+F4
) and disable close by ESC
and ENTER
key - all what we need - call DestroyWindow
when process (WM_SYSCOMMAND, SC_CLOSE)
and do nothing on (WM_COMMAND, IDCANCEL, IDOK)
. we not need special message loop or subcluss any controls. and not have buttons with IDOK/ IDCANCEL id in dialog
INT_PTR DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SYSCOMMAND:
if ((wParam & 0xfff0) == SC_CLOSE) DestroyWindow(hwndDlg);
break;
case WM_COMMAND:
switch (wParam)
{
case MAKEWPARAM(IDOK, BN_CLICKED):
case MAKEWPARAM(IDCANCEL, BN_CLICKED):
// ignore this
break;
....
}
}
....
}
这篇关于在无模式对话框中阻止 ESC 和 Enter 键(Win32,非 MFC)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!