{"id":2053,"date":"2014-01-17T07:00:00","date_gmt":"2014-01-17T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/01\/17\/psychic-debugging-why-messages-arent-getting-processed-by-your-message-pump\/"},"modified":"2014-01-17T07:00:00","modified_gmt":"2014-01-17T07:00:00","slug":"psychic-debugging-why-messages-arent-getting-processed-by-your-message-pump","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140117-00\/?p=2053","title":{"rendered":"Psychic debugging: Why messages aren&#039;t getting processed by your message pump"},"content":{"rendered":"<p>\nThe second parameter to the\n<code>Get&shy;Message<\/code>\nis an optional window handle that is used to tell the\n<code>Get&shy;Message<\/code> function to retrieve\nonly messages that belong to the specified window.\n<\/p>\n<p>\nA filtered\n<code>Get&shy;Message<\/code>\nis nearly always a bad idea,\nbecause your program will not respond to messages that don&#8217;t meet\nthe filter.\nUnlike a filtered <code>Peek&shy;Message<\/code> (which simply\nreturns &#8220;no messages satisfy the filter&#8221;),\n<code>Get&shy;Message<\/code> blocks your thread and does not return\nuntil a satisfactory message arrives.\nInstead, they just pile up like newspapers on your doorstep.\n<\/p>\n<p>\nA common mistake I encounter is using a filtered\n<code>Get&shy;Message<\/code> as the main message pump:\n<\/p>\n<pre>\nhwnd = CreateWindow(...);\nif (hwnd == NULL) { return error }\n<i>while (GetMessage(&amp;msg, hwnd, 0, 0)) {<\/i>\n ...\n}\n<\/pre>\n<p>\nI don&#8217;t know for sure, but I&#8217;m guessing that the author said,\n&#8220;Well, I created only one window, so clearly that is the only\nwindow that can receive messages,\nand therefore that is the only window I care about.&#8221;\n<\/p>\n<p>\nThat may be the only window you explicitly created\n<i>in that function<\/i>,\nbut there are still plenty of opportunities\nfor other windows to get created.\nFor example, there may be child windows of your main window.\nOr there may be hidden windows created by other components\nsuch as OLE which are used for cross-thread communication.\nFiltering your message pump&#8217;s\n<code>Get&shy;Message<\/code> prevents those other windows\nfrom receiving queued messages,\nand consequently prevents those windows from getting done\nwhatever it was you asked them to do.\n<\/p>\n<p>\nWhen a support request comes in for a program that hangs\nor acts erratically,\nyou don&#8217;t think to look at the message pump,\nbecause that is nearly always just boilerplate code.\nOnly when you glance at it and notice that the boilerplate\ncode has been tweaked do you realize that\nthe tweaking is the source of the problem.\n(And when I point out the mistake, I may get a &#8220;Thank you&#8221;\nand possibly even a &#8220;I didn&#8217;t realize that&#8221;,\nbut never a\n&#8220;This is what I was thinking when I wrote that in the first place,&#8221;\nso I never figure out why they went to the extra effort of adding a\n<code>Get&shy;Message<\/code> filter.)\n<\/p>\n<p>\nArmed with this new psychic power, you can help this\ncustomer out:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nI can&#8217;t get combo boxes to work outside of a dialog box.\nWhen used as a standalone window,\nthe combo box doesn&#8217;t work correctly.\nIt doesn&#8217;t respond to mouse hover,\nsometimes it ignores clicks,\nsometimes it makes my app hang when I select an item with the\nmouse.\nBut if I put the combo box inside a dialog,\nthen it works perfectly.\nAs you can see in the attached project,\nthe exact same function (<code>Create&shy;Combo<\/code>)\nworks if called from a dialog box, but not from a regular window.\nIs there something special about combo boxes that prevent\nthem from being used outside of a dialog box?\n<\/p>\n<pre>\nvoid CreateCombo(HWND hwndParent)\n{\n HWND hwndCombo = CreateWindow(TEXT(\"combobox\"), 0,\n  WS_BORDER | WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,\n  10, 10, 200, 200, hwndParent, NULL, g_hinst);\n ComboBox_AddString(hwndCombo, TEXT(\"Item 0\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 1\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 2\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 3\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 4\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 5\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 6\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 7\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 8\"));\n ComboBox_AddString(hwndCombo, TEXT(\"Item 9\"));\n}\n\/\/ Dialog box version\nINT_PTR CALLBACK DialogProc(\n    HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n case WM_INITDIALOG:\n  CreateCombo(hdlg);\n  return TRUE;\n case WM_CLOSE:\n  EndDialog(hdlg, 0);\n  return TRUE;\n }\n return FALSE;\n}\nvoid TestDialog()\n{\n DialogBox(g_hinst, MAKEINTRESOURCE(IDD_DIALOG),\n           NULL, DialogProc);\n}\n\/\/ Plain window version\nLRESULT CALLBACK WndProc(\n    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n case WM_CREATE:\n  CreateCombo(hwnd);\n  return 0;\n case WM_DESTROY:\n  PostQuitMessage(0);\n  return 0;\n }\n return DefWindowProc(hwnd, uMsg, wParam, lParam);\n}\nvoid TestWindow()\n{\n WNDCLASS wc = { 0, WndProc, 0, 0, g_hinst, NULL, NULL,\n                 (HBRUSH)(COLOR_WINDOW+1), NULL, TEXT(\"Test\"));\n RegisterClassEx(&amp;wc); \/\/ succeeds\n HWND hwnd = CreateWindow(TEXT(\"Test\"), TEXT(\"Test\"),\n                  WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,\n                  CW_USEDEFAULT, CW_USEDEFAULT,\n                  CW_USEDEFAULT, CW_USEDEFAULT,\n                  NULL, NULL, g_hinst, NULL);\n MSG msg;\n while (GetMessage(&amp;msg, hwnd, 0, 0)) {\n  TranslateMessage(&amp;msg);\n  DispatchMessage(&amp;msg);\n }\n UnregisterClass(TEXT(\"Test\"), g_hinst);\n}\n<\/pre>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>The second parameter to the Get&shy;Message is an optional window handle that is used to tell the Get&shy;Message function to retrieve only messages that belong to the specified window. A filtered Get&shy;Message is nearly always a bad idea, because your program will not respond to messages that don&#8217;t meet the filter. Unlike a filtered Peek&shy;Message [&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-2053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The second parameter to the Get&shy;Message is an optional window handle that is used to tell the Get&shy;Message function to retrieve only messages that belong to the specified window. A filtered Get&shy;Message is nearly always a bad idea, because your program will not respond to messages that don&#8217;t meet the filter. Unlike a filtered Peek&shy;Message [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2053","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=2053"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2053\/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=2053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=2053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=2053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}