{"id":7133,"date":"2012-07-13T07:00:00","date_gmt":"2012-07-13T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/07\/13\/why-doesnt-realgetwindowclass-return-the-real-window-class-for-my-superclass\/"},"modified":"2012-07-13T07:00:00","modified_gmt":"2012-07-13T07:00:00","slug":"why-doesnt-realgetwindowclass-return-the-real-window-class-for-my-superclass","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120713-00\/?p=7133","title":{"rendered":"Why doesn&#039;t RealGetWindowClass return the real window class for my superclass?"},"content":{"rendered":"<p>\nA customer was reporting that the\n<code>Real&shy;Get&shy;Window&shy;Class<\/code> function\nwas not reporting the base window class of their superclass.\n(Error checking has been elided for expository purposes.)\n<\/p>\n<pre>\n\/\/ Get the static window class window procedure\nWNDCLASS wc;\nGetClassInfo(NULL, TEXT(\"static\"), &amp;wc);\nWNDPROC StaticWndProc = wc.lpfnWndProc;\n\/\/ Build our derived class\nwc.lpfnWndProc = AwesomeWndProc;\nwc.hInstance = g_hinst;\nwc.lpszClassName = TEXT(\"AwesomeWindow\");\nRegisterClass(&amp;wc);\nLRESULT CALLBACK AwesomeWndProc(HWND hwnd, UINT uMsg,\n                                WPARAM wParam, LPARAM lParam)\n{\n    TCHAR szClass[128];\n    RealGetWindowClass(hwnd, szClass, 128);\n    ASSERT(strcmp(szClass, TEXT(\"static\")) == 0);\n    switch (uMsg) { ... }\n    return CallWindowProc(StaticWndProc, hwnd, uMsg, wParam, lParam);\n}\n<\/pre>\n<p>\nThe customer found that the assertion fails,\nreturning a window class name of &#8220;AwesomeWindow&#8221;\ninstead of &#8220;static&#8221;.\n&#8220;I thought the point of RealGetWindowClass was to dig\nthrough the superclassing to find the base class.\nBut it&#8217;s not returning the base class.&#8221;\n<\/p>\n<p>\nThat&#8217;s right, because you haven&#8217;t told it what the base class is yet!\n<\/p>\n<p>\n&#8220;What do you mean I haven&#8217;t told it?\nIt&#8217;s right there at the end of my function:\n<code>CallWindowProc(StaticWndProc)<\/code>.&#8221;\n<\/p>\n<p>\nYeah, but that line of code hasn&#8217;t executed yet.\nThe external behavior of your program is like this:\n<\/p>\n<pre>\nWNDCLASS wc;\nwc.style = (something);\nwc.lpfnWndProc = AwesomeWndProc;\nwc.cbClsExtra = (something);\nwc.cbWndExtra = (something);\nwc.hInstance = g_hinst;\nwc.hIcon = (something);\nwc.hCursor = (something);\nwc.hbrBackground = (something);\nwc.lpszMenuName = (something);\nwc.lpszClassName = TEXT(\"AwesomeWindow\");\nRegisterClass(&amp;wc);\nLRESULT CALLBACK AwesomeWndProc(HWND hwnd, UINT uMsg,\n                                WPARAM wParam, LPARAM lParam)\n{\n    TCHAR szClass[128];\n    RealGetWindowClass(hwnd, szClass, 128);\n    ASSERT(strcmp(szClass, TEXT(\"static\")) == 0);\n    \/\/ ... it doesn't matter what goes here\n    \/\/ because it hasn't executed yet ...\n<\/pre>\n<p>\nThe window manager isn&#8217;t clairvoyant.\nIt doesn&#8217;t know that <code>AwesomeWndProc<\/code> is\ngoing to do a\n<code>CallWindowProc(StaticWndProc)<\/code>\nin the future.\nAll it knows is that somebody registered a class,\nand then in response to its very first message,\nthat class asked, &#8220;Hey, you&#8217;re so smart, tell me what my base class is.&#8221;\n<\/p>\n<p>\nThe window manager says, &#8220;Dude, you haven&#8217;t shown me any base class yet.\nSo I&#8217;m just going to say that you are your own base class.&#8221;\n<\/p>\n<p>\nSince anything can go into the &#8220;&#8230; it doesn&#8217;t matter what goes here &#8230;&#8221;,\nwe can demonstrate that the window manager cannot possibly know what\nyou&#8217;re going to pass to <code>CallWindowProc<\/code> by rewriting it\nlike this:<\/p>\n<pre>\n\/\/ Get the static window class window procedure\nWNDCLASS wc;\nGetClassInfo(NULL, TEXT(\"static\"), &amp;wc);\nWNDPROC StaticWndProc = wc.lpfnWndProc;\n\/\/ Build our class\nwc.lpfnWndProc = AwesomeWndProc;\nwc.hInstance = g_hinst;\nwc.lpszClassName = TEXT(\"AwesomeWindow\");\nRegisterClass(&amp;wc);\nLRESULT CALLBACK AwesomeWndProc(HWND hwnd, UINT uMsg,\n                                WPARAM wParam, LPARAM lParam)\n{\n    TCHAR szClass[128];\n    RealGetWindowClass(hwnd, szClass, 128);\n    ASSERT(strcmp(szClass, TEXT(\"static\")) == 0);\n    switch (uMsg) { ... }\n    <font COLOR=\"blue\">\/\/ Psych! You thought that when I asked for StaticWndProc\n    \/\/ I was going to be a superclass of \"static\", but in fact\n    \/\/ I'm just a regular boring window class.\n    return DefWindowProc(hwnd, uMsg, wParam, lParam);<\/font>\n}\n<\/pre>\n<p>\nIf you felt really crazy, you could do this:\n<\/p>\n<pre>\n\/\/ Get the button window class procedure\nWNDCLASS wcButton;\nGetClassInfo(NULL, TEXT(\"button\"), &amp;wcButton);\nWNDPROC ButtonWndProc = wcButton.lpfnWndProc;\n\/\/ Get the static window class window procedure\nWNDCLASS wc;\nGetClassInfo(NULL, TEXT(\"static\"), &amp;wc);\nWNDPROC StaticWndProc = wc.lpfnWndProc;\n\/\/ Build our class\nwc.lpfnWndProc = AwesomeWndProc;\nwc.hInstance = g_hinst;\nwc.lpszClassName = TEXT(\"AwesomeWindow\");\nwc.cbWndExtra = max(wc.cbWndExtra, wcButton.cbWndExtra);\nwc.cbClsExtra = max(wc.cbClsExtra, wcButton.cbClsExtra);\nRegisterClass(&amp;wc);\nLRESULT CALLBACK AwesomeWndProc(HWND hwnd, UINT uMsg,\n                                WPARAM wParam, LPARAM lParam)\n{\n    TCHAR szClass[128];\n    RealGetWindowClass(hwnd, szClass, 128);\n    ASSERT(strcmp(szClass, TEXT(\"static\")) == 0);\n    switch (uMsg) { ... }\n    <font COLOR=\"blue\">\/\/ Decide at the last moment what we are.\n    static WNDPROC BaseClass = nullptr;\n    if (BaseClass == nullptr)\n    {\n        BaseClass = rand() % 2 ? StaticWndProc : ButtonWndProc;\n        \/\/ Or if you are particularly perverse,\n        \/\/ BaseClass = <a HREF=\"http:\/\/en.wikipedia.org\/wiki\/Schr%C3%B6dinger's_cat\">radioactive_decay_has_occurred<\/a>() ?\n        \/\/                StaticWndProc : ButtonWndProc;\n    }\n    return CallWindowProc(BaseClass, hwnd, uMsg, wParam, lParam);<\/font>\n}\n<\/pre>\n<p>\nSince the code to decide the base class hasn&#8217;t run yet,\nthe window manager will have to use\n<a HREF=\"https:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/01\/31\/10122197.aspx\">\nthat time machine that the research division has been working on<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer was reporting that the Real&shy;Get&shy;Window&shy;Class function was not reporting the base window class of their superclass. (Error checking has been elided for expository purposes.) \/\/ Get the static window class window procedure WNDCLASS wc; GetClassInfo(NULL, TEXT(&#8220;static&#8221;), &amp;wc); WNDPROC StaticWndProc = wc.lpfnWndProc; \/\/ Build our derived class wc.lpfnWndProc = AwesomeWndProc; wc.hInstance = g_hinst; wc.lpszClassName [&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-7133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer was reporting that the Real&shy;Get&shy;Window&shy;Class function was not reporting the base window class of their superclass. (Error checking has been elided for expository purposes.) \/\/ Get the static window class window procedure WNDCLASS wc; GetClassInfo(NULL, TEXT(&#8220;static&#8221;), &amp;wc); WNDPROC StaticWndProc = wc.lpfnWndProc; \/\/ Build our derived class wc.lpfnWndProc = AwesomeWndProc; wc.hInstance = g_hinst; wc.lpszClassName [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7133","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=7133"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/7133\/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=7133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=7133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=7133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}