{"id":25513,"date":"2007-08-20T10:00:00","date_gmt":"2007-08-20T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/08\/20\/just-because-youre-a-control-doesnt-mean-that-youre-necessarily-inside-a-dialog-box\/"},"modified":"2007-08-20T10:00:00","modified_gmt":"2007-08-20T10:00:00","slug":"just-because-youre-a-control-doesnt-mean-that-youre-necessarily-inside-a-dialog-box","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070820-00\/?p=25513","title":{"rendered":"Just because you&#039;re a control doesn&#039;t mean that you&#039;re necessarily inside a dialog box"},"content":{"rendered":"<p><i>Prerequisites: Moderate to advanced understanding of the window and dialog managers.<\/i>\n When you&#8217;re implementing a control, you need to be aware that you aren&#8217;t necessarily being hosted inside a dialog box. <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/10\/12\/819674.aspx#822041%0A\"> One commenter suggested handling <code>WM_KEYDOWN<\/code> and closing the dialog box<\/a> as a way to prevent multi-line edit controls from eating the Enter key. But the edit control can&#8217;t do that because people create edit controls outside of dialog boxes. How do you &#8220;close the dialog box&#8221; when there isn&#8217;t one?\n This leads to a related topic brought up by another comment:<\/p>\n<blockquote class=\"q\"><p> <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/10\/12\/819674.aspx#819885\"> Doesn&#8217;t <code>ES_WANTRETURN<\/code> do exactly this?<\/a> The MSDN states the following (emphasis mine): &#8220;ES_WANTRETURN: Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, <b>pressing the ENTER key has the same effect as pressing the dialog box&#8217;s default pushbutton<\/b>. This style has no effect on a single-line edit control.&#8221; <\/p><\/blockquote>\n<p> I remarked that <code>ES_WANTRETURN<\/code> is a messy subject. Now I&#8217;m going to show you the mess. It&#8217;s sort of like visiting your friend&#8217;s house when they&#8217;re not expecting you and wandering into their bedroom where they haven&#8217;t tidied up and there&#8217;s clothes all over the floor.\n The authors of the edit control back in 1981 didn&#8217;t follow the above guidance. Probably&sup1; because back in the days when the edit control was first written, the window manager was still in a state of flux and its design hadn&#8217;t settled down. You can&#8217;t blame the edit control for not following guidance that didn&#8217;t exist.\n The edit control implements <code>ES_WANTRETURN<\/code> as you might expect: It include <code>DLGC_WANTALLKEYS<\/code> in its response to <code>WM_GETDLCODE<\/code>, which causes all keys, including Enter, to go to the edit control.\n What&#8217;s more interesting is how the edit control implemented the absence of <code>ES_WANTRETURN<\/code>: It still includes <code>DLGC_WANTALLKEYS<\/code>, but when it receives the Enter key, it first attempts to detect whether it&#8217;s inside a dialog box, and if so, it tries to mimic what the dialog box would have done: It asks its parent dialog box for the default ID, sets focus to the corresponding control, and <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2005\/05\/30\/423202.aspx\"> simulates input via <code>PostMessage<\/code><\/a> to make that control act as if the user had pressed Enter. Since only button controls can be the default ID, the edit control &#8220;knows&#8221; that the recipient of the simulated input is the button control. The author of the edit control then went in and modified the button control so that it didn&#8217;t rely on virtualized input state when handling the <code>WM_KEYDOWN<\/code> message.\n This is ugly no matter how you slice it, and it violates so many principles of control design it isn&#8217;t funny. For one thing, the way it detects whether the control it hosted inside a dialog is fragile and can be tricked into guessing wrong. Next, its mimcry of the <code>IsDialogMessage<\/code> function is incorrect. When it wants to invoke the default button, it does so by simulating input, which we already know is wrong. And before it does so, it sets focus to the control, which is also wrong; the <code>IsDialogMessage<\/code> function generates a <code>WM_COMMAND<\/code> message <i>without changing focus<\/i>. And finally, it totally misses the boat if the edit control is inside a nested dialog.\n As I noted, all these mistakes are obvious in retrospect, but when the control was first written, these mistakes might not&sup1; even have been mistakes. (For example, nested dialogs didn&#8217;t appear on the scene until Windows&nbsp;95.) Why haven&#8217;t these mistakes been fixed? Well, how can you prove that there aren&#8217;t any programs that rely on the mistakes? One thing you quickly learn in application compatibility is that a bug once shipped gains the status of a feature, because you can be pretty sure that some program somewhere relies on it. (I&#8217;ve seen a plugin that relies on a memory leak in Explorer, for example.) This goes doubly true for core controls like the edit control. Any change to the edit control must be taken with a great deal of trepidation, because your change affects pretty much every single Windows program on the entire planet. With that high a degree of risk, the prudent choice is often to let sleeping dogs lie.\n <b>Nitpicker&#8217;s Corner<\/b><\/p>\n<p> &sup1;Note weasel words. This is my educated guess as to what happened based on personal observation and thought. It is not a <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/08\/10\/4315707.aspx#4327521\"> statement of the official position of Microsoft Corporation<\/a>, and this guess may ultimately prove incorrect. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prerequisites: Moderate to advanced understanding of the window and dialog managers. When you&#8217;re implementing a control, you need to be aware that you aren&#8217;t necessarily being hosted inside a dialog box. One commenter suggested handling WM_KEYDOWN and closing the dialog box as a way to prevent multi-line edit controls from eating the Enter key. But [&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":[2],"class_list":["post-25513","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Prerequisites: Moderate to advanced understanding of the window and dialog managers. When you&#8217;re implementing a control, you need to be aware that you aren&#8217;t necessarily being hosted inside a dialog box. One commenter suggested handling WM_KEYDOWN and closing the dialog box as a way to prevent multi-line edit controls from eating the Enter key. But [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25513","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=25513"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25513\/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=25513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=25513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=25513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}