{"id":18333,"date":"2009-05-07T10:00:00","date_gmt":"2009-05-07T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/05\/07\/when-you-subclass-a-window-its-the-original-window-procedure-of-the-window-you-subclass-you-have-to-call-when-you-want-to-call-the-original-window-procedure\/"},"modified":"2009-05-07T10:00:00","modified_gmt":"2009-05-07T10:00:00","slug":"when-you-subclass-a-window-its-the-original-window-procedure-of-the-window-you-subclass-you-have-to-call-when-you-want-to-call-the-original-window-procedure","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090507-00\/?p=18333","title":{"rendered":"When you subclass a window, it&#8217;s the original window procedure of the window you subclass you have to call when you want to call the original window procedure"},"content":{"rendered":"<p><P>\nWhen you subclass a window, you set the window procedure\nto a function of your choosing, and you remember the original\nwindow procedure so you can pass it to the <CODE>CallWindowProc<\/CODE>\nfunction when your subclass function wants to pass the message to the\noriginal window procedure.\nFor example, if you subclass a window like this:\n<\/P>\n<PRE>\nSubclassWidgetDialog(HWND hdlgWidget)\n{\n  HWND hwndButton = GetDlgItem(hdlgWidget, &#8230;);\n  wndProcOrig = (WNDPROC)\n     SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)SubclassWndProc);\n  \/\/ -or-\n  \/\/ wndprocOrig = SubclassWindow(hwndButton, SubclassWndProc);\n  &#8230;\n}\n<\/PRE>\n<P>\nthen your subclass function should go something like this:\n<\/P>\n<PRE>\nLRESULT CALLBACK SubclassWndProc(\n    HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)\n{\n  switch (wm) {\n  &#8230;\n  default:\n    return CallWindowProc(<FONT COLOR=\"blue\">wndprocOrig<\/FONT>, hwnd, wm, wParam, lParam);\n  }\n}\n<\/PRE>\n<P>\nThe window procedure you pass to <CODE>CallWindowProc<\/CODE>\nis the one which was the window procedure of that window\nbefore you subclassed it,\nnot the window procedure from some other window.\nIn the same way that when you create a derived C++ class,\nyou pass method calls along to your base class,\nnot to somebody else&#8217;s base class:\n<\/P>\n<PRE>\nclass DerivedClass : public BaseClass {\n &#8230;\n \/\/ override base class: do some extra stuff\n int Method(int param)\n {\n  ExtraDerivedStuff();\n  return <FONT COLOR=\"blue\">BaseClass::Method(param)<\/FONT>;\n }\n};\n<\/PRE>\n<P>\nWhen you are finished with your customization in\n<CODE>DerivedClass::Method<\/CODE>, you let the base class\ndo what normally would have happened if you hadn&#8217;t overridden\nthe method in the first place by calling\n<CODE>BaseClass::Method<\/CODE> and not by calling\n<CODE>SomeOtherClass:Method<\/CODE>.\n<\/P>\n<P>\nThis sounds blatantly obvious, but you&#8217;d be surprised how often\npeople mess this up.\nFor example,\nif you subclass multiple widget dialogs,\nyou have to save the old window procedure in a different place\nfor each one,\nbecause each button may have had a different window procedure\nby the time you got around to subclassing it.\nFor example, one of them might be a plain button, whereas another\nof them was subclassed in order to provide a tooltip.\nIf you make <CODE>wndprocOrig<\/CODE> a global or static variable,\nthen you&#8217;re assuming that every widget button has the same\nwindow procedure.\nYou are subclassing a window and forgetting to handle the case\nwhere the window is already subclassed!\nYou forgot that somebody else could have done exactly what you&#8217;re doing.\n<\/P>\n<P>\nThere is a popular commercial program that comes preinstalled\non many computers which creates a\ncommon file open dialog box and subclasses both the file name combo box\nand the file type combo box,\nand figures that, well, since they&#8217;re both combo boxes,\nthey must have the same window procedure, right?\nUnfortunately, there&#8217;s no guarantee that they do,\nbecause the common file dialog is free to subclass them in order to\nprovide custom behavior like autocomplete.\nIt so happens that the program grabs the window procedure from\nthe subclassed combo box window and uses it for all combo boxes.\n(These are probably the same folks who would have called the\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/10\/15\/55296.aspx\">\n<CODE>BOZOSLIVEHERE<\/CODE> function<\/A>\nif given the chance.)\n<\/P>\n<P>\nThis makes for very exciting crashes when they take the original\nwindow procedure from the subclassed combo box\nand use it for the other, unsubclassed, combo box.\nThe subclass window procedure\nfinds itself handed a window <I>that it never subclassed<\/I>.\nAs a result, it not only can&#8217;t perform its own subclass behavior,\nbut can&#8217;t even just fall back and say &#8220;Well, I can&#8217;t do my custom stuff,\nso I&#8217;ll just forward to the original window procedure&#8221;\nsince it can&#8217;t figure out what the original window procedure was either.\nIt&#8217;s the window manager version of writing this strange C++ code:\n<\/P>\n<PRE>\nclass SiblingClass : public BaseClass { &#8230; };\nclass DerivedClass : public BaseClass {\n &#8230;\n \/\/ override base class: do some extra stuff\n \/\/ then pass method to the WRONG base class\n int Method(int param)\n {\n  ExtraDerivedStuff();\n  <I>return <FONT COLOR=\"blue\">((SiblingClass*)this)-&gt;Method(param)<\/FONT><\/I>;\n }\n};\n<\/PRE>\n<P>\nWhen you subclass a window, and you want to call the original window\nprocedure, make sure you call the correct original window procedure:\nThe one that was the window procedure of that window\nbefore you subclassed it.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you subclass a window, you set the window procedure to a function of your choosing, and you remember the original window procedure so you can pass it to the CallWindowProc function when your subclass function wants to pass the message to the original window procedure. For example, if you subclass a window like this: [&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-18333","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>When you subclass a window, you set the window procedure to a function of your choosing, and you remember the original window procedure so you can pass it to the CallWindowProc function when your subclass function wants to pass the message to the original window procedure. For example, if you subclass a window like this: [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/18333","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=18333"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/18333\/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=18333"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=18333"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=18333"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}