![]() |
Text (Pfadangabe) per Windows Message verschicken
Hallo,
ist es möglich Text per eigene Message zu verschicken und dabei nicht WM_COPYDATA zu nutzen?? Habe schon das hier gefunden: ![]() aber das ist nicht das wahre, da er ab und zu nur Kaudawelsch bekommt! Oder liegts an mir?? |
Re: Text (Pfadangabe) per Windows Message verschicken
Reservier den notwendigen Speicher und übergib den Zeiger in LParam oder WParam. Dein Beispiel ist aber auch nichts anderes. Das gilt natürlich auch für Zeiger auf Records oder Instancen von Klassen (also Objekte).
Gruß oki |
Re: Text (Pfadangabe) per Windows Message verschicken
Wie soll ich den speicher reservieren? In der anderen Anwendung weiß ich ja nicht wie groß der Text ist, der dort ankommt? Oder hab ich gerade nur ne Denkblockade?
|
Re: Text (Pfadangabe) per Windows Message verschicken
nja, direkt Speicher reservieren mußt du nicht ... du mußt nur einen Zeiger auf die geünschten Daten verschicken und beim Empfänger ab dieser Adresse die Daten auslesen (wenn es ein anderer Prozeß ist, dann z.B. per
![]() |
Re: Text (Pfadangabe) per Windows Message verschicken
Joop, so wie himitsu es beschreibt. Eigentlich ist jede Variable auch ein Zeiger auf eine Speicherstelle. Der Witz ist nur, ob dieser Zeigen auch noch gültig ist wenn die Message ankommt. Bei einer lokalen Variable sehe ich das sehr kritisch.
Die Verwendung von SendMessage kommt nicht von Ohne. SendMessage wartet eigentlich auf die Ausführung und kehrt nach der Ausführung wieder zurück. Damit sollte eigentlich nichts schief gehen. Vertrauen würd ich darauf jetzt aber nicht. Gruß oki |
Re: Text (Pfadangabe) per Windows Message verschicken
Ich hab jetzt noch eine Möglichkeit gefunden das mit der GlobalAtom Function von Windows zu machen! Ist das eine gute lösung oder sollte ich davon lieber die Finger lassen? Hab nicht wirklich nen Schimmer wozu genau diese GlobalAtom Function ist oO
|
Re: Text (Pfadangabe) per Windows Message verschicken
Damit kannst du sozusagen einen systemweiten Wert registrieren (oder so). Das ist aber eher nicht dein Weg. Mehr mit Kanonen auf Spatzen geschossen.
Mußt du denn unbedingt SendMessage verwenden? Trotzdem sollte das mit dem PChar im Param klappen. Wenn dabei Mist raus kommt, dann ist dein Zeiger ungültig geworden oder an einer anderen Stelle schmiert was über den Speicher. Gruß oki |
Re: Text (Pfadangabe) per Windows Message verschicken
Zitat:
Messages währen eigentlich genau das richtige denke ich :gruebel: |
Re: Text (Pfadangabe) per Windows Message verschicken
Nutze dazu u.a. die GlobalLock() Funktion. Du versendest das Handle und jede Anwendung holt sich den Zeiger für den Zugriff mit GlobalLock.
|
Re: Text (Pfadangabe) per Windows Message verschicken
Habs jetzt so gelöst, aber irgendwie bekomme ich immer nur die ersten 3 Zeichen von der Pfandangabe! Was ist da noch falsch?
Delphi-Quellcode:
Den Code hab ich mehr oder weniger hier aus dem Forum!
procedure GlobalAllocFileName(aWnd: HWND; aText: String);
var Data: THandle; DataPtr: Pointer; Size: Integer; oldWND: HWND; begin Size := Length(aText) + 1; Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size); try DataPtr := GlobalLock(Data); try Move(PChar(aText)^, DataPtr^, Size); PostMessage(aWnd, WM_TSOPLAYFILE, INTEGER(dataptr^), 0) finally GlobalUnlock(Data); end; except GlobalFree(Data); raise; end; end; |
Re: Text (Pfadangabe) per Windows Message verschicken
ich würd es am Einfachsten so machen ... auf jedenfall mußt du data verschicken, der andere Prozess holt sich dann über diesen globalen Wert in data selber per GlobalLock die Daten in seinen Arbeitsspeicher und kann dann daraus lesen.
Delphi-Quellcode:
PS: hiermit INTEGER(dataptr^) versendest du nur die ersten 4 Byte direkt im Parameter.
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size);
try DataPtr := GlobalLock(Data); try CopyMemory(DataPtr, PChar(aText), Size); finally GlobalUnlock(Data); end; SendMessage(aWnd, WM_TSOPLAYFILE, data, 0); finally GlobalFree(Data); end; |
Re: Text (Pfadangabe) per Windows Message verschicken
Ich dachte ich kann die Daten dann in der Message des Empfängers einfach per Pointer auslesen! Muss ich dort auch mit GlobalAlloc arbeiten?
Im Empänger sieht es so aus:
Delphi-Quellcode:
var
MSGFile: PChar; WM_TSOPLAYFILE: begin; MSGFile := PChar(@wParam); MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING); //mit deinem Code bekomme ich jetzt hier eine endlos lange Message... if FileExists(MSGFile) then begin; PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0); if Succeeded(CheckFile(MSGFile)) then PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0) end; end; Wie muss das hier aussehen? Also wie lese ich den Speicher mit GlobalAlloc? Edit: Achja, ist PostMessage in dem Fall nicht besser als SendMessage in deinem Code? @himitsu |
Re: Text (Pfadangabe) per Windows Message verschicken
Einfach so mit einem Pointer geht das nicht ... wie auch, da beide Programme ihren eigenen virtuellen Arbeitsspeicher haben.
Delphi-Quellcode:
mit GloablAlloc wird Speicher außerhalb deiner Anwendung reserviert
DataPtr := GlobalLock(wParam);
try s := PChar(DataPtr); // oder sonstwas finally GlobalUnlock(wParam); end; und mit GlobalLock wird dieser Speicher in den Adreßraum deiner Anwendung verschoben danach mit GlobalUnlock wieder aus dem Adreßraum deiner anwendung entfernt und nun kann sich die andere Anwendung diesen Speicher auch mal in ihren Adreßraum legen und diesen so auslesen. |
Re: Text (Pfadangabe) per Windows Message verschicken
Erstmal danke für deine Erklärung :thumb:
Hab das ganze nun erstmal wieder in eine Funktion gepackt, die es dann auslesen soll (sonnst seh ich bald gar nicht mehr durch^^)
Delphi-Quellcode:
function GetAllocFileName(wParam: WPARAM): PChar;
var DataPtr: Pointer; begin; Result := ''; DataPtr := GlobalLock(wParam); try Result := PChar(DataPtr); // oder sonstwas finally GlobalUnlock(wParam); end; end;
Delphi-Quellcode:
Aber ich bekomme schon wieder nur 3x Cryptisches Zeug angezeigt??
WM_TSOPLAYFILE:
begin; MSGFile := GetAllocFileName(wParam);//PChar(@wParam); MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING); if FileExists(MSGFile) then begin; PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0); if Succeeded(CheckFile(MSGFile)) then PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0) end; end; Das aber ne schwere Geburt mit mir und GlobalAlloc :lol: |
Re: Text (Pfadangabe) per Windows Message verschicken
Zitat:
und das hab ich hier mal ausgenutzt, damit die Speicher reservierung und Freigabe in einer Hand (Programm) bleibt.
Delphi-Quellcode:
da die Speicherverwaltung des Strings aber Delphi übernimmt und PChar intern für einen vorhandenen Speicher sorgt, kann eigentlich keine Exception entstehen (es sei den du hast irgendwo anders ein großes Problem)
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size);
If Data <> 0 Then Begin Try DataPtr := GlobalLock(Data); If DataPtr <> nil Then Begin Try CopyMemory(DataPtr, PChar(aText), Size); If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler}; Finally GlobalUnlock(Data); End; End Else {Fehler}; Finally GlobalFree(Data); End; End Else {Fehler};
Delphi-Quellcode:
und die andere Seite hatte ich ja schon geschrieben
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Length(aText) + 1);
If Data <> 0 Then Begin DataPtr := GlobalLock(Data); If DataPtr <> nil Then Begin CopyMemory(DataPtr, PChar(aText), Length(aText) + 1); If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler}; GlobalUnlock(Data); End Else {Fehler}; GlobalFree(Data); End Else {Fehler};
Delphi-Quellcode:
DataPtr := GlobalLock(wParam);
If DataPtr = nil Then Begin Try s := PChar(DataPtr); // oder sonstwas Finally GlobalUnlock(wParam); End; End Else {Fehler}; |
Re: Text (Pfadangabe) per Windows Message verschicken
Zitat:
Eine WindowMessage gilt als empfangen, wenn die WndProc des Empgängers verlassen wurde. Eine Verarbeitung im WndProc ist daher sehr bedenklich, da das andere Programm solange blockiert wird. Besser wäre die Variable im anderen Programm solange gültig zu halten bis eine "Verarbeitung-Beendet" Message zurück kommt. Zitat:
|
Re: Text (Pfadangabe) per Windows Message verschicken
Sorry, ist schon ne Weile her, hatte aber nicht viel Zeit :(
Aufjedenfall habe ich immer noch das Problem, das nichts ankommt, sieht vllt irgendjemand noch nen Fehler?? Ich bin schon tierisch am Verzweifeln :( und das verstehe ich auch nicht so:
Delphi-Quellcode:
Wieso soll der Ptr nil sein?? muss der nicht auf ne Addresse zeigen?
If DataPtr = nil Then Begin
Try s := PChar(DataPtr); // oder sonstwas Finally GlobalUnlock(wParam); End; |
Re: Text (Pfadangabe) per Windows Message verschicken
ups ... <> nil natürlich :oops:
im Fehlerfall liefert GlobalLock ein NIL zurück. |
Re: Text (Pfadangabe) per Windows Message verschicken
OK, aber wenn ich auf ungleichheit Prüfe kommt bei mir der Fehler, also ist GlobalLock fehlgeschlagen, aber wieso??
Meine Funktionen: Senden:
Delphi-Quellcode:
Empfangen:
procedure GlobalAllocFileName(aWnd: HWND; aText: String);
var Data: THandle; DataPtr: Pointer; Size: Integer; oldWND: HWND; begin { Size := Length(aText) + 1; Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size); try DataPtr := GlobalLock(Data); try CopyMemory(DataPtr, PChar(aText), Size); finally GlobalUnlock(Data); end; SendMessage(aWnd, WM_TSOPLAYFILE, data, 0); finally GlobalFree(Data); end; } Data := GlobalAlloc({GMEM_MOVEABLE or GMEM_DDESHARE}GHND, Length(aText) + 1); If Data <> 0 Then Begin DataPtr := GlobalLock(Data); If DataPtr <> nil Then Begin CopyMemory(DataPtr, PChar(aText), Length(aText) + 1); If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler} begin MessageBox(0, 'senden fehlgeschlagen', 'fehler', MB_OK or MB_ICONWARNING); GlobalUnlock(Data); end; End Else {Fehler} MessageBox(0, 'dataptr leer', 'fehler', MB_OK or MB_ICONWARNING); GlobalFree(Data); End Else {Fehler} MessageBox(0, 'data leer', 'fehler', MB_OK or MB_ICONWARNING); end;
Delphi-Quellcode:
function GetAllocFileName(wParam: WPARAM): PChar; //wparam ist nicht 0
var DataPtr: Pointer; begin; Result := ''; DataPtr := GlobalLock(wParam); //aber hier gibts nen "nil" ich vermute das hier irgendwo mein Fehler steckt If DataPtr <> nil Then Begin Try Result := PChar(DataPtr); // oder sonstwas MessageBox(0, 'get - pointer nil', 'fehler', MB_OK or MB_ICONWARNING); Finally GlobalUnlock(wParam); End; End Else {Fehler} MessageBox(0, 'get - dataptr leer', 'fehler', MB_OK or MB_ICONWARNING); end; Nachrichtenschleife vom Hauptprogramm:
Delphi-Quellcode:
initialization abschnitt von der Anwendung:
WM_TSOPLAYFILE:
begin; MSGFile := GetAllocFileName(wParam);//PChar(@wParam); MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING); if FileExists(MSGFile) then begin; PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0); if Succeeded(CheckFile(MSGFile)) then PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0) end; Result := 1; end;
Delphi-Quellcode:
initialization
begin; if paramcount > 0 then Param := paramstr(1); tMutex := CreateMutex(nil, True, ClassName); if GetLastError = ERROR_ALREADY_EXISTS then begin; if fileexists(Param) then begin; if (FindWindow(ClassName, AppName) > 0) then GlobalAllocFileName(FindWindow(ClassName, AppName), Param) // PostMessage(FindWindow(ClassName, AppName), WM_TSOPLAYFILE, INTEGER(@Param), 0) end else MessageBox(0, 'The Program is already running.', ClassName, MB_OK or MB_ICONWARNING); Halt; end; end; Sorry für nen bissel viel Code :) |
Re: Text (Pfadangabe) per Windows Message verschicken
Dein Problem derzeit ist, dass der Sender den Speicher noch immer gelockt hat. Du hast derzeit beim Sender folgenden Ablauf:
1. Speicher alloziieren 2. Speicher locken, Pointer holen 3. Speicher befüllen (Pointer beschreiben) 4. Nachricht versenden mit dem Handle von 1. 5. Speicher unlocken 6. Speicher freigeben. Wenn du an Stelle 4. bist, dann empfängt dieser das Handle von 1. und versucht nun ebenfalls mit GlocalLock ein exklusiven Lock zu bekommen, was ihm aber von Windows verwehrt wird, da das Handle derzeit von deinem Sender noch gelockt ist. Also, der korrekte Ablauf sollte anhand der Nummerierung von zuvor wie folgt sein: 1., 2., 3., 5., 4., 6. Also vorher unlocken, nur im ungelockten Zustand kann Windows den speicher virtuell zwischen den Prozessen verschieben. So lange einer den glockt hat, hat er den Finger drauf und Windows ist machtlos. |
Re: Text (Pfadangabe) per Windows Message verschicken
Ich bin echt mit meinem Latein am ende :(
Habs so gemacht wie du gesagt hast aber geht nicht :(
Delphi-Quellcode:
Erstmal danke für deine Hilfe, fällt dir noch was ein was falsch sein könnte?? *grummel*
function GetAllocFileName(wParam: WPARAM): PChar; //wparam ist nicht 0
var DataPtr: Pointer; begin; Result := ''; DataPtr := GlobalLock(wParam); //aber hier gibts nen "nil" ich vermute das hier irgendwo mein Fehler steckt // hier gibts laut getlasterror ein ungültiges handle :( If DataPtr <> nil Then Begin Try Result := PChar(DataPtr); // oder sonstwas MessageBox(0, 'get - pointer nil', 'fehler', MB_OK or MB_ICONWARNING); Finally GlobalUnlock(wParam); End; End Else {Fehler} MessageBox(0, 'get - dataptr leer', 'fehler', MB_OK or MB_ICONWARNING); end; mfg Caleb |
Re: Text (Pfadangabe) per Windows Message verschicken
Was spricht eigentlich gegen WM_COPYDATA? Warum der Umstand?
|
Re: Text (Pfadangabe) per Windows Message verschicken
@Luckie: Das habe ich mich auch gefragt. wm_copydata ist die einfachste Variante (da dabei automatisch dafür gesorgt wird das die Daten im anderen Prozess gelesen werden können). Aber weil das nicht auf Anhieb funktioniert hat, wird eine kompliziertere Lösung gesucht bei der letzendlich genau an der gleichen Stelle der Fehler zu beseitigen ist + das was wm_copydata für einen von allein macht.
Anstelle hier einen riesen Umweg zu gehen wäre es aus meiner sicht Ratsamer zu schauen was und warum wm_copydata angeblich nicht funktioniert. |
Re: Text (Pfadangabe) per Windows Message verschicken
Hallo,
das ist richtig, es ist die einfachste Lösung, und ja sie Funktioniert auch, aber ich möchte ganz gerne den anderen Weg geklärt haben ;) In späteren Programmen möchte ich dann auf diesen weg weiter arbeiten, und wenn ich den Fehler finde, sollte die Funktionen auch gehen! Bloß weil es im mom ein wenig schwierig ist (insbesondere weil ich nicht so rcht weiß wo der Fehler liegt) muss es Ihn aber geben, und ich währe halt zufrieden wenn ich diese Lösung benutzen könnte! Wenn alles nichts hilft, dann muss ich wohl auf WM_COPYDATA umsteigen, was ich aber eigentlich nicht vorgehabt habe, da ich dort KEINE eigene Messages nutzen kann. |
Re: Text (Pfadangabe) per Windows Message verschicken
Eigene nachrichten brauchst du doch aich nicht. Die Datenstruktur für WM_COPYDATA bietet dir ein frei verwendbares Integer-Feld. Dieses kannst du nutzen, um die enthaltenen daten zu unterscheiden:
http://msdn.microsoft.com/en-us/library/ms649010(VS.85).aspx -> dwData Specifies data to be passed to the receiving application.
Delphi-Quellcode:
case dwData of
0: ; // mach dies mit den Daten 1: ; // mach jenes mit den Daten end; |
Re: Text (Pfadangabe) per Windows Message verschicken
Hallo, ich habe iene möglichkeit gefunden wie ich es mit WM_COPYDATA machen kann, aber wie oben beschrieben war das nicht mein Hauptziel! Sondern es mit eigenen Messages hinzubekommen! Trotzdem danke :thumb:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz