【发布时间】:2023-04-03 17:47:01
【问题描述】:
我有一个自定义对话框,其中包含更改对话框默认按钮的方法。
在WM_INITDIALOG期间,以下函数用于在默认按钮(系统选择的按钮)上绘制焦点矩形
case WM_INITDIALOG:
// ...
// ensure focus rectangle is properly drawn around control with focus
PostMessageW(mhWnd, WM_KEYDOWN, VK_TAB, 0);
return TRUE;
Dialog 类有 SetDefaultControl 方法,让我可以在创建对话框后指定不同的按钮作为默认按钮:
bool Dialog::SetDefaultControl(DWORD ctrlID) const noexcept
{
BOOL result = TRUE;
// Get current default button
const LRESULT status = SendMessageW(mhWnd, DM_GETDEFID, 0, 0);
if (HIWORD(status) == DC_HASDEFID)
{
// remove focus rectangle from default
result = PostMessageW(GetDlgItem(mhWnd, LOWORD(status)), BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
}
// change default button to specified ctrlID
result = result && PostMessageW(mhWnd, DM_SETDEFID, ctrlID, 0);
return result != FALSE;
}
默认对话框有确定和取消按钮,在WM_INITDIALOG期间确定按钮被设置为默认,后来我使用上面的函数将它设置为默认,结果是这样的:
发生的情况是取消按钮是新的默认按钮,但是焦点矩形并未从以前的默认按钮(即确定按钮)中删除。
SetDefaultControl 通过向 OK 按钮发送 BM_SETSTYLE 消息来处理这种情况,但是我不知道应该发送什么样式来从 OK 按钮中删除焦点边框。
根据 MSDN 更改按钮样式:
发送 DM_SETDEFID 消息来更改默认按钮不会 始终从第一个按钮中删除默认状态边框。在 在这些情况下,应用程序应该发送一个 BM_SETSTYLE 消息到 更改第一个按钮边框样式。
https://docs.microsoft.com/en-us/windows/win32/dlgbox/dm-getdefid
我不知道如何继续,我应该在以前的默认按钮上设置什么样式来移除焦点边框状态。
按钮是用WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON创建的
【问题讨论】:
-
DM_SETDEFID告诉对话框在用户按 Enter 时激活哪个按钮,但不会更新任何样式以在 UI 中反映这一点。您可以使用GetWindowLong(hwndButton, GWL_STYLE)获取当前样式,然后将BS_PUSHBUTTON更改为BS_DEFPUSHBUTTON(使其具有默认外观)或将其改回(使其看起来非默认)。此外,发布虚假键盘消息不是触发焦点矩形的方式。使用WM_CHANGEUISTATE。 -
WM_CHANGEUISTATEdocs 对我来说不清楚,如果我想将焦点矩形从一个按钮移动到另一个按钮,这是行不通的:SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS), 0)以下都不起作用MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS) -
WM_CHANGEUISTATE不适用于移动焦点。它用于强制焦点矩形可见(通常在第一次按 TAB 之前隐藏。要移动焦点,请使用WM_NEXTDLGCTL。 -
现在我有了解决这个问题所需的所有信息! + 需要了解 UI 状态。与往常一样,Raymond,感谢您的有用回复!
-
WM_NEXTDLGCTL解决了我的问题,无需讨论任何其他内容,您可能想写一个答案。