{"id":34673,"date":"2005-08-08T10:00:16","date_gmt":"2005-08-08T10:00:16","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/08\/08\/the-dangers-of-playing-focus-games-when-handling-a-wm_killfocus-message\/"},"modified":"2005-08-08T10:00:16","modified_gmt":"2005-08-08T10:00:16","slug":"the-dangers-of-playing-focus-games-when-handling-a-wm_killfocus-message","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050808-16\/?p=34673","title":{"rendered":"The dangers of playing focus games when handling a WM_KILLFOCUS message"},"content":{"rendered":"<p><P>\nI had noted last year that\n<a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/04\/19\/115912.aspx\">\n<CODE>WM_KILLFOCUS<\/CODE> is the wrong time to do field validation<\/A>.\nHere&#8217;s another example of how messing with the focus during a\n<CODE>WM_KILLFOCUS<\/CODE> message can create confusion.\n<\/P>\n<P>\nConsider an edit control that displays feedback via a balloon tip.\nFor example, password edit controls often warn you if you&#8217;re typing\nyour password while CapsLock is in effect.\nOne of the things you probably want to do is to remove the balloon\ntip if the user moves focus to another control, since there&#8217;s no\npoint telling the user about a problem with something they aren&#8217;t\nusing.\nYou might be tempted to subclass the edit control and do\nsomething like this:\n<\/P>\n<PRE>\nLRESULT CALLBACK EditSubclass(\n    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n  switch (uMsg) {\n  &#8230;\n  case WM_KILLFOCUS:\n    if (hwndBalloonTip) {\n      DestroyWindow(hwndBalloonTip);\n      hwndBalloonTip = NULL;\n    }\n    break;\n  &#8230;\n  }\n  return CallWindowProc(prevWndProc, hwnd, uMsg, wParam, lParam);\n}\n<\/PRE>\n<P>\nWhen you give this code a shot, it works great&#8230;\nunless the user clicks <STRONG>on the balloon tip itself<\/STRONG>\nthe edit control&#8217;s caret (the blinking insertion point thingie) disappears.\nWhat happened?\n<\/P>\n<P>\nWhat happened is that you gummed up the focus change process by\ndestroying the window that focus was going to!\nThe focus change process goes like this:\n<\/P>\n<UL>\n<LI>Put focus on new focus window.\n<LI>Send WM_KILLFOCUS to old focus window (if any).\n<LI>Send WM_SETFOCUS to new focus window (if any).\n<\/UL>\n<P>\nBut in the second step, we <STRONG>destroyed the new focus window<\/STRONG>.\nWhen the focus window is destroyed, the window manager tries to find a new\nfocus window, and it settles upon the edit control itself.\nThis starts a recursive focus change cycle,\ntelling the edit control that it now has focus again.\n<\/P>\n<P>\nLet&#8217;s look at the flow in this nested focus change scenario\nwhen the user clicks on the tooltip window.\n<\/P>\n<UL>\n<LI>Put focus on tooltip.\n<LI>Send WM_KILLFOCUS to edit control.\n    <UL>\n    <LI>EditSubclass destroys the tooltip.\n        <UL>\n        <LI>Window manager puts focus on the edit control.\n        <LI>Nobody to send WM_KILLFOCUS to.\n        <LI>Send WM_SETFOCUS to edit control.\n            <UL>\n            <LI>EditSubclass passes WM_SETFOCUS to the original window procedure.\n            <\/UL>\n        <\/UL>\n    <LI>EditSubclass passes WM_KILLFOCUS to the original window procedure.\n    <\/UL>\n<LI>Send WM_SETFOCUS to tooltip &#8211; fails (tooltip was destroyed).\n<\/UL>\n<P>\nDo you see the problem yet?\n<\/P>\n<P>\nLook at the message traffic as it reaches the original edit control window\nprocedure:\n<\/P>\n<UL>\n<LI>WM_SETFOCUS (from the nested focus change)\n<LI>WM_KILLFOCUS (from the original focus change)\n<\/UL>\n<P>\nAs far as the edit control is concerned, it gained focus then lost it.\nTherefore, no caret, since the edit control displays a caret only when\nit has focus, and your recursive focus changing has resulted in the\nedit control thinking it doesn&#8217;t have focus even though it does.\n<\/P>\n<P>\nThere are many ways out of this mess.\n<\/P>\n<P>\nFirst, notice that you don&#8217;t need to subclass the edit control;\nyou can just react to the <CODE>EN_KILLFOCUS<\/CODE> notification.\nSecond, you can respond to the <CODE>EN_KILLFOCUS<\/CODE> by\nposting yourself a message and destroying the tooltip on receipt\nof that posted message.\nBy doing it via a posted message,\nyou avoid the recursive focus change since your work is now being\ndone outside a focus change cycle.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had noted last year that WM_KILLFOCUS is the wrong time to do field validation. Here&#8217;s another example of how messing with the focus during a WM_KILLFOCUS message can create confusion. Consider an edit control that displays feedback via a balloon tip. For example, password edit controls often warn you if you&#8217;re typing your password [&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-34673","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>I had noted last year that WM_KILLFOCUS is the wrong time to do field validation. Here&#8217;s another example of how messing with the focus during a WM_KILLFOCUS message can create confusion. Consider an edit control that displays feedback via a balloon tip. For example, password edit controls often warn you if you&#8217;re typing your password [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/34673","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=34673"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/34673\/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=34673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=34673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=34673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}