为什么我没有获得WM_UPDATEUISTATE?

时间:2017-03-06 23:15:16

标签: c winapi

我有一个带有编辑控件和自定义按钮的主窗口。当编辑控件具有焦点并按Tab键时,按钮控件会获得焦点,但它永远不会收到WM_UPDATEUISTATE?我在主窗口的消息循环中使用IsDialogMessage()。关于为什么会发生这种情况的任何想法?

修改:为什么自定义按钮控件无法接收WM_UPDATEUISTATE

修改:IsDialogMessage()在此示例中未发送WM_UPDATEUISTATEWM_CHANGUISTATE

#include <windows.h>
#include <tchar.h>

HINSTANCE g_hInst;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ 
    static HWND hBtn1, hBtn2;

    switch(msg)
    {
    case WM_CREATE:
        hBtn1 = CreateWindowEx(0, TEXT("Button"), TEXT("Button 1"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
            4, 4, 100, 40, hwnd, 0, g_hInst, 0);
        if(!hBtn1) return -1;

        hBtn2 = CreateWindowEx(0, TEXT("Button"), TEXT("Button 2"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
            114, 4, 100, 40, hwnd, 0, g_hInst, 0);
        if(!hBtn1) return -1;
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break; 

    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}


int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{ 
    const TCHAR szClassName[] = TEXT("Main////");
    WNDCLASSEX wc;
    HWND hwnd;
    MSG msg;

    SecureZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.hIcon         = LoadIcon(0, IDI_APPLICATION);;
    wc.hInstance     = hInstance;
    wc.lpfnWndProc   = WndProc;
    wc.lpszClassName = szClassName;
    if(!RegisterClassEx(&wc)) return 0;

    g_hInst = hInstance;
    hwnd = CreateWindowEx(0, szClassName, TEXT("Main"), WS_OVERLAPPEDWINDOW, 140, 140, 440, 240, 0, 0, hInstance, 0); 
    if(!hwnd) return 0;

    ShowWindow(hwnd, nCmdShow);

    while(GetMessage(&msg, 0, 0, 0) > 0)
    {
        if(!IsDialogMessage(hwnd, &msg))
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg);
        }
    }

    return (int)msg.wParam;
}

我在主窗口使用spy ++,在按Tab键时使用了2个按钮,我在任何地方都看不到WM_UPDATEUISTATEWM_CHANGEUISTATE,但是标准按钮控件绘制了焦点rect 。标准按钮如何知道何时绘制焦点矩形?

enter image description here

1 个答案:

答案 0 :(得分:0)

具有焦点的窗口应显示其焦点指示器。为此,控件应注意WM_SETFOCUSWM_KILLFOCUS。当具有焦点时,行为良好的控件将通过向自身发送WM_QUERYUISTATE来检查UI状态,并且,如果UI状态设置了UISF_HIDEFOCUS标志,则该控件将不会绘制焦点指示器。

WM_CHANGEUISTATEWM_UPDATEUISTATE负责控制窗口树(包括控件)是否应该显示键盘“提示”和焦点指示器 。例如,如果未显示提示,而您单击ALT键,则这些消息将更新树中窗口的UI状态,以便它们开始显示提示。这些消息不用于从一个控件中隐藏焦点指示符,并在用户通过这些控件TAB时将其显示在下一个控件中。之所以会产生这种效果,是因为控件要注意焦点更改消息。

通常来说,自定义控件应监视焦点更改消息,并让DefWindowProc处理UI状态消息。

Raymond Chen拥有一系列有关UI状态以及这些消息如何传播的博客文章。

当我最近再次尝试解决所有这些问题时,我发现这些功能很有帮助。有关该主题的官方文档的当前状态在某些地方还有些模糊和含糊。

注意:即使在Microsoft的官方文档和某些API名称中,术语“助记符”,“加速键”和“热键”也已模糊在一起。当我说“键盘提示”时,我主要是指助记符(有时称为“快捷键”或“访问键”)。这些是控件标签和菜单项中带下划线的字符,使用户知道ALT+<character>将选择带标签的项。