{"id":327,"date":"2008-09-21T15:46:14","date_gmt":"2008-09-21T13:46:14","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=327"},"modified":"2008-09-18T19:47:10","modified_gmt":"2008-09-18T17:47:10","slug":"die-return-taste-in-dialogen-eine-unendliche-geschichte","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/09\/21\/die-return-taste-in-dialogen-eine-unendliche-geschichte\/","title":{"rendered":"Die Return-Taste in Dialogen, eine unendliche Geschichte"},"content":{"rendered":"<p>Wer sich in Windows-Programmierer-Foren tummelt, dem wird die folgende Frage mindestens einmal in der Woche \u00fcber den Weg laufen:<\/p>\n<blockquote><p>Ich m\u00f6chte in einem Dialog die Eingabetaste abfangen, so dass sich der Dialog nicht schlie\u00dft.<br \/>\nWie geht das?<\/p><\/blockquote>\n<p>Vom Sinn und Unsinn dieses Wunsches wollen wir mal hier nicht reden. Also schauen wir mal auf dieses Problem etwas genauer.<\/p>\n<p>Die L\u00f6sung <em>WM_COMMAND <\/em>mit <em>IDOK <\/em>abfangen, lasse ich nicht gelten , denn evtl. hat der Dialog ja einen OK Button. (In der MFC k\u00e4me das mit dem \u00dcberschreiben von <em>CDialog::OnOK <\/em>gleich)<\/p>\n<p>Die Standardantwort von <em>MFC <\/em>Entwicklern lautet immer:<\/p>\n<blockquote><p>\u00dcberschreibe <em>PreTranslateMessage <\/em>und fange <em>WM_KEYDOWN <\/em>mit <em>VK_RETURN <\/em>dort ab und behandle die Nachricht dort.<\/p><\/blockquote>\n<p>OK. Aber was macht ein Win32-API Entwickler. Der hat keinen Einfluss auf die Message-Loop. Muss der nun zu der Hook-Kanone greifen?<\/p>\n<p>Wo liegt eigentlich das Problem?<br \/>\nDie Funktion, die <em>VK_RETURN <\/em>in ein <em>WM_COMMAND <\/em>mit <em>IDOK <\/em>umwandelt ist die API Funktion <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms645498(VS.85).aspx\">IsDialogMessage<\/a>. Diese Funktion wird in der Messageloop von modalen Dialogen verwendet. In der <em>MFC<\/em> direkt in <em>CDialog::PreTranslateMessage <\/em>und in Win32 Dialogen wird sie in der Messageloop die <em><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms645452(VS.85).aspx\">DialogBox <\/a><\/em>ausf\u00fchrt.<\/p>\n<p>Diese Funktion geht aber mit solchen Tastatureingaben nicht einfach wahllos um. Sie macht das sehr intelligent. Das sieht man schon daran, dass man in einer aufgeklappten ComboBox die Eingabetaste dr\u00fccken kann und es schlie\u00dft die ComboBox und nicht der Dialog.<br \/>\nEbenfalls kennt man den Effekt, dass ein mehrzeiliges Eingabefeld (Edit Control) sehr wohl die Eingabetaste als Zeilenschaltung nutzen kann und auch hier schlie\u00dft der Dialog nicht.<br \/>\nKennt also <em>IsDialogMessage <\/em>seine Pappenheimer von Controls?<\/p>\n<p>Woher wei\u00df <em>IsDialogMessage <\/em>also wann <em>VK_RETURN <\/em>mal so und mal so behandelt werden muss?<br \/>\nDie Antwort ist einfach: <em>IsDialogMessage <\/em>fragt seine Controls ab was sie gerne h\u00e4tten!<br \/>\nUnd das wird erreicht mit einer einfachen Windows-Nachricht, die in diesem Zusammenhang fast nie genannt wird: <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms645425(VS.85).aspx\">WM_GETDLGCODE<\/a>.<\/p>\n<p>Bevor <em>IsDialogMessage <\/em>eine Tastatureingabe selbst behandelt, fragt die Funktion das Zielfenster mit <em>WM_GETDLGCODE <\/em>ab, ob das Fenster evtl. selbst Verwendung f\u00fcr diese Tastatureingabe hat.<br \/>\n<em>WM_GETDLGCODE <\/em>kann hier sehr flexibel reagieren, denn in wParam erh\u00e4lt die Nachricht den virtuellen Tastencode und das Control wei\u00df nun sehr genau um was es hier geht.<\/p>\n<p>Kann man also in jedem Control (das nat\u00fcrlich den Fokus hat) die Eingabetaste selbst behandeln?<br \/>\nAntwort: Ja!<\/p>\n<p>Das Control muss nur einfach <em>WM_GETDLGCODE <\/em>behandeln f\u00fcr die Taste <em>VK_RETURN<\/em>. In diesem Fall gibt es <em>DLGC_WANTMESSAGE <\/em>zur\u00fcck (ist \u00fcbrigends identisch zu <em>DLGC_WANTALLKEYS<\/em>). <em>IsDIalogMessage <\/em>wird in diesem Fall die Eingabetaste an das Control weitergeben und nicht selbst behandeln. So macht es \u00fcbrigens auch eine ComboBox die aufgeklappt ist wenn die Eingabetaste gedr\u00fcckt wird.<\/p>\n<p>Ich habe einfach mal hier eine Win32 L\u00f6sung aufgebaut. Es wird einfach das entsprechende Control mit einer eigenen WndProc gesubclassed und das sieht etwa so aus:<\/p>\n<pre lang=\"cpp\">LRESULT CALLBACK SpecialWndProc(HWND hWnd,\r\n                        UINT message, WPARAM wParam, LPARAM lParam)\r\n{\r\n    switch (message)\r\n    {\r\n    case WM_GETDLGCODE:\r\n        if (wParam==VK_RETURN)\r\n            return DLGC_WANTMESSAGE;\r\n        break;\r\n    case WM_KEYDOWN:\r\n        if (wParam==VK_RETURN)\r\n        {\r\n            MessageBox(hWnd,_T(\"VK_RETURN received!\"),NULL,MB_OK);\r\n            return 0;\r\n        }\r\n        break;\r\n    }\r\n    WNDPROC pWndProc = reinterpret_cast(GetWindowLongPtr(hWnd,GWL_USERDATA));\r\n    return CallWindowProc(pWndProc,hWnd,message,wParam,lParam);\r\n}\r\n\r\n...\r\n\/\/ Subclass the control\r\nHWND hWndEdit = GetDlgItem(hDlg,IDC_EDIT1);\r\nLONG_PTR pOldWndProc = SetWindowLongPtr(hWndEdit,GWL_WNDPROC,\r\n                        reinterpret_cast(SpecialWndProc));\r\nSetWindowLongPtr(hWndEdit,GWL_USERDATA,pOldWndProc);<\/pre>\n<p>Effekt: Jedes Control, dass man mit dieser <em>WndProc <\/em>subclassed wird die Messagebox anzeigen und der Dialog wird nicht geschlossen! Subclassed man also alle Controls eines Dialoges, die den Fokus bekommen k\u00f6nnen, dann kann man sofort ohne Hook, auch die Eingabetaste selbst behandeln.<br \/>\nSinnvollerweise sendet man bei Erhalt von <em>VK_RETURN dann <\/em>einfach eine entsprechende Nachricht an das Parent, dass die gew\u00fcnschte Aktion dann ausf\u00fchrt, sofern nicht das Control selbst die Eingabetaste direkt behandelt.<\/p>\n<p>Man kommt also auch in reinen Win32 API Programmen ganz ohne Hooks aus, um <em>VK_RETURN <\/em>in Dialogen so zu behandeln wie man es selbst gerne m\u00f6chte!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wer sich in Windows-Programmierer-Foren tummelt, dem wird die folgende Frage mindestens einmal in der Woche \u00fcber den Weg laufen: Ich m\u00f6chte in einem Dialog die Eingabetaste abfangen, so dass sich der Dialog nicht schlie\u00dft. Wie geht das? Vom Sinn und Unsinn dieses Wunsches wollen wir mal hier nicht reden. Also schauen wir mal auf dieses &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/09\/21\/die-return-taste-in-dialogen-eine-unendliche-geschichte\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eDie Return-Taste in Dialogen, eine unendliche Geschichte\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25,30,4,3,2],"tags":[370,352,61],"class_list":["post-327","post","type-post","status-publish","format-standard","hentry","category-atl","category-c","category-mfc","category-programmieren","category-windows-api","tag-c","tag-mfc","tag-winapi"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/327","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=327"}],"version-history":[{"count":1,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/327\/revisions"}],"predecessor-version":[{"id":328,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/327\/revisions\/328"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=327"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=327"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=327"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}