{"id":24583,"date":"2007-11-05T10:00:00","date_gmt":"2007-11-05T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/11\/05\/why-do-we-even-have-the-defwindowproc-function\/"},"modified":"2007-11-05T10:00:00","modified_gmt":"2007-11-05T10:00:00","slug":"why-do-we-even-have-the-defwindowproc-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20071105-00\/?p=24583","title":{"rendered":"Why do we even have the DefWindowProc function?"},"content":{"rendered":"<p>\nSome time ago, I looked at two ways of reimplementing\nthe dialog procedure\n(<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/11\/12\/55659.aspx\">method&nbsp;1<\/a>,\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/11\/13\/55662.aspx\">\nmethod&nbsp;2<\/a>).\nCommenter &#8220;8&#8221; wondered\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/04\/25\/583093.aspx#584521\">\nwhy we have a <code>DefWindowProc<\/code> function at all<\/a>.\nCouldn&#8217;t window procedures have followed the dialog box model,\nwhere they simply return <code>FALSE<\/code> to indicate that\nthey want default processing to occur?\nThen there would be no need to export the <code>DefWindowProc<\/code>\nfunction.\n<\/p>\n<p>\nThis overlooks one key pattern for derived classes:\nUsing the base class as a subroutine.\nThat pattern is what prompted people to ask for\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/11\/12\/55659.aspx\">\ndialog procedures that acted like window procedures<\/a>.\nIf you use the &#8220;Return <code>FALSE<\/code> to get default behavior&#8221;\npattern,\nwindow procedures would go something like this:\n<\/p>\n<pre>\nBOOL DialogLikeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n ... handle messages and return TRUE ...\n }\n \/\/ We didn't have any special processing; do the default thing\n return FALSE;\n}\n<\/pre>\n<p>\nSimilarly, subclassing in this hypothetical world would go like this:\n<\/p>\n<pre>\nBOOL DialogLikeSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n switch (uMsg) {\n ... handle messages and return TRUE ...\n }\n \/\/ We didn't have any special processing; let the base class try\n CallDialogLikeWindowProc(PrevDialogLikeWndProc, hwnd, uMsg, wParam, lParam);\n}\n<\/pre>\n<p>\nThis works as long as what you want to do is override the base class\nbehavior entirely.\nBut what if you just want to augment it?\nCalling the previous window procedure is analogous to calling the\nbase class implementation from a derived class,\nand doing so is quite common in object-oriented programming,\nwhere you want the derived class to behave &#8220;mostly&#8221; like the\nbase class.\nConsider, for example, the case where we want to allow the user\nto drag a window by grabbing anywhere in the client area:\n<\/p>\n<pre>\nLRESULT CALLBACK CaptionDragWndProc(\n    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\n{\n LRESULT lres;\n switch (uMsg) {\n case WM_NCHITTEST:\n  lres = DefWindowProc(hwnd, uMsg, wParam, lParam);\n  if (lres == HTCLIENT) lres = HTCAPTION;\n  return lres;\n ...\n }\n return DefWindowProc(hwnd, uMsg, wParam, lParam);\n}\n<\/pre>\n<p>\nWe want our hit-testing to behave just like normal,\nwith the only exception that clicks in the client area\nshould be treated as clicks on the caption.\nWith the <code>DefWindowProc<\/code> model,\nwe can do this by calling <code>DefWindowProc<\/code> to\ndo the default processing, and then modifying\nthe result on the back end.\nIf we had use the dialog-box-like model,\nthere would have been no way to call the &#8220;default handler&#8221;\nas a subroutine in order to make it to the heavy lifting.\nWe would be forced to do all the work or none of it.\n<\/p>\n<p>\nAnother avenue that an explicit <code>DefWindowProc<\/code>\nfunction opens up is <strong>modifying<\/strong> messages\nbefore they reach the default handler.\nFor example, suppose you have a read-only edit control,\nbut you want it to look like a normal edit control instead\nof getting the static look.\nYou can do this by modifying the message that you pass\nto <code>DefWindowProc<\/code>:\n<\/p>\n<pre>\n...\n case WM_CTLCOLORSTATIC:\n  if (GET_WM_CTLCOLOR_HWND(wParam, lParam) == m_hwndEdit)\n  {\n   \/\/ give it the \"edit\" look\n   return DefWindowProc(hwnd, WM_CTLCOLOREDIT, wParam, lParam);\n  }\n  ...\n<\/pre>\n<p>\nAnother common operation is changing one color attribute of an\nedit control while leaving the others intact.\nFor this, you can use <code>DefWindowProc<\/code> as a subroutine\nand then tweak the one attribute you want to customize.\n<\/p>\n<pre>\n case WM_CTLCOLORSTATIC:\n  if (GET_WM_CTLCOLOR_HWND(wParam, lParam) == m_hwndDanger)\n  {\n   \/\/ Start with the default color attributes\n   LRESULT lres = DefWindowProc(hwnd, uMsg, wParam, lParam);\n   \/\/ Change text color to red; leave everything else the same\n   SetTextColor(GET_WM_CTLCOLOR_HDC(wParam, lParam), RGB(255,0,0));\n   return lres;\n  }\n  ...\n<\/pre>\n<p>\nGetting these types of operations to work with the dialog box\nmodel would be a significantly trickier undertaking.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some time ago, I looked at two ways of reimplementing the dialog procedure (method&nbsp;1, method&nbsp;2). Commenter &#8220;8&#8221; wondered why we have a DefWindowProc function at all. Couldn&#8217;t window procedures have followed the dialog box model, where they simply return FALSE to indicate that they want default processing to occur? Then there would be no need [&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-24583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Some time ago, I looked at two ways of reimplementing the dialog procedure (method&nbsp;1, method&nbsp;2). Commenter &#8220;8&#8221; wondered why we have a DefWindowProc function at all. Couldn&#8217;t window procedures have followed the dialog box model, where they simply return FALSE to indicate that they want default processing to occur? Then there would be no need [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24583","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=24583"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/24583\/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=24583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=24583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=24583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}