11. juli 2008 - 11:38Der er
3 kommentarer og 1 løsning
Window subclass og min egen WinProc fejler
Hejsa, Jeg eksperimenterer med at subclasse et TMemo i min egen applikation for at kunne filtrere på de messages der bliver sendt til det enkelte vindue. Jeg har følgende kode, meget simpelt:
procedure SendText(themessage: string); var remoteWindow: HWND; cds: COPYDATASTRUCT; begin remoteWindow := FindWindow(nil, 'Grapper'); if remoteWindow <> 0 then begin ZeroMemory(@cds, sizeof(COPYDATASTRUCT)); cds.dwData := 0; cds.cbData := 1 + Length(themessage); cds.lpData := PChar(themessage); SendMessage(remoteWindow, WM_COPYDATA, WPARAM(remoteWindow), LPARAM(@cds)); end; end;
procedure TForm1.Button1Click(Sender: TObject); begin // SendText('This is the text sendt'); SubClassWin(GrapperSourceWindow.Handle); end;
function NewWinProc(hWnd: HWND; Msg: WORD; wParam: WORD; lParam: LONGINT): LONGINT; var messageProcessed: boolean; begin messageProcessed := false; if Msg = WM_SETTEXT then begin SendText('called set text'); messagePRocessed := true; end;
if not MessageProcessed then Result := CallWindowProc(Pointer(OldWinProc), hWnd,Msg,wParam,lParam) else Result := 0;
end;
procedure TForm1.SubClassWin(hWnd: HWND); begin OldWinProc := SetWindowLong(hWnd, GWL_WNDPROC, LongInt(@NewWinProc)); end;
procedure TForm1.UnSubClassWin(hWnd: HWND); begin SetWindowLong(hWnd,GWL_WNDPROC,OldWinProc); end;
procedure TForm1.Button2Click(Sender: TObject); begin GrapperSourceWindow.Text := GrapperSourceWindow.Text+'ABC.'; end;
end.
Problemet opstår når den løber min egen WinProc igennem (NewWinProc) det ser ud til den får lov at løbe et par gange og så går den ned. Jeg klikker på min knap, og hvis jeg flytter musen ind på mit memo kommer den ind i min egen winproc og laver en exception og stiller sig i cpu vinduet.. jeg aner ikke hvad jeg skal gøre... Arbejder normalt med C# :-)
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
ved første øjekast, kan jeg se at du har valgt at bruge en fordefineret type både som variable navn og type (hWnd og HWND ), Delphi er ikke Case-Sensitive som C++ er (mener også C skarp er men skal ikke gøre mig klog på) :)
Det kan godt være at Psykosoft har fat i noget her. Jeg plæderer altid for at foranstille parametre med et "a" således, at din UnSubClass får parametrene (aHWND: HWND).
Eksempelvis sådan her:
function NewWinProc(aHWND: HWND; aMsg: WORD; aWParam: WORD; aLParam: LONGINT): LONGINT; begin if aMsg = WM_SETTEXT then begin SendText('called set text'); Result := 0; end else Result := CallWindowProc(Pointer(OldWinProc), aHWND,aMsg,aWParam,aLParam) end;
I øvrigt kan du prøve at benytte dig af OutputDebugString til at pumpe debugmeddelelser ud.
På samme måde plejer man i Delphi at sætte et "f" foran de private attributter. En af de her De-facto standarder.
I øvrigt er C# et brain child af Anders Hejlsberg ... som fostrede Compas-/Poly-/Turbo-Pascal og i sidste ende Delphi. Da AH. rejste til MS fik han nok chancen for bygge det bedste med over. Savner en garbage collector selvom den sikkert er en ydelsesdræber (æv, nu døde Dennis Hopper og Peter Fonda igen).
Prøvede det, men uden held. Kan godt se at det ville give problemer, man skal lige vænne sig til at skifte til et nyt miljø :-)
Jeg prøvede at køre igen, men det ser ud til at den stopper i min nye WinProc (NewWinProc) den looper den igennem et par gange og så stopper den på den sidste "end" i min funktion (i stedet for at returnere) så venter den bare i et par sekunder og laver så en fejl om at den ikke kan læse instruktionen i blablabla 0x000000 Det ser ud til at den har kørt rekursivt og laver nu backtracking og har tabt en reference??? nogle gode ideer?
Fik det til at virke, ved ikke helt hvorfor ændringen virker bedre... (gå fra function til procedure). Til alle der forsøger i fremtiden, dette virker:
procedure TForm1.UnSubClassWin(aHWND: HWND); begin SetWindowLong(aHWND,GWL_WNDPROC,OldWinProc); end;
procedure TForm1.Button2Click(Sender: TObject); begin GrapperSourceWindow.Text := GrapperSourceWindow.Text+'ABC.'; end;
procedure TForm1.NewWinProc(var aMsg: TMessage); begin case aMsg.msg of WM_SIZE: begin SendText('Resize the memo'); end; end; //all unhandled messages are sent to original procedure. Here, //hproc is the handle to the original window procedure. aMsg.result := CallWindowProc(hproc, sourceWindow, aMsg.msg, aMsg.wparam, aMsg.lparam);
end;
end.
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.