{"id":8923,"date":"2011-12-12T07:00:00","date_gmt":"2011-12-12T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/12\/12\/how-can-i-tell-whether-a-window-is-modal\/"},"modified":"2011-12-12T07:00:00","modified_gmt":"2011-12-12T07:00:00","slug":"how-can-i-tell-whether-a-window-is-modal","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20111212-00\/?p=8923","title":{"rendered":"How can I tell whether a window is modal?"},"content":{"rendered":"<p>\nA customer wanted a way to determine whether a particular\nwindow is modal. They listed a few methods they had tried\nbut found that it didn&#8217;t work and asked for assistance.\n<\/p>\n<p>\nAs <a HREF=\"http:\/\/blogs.msdn.com\/ericlippert\/\">Eric Lippert<\/a>\nis fond of saying,\n&#8220;<a HREF=\"http:\/\/stackoverflow.com\/questions\/921180\/c-round-up\/926806#926806\">First, write your spec<\/a>.&#8221;\nUntil you know what you want, you won&#8217;t know how to get it.\n<\/p>\n<p>\nFirst, you need to define what you mean by <i>a modal window<\/i>.\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2005\/02\/18\/376080.aspx\">\nThere are multiple competing definitions<\/a>.\n<\/p>\n<p>\nThe customer decided that the definition of <i>modal window<\/i>\nthey want is this one:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nA modal window is a child window that requires the user\nto interact with it before they can return to operating\nthe parent application,\nthus preventing any work on the application main window.\n<\/p><\/blockquote>\n<p>\nOne thing you notice in this definition is that it talks\nboth about <i>windows<\/i> and <i>applications<\/i>.\nYou have a child <i>window<\/i>, a parent <i>application<\/i>,\nand even an <i>application main window<\/i>.\nThis implies that a modal window must be in a different application\nfrom its parent.\n(If it were in the same application, then it vacuously does not\nprevent you from interacting with the parent application because\nit <i>is<\/i> the parent application.)\nBut modality is a user interface concept, not a process management\nconcept, so it&#8217;s unclear why process considerations appear in the definition.\nEnd-users sitting in front of a user interface see windows,\nnot processes.\nI&#8217;m going to assume that the use of the term <i>application<\/i> here\nis a mistake, and that all we&#8217;re talking about is <i>windows<\/i>.\n<\/p>\n<p>\nThe second thing you realize from this definition is that it\nis describing something impossible.\nIn Windows, child windows cannot be interacted with when their\nparent window is disabled.\nThis definition appears to be using a common abuse of terminology,\nusing the words <i>child<\/i> and <i>parent<\/i>\ninstead of the more accurate but clumsier\n<i>owned<\/i> and <i>owner<\/i>.\nThis common abuse of terminology rarely causes trouble among\npeople with experience programming the Windows user interface,\nbut it is often a source of confusion for beginners,\nwhich is why I try to use the precise terminology\nrather than the casual terminology.\nAnd this question was clearly asked by a beginner.\n<\/p>\n<p>\nAnother thing you notice about this definition is that it\ninvolves not two but <i>three<\/i> windows:\nThe child window, the parent window, and the application main window.\nConsider the situation where you have an application main window\n(which is interactive), a secondary window (which is not interactive),\nand a tertiary window which is a child of by the secondary window\nwith which the user must interact in order to return to operating\nthe secondary window.\n<\/p>\n<table BORDER=\"0\" CELLSPACING=\"0\" STYLE=\"border-collapse: collapse\">\n<tr>\n<td ALIGN=\"center\" STYLE=\"border: solid .75pt black;padding: 1em\">Application<br \/>main window<\/td>\n<td STYLE=\"width: 1em\"><\/td>\n<td ALIGN=\"center\" STYLE=\"border: dotted .75pt black;padding: 1em\">Secondary<\/td>\n<td STYLE=\"width: 1em\"><\/td>\n<td ROWSPAN=\"3\">Solid borders represent interactive windows;<br \/>\n                  dotted borders represent non-interactive windows.<br \/>\n                  Lines connect children (below) to parents (above).\n    <\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<td ALIGN=\"center\">\n    <span STYLE=\"border-right: solid .75pt black\">&nbsp;<\/span><\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<td ALIGN=\"center\" STYLE=\"border: solid .75pt black;padding: 1em\">Tertiary<\/td>\n<\/tr>\n<\/table>\n<p>\nIs the tertiary window modal, according to this definition?\nI&#8217;m not sure.\nIt is not clear to me whether the clause\n&#8220;thus preventing any work on the application main window&#8221;\nis an additional constraint or is merely elaborative.\nIf the clause is an additional contraint, then the situation\nis not modal, because the application main window is still interactive.\nOn the other hand, if the clause is merely elaborative,\nthen the situation <i>is<\/i> modal, because the tertiary window\nprevents the user from interacting with the secondary window.\n<\/p>\n<p>\nThe fourth thing you realize from this definition is that it\nrequires predicting the future.\nHow do you know that the owner window will be available for\nuse once you dismiss the owned window?\nMabe the application does &#8220;<code>if (time(NULL) % 2)\nmake_parent_available();<\/code>&#8220;.\n(Perhaps we can call upon the\n<a HREF=\"http:\/\/www.cio.com\/article\/596981\/Chicago_School_to_Offer_Degree_in_Predicting_the_Future\">\ngraduates of the DePaul University with a degree in predicting the future<\/a>\nto help us here.)<\/p>\n<p>Even if the result doesn&#8217;t depend on predicting the future,\ndetermining whether the window will re-enable its parent\nrequires a level of code understanding beyond what can easily\nbe achieved programmatically.\n(You would have to find the code in the other program\nand study it to determine whether it re-enables the parent window\nas part of its interaction. This can be hard to do by a human being\nwith source code,\nmuch less by a computer program with only object code, especially\nif the object code is in an interpreted language, since you now have\nto reverse-engineer the interpreter too!)\n<\/p>\n<p>\nNo wonder the problem is so difficult:\nThe spec uses imprecise terminology, is unclear on its criteria,\nand requires\nmetaphysical\ncertitude beyond the current level of scientific understanding.\n<\/p>\n<p>\nLet&#8217;s see what we can salvage from this definition.\nFirst, let&#8217;s make the terminology more precise:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nA modal window is an owned window that requires the user\nto interact with it before they can return to operating\nthe owner window,\nthus preventing any work on the application main window.\n<\/p><\/blockquote>\n<p>\nNext, let&#8217;s delete the clause whose meaning is unclear.\n<\/p>\n<blockquote CLASS=\"q\"><p>\nA modal window is an owned window that requires the user\nto interact with it before they can return to operating\nthe owner window.\n<\/p><\/blockquote>\n<p>\nFinally, let&#8217;s remove the part that requires predicting\nthe future.\nInstead of describing future behavior (which is hard to predict),\nwe&#8217;ll make our\nrequirements based on <i>present<\/i> behavior\n(which can be observed without the aid of a time machine).\n<\/p>\n<blockquote CLASS=\"q\"><p>\nA modal window is an owned window\nwhose owner window cannot be interacted with.\n<\/p><\/blockquote>\n<p>\nThe revised spec says that a modal window is an owned window\nwhose owner is disabled.\nBingo, there&#8217;s your algorithm for detecting whether a window is modal.\nOnce you have a good spec, the code pretty much writes itself:\n<\/p>\n<pre>\nBOOL IsModalWindowAccordingToThisParticularSpec(HWND hwnd)\n{\n \/\/ child windows cannot have owners\n if (GetWindowStyle(hwnd) &amp; WS_CHILD) return FALSE;\n HWND hwndOwner = <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/12\/07\/10244820.aspx\">GetWindow(hwnd, GW_OWNER)<\/a>;\n if (hwndOwner == NULL) return FALSE; \/\/ not an owned window\n if (IsWindowEnabled(hwndOwner)) return FALSE; \/\/ owner is enabled\n return TRUE; \/\/ an owned window whose owner is disabled\n}\n<\/pre>\n<p>\nMind you, this spec may still not be what you actually want.\nConsider the Notepad program.\nType Ctrl+F to call up the Find dialog.\nThis is a modeless dialog:\nThe main window is still interactive.\nWhile the Find dialog is up,\ncall up the About dialog from the Help menu.\nYou now have the main Notepad window with two owned windows,\nan About dialog that will re-enable the main Notepad window\nwhen it is dismissed,\nand a Find dialog that will not.\n<\/p>\n<table BORDER=\"0\" CELLSPACING=\"0\" STYLE=\"border-collapse: collapse\">\n<tr>\n<td COLSPAN=\"3\" ALIGN=\"center\" STYLE=\"border: dotted .75pt black;padding: 1em\">Notepad main window<\/td>\n<td STYLE=\"width: 1em\"><\/td>\n<td ROWSPAN=\"3\">A connector is solid if the owned window re-enables\n                  the owner, dotted if it does not.\n                  (Remember, whether the line is dotted or not cannot\n                  be determined algorithmically.)\n                  <\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\"><span STYLE=\"border-right: solid .75pt black\">&nbsp;<\/span><\/td>\n<td STYLE=\"width: 1em\"><\/td>\n<td ALIGN=\"center\"><span STYLE=\"border-right: dotted .75pt black\">&nbsp;<\/span><\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\" STYLE=\"border: solid .75pt black;padding: 1em\">About<\/td>\n<td STYLE=\"width: 1em\"><\/td>\n<td ALIGN=\"center\" STYLE=\"border: solid .75pt black;padding: 1em\">Find<\/td>\n<\/tr>\n<\/table>\n<p>\nAccording to our spec, which of these windows is modal?\nDoes that match your intuitive sense?\n<\/p>\n<p>\nHere&#8217;s another case:\nFrom Notepad&#8217;s Open dialog, type the name of a file that does not\nexist.\n<\/p>\n<table BORDER=\"0\" CELLSPACING=\"0\" STYLE=\"border-collapse: collapse\">\n<tr>\n<td COLSPAN=\"3\" ALIGN=\"center\" STYLE=\"border: dotted .75pt black;padding: 1em\">Notepad main window<\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\"><span STYLE=\"border-right: solid .75pt black\">&nbsp;<\/span><\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\" STYLE=\"border: dotted .75pt black;padding: 1em\">Open<\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\"><span STYLE=\"border-right: solid .75pt black\">&nbsp;<\/span><\/td>\n<\/tr>\n<tr>\n<td ALIGN=\"center\" STYLE=\"border: solid .75pt black;padding: 1em\">File not found<\/td>\n<\/tr>\n<\/table>\n<p>\nWhich of these windows is a modal window?\n<\/p>\n<p>\nStill unresolved is whether\nthis is the right definition for the customer&#8217;s needs.\nThe customer never explained why they needed to identify\nmodal windows, and once we gave them the\n<code>Is&shy;Modal&shy;Window&shy;According&shy;To&shy;This&shy;Particular&shy;Spec<\/code>\nfunction, they never wrote back.\n<\/p>\n<p>\nIf they were trying to identify modal windows so they could try\nto close them, then in the <i>File not found<\/i> case above,\nthey may try to close the <i>Open<\/i> window, when the correct\nwindow to close first is the <i>File not found<\/i> window,\nbecause you need to\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2005\/02\/28\/381591.aspx\">\nrespect a window&#8217;s disabled state<\/a>.\n<\/p>\n<p>\nSince the customer never wrote back, we will never know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer wanted a way to determine whether a particular window is modal. They listed a few methods they had tried but found that it didn&#8217;t work and asked for assistance. As Eric Lippert is fond of saying, &#8220;First, write your spec.&#8221; Until you know what you want, you won&#8217;t know how to get it. [&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-8923","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer wanted a way to determine whether a particular window is modal. They listed a few methods they had tried but found that it didn&#8217;t work and asked for assistance. As Eric Lippert is fond of saying, &#8220;First, write your spec.&#8221; Until you know what you want, you won&#8217;t know how to get it. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8923","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=8923"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/8923\/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=8923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=8923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=8923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}