Nachrichtenaustausch zwischen Fenstern
-
falsch:
HWND hChild;richtig:
static HWND hChild;
-
@_msg
Danke, hätte ich eigentlich selber sehen müssen.
Wenn Dummheit quietschen würde.Aber jetzt kommt ein echtes Problem. Ich habe das Programm etwas ausgebaut, um mit diesen Nachrichten einen Zeiger auf eine Structur (in der die Mauskoordinaten gespeichert sind), an die ChildProc zu übergeben. Das sieht so aus:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hChild; static OutputData OutData; struct OutputData *pOutData = &OutData; //Initialisieren des Zeigers pOutData->i = 0; switch (message) { case WM_CREATE: { hChild = CreateWindow (/*das Übliche*/); return 0; } ////////////////////////////////////////////////////////////////////////// case WM_GETDATA: { bool Pm; MessageBox(hWnd, "WM_GETDATA ist angekommen", "Fensternachricht", MB_OK); Pm = PostMessage(hChild, WM_SENDDATA, 0, (LPARAM)pOutData); if (Pm == FALSE) { MessageBox(hWnd, "WM_SENDDATA wurde nicht gesendet", "Fensternachricht", MB_OK); } return 0; } LRESULT CALLBACK ChildProc (HWND hChild, UINT message, WPARAM wParam, LPARAM lParam) { static OutputData *pOutData = NULL; switch (message) { case WM_CREATE: { PostMessage(GetParent(hChild), WM_GETDATA, 0, 0); return 0; } case WM_SENDDATA: { /////////////////////////////////////////////////////////////////////// pOutData = (OutputData*)lParam; MessageBox(hChild, "WM_SENDDATA angekommen", "Fensternachricht", MB_OK); /////////////////////////////////////////////////////////////////////// return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; char szKeyStatus[40]; int iKeyLength; hDC=BeginPaint(hChild, &ps); for (pOutData->i = 0; pOutData->i<4; pOutData->i++)//Hier beginnen die Probleme { iKeyLength = wsprintf(szKeyStatus, "Status Pfeiltaste %i: %i", pOutData->i, pOutData->ArrowKeys[pOutData->i]); GetTextExtentPoint32(hDC, szKeyStatus, iKeyLength, &pOutData->size); TextOut(hDC, pOutData->x, pOutData->y + pOutData->i * pOutData->size.cy, szKeyStatus, iKeyLength); TextOut(hDC, pOutData->x, pOutData->y + 5 * pOutData->size.cy, pOutData->szLbtMsg, lstrlen(pOutData->szLbtMsg)); TextOut(hDC, pOutData->x, pOutData->y + 6 * pOutData->size.cy, pOutData->szRbtMsg, lstrlen(pOutData->szRbtMsg)); TextOut(hDC, pOutData->x, pOutData->y + 7 * pOutData->size.cy, pOutData->szMmvMsg, lstrlen(pOutData->szRbtMsg)); } EndPaint(hChild, &ps); return 0; }Um genau zu sein: In der Struct sind die Daten des Mauscursors und die Koordinaten, an denen ein Button geklickt wurde, festgehalten. Die will ich im Childfenster ausgeben. Die Ausgabe im Hauptfenster funktioniert, das ist schon ausprobiert.
Das Problem: Überall dort, wo über den Zeiger auf einen Member der Sturktur zugegriffen werden soll, produziert das Programm einen Zugriffsfehler- zum ersten mal eben bei dem Zähler (hab ich im Code kommentiert). Ich vermute, daß ich bei der Konvertierung und Übergabe des Zeigers in lParam etwas falsch mache (allerdings gibt es keinen Compiler-Fehler). Also, wie mache ich das richtig?@CodeFinder: Bitte nicht mit "reinterpret_cast", es muß ja auch eine gängige Variante geben.
-
Überprüfe mal mit Debug-Ausgaben, in welcher Reihenfolge die Messages eintreffen. Ich würde mich nicht wundern, wenn WM_PAINT vor WM_SENDDATA eintrifft. In diesem Fall wäre pOutdata noch nicht initialisiert.
Warum verwendest Du für OutputData nicht einfach eine modulweit definierte Variable?
-
Nein, WM_SENDDATA trifft vor WM_PAINT ein, nämlich direkt nach WM_CREATE. Das habe ich mit den MessageBoxen schon herausgefunden. Sonst dürfte die Meldung "WM_SENDDATE angekommen" nicht erscheinen.
Aber ich kann mal versuchen, die WM-PAINT-Bearbeitung auszu"if"en.Wie ich schon sagte, bin ich am üben. Es geht mir auch darum, daß die Strukturvariablen nur lokal verfügbar sind. Da ich den Zeiger nicht mit den Funktionsparametern übergeben kann, muß ich ihn per WM_Message abliefern.
-
Elektronix schrieb:
Da ich den Zeiger nicht mit den Funktionsparametern übergeben kann, muß ich ihn per WM_Message abliefern.
Du kannst den Zeiger mit dem letzten Funktionsparameter von CreateWindow übergeben. Hilfreich für die Fehlersuche wäre es übrigens, wenn Du den kompletten Code postest, so dass man ihn mal laufen lassen kann.
-
Elektronix schrieb:
@CodeFinder: Bitte nicht mit "reinterpret_cast", es muß ja auch eine gängige Variante geben.
LOL, das entspricht nem einfach C-Cast. Ist ganz einfach C++:
Type* pName = reinterpret_cast<Type*>(pvData); Type* pName = (Type*)pvData;_mgs schrieb:
Warum verwendest Du für OutputData nicht einfach eine modulweit definierte Variable?
Die sollte man immer vermeiden
.Elektronix schrieb:
Wie ich schon sagte, bin ich am üben. Es geht mir auch darum, daß die Strukturvariablen nur lokal verfügbar sind. Da ich den Zeiger nicht mit den Funktionsparametern übergeben kann, muß ich ihn per WM_Message abliefern.
Ist sicherlich ne gute Übung
. Ich würde die Initialisierung bzw Variablenübergabe aber mal so machen:// ... static OutputData OutData; // ... Pm = PostMessage(hChild, WM_SENDDATA, 0, (LPARAM)&OutData); /* // ODER, *grinz*: Pm = PostMessage(hChild, WM_SENDDATA, 0, reinterpret_cast<LPARAM>(&OutData)); */
Id est
:LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hChild; static OutputData OutData; switch (message) { case WM_CREATE: { OutData.i = 0; hChild = CreateWindow (/*das Übliche*/); return 0; } ////////////////////////////////////////////////////////////////////////// case WM_GETDATA: { MessageBox(hWnd, TEXT("WM_GETDATA ist angekommen"), TEXT("Fensternachricht"), MB_OK); bool fResult = PostMessage(hChild, WM_SENDDATA, 0, (LPARAM)&OutData); if(!fResult) MessageBox(hWnd, TTEXT("WM_SENDDATA wurde nicht gesendet"), TEXT("Fensternachricht"), MB_OK); return (0); } // ...Noch ein Hinweis: In C++ sind alle Strukturen auch Typen. Es reicht zur Definition also das:
C++SInfoData data;In C sähe es so aus (wie du es schon richtig gemacht hast
):
Cstruct SInfoData data;Du kannst das jedoch anpassen, in dem du das Schlüsselwort typedef verwendest.
typedef struct { int iValue; long lValue; // and so on ... } SInfoData;Finde, das sieht besser aus
. Danach reicht dann das:SInfoData data;PS: In Kombination mit dem Datentyp bool wird normalerweise auch true und false verwendet, nicht TRUE und FALSE
-
Wow, CodeFinder, ich wußte, auf Dich ist Verlaß!

Ich habe Deine Tips noch nicht ausprobiert, aber danke für die umfangreichen Auskünfte.
Kleine Frage noch: Was ist der Unterschied zwischen TRUE und true?
-
Elektronix schrieb:
Wow, CodeFinder, ich wußte, auf Dich ist Verlaß!

Jo danke
.Elektronix schrieb:
Kleine Frage noch: Was ist der Unterschied zwischen TRUE und true?
Hm also true/false sind Schlüsselwörter, werden also vom Compiler direkt 'erkannt'. Und
TRUE und FALSE sind, von der Wertedefinition (Also: true/TRUE = 1, false/FALSE = 0) gleichwertig und einfach
mit der Präprozessor-Direktive #define festgelegt. Nur TRUE und FALSE wurden mit dem von Windows eingeführten 'Datentyp' BOOL (entspricht int) definiert, da C keinen Typ Boolean kennt.
Summa sumarum ist es also das gleich nur wenn man bool (C++) verwendet sollte man der Schönheit
wegen auch passend dazu true und false verwenden
.
-
SUPI!!! Es hat geklappt.
CodeFinder war der Schlüssel.
Jetzt wird die Position des Mauscursers innerhalb des Cildfensters ausgegeben.Danke allen Helfern.
-
CodeFinder schrieb:
Du kannst das jedoch anpassen, in dem du das Schlüsselwort typedef verwendest.
typedef struct { int iValue; long lValue; // and so on ... } SInfoData;Finde, das sieht besser aus
. Danach reicht dann das:SInfoData data;Bringt das typedef eigentlich was vor dem struct? Benutze immer nur struct...
Soweit ich das sehe, gibts ja mindestens 3 Varianten:So mache ich das immer:
strct MyStruct { };Á lá Mr. Codefinder:
typedef struct MyStruct { };Kenn ich aus windows.h:
tpydef struct _MyStruct { } MyStruct;Hier wird ja gleich schon ne Variable von MyStruct deklariert:
struct MyStruct { } VarMyStruct;Schätze, hier wird keine Variable deklariert?:
tpydef struct _MyStruct { } MyStruct;Wegen dem typedef?
-
Badestrand schrieb:
So mache ich das immer:
strct MyStruct { };Jo so kannstes auch machen, da du warscheinlich mit nem C++ Compiler arbeitest, dann sind structs automatisch
Typen. Falls nicht müsstest du bei einer Variablendefinition/deklaration schreiben:struct SData sdName;Badestrand schrieb:
Hier wird ja gleich schon ne Variable von MyStruct deklariert:
struct MyStruct { } VarMyStruct;Jops.
Badestrand schrieb:
Schätze, hier wird keine Variable deklariert?:
tpydef struct _MyStruct { } MyStruct;Genau! Hier wird eine Strukur _MyStruct und ein Typ MyStruct definiert.
Badestrand schrieb:
Wegen dem typedef?
Genau deswegen
.