SendMessage PostMessage Struktur
-
@Dipl.Inf.Student
Erlaube mir mal eine Frage: Wer außer Dir hat was von zwei Prozessen geschrieben? Der Threadersteller jedenfalls nicht.
Westworld schrieb:
Hallo,
Ich möchte gerne via SendMessage bzw. PostMessage eine Nachricht an ein anderes Fenster schicken. Die Nachricht soll über meinetwegen WM_MYMESSAGE (benutzdefiniert) heißen. Funktioniert ja auch alles bis hierher. Aber wenn ich eine Zeichenkette oder gar eine Struktur (struct XYZ { char str1[256]; char str2[256]; }; )über diese Funktionen schicke kriege ich im anderen Fenster nur Schrott. ALles versucht bis hin zu HGLOBAL und Co. Vielleicht weiß jemand weiter. Danke.
Du brauchst offenbar den zweiten Prozess, damit Du Recht behältst, obwohl Du auf dem falschen Dampfer bist.
Als Student sollte man erstmal richtig lesen können, bevor man sich als Unreg so aufplustert.
-
BorisDieKlinge schrieb:
Pseudo Code
Prozess A:
DATA* ad = new DATA(); SendMessage(...,WM_INSERTTOLIST,0,(LPARAM)ad);
Prozess B:
OnData( WPARAM WPara, LPARAM LPara) DATA * ad = (DATA *) LPara; }
-
Elektronix schrieb:
@Dipl.Inf.Student
Erlaube mir mal eine Frage: Wer außer Dir hat was von zwei Prozessen geschrieben? Der Threadersteller jedenfalls nicht.
Westworld schrieb:
Hallo,
Ich möchte gerne via SendMessage bzw. PostMessage eine Nachricht an ein anderes Fenster schicken. Die Nachricht soll über meinetwegen WM_MYMESSAGE (benutzdefiniert) heißen. Funktioniert ja auch alles bis hierher. Aber wenn ich eine Zeichenkette oder gar eine Struktur (struct XYZ { char str1[256]; char str2[256]; }; )über diese Funktionen schicke kriege ich im anderen Fenster nur Schrott. ALles versucht bis hin zu HGLOBAL und Co. Vielleicht weiß jemand weiter. Danke.
Du brauchst offenbar den zweiten Prozess, damit Du Recht behältst, obwohl Du auf dem falschen Dampfer bist.
Als Student sollte man erstmal richtig lesen können, bevor man sich als Unreg so aufplustert.
Die Frage wegen der zwei Prozesse ist immer noch nicht beantwortet.
-
Lenk nicht ab, Elektrochecknix. Boris hat Müll gelabert und dachte er kann sich hier wie El Chéf aufspielen, obwohl er offensichtlich 0 Ahnung hat. Ich wollte ihn noch vor der Selbstdemontage retten, aber er wollte ja nicht hören.
-
Ich bin zwar nicht Elektrochecknix, aber den Müll hast Du selbst gelabert, weil Du eine Frage beantwortest, die gar nicht gestellt wurde. Lernt man sowas auf der Uni?
Registrier Dich und halt Dich an die Nettiquette (dazu gehört auch, die Nicks anderer User nicht zu verballhornen). Dann können wir weiterreden.
-
@Dipl. Inf. Student: Geh philosophy studieren... natürlich kann man über LPARAM /WPARAM Pointer auf Datenbereiche bzw. Objekte übergeben... als Beispiel Kommunikation Thread und GUI...
-
Tue mir einen Gefallen und lern lesen, dann kannst du dir vielleicht auch die nötigen Grundlagen aneigenen, um mitreden zu können. Wir sprachen über IPC.
-
Was soll dein "Grundlagen" geschwätz ! Was ist wohl Interprozesskommunikation
Thread -> GUI PostMessage... um das gings hier "Daten" an ein Fenster schicken....
Du solltest nich nur Bücher lesen...sonder auch mal praktisch arbeiten...
-
Prozessübergreifend
-
WestWorld schrieb:
Hallo,
Ich möchte gerne via SendMessage bzw. PostMessage eine Nachricht an ein anderes Fenster schicken. Die Nachricht soll über meinetwegen WM_MYMESSAGE (benutzdefiniert) heißen. Funktioniert ja auch alles bis hierher. Aber wenn ich eine Zeichenkette oder gar eine Struktur (struct XYZ { char str1[256]; char str2[256]; }; )über diese Funktionen schicke kriege ich im anderen Fenster nur Schrott. ALles versucht bis hin zu HGLOBAL und Co. Vielleicht weiß jemand weiter. Danke.
Zeiger auf Strings oder Strukturen sollte man nie mit PostMessage schicken (es sei denn, man weiß genau, was man tut). Im Gegensatz zu SendMessage kehrt PostMessage sofort zum Aufrufer zurück und der Code wird weiter abgearbeitet. Übergibt man PostMessage Zeiger auf lokale Variablen, dann sind diese schon ungültig, wenn der Empfänger die Nachricht bekommt.
-
Langsam plädiere ich doch dafür, unregistrierte arrogante Dipl.Inf.Studenten auszuschließen.
Typen wie ihm verdanken wir solche Diskussionen:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-212868.html
-
Jetzt pack aber mal wieder die unreg Keule ein.
Boris hat in seinem Codebeispiel behauptet, dass man einfach mittels Pointer Daten zwischen 2 Prozessen austauschen kann:
Boris schrieb:
wieso? wenn die daten im prozess B aufm heap liegen kann prozess A über dnen zeiger auf diedaten zugriefen..
Also kann man einfach einen Zahlenwert zwischen 2 prozessen verschicken, und dann auf die date zugreifen.
Na wenn das die Meinung der Mehrheit ist, dann wundert mich nichts mehr ...
-
Übergibt man PostMessage Zeiger auf lokale Variablen, dann sind diese schon ungültig, wenn der Empfänger die Nachricht bekommt.
ich spreche auch nicht von lokalen variabeln.... "heap"
Boris hat recht wenn er mit Prozessen zwei unterschiedliche Thread in ner anwendung meint....
-
@Wurst
Das war auch nicht auf Dich gemünzt. Es gibt genügend Profis hier, die sagen: Man kann per SendMessage Zeiger versenden- und die werden wohl wissen, was sie erzählen. Ich kann es nur nicht leiden, wenn ein dahergelaufener Unreg den Profis in der Community sagen will, daß sie zu blöd sind. Wenn er das nötig hat, soll er sich ein Forum suchen, wo das aktzeptiert wird. Hier ist es unerwünscht.Ich wundere mich, daß hier immer von "Prozessübergreifend" geredet wird, obwohl im Eingangspost davon keine Rede ist. Der Dipl.Inf.Student hat das gleich in seiner ersten Antwort erfunden, um allen anderen ihre Blödheit vorzuhalten. Aber bezogen auf den Fragesteller: Wer mit SendMessage noch nicht umgehen kann, wird wohl kaum mit Prozessen um sich schmeißen.
Es kann ja sein, daß ich was falsch verstehe: Benötigt jedes Fenster, auch jedes Child-Fenster- einen eigenen Prozess? Oder kann ein einzelner Prozess nicht mit mehreren Fenstern umgehen?
Ich bin zwar kein Profi-Progger. Aber: Dieses Prgramm versendet die Adresse einer Struct an ein Child-Fenster (Usernachricht WM_SENDDATA), und es funktioniert:
#define STRICT #include <windows.h> #define ChildHight 140 #define ChildWidth 300 struct OutputData{ POINT ptCursor; //Position des Mauscursors SIZE size; //Textgröße char szLbtMsg[128]; //Ausgabe linke Maustaste char szRbtMsg[128]; //Ausgabe rechte Maustaste char szMmvMsg[128]; //Ausgabe Mausposition bool ArrowKeys[4]; int x, y; int i; // Zähler }; const UINT WM_GETDATA = WM_APP + 1; const UINT WM_SENDDATA = WM_APP + 2; LRESULT CALLBACK ChildProc (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); const char szAppName[] = "Tastaturabfrage"; const char szChildName[] = "ChildWindow"; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MSG msg; HWND hWnd; WNDCLASS wc; wc.cbClsExtra =0; wc.cbWndExtra =0; wc.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH); wc.hCursor =LoadCursor(NULL, IDC_ARROW); wc.hIcon =LoadIcon(NULL, IDI_APPLICATION); wc.hInstance =hInstance; wc.lpfnWndProc =WndProc; wc.lpszClassName =szAppName; wc.lpszMenuName =NULL; wc.style =CS_VREDRAW|CS_HREDRAW; RegisterClass(&wc); wc.hIcon = NULL; wc.lpfnWndProc =ChildProc; wc.lpszClassName =szChildName; RegisterClass(&wc); hWnd = CreateWindow( szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hChild; static OutputData OutData; //OutData.i = 0;//Variante mit dem Wert der Variablen //struct OutputData *pOutData = &OutData;//Initialisieren des Zeigers //pOutData->i = 0; //einfache Schreibform mit Zeiger //(*pOutData).i = 0; //normale Schreibform mit Zeiger switch (message) { case WM_CREATE: { hChild = CreateWindow (szChildName, NULL, WS_CHILD|WS_VISIBLE|WS_DLGFRAME, 0, 0, ChildWidth, ChildHight, hWnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL); return 0; } ////////////////////////////////////////////////////////////////////////// case WM_GETDATA: { bool Pm; MessageBox(hWnd, "WM_GETDATA ist angekommen", "Fensternachricht", MB_OK); Pm = PostMessage(hChild, WM_SENDDATA, 0, (LPARAM)&OutData); if (Pm == FALSE) { MessageBox(hWnd, "WM_SENDDATA wurde nicht gesendet", "Fensternachricht", MB_OK); } return 0; } //////////////////////////////////////////////////////////////////////////// case WM_SENDDATA: { //MessageBox(hWnd, "WM_SENDDATA angekommen", "Fensternachricht", MB_OK); OutData.ptCursor.x= OutData.ptCursor.x + LOWORD(lParam); OutData.ptCursor.y = OutData.ptCursor.y + HIWORD(lParam); MoveWindow(hChild,OutData.ptCursor.x,OutData.ptCursor.y, ChildWidth, ChildHight, TRUE); } case WM_SIZE: { RECT rect; rect.left = 0; rect.right = 0; rect.right = LOWORD(lParam); rect.bottom = HIWORD(lParam); return 0; } case WM_MOUSEMOVE: { switch (wParam) { case MK_RBUTTON: { OutData.ptCursor.x = LOWORD(lParam); //ohne diese beiden Zeilen läuft die OutData.ptCursor.y = HIWORD(lParam); //Schrift dem Cursor hinterher. OutData.x = OutData.ptCursor.x; OutData.y = OutData.ptCursor.y; MoveWindow(hChild,OutData.ptCursor.x,OutData.ptCursor.y, ChildWidth, ChildHight, TRUE); } } OutData.ptCursor.x = LOWORD(lParam); OutData.ptCursor.y = HIWORD(lParam); wsprintf(OutData.szMmvMsg, "Mauscursor an Pos.:x = %-04d, y = %-041d", OutData.ptCursor.x, OutData.ptCursor.y); InvalidateRect(hWnd, 0, TRUE); break; } case WM_LBUTTONDOWN: { OutData.ptCursor.x = LOWORD(lParam); OutData.ptCursor.y = HIWORD(lParam); wsprintf(OutData.szLbtMsg, "Linke Maustaste an Pos.:x = %04d, y = %04d", OutData.ptCursor.x, OutData.ptCursor.y); InvalidateRect(hWnd, 0, TRUE); break; } case WM_RBUTTONDOWN: { wsprintf(OutData.szRbtMsg, "Rechte Maustaste an Pos.:x = %04d,y= %04d", OutData.ptCursor.x, OutData.ptCursor.y); InvalidateRect(hWnd, 0, TRUE); break; } case WM_KEYDOWN: { switch (wParam) { case VK_LEFT: OutData.ArrowKeys[0] = true; break; case VK_UP: OutData.ArrowKeys[1] = true; break; case VK_RIGHT: OutData.ArrowKeys[2] = true; break; case VK_DOWN: OutData.ArrowKeys[3] = true; break; default: return 0; } //InvalidateRect (hWnd, NULL, FALSE);//Macht den Client-Bereich ungültig, dieser wird bei //der nächsten WM_PAINT neu gezeichnet. return 0; } case WM_KEYUP: { switch (wParam) { case VK_LEFT: OutData.ArrowKeys[0] = false; break; case VK_UP: OutData.ArrowKeys[1] = false; break; case VK_RIGHT: OutData.ArrowKeys[2] = false; break; case VK_DOWN: OutData.ArrowKeys[3] = false; break; default: return 0; } //InvalidateRect (hWnd, NULL, FALSE); return 0; } //!! Ohne das ChildWindow käme die Ausgabe in diesem Abschnitt. !! /*case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; char szKeyStatus[40]; int iKeyLength; hDC=BeginPaint(hWnd, &ps); for (OutData.i = 0; OutData.i<4; OutData.i++) { iKeyLength = wsprintf(szKeyStatus, "Status Pfeiltaste %i: %i", OutData.i, OutData.ArrowKeys[OutData.i]); GetTextExtentPoint32(hDC, szKeyStatus, iKeyLength, &OutData.size); TextOut(hDC, OutData.x, OutData.y + OutData.i * OutData.size.cy, szKeyStatus, iKeyLength); TextOut(hDC, OutData.x, OutData.y + 5 * OutData.size.cy, OutData.szLbtMsg, lstrlen(OutData.szLbtMsg)); TextOut(hDC, OutData.x, OutData.y + 6 * OutData.size.cy, OutData.szRbtMsg, lstrlen(OutData.szRbtMsg)); TextOut(hDC, OutData.x, OutData.y + 7 * OutData.size.cy, OutData.szMmvMsg, lstrlen(OutData.szRbtMsg)); } EndPaint(hWnd, &ps); return 0; }*/ case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd, message, wParam, lParam); } ////////////////////////////////////////////////////////////////////////////////////// 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_MOUSEMOVE: { switch (wParam) { case MK_RBUTTON: SendMessage(GetParent(hChild), WM_SENDDATA, LOWORD(lParam), HIWORD(lParam)); break; } return 0; } case WM_SENDDATA: { /////////////////////////////////////////////////////////////////////// /*(OutputData*)*/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); if (pOutData != NULL) { for (pOutData->i = 0; pOutData->i<4; pOutData->i++)//F E H L E R { iKeyLength = wsprintf(szKeyStatus, "Status Pfeiltaste %i: %i", pOutData->i, pOutData->ArrowKeys[pOutData->i]); GetTextExtentPoint32(hDC, szKeyStatus, iKeyLength, &pOutData->size); TextOut(hDC, 1, pOutData->i * pOutData->size.cy, szKeyStatus, iKeyLength); TextOut(hDC, 1, 5 * pOutData->size.cy, pOutData->szLbtMsg, lstrlen(pOutData->szLbtMsg)); TextOut(hDC, 1, 6 * pOutData->size.cy, pOutData->szRbtMsg, lstrlen(pOutData->szRbtMsg)); TextOut(hDC, 1, 7 * pOutData->size.cy, pOutData->szMmvMsg, lstrlen(pOutData->szRbtMsg)); } } else { MessageBox(hChild, "WM_PAINT angekommen", "Fensternachricht", MB_OK); } EndPaint(hChild, &ps); return 0; } case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hChild, message, wParam, lParam); }
-
Prof. Dr. Dr. Gates schrieb:
Übergibt man PostMessage Zeiger auf lokale Variablen, dann sind diese schon ungültig, wenn der Empfänger die Nachricht bekommt.
ich spreche auch nicht von lokalen variabeln.... "heap"
Boris hat recht wenn er mit Prozessen zwei unterschiedliche Thread in ner anwendung meint....
Wenn du Prozess als "zwei unterschiedliche Threads in ner anwendung" definierst, dann wundert es mich nicht, daß du keinen Plan hast.
Man muss mich nicht mögen, aber hier jetzt auf Biegen und Brechen zu versuchen, die FALSCHINFORMATION von Boris zu verteidigen, ist hochgradig lächerlich. Aber vermutlich steckt hinter "Prof. Dr. Dr. Gates" auch niemand geringeres als er selbst
-
Die definition von Prozess war von ihm falsch gewählt...
Aber wenn du dich hier so aufplustert, und meinst du bist der übelste super Informatik Student.( Der Nick ist eh lächerlich sehr viele hier sind Diplom. Informatiker) .und die haben keine so große Klappe:)
Und wenn du denkst man kann nur Werte versenden und keine Pointer welche auf Daten zeigen dann solltest du noch paar Semester drauf legen.
-
Laber keinen Müll. Ich hab dich doch vorher noch gewarnt, aber du wolltest dich ja unbedingt aufplustern. jetzt musstest du es eben auf die harte tour lernen, aber jetzt kannste auch wieder aufhören zu heulen.
-
Elektronix schrieb:
@Wurst
Das war auch nicht auf Dich gemünzt. Es gibt genügend Profis hier, die sagen: Man kann per SendMessage Zeiger versenden- und die werden wohl wissen, was sie erzählen.Das geht mit WM_COPYDATA, wo man dann einen zeiger+länge angibt, und dann die daten byte für byte in den prozess des zielfensters kopiert werden, und der pointer dann im zielprozess ganz ander aussehen kann.
Aber bezogen auf den Fragesteller: Wer mit SendMessage noch nicht umgehen kann, wird wohl kaum mit Prozessen um sich schmeißen.
Der OP meint mit anderes Fenster wohl einen anderen Prozess, da er von HGLOBAL geredet hat, und das zu 16-Bit Zeiten für Prozessübergreifenden speicher verwendet wurde.
Es kann ja sein, daß ich was falsch verstehe: Benötigt jedes Fenster, auch jedes Child-Fenster- einen eigenen Prozess?
Nö, das währe reine resourcenverschwendung.
...
Hier passiert alles in einem einzigen Prozess also ohne IPC/WM_COPYDATA
Ich hoffe ich konnte die Sache etwas aufklären,
Gruß wurst
-
Oha, was ein Post
.
Also mich stört das aggressive posten von "Dipl.Inf.Student" auch etwas und nur weils im Namen steht, kann da ja trotzdem ein (kleines) Script-Kiddie hinter sitzen, ABER: er hat sozusagen Recht
(hab den Thread nur überfolgen). Der Threadersteller hat weder was von Threads noch was von Prozesses gesagt und genau das ist das Problem: Mit "eine Nachricht an ein Fenster senden" kann sowohl ein Fenster des eigenen Threads, als auch ein Fenster eines anderen Prozesses gemeint sein (
fehlende Hintergrundinformation). Daher war die Frage von "Dipl.Inf.Student" schon sinnvoll - wäre auch meine Gegenfrage gewesen. Das vllt. erstmal zur Konfliktauflösung^^.
Zum Problem (keine Ahnung, ob das jetzt so klar wurde): Threads gehören immer zu einem Prozess. Innerhalb eines Prozesses (und damit auch innerhalb von Threads mit dem gleichen Prozess) gilt der Adressraum für das jeweilige Programm, dabei kann aber nicht auf den Adressraum eines anderen Programmes/Prozesses zugegriffen werden, da Windows das verbietet (sicherer). Stürzt nämlich ein Programm wären fehlerhafter Zeigerarithmetik ab, sorgt das nicht für den Absturz aller Programm oder sogar des gesamten OS. Man kann mit SendMessage/PostMessage also prozess-intern Daten "verschicken". An Fenster anderer Programm geht das aber nicht.
Dabei sollte der Unterschied zwischen SendMessage und PostMessage vllt. noch klar werden: SendMessage sorgt, falls die Nachricht an ein Fenster aus einem anderen Thread geschickt wird, für ein Context-Swichting. Das heißt, dass der Thread aufgrund des Aufrufs gewechselt wird und die Funktion erst dann zurückkehrt, wenn die jeweilige Fensterprozedur "geantwortet" hat. Das ist wichtig bei der Synchronisation von Threads und wichtig bei der Übermittlung von Zeigern: Es muss nämlich sichergestellt werden, dass der Zeiger in der Fensterprozedur noch gültig ist, dazu folgendes Beispiel:// ... UINT uiLen = ...; SendMessage(hWnd, WM_USER + 1, 0, reinterpret_cast<LPARAM>(new TCHAR[uiLen])); // ... /* In der entsprechenden Ziel-WndProc: */ case WM_USER + 1: { TCHAR* pszBuf = reinterpret_cast<TCHAR*>(lParam); assert(pszBuf); // Irgendwas mit pszBuf machen [...]. delete [] pszBuf; } break; // bzw. return
Ob man nun SendMessage oder PostMessage im obrigen Beispiel verwendet, ist egal. (Wenn das SendMessage in einem Thread aufgerufen wird, sollte man auf jeden Fall PostMessage verwenden!)
Bei folgendem Beispiel hingegen, *muss* man SendMessage verwenden:TCHAR szBuf[1024]; SendMessage(hWnd, WM_USER + 1, 0, reinterpret_cast<LPARAM>(szBuf)); // ... /* In der entsprechenden Ziel-WndProc: */ case WM_USER + 1: { TCHAR* pszBuf = reinterpret_cast<TCHAR*>(lParam); assert(pszBuf); // Irgendwas mit pszBuf machen [...]. } break; // bzw. return
Hoffe, damit ist es allen klar
.
-
@Wurst und Codefinder
Danke für die Aufklärung und @Codefinder für das diplomatische Einmischen.
@Wurst
Ich habe den Eingangspost so verstanden, daß er Zeiger zwischen Fenstern eines einzelnen Prozesses versenden will und nur aus Ratlosigkeit
Alles versucht bis hin zu HGLOBAL und Co.
Kann natürlich sein, daß ich das mißverstehe. Aber ich denke, wenn jemand mit mehrfach-Prozessen umgeht, ist er auch klug genug, seine Frage entsprechend zu formulieren bzw. SendMessage und PostMessage richtig einzusetzen. CodeFinder hat fehlende Hintergrundinfos erwähnt, das sollte beim Umgang mit Prozessen eigentlich nicht passieren. Daher denke ich eher, es bleibt bei einem Childfenster im selben Prozess.
Wäre vom OP halt schön, wenn er das selbst aufklären könnte.Wie auch immer, hoffentlich kommt jetzt ein bißchen Ruhe in die Diskussion.