13. juni 2003 - 09:04Der er
4 kommentarer og 1 løsning
Send en msg til anden instance af samme application.
Det skulle vel sige det hele meeen: Programmet skal sende en msg til alle instance af sig selv, undtagen sig selv. Messagen skal fx være en integer. Hvordan gør man det ?
Check RegisterWindowMessage() og PostMessage med HWND_BROADCAST. De holder, hvis du kun vil bruge integers (evt. to). Du er sæføli' nødt til selv at holde styr hvem der har sendt.
Hvis du vil sende større data, ville Shared Memory ovenpå ovenstående teknik være en mulig vej. Check CreateFileMapping()-familien.
procedure TfrmMain.WMclose(var Message: TMessage); begin info('i wm close'); if not FinMutex then close; end;
procedure TfrmMain.WndProc(var Message: TMessage); begin if Message.Msg <> FCustMsg then inherited else begin info('i wnd proc FcustMsg'); PostMessage(HWND_BROADCAST ,FcustMsg, Message.LParam, 0); Message.Result:= 0; end; end;
Jeg sender på følgende måde:
procedure TfrmMain.FormCreate(sender: tobject);
procedure testMutex; begin FCustMsg:= RegisterWindowMessage(MUTEX_NAME); FMutex:= CreateMutex(nil, false, MUTEX_NAME); FFirstMutex:= (GetLastError = 0); if not FFirstMutex then begin info('sender luk'); PostMessage(HWND_BROADCAST, FcustMsg, WM_close,0); //sender luk til alle end; end;
begin FinMutex:=true; testMutex; FinMutex:=false; ... end;
Jeg forstår ikke hvorfor man skal have wndproc'en (stjålet fra andet prog), og desuden kommer den aldrig til info'en i wndproc'en, så msg'en kommer vel aldrig ud af programmet ? Kan du se hvad jeg gør galt, ellers må du give en lidt mere komplet løsning. --nop
1) WM_CLOSE redefineres til LB_GETSELITEMS(!). Hvorfor nu det? Hvis du bare inkluderer "messages.pas" i din uses er du home free.
2) Du skal bruge wndproc fordi du benytter en på runtime bestemt message (din FCustMsg). Compileren kan ikke mappe disse med de sædvanlige "message"-direktiver.
3) Du bruger samme navn til RegisterWindowMessage() og CreateMutex() - jeg er ikke klar over hvorvidt det er sundt eller ej (jeg ville aldrig gøre det).
4) I følgende kode: FMutex:= CreateMutex(nil, false, MUTEX_NAME); FFirstMutex:= (GetLastError = 0); if not FFirstMutex then begin info('sender luk'); PostMessage(HWND_BROADCAST, FcustMsg, WM_close,0); //sender luk til alle end;
mangler du et check på om FFirstMutex er oprettet korrekt (CreateMutex returnere != NULL).
Men det alt overskyggende problem er følgende fælde: PostMessage sammen med HWND_BROADCAST fungerer kun med top-level vinduer. Delphi forms har TApplication som owner, hvorfor de ikke er top-level.
Mulige løsninger er, at bruge SendMessage i stedet (ikke videre kønt), at fjerne TApplication som owner, eller på forhånd at finde ud af hvem du skal post'e til (f.eks. med EnumWindows()-familien) og så poste til dem en ad gangen.
1: Hvad mener du ? 2: ok, mapping ! 3: Nej ok, men måske er det i to forskellige context'te, men vælger bare et andet navn. 4: Jeg bruger vel getLastError til netop at teste om oprettet, fordi der kun kan oprettes én mutex med et givent navn, det må være rigtigt det jeg har lavet.
Jeg synes at din enumwindows lyder som om at jeg kan bruge den, jeg kender jo navnet på windows'ene og når jeg så looper alle de fundene igennem kan jeg teste om handlet er det samme som application.handle og dermed undlade at sende til denne instance (mySelf !). Du får pointene måske gider du alligevel svare på nr 1 ? Tak for hjælpen men en dag vil jeg altså have check på msg'es. --nop
Du definere WM_CLOSE = 401 i toppen. WM_CLOSE er allerede defineret til dens korrekt værdi (16) i messages.pas.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.