{"id":42083,"date":"2003-10-21T12:13:00","date_gmt":"2003-10-21T12:13:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2003\/10\/21\/using-the-tab-key-to-navigate-in-non-dialogs\/"},"modified":"2003-10-21T12:13:00","modified_gmt":"2003-10-21T12:13:00","slug":"using-the-tab-key-to-navigate-in-non-dialogs","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20031021-00\/?p=42083","title":{"rendered":"Using the TAB key to navigate in non-dialogs"},"content":{"rendered":"<p>\n        The IsDialogMessage function works even if you aren&#8217;t a dialog. As long as your child\n        windows have the WS_TABSTOP and\/or WS_GROUP styles, they can be navigated as if they\n        were part of a dialog box. One caveat is that IsDialogMessage will send DM_GETDEFID\n        and DM_SETDEFID messages to your window, which are message numbers WM_USER and WM_USER+1,\n        so you should avoid using those messages in your window procedure for some other purpose.\n    <\/p>\n<p>\n        These changes to our scratch program illustrate how you can use the TAB key to navigate\n        within a non-dialog.\n    <\/p>\n<pre>HWND g_hwndLastFocus;\nvoid OnSetFocus(HWND hwnd, HWND hwndOldFocus)\n{\n    if (g_hwndLastFocus) {\n        SetFocus(g_hwndLastFocus);\n    }\n}\nvoid OnActivate(HWND hwnd, UINT state,\n                HWND hwndActDeact, BOOL fMinimized)\n{\n    if (state == WA_INACTIVE) {\n        g_hwndLastFocus = GetFocus();\n    }\n}\n\/\/ Just display a messagebox so you can see something\nvoid OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)\n{\n    switch (id) {\n    case 100:\n        MessageBox(hwnd, TEXT(\"Button 1 pushed\"),\n                   TEXT(\"Title\"), MB_OK);\n        break;\n    case 101:\n        MessageBox(hwnd, TEXT(\"Button 2 pushed\"),\n                   TEXT(\"Title\"), MB_OK);\n        break;\n    case IDCANCEL:\n        MessageBox(hwnd, TEXT(\"Cancel pushed\"),\n                   TEXT(\"Title\"), MB_OK);\n        break;\n    }\n}\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n    HWND hwndChild =\n        CreateWindow(\n        TEXT(\"button\"),                 \/* Class Name *\/\n        TEXT(\"Button &amp;1\"),              \/* Title *\/\n        WS_CHILD | WS_VISIBLE | WS_TABSTOP |\n        BS_DEFPUSHBUTTON | BS_TEXT,     \/* Style *\/\n        0, 0, 100, 100,                 \/* Position and size *\/\n        hwnd,                           \/* Parent *\/\n        (HMENU)100,                     \/* Child ID *\/\n        g_hinst,                        \/* Instance *\/\n        0);                             \/* No special parameters *\/\n    if (!hwndChild) return FALSE;\n    g_hwndLastFocus = hwndChild;\n    hwndChild =\n        CreateWindow(\n        TEXT(\"button\"),                 \/* Class Name *\/\n        TEXT(\"Button &amp;2\"),              \/* Title *\/\n        WS_CHILD | WS_VISIBLE | WS_TABSTOP |\n        BS_PUSHBUTTON | BS_TEXT,        \/* Style *\/\n        100, 0, 100, 100,               \/* Position and size *\/\n        hwnd,                           \/* Parent *\/\n        (HMENU)101,                     \/* Child ID *\/\n        g_hinst,                        \/* Instance *\/\n        0);                             \/* No special parameters *\/\n    if (!hwndChild) return FALSE;\n    hwndChild =\n        CreateWindow(\n        TEXT(\"button\"),                 \/* Class Name *\/\n        TEXT(\"Cancel\"),                 \/* Title *\/\n        WS_CHILD | WS_VISIBLE | WS_TABSTOP |\n        BS_PUSHBUTTON | BS_TEXT,        \/* Style *\/\n        200, 0, 100, 100,               \/* Position and size *\/\n        hwnd,                           \/* Parent *\/\n        (HMENU)IDCANCEL,                \/* Child ID *\/\n        g_hinst,                        \/* Instance *\/\n        0);                             \/* No special parameters *\/\n    if (!hwndChild) return FALSE;\n    return TRUE;\n}\n\/\/  Add to WndProc\n    HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);\n    HANDLE_MSG(hwnd, WM_ACTIVATE, OnActivate);\n    HANDLE_MSG(hwnd, WM_SETFOCUS, OnSetFocus);\n    \/\/ Add blank case statements for these to ensure we don't use them\n    \/\/ by mistake.\n    case DM_GETDEFID: break;\n    case DM_SETDEFID: break;\n\/\/  Change message loop\n    MSG msg;\n    while (GetMessage(&amp;msg, NULL, 0, 0)) {\n        if (IsDialogMessage(hwnd, &amp;msg)) {\n            \/* Already handled by dialog manager *\/\n        } else {\n            TranslateMessage(&amp;msg);\n            DispatchMessage(&amp;msg);\n        }\n    }\n<\/pre>\n<p>\n        One subtlety is the additional handling of the WM_ACTIVATE and WM_SETFOCUS messages\n        to preserve the focus when the user switches away from the window and back. Notice\n        also that we picked Button 1 as our initial default button by setting it with the\n        BS_DEFPUSHBUTTON style.\n    <\/p>\n<p>\n        Observe that all the standard dialog accelerators now work. The TAB key navigates,\n        the Alt+1 and Alt+2 keys act as accelerators for the two buttons, the Enter key presses\n        the default button, and the ESC key pushes the Cancel button since its control ID\n        is IDCANCEL.\n    <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The IsDialogMessage function works even if you aren&#8217;t a dialog. As long as your child windows have the WS_TABSTOP and\/or WS_GROUP styles, they can be navigated as if they were part of a dialog box. One caveat is that IsDialogMessage will send DM_GETDEFID and DM_SETDEFID messages to your window, which are message numbers WM_USER and [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-42083","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The IsDialogMessage function works even if you aren&#8217;t a dialog. As long as your child windows have the WS_TABSTOP and\/or WS_GROUP styles, they can be navigated as if they were part of a dialog box. One caveat is that IsDialogMessage will send DM_GETDEFID and DM_SETDEFID messages to your window, which are message numbers WM_USER and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/42083","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=42083"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/42083\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=42083"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=42083"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=42083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}