<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[WinAPI Wrapper: Messages]]></title><description><![CDATA[<p>Hallo!<br />
ich will gerade das WinAPI-Message-System etwas wrappen. Dabei muss man eine Funktion erstellen. Rückgabetyp ist void und Parameter ist (leider) ein HWND. Dann macht man noch eine Const int ID und übergibt die ID und die Funktionsadresse einer Bind-Funktion. Diese packt das einfach nur in eine std::map, key ist die ID, value der Funktionszeiger:</p>
<pre><code class="language-cpp">// Deklaration static std::map&lt;const int, void (*)(iZWindow)&gt; _evList; 
// static wegen der statischen WndProc

// Bekommt ID und Funktionsadresse und fügt ein
void iZWindow::BindAction(const int ID, void (*fptr)(iZWindow)) {
	iZWindow::_evList[ID] = fptr;
}
</code></pre>
<p>Soweit sogut. z.B. will man jetzt ein Menu erstellen. Das Menu hat eine eigene Klasse, aber am Ende, wenn man es in das Fenster ausgeben will muss man Fensterklasse.SetMenu(Menubarklasse); aufrufen:</p>
<pre><code class="language-cpp">iZMenubar menu;
iZPopup popup(100);
iZPopup popup2(200);
popup.AppendMenu(105, &quot;Drucken\tCTRL+P&quot;); // Popups mit Einträgen füllen
popup.AppendMenu(111, &quot;Beenden\tALT+F4&quot;);
popup2.AppendMenu(666, &quot;Ausschneiden&quot;);
menu.AppendMenubar(popup, &quot;Datei&quot;); // Popups in die Menubar
menu.AppendMenubar(popup2, &quot;Bearbeiten&quot;);
wnd.SetMenu(menu); // Menubar in das Fenster-Objekt wnd
</code></pre>
<p>Die Funktion zur Menuerstellung sollte also besser die Fensterklasse und nicht HWND als Parameter besitzten, ich rufe ja schließlich wnd.SetMenu(menu) auf.<br />
Zu dumm, dass ja dann am Ende WndProc die Aufgabe hat, die Funktion bei der übergebenen ID als Message aufzurufen und dabei ihr einen Parameter zu übergeben. WndProc bietet aber nur das HWND:</p>
<pre><code class="language-cpp">LRESULT CALLBACK iZWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	for(std::map&lt;const int, void (*)(iZWindow)&gt;::const_iterator iter = iZWindow::_evList.begin();
		iter != iZWindow::_evList.end(); iter++) {
		// event-map auslesen
			if((*iter).first == WM_CREATE) { // wenn key (=message) == WM_CREATE
				iter-&gt;second(hWnd); // value (=funktionszeiger) aufrufen und Parameter übergeben
			}
	}

// usw...
</code></pre>
<p>Mir wäre lieber, ich könnte das Fensterobjekt übergeben, um HWND zu wrappen, aber davon weiß WndProc nichst, da diese Funktion static ist, da gibts kein this. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Wie kann WndProc vom Fensterobjekt erfahren, es ist eine statische Methode der Klasse.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/244405/winapi-wrapper-messages</link><generator>RSS for Node</generator><lastBuildDate>Fri, 03 Apr 2026 21:26:37 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/244405.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 29 Jun 2009 19:47:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Mon, 29 Jun 2009 19:47:37 GMT]]></title><description><![CDATA[<p>Hallo!<br />
ich will gerade das WinAPI-Message-System etwas wrappen. Dabei muss man eine Funktion erstellen. Rückgabetyp ist void und Parameter ist (leider) ein HWND. Dann macht man noch eine Const int ID und übergibt die ID und die Funktionsadresse einer Bind-Funktion. Diese packt das einfach nur in eine std::map, key ist die ID, value der Funktionszeiger:</p>
<pre><code class="language-cpp">// Deklaration static std::map&lt;const int, void (*)(iZWindow)&gt; _evList; 
// static wegen der statischen WndProc

// Bekommt ID und Funktionsadresse und fügt ein
void iZWindow::BindAction(const int ID, void (*fptr)(iZWindow)) {
	iZWindow::_evList[ID] = fptr;
}
</code></pre>
<p>Soweit sogut. z.B. will man jetzt ein Menu erstellen. Das Menu hat eine eigene Klasse, aber am Ende, wenn man es in das Fenster ausgeben will muss man Fensterklasse.SetMenu(Menubarklasse); aufrufen:</p>
<pre><code class="language-cpp">iZMenubar menu;
iZPopup popup(100);
iZPopup popup2(200);
popup.AppendMenu(105, &quot;Drucken\tCTRL+P&quot;); // Popups mit Einträgen füllen
popup.AppendMenu(111, &quot;Beenden\tALT+F4&quot;);
popup2.AppendMenu(666, &quot;Ausschneiden&quot;);
menu.AppendMenubar(popup, &quot;Datei&quot;); // Popups in die Menubar
menu.AppendMenubar(popup2, &quot;Bearbeiten&quot;);
wnd.SetMenu(menu); // Menubar in das Fenster-Objekt wnd
</code></pre>
<p>Die Funktion zur Menuerstellung sollte also besser die Fensterklasse und nicht HWND als Parameter besitzten, ich rufe ja schließlich wnd.SetMenu(menu) auf.<br />
Zu dumm, dass ja dann am Ende WndProc die Aufgabe hat, die Funktion bei der übergebenen ID als Message aufzurufen und dabei ihr einen Parameter zu übergeben. WndProc bietet aber nur das HWND:</p>
<pre><code class="language-cpp">LRESULT CALLBACK iZWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	for(std::map&lt;const int, void (*)(iZWindow)&gt;::const_iterator iter = iZWindow::_evList.begin();
		iter != iZWindow::_evList.end(); iter++) {
		// event-map auslesen
			if((*iter).first == WM_CREATE) { // wenn key (=message) == WM_CREATE
				iter-&gt;second(hWnd); // value (=funktionszeiger) aufrufen und Parameter übergeben
			}
	}

// usw...
</code></pre>
<p>Mir wäre lieber, ich könnte das Fensterobjekt übergeben, um HWND zu wrappen, aber davon weiß WndProc nichst, da diese Funktion static ist, da gibts kein this. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Wie kann WndProc vom Fensterobjekt erfahren, es ist eine statische Methode der Klasse.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1734724</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1734724</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Mon, 29 Jun 2009 19:47:37 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Mon, 29 Jun 2009 20:24:47 GMT]]></title><description><![CDATA[<p>Wieso baust Du dir die Message-Loop nicht einfach selbst und startest sie innerhalb einer Member-Funktion deiner Klasse?</p>
<pre><code class="language-cpp">void iZWindow::run ()
{
    while (GetMessage (&amp;msg, NULL, 0, 0))
    {
        TranslateMessage (&amp;msg);
        switch (msg.message)
        {
            // ...
        }
    }
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1734748</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1734748</guid><dc:creator><![CDATA[devkid]]></dc:creator><pubDate>Mon, 29 Jun 2009 20:24:47 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Mon, 29 Jun 2009 20:55:22 GMT]]></title><description><![CDATA[<p>Wie kommst du auf void? Es muss doch LRESULT zurückgegeben werden?!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1734772</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1734772</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Mon, 29 Jun 2009 20:55:22 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Tue, 30 Jun 2009 06:46:47 GMT]]></title><description><![CDATA[<p>Indem Du den Zeiger auf Deine Klasse in GWL_USERDATA reinpackst.<br />
Suchmal im Netz danach.<br />
Oder Du baust einen Thunk wie die ATL, die die Fensterfunktion wrappt...</p>
<p>Warum verwendest Du nicht die ATL/MFC/WTL?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1734863</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1734863</guid><dc:creator><![CDATA[Martin Richter]]></dc:creator><pubDate>Tue, 30 Jun 2009 06:46:47 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Tue, 30 Jun 2009 16:43:18 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Wie kommst du auf void? Es muss doch LRESULT zurückgegeben werden?!</p>
</blockquote>
<p>Das soll doch keine <code>WndProc</code> -Funktion darstellen, sondern irgend eine (nicht-statische) Memberfunktion, die irgendwo im Code aufgerufen werden kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1735163</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1735163</guid><dc:creator><![CDATA[devkid]]></dc:creator><pubDate>Tue, 30 Jun 2009 16:43:18 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Tue, 30 Jun 2009 19:03:49 GMT]]></title><description><![CDATA[<p>An Martin Richter:</p>
<p>Danke, dein Stichwort &quot;GWL_USERDATA&quot; hat mein Message-Handling-Problem gelöst, hoffe ich. WndProc bleibt bei mir eine statische Memberfunktion der Fensterklasse, damit ich Zugriff auf die Attribute behalte.<br />
Die relevanten Codestellen:</p>
<pre><code class="language-cpp">// this, das Fensterobjekt an WM_CREATEs LPARAM übergeben
_hWnd = CreateWindowEx(0, _appName, _appName, WS_OVERLAPPEDWINDOW, x, y,
						   width, height, NULL, NULL, _appInfo._hInstance, this);

// ...

LRESULT CALLBACK iZWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

	switch(message) {
		case WM_CREATE:
			{
				// Adresse der Klasse aus dem LParam über CREATESTRUCT abholen
				LPCREATESTRUCT cs = (LPCREATESTRUCT)(lParam);
				if(!cs-&gt;lpCreateParams) {
					MessageBox(hWnd, &quot;An unexpected error occured passing the window object.&quot;, &quot;Runtime Error&quot;, MB_ICONERROR | MB_OK);
					SendMessage(hWnd, WM_CLOSE, wParam, lParam);
				}
				else { // In einen Long-Pointer die gecasteten Klassenadresse schreiben und mit jeder Message versenden
					SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)(cs-&gt;lpCreateParams));
				}

				Adresse abholen, casten und in lokales Objekt lasen
				iZWindow *lpWndHandle = (iZWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
// benutzerdefinierte Funktion, gespeichert in einer std::map aufrufen
				lpWndHandle-&gt;_evList[WM_CREATE](*lpWndHandle);
				return 0;
			}
		case WM_CLOSE:
			PostQuitMessage(0);
			return 0;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}
</code></pre>
<p>Lässt sich wunderbar kompilieren, keine RT-Errors. Erstklassig. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Die MFC verwende ich nicht, weil ich mich wirklich mit Win beschäftigen will <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /> Die schnöde API durchzugehen ist zu langweilig, dann kapsele ich sie als Übungszweck lieber gleich in Klassen.<br />
Außerdem will ich momentan nicht noch mehr Geld für C++ ausgeben, die Bücher sind schon teuer genug. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Ein anderes Problem:<br />
Was ich jetzt produziert habe, ist am Ende doch recht schlechtes C++. Der Nutzer der Klasse muss Funktionen oder statische Member erstellen, um Messages zu bearbeiten, das ist nicht gerade schönes OOP.</p>
<p>Ich habe überlegt, eventuell für alle Messages virtuelle Methoden in der Window-Klasse anzulegen, für WM_CREATE einfach virtual void OnCreate(), die werden dann bei Standard-Messages aufgerufen. In der Window-Klasse werden in den Definitionen der Message-Methoden nichts drinstehen, aber sie sind ja virtuell und können von Subklassen erweitert werden, darauf will ich hinaus, das man seine eigene Fensterklasse erstellt, von der Hauptklasse erbt und die Message-Funktionen implementiert, die man braucht, der Rest bleibt leer und DefWindowProc() macht den Rest.<br />
Ist das &quot;schöner&quot;?<br />
Wenn ich so überlege, Attribute der Windowklasse wie hWnd, message, windowclass usw. müssen ja dann auch in den Subklassen verfügbar sein ---&gt; also sind die protected. Das ist auch nicht schön. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /><br />
Gibt's da eine schöne Möglichkeit? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>@ devkid</p>
<p>Ja, entschuldige, ich habe die Augen (oder das Gehirn) zu der Uhrzeit nicht mehr richtig koordinieren können.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1735206</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1735206</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Tue, 30 Jun 2009 19:03:49 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Tue, 30 Jun 2009 22:25:21 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Ja, entschuldige, ich habe die Augen (oder das Gehirn) zu der Uhrzeit nicht mehr richtig koordinieren können.</p>
</blockquote>
<p>selbes gilt auch für mich jetzt, also kann sich was in sachen rechtschreibung<br />
einschleichen.</p>
<p>in meiner windowsklasse habe ich das ganze ebenfalls wie windows durch ein call-<br />
back gelöst, statt durch vererbung.</p>
<p>besonders gefallen (was ic auch aktuell verwende ) hat mir:</p>
<pre><code class="language-cpp">struct Params
{
    UINT msg;
    WPARAM wParam;
    LPARAM lParam;
    LRESULT retcode;
    bool changed; // gibt an, ob man den returncode gesetzt hat oder ob man DefWindowProc den rest machen lässt
};
void Func(Window *w, Params *p);
</code></pre>
<p>Window hat verschiedene methoden über die man an das handle z.b. kommt.<br />
die emthode mit der map eignet sich für einen keyhandler ganz gut.</p>
<p>wenn dir der returncode egal ist, kannst du auch eine std::queue verwalten,<br />
die deine eigene nachrichtenschleife ist</p>
<p>von der fensterklasse ableiten finde ich persönlich nicht so schön</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1735302</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1735302</guid><dc:creator><![CDATA[helferlein_unreg]]></dc:creator><pubDate>Tue, 30 Jun 2009 22:25:21 GMT</pubDate></item><item><title><![CDATA[Reply to WinAPI Wrapper: Messages on Wed, 01 Jul 2009 15:02:24 GMT]]></title><description><![CDATA[<blockquote>
<p>&gt; von der fensterklasse ableiten finde ich persönlich nicht so schön</p>
</blockquote>
<p>Funktioniert merkwürdigerweise auch bei mir nicht richtig, die WNDCLASSEX lässt sich registieren, (im Basisklassenkonstruktor, der von der Subklasse aufgerufen wird), aber CreateWindowEx scheitert. Naja, suche bessere Vorschläge. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Mir gehts einfach nur darum, dass der Nutzer nicht prozedural, sondern (auch) objektorientiert programmieren kann, wie es in richtigem C++ auch eine gute Mischung der Paradigmen ausmacht. wxWidgets hat an der Stelle keine schöne Lösung, finde ich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1735624</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1735624</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Wed, 01 Jul 2009 15:02:24 GMT</pubDate></item></channel></rss>