{"id":36413,"date":"2005-02-18T07:01:00","date_gmt":"2005-02-18T07:01:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/02\/18\/modality-part-1-ui-modality-vs-code-modality\/"},"modified":"2005-02-18T07:01:00","modified_gmt":"2005-02-18T07:01:00","slug":"modality-part-1-ui-modality-vs-code-modality","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050218-00\/?p=36413","title":{"rendered":"Modality, part 1: UI-modality vs code-modality"},"content":{"rendered":"<p>\nFrom the end-users&#8217; point of view, modality occurs when the\nusers are locked into completing a task once it is begun,\nwith the only escape being to cancel the entire operation.\nOpening a file is an example of a modal operation:\nOnce the &#8220;Open&#8221; command has been selected, users have\nno choice but to select a file for opening (or to cancel\nthe operation).  While attempting to open a document,\nthe users cannot interact with the existing\ndocument (for example, scroll it around to look for some\ntext that would give a clue as to what file to open next).\n<\/p>\n<p>\nFrom a programmer&#8217;s point of view, modality can be\nviewed as a function that performs some UI and doesn&#8217;t\nreturn until that UI is complete.\nIn other words, modality is\na nested message loop that continues processing\nmessages until some exit condition is reached.\nIn our example above, the modality is inherent in\nthe <code>GetOpenFileName<\/code> function, which does not return\nuntil the user selects a filename or cancels the dialog box.\n<\/p>\n<p>\nNote that these concepts do not necessarily agree.\nYou can create something that is UI-modal&mdash;that is,\ndoes not let the user interact with the main window\nuntil some other action is complete&mdash;while internally\ncoding it as a non-modal function.\n<\/p>\n<p>\nLet&#8217;s code up an example of this behavior,\nto drive the point home.\n<\/p>\n<p>\nAs always,\n<a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/07\/23\/54576.aspx\">\nstart with our scratch program<\/a>.\n<\/p>\n<pre>\n#include &lt;commdlg.h&gt;\nHWND g_hwndFR;\nTCHAR g_szFind[80];\nFINDREPLACE g_fr = { sizeof(g_fr) };\nUINT g_uMsgFindMsgString;\nvoid CreateFindDialogUIModally(HWND hwnd)\n{\n  if (!g_hwndFR) {\n    g_uMsgFindMsgString = RegisterWindowMessage(FINDMSGSTRING);\n    if (g_uMsgFindMsgString) {\n      g_fr.hwndOwner = hwnd;\n      g_fr.hInstance = g_hinst;\n      g_fr.lpstrFindWhat = g_szFind;\n      g_fr.wFindWhatLen = 80;\n      g_hwndFR = FindText(&amp;g_fr);\n    }\n  }\n}\nvoid OnChar(HWND hwnd, TCHAR ch, int cRepeat)\n{\n  switch (ch) {\n  case ' ': CreateFindDialogUIModally(hwnd); break;\n  }\n}\nvoid OnFindReplace(HWND hwnd, FINDREPLACE *pfr)\n{\n  if (pfr-&gt;Flags &amp; FR_DIALOGTERM) {\n      DestroyWindow(g_hwndFR);\n      g_hwndFR = NULL;\n  }\n}\n\/\/ Add to WndProc\n    HANDLE_MSG(hwnd, WM_CHAR, OnChar);\n    default:\n      if (uiMsg == g_uMsgFindMsgString &amp;&amp; g_uMsgFindMsgString) {\n        OnFindReplace(hwnd, (FINDREPLACE*)lParam);\n      }\n      break;\n\/\/ Edit WinMain\n    while (GetMessage(&amp;msg, NULL, 0, 0)) {\n        <font COLOR=\"blue\">if (g_hwndFR &amp;&amp; IsDialogMessage(g_hwndFR, &amp;msg)) {\n        } else {<\/font>\n          TranslateMessage(&amp;msg);\n          DispatchMessage(&amp;msg);\n        <font COLOR=\"blue\">}<\/font>\n    }\n<\/pre>\n<p>\nThis is an unexciting example of a modeless dialog;\nin our case, the Find dialog is displayed\nwhen you hit the space bar.  Observe that you can click\nback to the main window while the Find dialog is up;\nthat&#8217;s because the Find dialog is modeless.\nAs is typical for modeless dialogs, dispatching its\nmessages is handled in the main message loop with\na call to\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/winui\/WinUI\/WindowsUserInterface\/Windowing\/DialogBoxes\/DialogBoxReference\/DialogBoxFunctions\/IsDialogMessage.asp\">\nthe <code>IsDialogMessage<\/code> function<\/a>.\n<\/p>\n<p>\nWe can turn this into a UI-modal dialog very simply:\n<\/p>\n<pre>\nvoid CreateFindDialogUIModally(HWND hwnd)\n{\n  if (!g_hwndFR) {\n    g_uMsgFindMsgString = RegisterWindowMessage(FINDMSGSTRING);\n    if (g_uMsgFindMsgString) {\n      g_fr.hwndOwner = hwnd;\n      g_fr.hInstance = g_hinst;\n      g_fr.lpstrFindWhat = g_szFind;\n      g_fr.wFindWhatLen = 80;\n      g_hwndFR = FindText(&amp;g_fr);\n      <font COLOR=\"blue\">if (g_hwndFR) {\n        EnableWindow(hwnd, FALSE);\n      }<\/font>\n    }\n  }\n}\nvoid OnFindReplace(HWND hwnd, FINDREPLACE *pfr)\n{\n  if (pfr-&gt;Flags &amp; FR_DIALOGTERM) {\n      <font COLOR=\"blue\">EnableWindow(hwnd, TRUE);<\/font>\n      DestroyWindow(g_hwndFR);\n      g_hwndFR = NULL;\n  }\n}\n<\/pre>\n<p>\nNotice that we carefully observed\n<a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/02\/27\/81155.aspx\">\nthe rules for enabling and disabling windows<\/a>.\n<\/p>\n<p>\nWhen you run this modified program, everything seems the\nsame except that the Find dialog is now modal.  You can&#8217;t\ninteract with the main window until you close the Find\ndialog.  The Find dialog is modal in the UI sense.\nHowever, the code is structured in the non-modal manner.\nThere is no dialog loop; the main window\nloop dispatches dialog messages as necessary.\n<\/p>\n<p>\nOne typically does not design one&#8217;s modal UI in this manner\nbecause it makes the code harder to structure.\nObserve, for example, that the code to manage the dialog box\nis scattered about and the management of the dialog needs to\nbe handled as a state machine since each phase returns back\nto the main message loop.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>From the end-users&#8217; point of view, modality occurs when the users are locked into completing a task once it is begun, with the only escape being to cancel the entire operation. Opening a file is an example of a modal operation: Once the &#8220;Open&#8221; command has been selected, users have no choice but to select [&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,143],"class_list":["post-36413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code","tag-modality"],"acf":[],"blog_post_summary":"<p>From the end-users&#8217; point of view, modality occurs when the users are locked into completing a task once it is begun, with the only escape being to cancel the entire operation. Opening a file is an example of a modal operation: Once the &#8220;Open&#8221; command has been selected, users have no choice but to select [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36413","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=36413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36413\/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=36413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}