{"id":4203,"date":"2013-05-31T07:00:00","date_gmt":"2013-05-31T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/05\/31\/posted-messages-are-processed-ahead-of-input-messages-even-if-they-were-posted-later\/"},"modified":"2013-05-31T07:00:00","modified_gmt":"2013-05-31T07:00:00","slug":"posted-messages-are-processed-ahead-of-input-messages-even-if-they-were-posted-later","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130531-00\/?p=4203","title":{"rendered":"Posted messages are processed ahead of input messages, even if they were posted later"},"content":{"rendered":"<p><P>\nRegardless of \n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/05\/30\/10422199.aspx\">\nwhich interpretation you use<\/A>,\nit remains the case that posted messages\nare processed ahead of input messages.\nUnder the MSDN interpretation,\nposted messages and input messages all go into the <I>message queue<\/I>,\nbut\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/ms644936\">\nposted messages are pulled from the queue before input messages<\/A>.\nUnder the Raymond interpretation,\nposted messages and input messages are kept in separate queues,\nand the message retrieval functions will look first in the posted\nmessage queue before looking in the input queue.\n<\/P>\n<P>\nLet&#8217;s run an experiment to see posted messages get processed\nahead of input messages.\nStart with the\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2005\/04\/22\/410773.aspx\">\nnew scratch program<\/A>\nand make these changes:\n<\/P>\n<PRE>\n<FONT COLOR=\"blue\">#include &lt;strsafe.h&gt;<\/FONT><\/p>\n<p>class RootWindow : public Window\n{\npublic:\n virtual LPCTSTR ClassName() { return TEXT(&#8220;Scratch&#8221;); }\n static RootWindow *Create();<\/p>\n<p> <FONT COLOR=\"blue\">void AppendText(LPCTSTR psz)\n {\n    ListBox_SetCurSel(m_hwndChild,\n                      ListBox_AddString(m_hwndChild, psz));\n }<\/p>\n<p> void AppendFormat(LPCTSTR pszFormat, &#8230;)\n {\n  va_list ap;\n  va_start(ap, pszFormat);\n  TCHAR szMsg[256];\n  StringCchVPrintf(szMsg, ARRAYSIZE(szMsg), pszFormat, ap);\n  AppendText(szMsg);\n  va_end(ap);\n }<\/p>\n<p> void LogMessage(const MSG *pmsg)\n {\n   AppendFormat(TEXT(&#8220;%d\\t%04x\\t%p\\t%p&#8221;),\n                pmsg-&gt;time,\n                pmsg-&gt;message,\n                pmsg-&gt;wParam,\n                pmsg-&gt;lParam);\n }<\/FONT><\/p>\n<p> &#8230;\n};<\/p>\n<p>LRESULT RootWindow::OnCreate()\n{\n <FONT COLOR=\"blue\">m_hwndChild = CreateWindow(\n      TEXT(&#8220;listbox&#8221;), NULL,\n      LBS_HASSTRINGS | LBS_USETABSTOPS |\n      WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL,\n      0, 0, 0,0, GetHWND(), (HMENU)1, g_hinst, 0);<\/FONT><\/FONT>\n return 0;\n}<\/p>\n<p>int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,\n                   LPSTR lpCmdLine, int nShowCmd)\n{\n   &#8230;\n   while (GetMessage(&amp;msg, NULL, 0, 0)) {<\/p>\n<p>    <FONT COLOR=\"blue\">switch (msg.message) {\n    case WM_KEYDOWN:\n     prw-&gt;AppendText(TEXT(&#8220;Sleeping&#8221;));\n     UpdateWindow(prw-&gt;GetHWND());\n     Sleep(1000);\n     prw-&gt;AppendText(TEXT(&#8220;Posting&#8221;));\n     PostMessage(prw-&gt;GetHWND(), WM_USER, 0, 0);\n     break;\n    case WM_KEYUP:\n    case WM_USER:\n     prw-&gt;LogMessage(&amp;msg);\n     break;\n    }<\/FONT><\/p>\n<p>    TranslateMessage(&amp;msg);\n    DispatchMessage(&amp;msg);\n   &#8230;\n}\n<\/PRE>\n<P>\nThis program creates a list box so we can display some output.\nIn the message loop, it sniffs at all the queued messages and\ndoes the following:\n<\/P>\n<UL>\n<LI>If the message is <CODE>WM_KEY&shy;UP<\/CODE> or\n    <CODE>WM_USER<\/CODE>, then it logs the message timestamp\n    and some parameters.\n<LI>If the message is <CODE>WM_KEY&shy;DOWN<\/CODE>,\n    then it sleeps without processing messages for one second,\n    and then posts a <CODE>WM_USER<\/CODE> message\n    to the main window (which ignores it).\n<\/UL>\n<P>\nRun this program, and then tap the shift key.\n<\/P>\n<P>\nThe window gets a <CODE>WM_KEY&shy;DOWN<\/CODE>\nfor the shift key.\nIt sleeps for one second (plenty of time for you to release\nthe shift key),\nand then posts a <CODE>WM_USER<\/CODE> message.\n<\/P>\n<P>\nThe <CODE>WM_USER<\/CODE> and <CODE>WM_KEY&shy;UP<\/CODE>\nmessages arrive, and observe via the log window\nthat they arrive <I>out of order<\/I>.\n<CODE>WM_USER<\/CODE> message arrived first!\n<\/P>\n<P>\nThat&#8217;s because of the rule that says that\nposted messages are processed ahead of input messages.\n(Depending on how you want to look at it, you might say\nthat posted messages are &#8220;called out for preferential treatment&#8221;\nin the queue,\nor you might say that posted messages are placed in a different\nqueue from input messages, and the posted message queue has\nhigher priority.)\n<\/P>\n<P>\nObserve also that the timestamp on the <CODE>WM_USER<\/CODE>\nmessage is <I>greater than<\/I> the timestamp on the\n<CODE>WM_KEY&shy;UP<\/CODE> message,\nbecause the key went up before the <CODE>WM_USER<\/CODE>\nmessage was posted.\n<I>Time has gone backward<\/I>.\n<\/P>\n<P>\nMake the following change to our program:\nChange the message we post from\n<CODE>WM_USER<\/CODE> to\n<CODE>WM_KEY&shy;UP<\/CODE>:\n<\/P>\n<PRE>\n      PostMessage(hwnd, <FONT COLOR=\"blue\">WM_KEYUP<\/FONT>, 0, 0);\n<\/PRE>\n<P>\nRun the program again, and again tap the shift key.\nObserve that the posted <CODE>WM_KEY&shy;UP<\/CODE> message\nis processed ahead of the <CODE>WM_KEY&shy;UP<\/CODE> input message.\n(You can see the difference because we posted the\n<CODE>WM_KEY&shy;UP<\/CODE> message with <CODE>wParam<\/CODE>\nand <CODE>lParam<\/CODE> both zero,\nwhereas the\n<CODE>WM_KEY&shy;UP<\/CODE> input message has information in\nthose parameters.)\n<\/P>\n<P>\nThis little demonstration also reinforces some other things we already knew.\nFor example, it once again shows that the input manager\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/05\/24\/10421022.aspx\">\ndoes not wiretap your posted messages<\/A>.\nIf you post a\n<CODE>WM_KEY&shy;UP<\/CODE> message,\nit is treated like a posted message not an input message.\nWe saw earlier that\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2005\/05\/30\/423202.aspx\">\nposting a keyboard message does not update internal input states<\/A>.\nThe keyboard shift states are not updated to match your prank call message.\nIf somebody calls <CODE>Get&shy;Queue&shy;Status<\/CODE>,\nthey will not be told that there is input waiting.\nIt will not wake a\n<CODE>Msg&shy;Wait&shy;For&shy;Multiple&shy;Objects<\/CODE> function\nthat is waiting for <CODE>QS_INPUT<\/CODE>.\nAnd as we saw here today,\nthe message gets processed out of order.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Regardless of which interpretation you use, it remains the case that posted messages are processed ahead of input messages. Under the MSDN interpretation, posted messages and input messages all go into the message queue, but posted messages are pulled from the queue before input messages. Under the Raymond interpretation, posted messages and input messages are [&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-4203","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Regardless of which interpretation you use, it remains the case that posted messages are processed ahead of input messages. Under the MSDN interpretation, posted messages and input messages all go into the message queue, but posted messages are pulled from the queue before input messages. Under the Raymond interpretation, posted messages and input messages are [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4203","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=4203"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4203\/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=4203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=4203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=4203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}