Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Paint-Messages abfangen (https://www.delphipraxis.net/53940-paint-messages-abfangen.html)

n0b0dy 25. Sep 2005 23:08


Paint-Messages abfangen
 
hi ihr alle ;),

hab mal ne frage:
undzwar wie kann ich die paint-messages von dialogen abfangen? (weiß nicht ob ich das so richtig ausgedrück habe^^)
also ich will eigentlich das design von zB einem OpenDialog verändern....

deshalb müsste ich irgendwie an diese "drankommen". müsste irgendwie auf die form der dialoge zugreifen können. hat jemand ne idee wie ich das anstellen kann? :gruebel:


MfG

Olli 25. Sep 2005 23:55

Re: Paint-Messages abfangen
 
Ja man kann diese Nachrichten abfangen aber die GDI ist nicht multithreadfähig.

Man kann aber mit einem MSDN-Library durchsuchenOFNHookProc, anzugeben in der MSDN-Library durchsuchenOPENFILENAME-Struktur, die gewünschte Funktionalität erreichen!

n0b0dy 26. Sep 2005 00:11

Re: Paint-Messages abfangen
 
hm,
hört sich sehr kompliziert an :?

irgendwie finde ich nicht so recht nen ansatz. kann mir jemand dabei helfen?
also sagen wir einfach mal ich möchte die farbe von einem OpenDialog ändern. Wie mache ich das dann? :gruebel:


MfG

tigerman33 26. Sep 2005 08:27

Re: Paint-Messages abfangen
 
Du nimmst das Handle vom Dialog und schickst an dieses eine entsprechende Nachricht. Welche das ist weiß ich jetzt aus dem Kopf nicht, aber das sollte sich ja innerhalb von 10 Minuten in der OH finden lassen.

Olli 26. Sep 2005 08:45

Re: Paint-Messages abfangen
 
Gut gemeint, aber leider Quatsch. Man schickt dem Dialog zu diesem Behufe keine Nachricht, sondern man verarbeitet eine bestimmte Nachricht. Ich versuche nachher schnell was hinzuhacken.

Olli 26. Sep 2005 10:37

Re: Paint-Messages abfangen
 
Delphi-Quellcode:
function OFNHookProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): UINT; stdcall;
var
  col: COLORREF;
  brush: HBRUSH;
begin
  Writeln('OFNHookProc');
  brush := GetProp(Wnd, 'brush');
  case Msg of
  WM_CTLCOLORDLG:
  begin
    Writeln('WM_CTLCOLORDLG');
    col := RGB($ff, 0, 0);
    SetBkColor(wParam, col);
    SetBkMode(wParam, TRANSPARENT);
    if(brush <> 0)then
      DeleteObject(brush);
    brush := CreateSolidBrush(col);
    SetProp(Wnd, 'brush', brush);
    Result := brush;
  end;
  WM_CLOSE:
  begin
    if(brush <> 0) then
      DeleteObject(brush);
  end;
  else
    Result := ord(False);
  end;
end;

var
  ofn: tagOFNA;
  Buffer: array[0..MAX_PATH] of Char;
begin
  AllocConsole();
  ZeroMemory(@ofn, sizeof(ofn));
  ofn.lStructSize := sizeof(ofn);
  ofn.hWndOwner := GetDesktopWindow();
  ofn.hInstance := hInstance;
  ofn.lpstrFilter := 'Textfiles'#0'*.txt'#0'Rich Text Documents'#0'*.rtf'#0#0;
  ofn.lpstrFile := @Buffer;
  ofn.nMaxFile := sizeof(Buffer) div sizeof(Char);
  ofn.Flags := OFN_ENABLEHOOK or OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST;
  ofn.lpfnHook := @OFNHookProc;
  GetOpenFileName(ofn);
end.

n0b0dy 26. Sep 2005 10:57

Re: Paint-Messages abfangen
 
hui, also danke erstmal, aber kann damit leider nichts anfangen :(

was ist denn "tagOFNA;"? kann mit der OH die zugehörige unit nicht finden :roll:

Sprint 26. Sep 2005 11:05

Re: Paint-Messages abfangen
 
Zitat:

Zitat von n0b0dy
undzwar wie kann ich die paint-messages von dialogen abfangen? (weiß nicht ob ich das so richtig ausgedrück habe^^)
also ich will eigentlich das design von zB einem OpenDialog verändern....

Wenn du unbedingt mit der Klasse TOpenDialog weiter arbeiten willst, dann kannst du das per Subclassing machen.

Delphi-Quellcode:
var
  OldWndProc: TFNWndProc;
  NewWndProc: TFNWndProc;
  ParentHWnd: HWND;

// -------------------------------------------------------------------------------------------------

function ParentOpenDialogWndProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM)
  : LRESULT; stdcall;
begin

  if uMsg = WM_PAINT then
  begin
    // Hier dein Source Code
  end;

  CallWindowProc(OldWndProc, hWnd, uMsg, wParam, lParam);

end;

// -------------------------------------------------------------------------------------------------

procedure TForm1.OpenDialog1Show(Sender: TObject);
begin

  NewWndProc := @ParentOpenDialogWndProc;
  ParentHWnd := GetParent(OpenDialog1.Handle);
  OldWndProc := TFNWndProc(SetWindowLong(ParentHWnd, GWL_WNDPROC, Longint(NewWndProc)));

end;

// -------------------------------------------------------------------------------------------------

procedure TForm1.OpenDialog1Close(Sender: TObject);
begin

  SetWindowLong(ParentHWnd, GWL_WNDPROC, Longint(OldWndProc));

end;

// -------------------------------------------------------------------------------------------------

Olli 26. Sep 2005 11:35

Re: Paint-Messages abfangen
 
Zitat:

Zitat von n0b0dy
hui, also danke erstmal, aber kann damit leider nichts anfangen :(

CommDlg.pas eingebunden?

Das von mir gepostete Ding ist fast komplett. Da fehlt lediglich der Anfang (program Bla; uses Windows, Messages, CommDlg;).

teebee 26. Sep 2005 13:21

Re: Paint-Messages abfangen
 
Das ganze ist ja schön und gut, hat aber einen kleinen Haken: Wenn man den Dialog im Explorer-Style haben möchte, kommt in der Hook-Procedure kein WM_CTLCOLORDLG an. Windows erzeugt dann nämlich den neuen Dialog als Child eines unsichtbaren Standard-Dialogs und die DialogProcedure des Standard-Dialogs bekommt die Nachricht. Man muss also irgendwie in die DialogProc des unsichtbaren Parents der neuen DialogBox gelangen, was nur auf sehr schmutzige Art geht:
Delphi-Quellcode:
// Hier merken wir uns die Adresse der alten DialogProc des Parents unseres Dialogs
Var oldDlgProc: Pointer;

// Diese DialogProc bearbeitet WM_CTLCOLORDLG
Function DialogProc(hdlg: HWND; uiMsg: UINT; wParam: WPARAM; lParam:LPARAM): UINT; stdcall;
Begin
 case uiMsg of
  WM_CTLCOLORDLG:
   Result := GetStockObject(WHITE_BRUSH); // zu Demozwecken
 else
  Result := CallWindowProc(oldDlgProc,hdlg,uiMsg,wParam,lParam);
 end;
End;

// Das ist unsere eigentliche Hook-DialogProcedure
Function OpenFileNameHook(hdlg: HWND; uiMsg: UINT; wParam: WPARAM; lParam:LPARAM): UINT; stdcall;
Var ofnParent: Integer;
Begin
 Result := 0;
 Case uiMsg of
  WM_NOTIFY: Begin
              Result := 0;
              If ((POFNOTIFY(lparam)^.hdr.code)=CDN_INITDONE) then Begin
               // wir merken uns den Parent
               ofnParent := GetParent(hdlg);
               // und holen uns die Adresse der ParentDialogProc
               oldDlgProc := Pointer(GetWindowLong(ofnparent,DWL_DLGPROC));
               // und setzen die ParentDialogProc auf die obere Proc
               SetWindowLong(ofnParent,DWL_DLGPROC,Integer(@DialogProc));
               Result := 1;
              End;
             End;
 End;
End;

procedure TForm1.Button1Click(Sender: TObject);
Var ofn: TOpenFileName;
begin
 // rudimentäres Befüllen der Struktur zu Demozwecken
 ZeroMemory(@ofn,sizeof(ofn));
 ofn.lStructSize := sizeof(ofn);
 ofn.lpstrInitialDir := 'C:\';
 ofn.Flags := OFN_ENABLEHOOK or OFN_EXPLORER; // wir wollen den Explorer-Style
 ofn.lpfnHook := @OpenFileNameHook;
 GetOpenFileName(ofn);
end;
Zugegeben, sieht schmutzig aus, aber geht...

Gruß, teebee

Olli 26. Sep 2005 13:41

Re: Paint-Messages abfangen
 
Stimmt. Hatte ich leider nicht getestet :stupid: :oops:

n0b0dy 26. Sep 2005 15:14

Re: Paint-Messages abfangen
 
hm also irgendwie weiß ich net so recht....das will alles nicht so.
bei den ersten beiden lösungen seh ich neben der form immmer eine leere eingabeaufforderung.

und die von teebee reagiert irgendwie garnicht so recht.
weiß net was ich falsch mache :gruebel:

ursprünglich dachte ich auch an sowas wie TForm. also dass ich über die klasse TForm irgendwie den Dialog ändern kann wie ich will..
nur wenn das so kompliziert ist, muss ich das wohl leider sein lassen :?

gibts da ncihts einfacheres?

das mit der farbe ändern war ja nur ein beispiel. das ist eins von vielen sachen die ich vor hatte. ich wollte dann zB das Editfeld usw durch andere komponenten ersetzen oder so. schriftart ändern uswusw...


geht das überhaupt? :gruebel:

Sprint 26. Sep 2005 15:33

Re: Paint-Messages abfangen
 
Zitat:

Zitat von n0b0dy
geht das überhaupt?

Macht es da nicht Sinn, dir einen eigenen Dialog zu programmieren? z.B. mit den ShellCtrls

n0b0dy 26. Sep 2005 15:39

Re: Paint-Messages abfangen
 
hab ich mir schon überlegt, aber wie zB mache ich rechts die graue spalte wo Desktop, Eigene Dateien, usw drinne steht?

aber eigetnlich soll der alles können, was der von windows auch kann... ist das net zu umständlich sowas selber zu machen?

Olli 26. Sep 2005 17:10

Re: Paint-Messages abfangen
 
Zitat:

Zitat von n0b0dy
hm also irgendwie weiß ich net so recht....das will alles nicht so.
bei den ersten beiden lösungen seh ich neben der form immmer eine leere eingabeaufforderung.

Autsch :wall: ... also doch die Sorte, die alles vorgekaut haben muß :-?

Dann lösche AllocConsole() und es ist weg ... keine Eingabeaufforderung mehr, toll?! :roll:

Zitat:

Zitat von n0b0dy
geht das überhaupt? :gruebel:

Ja, sowohl mit Sprints als auch meiner Lösung sollte das gehen. Ich verstehe nur nicht, wieso Sprint die Klasse nicht wenigstens OOP-like ableitet :stupid: :mrgreen:

n0b0dy 26. Sep 2005 17:16

Re: Paint-Messages abfangen
 
ja schön dass nun keine eingabeaufforderung mehr da ist :D aber funzt trotzdem net.
aber is jetzt egal. dann bau ich mir halt eben selbst einen und poste ihn danach mal hier. könnt mir ja dann sagen, ob man das auch mit euren methoden hätte machen können^^

;)

trotzdem nochmal danke!


MfG

Olli 26. Sep 2005 17:26

Re: Paint-Messages abfangen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von n0b0dy
ja schön dass nun keine eingabeaufforderung mehr da ist :D aber funzt trotzdem net.

Scherzbold. Im Anhang findest du den Code bereinigt um AllocConsole() und Writeln()!

Soviel zu "aber funzt trotzdem net" ...

teebee 26. Sep 2005 17:27

Re: Paint-Messages abfangen
 
:gruebel: Ich weiss nicht so recht, wo das Problem ist. Meine Lösung kannst Du einfach in ein Projekt pasten, Formular mit einem Button, OnClick-Event verbinden, fertig. Dann kannst Du von da aus schrittweise Erweiterungen vornehmen. Wie Olli schon gesagt hat, nicht vergessen, CommDlg einzubinden.

Gruß, teebee

n0b0dy 26. Sep 2005 17:31

Re: Paint-Messages abfangen
 
Liste der Anhänge anzeigen (Anzahl: 1)
okay...das wundert mich nun echt. hab das genauso wies im anhang is geht aber net, wenn ichs neu kompiliere... :(

im übringen möchte ich einen "neuen" (oder wie auch immer man das ausdrücken will ;)) OpenDialog. Dieser hier ist mir in einem etwas zu alten Style. Geht das auch?

teebee 26. Sep 2005 17:38

Re: Paint-Messages abfangen
 
Der 'neue' Style heisst Explorer-Style, siehe mein erstes Posting.

Gruß, teebee

n0b0dy 26. Sep 2005 17:40

Re: Paint-Messages abfangen
 
Ah okay. dann probier ichs nochmal so. :)

war mir nicht bewusst, dass das der Explorer Style is :roll:

Olli 26. Sep 2005 17:47

Re: Paint-Messages abfangen
 
Zitat:

Zitat von n0b0dy
okay...das wundert mich nun echt. hab das genauso wies im anhang is geht aber net, wenn ichs neu kompiliere... :(

Du verwendest bei dir den Explorer-Stil. Etwas was oben schon Erwähnung fand.

EDIT: Übrigens kann es noch Probleme beim Setzen der Struktirgröße geben - NT 4.0 erwartet da eine bestimmte, wobei sizeof() dann nicht mehr funzt.

teebee 27. Sep 2005 13:26

Re: Paint-Messages abfangen
 
Habe gerade festgestellt, dass mein Beispiel ab einschl. Delphi 6 nicht problemlos funktioniert. Ab da wird nämlich eine OPENFILENAME-Strukur verwendet, die zusätzliche Felder beinhaltet (für Windows 2000 aufwärts), u. a. ein Flag zum Ein- und Ausschalten der Places-Bar. Setzt man jetzt die Strukturgröße mit
Delphi-Quellcode:
ofn.lStructSize := sizeof(ofn);
erkennt Windows, dass man die neue Struktur verwendet und wertet dieses Flag aus, allerdings muss man dann auch unbedingt
Delphi-Quellcode:
ofn.nMaxFile := MAX_PATH; // Länge des Filename-Buffers
setzen, damit der Dialog überhaupt erzeugt wird.

Setzt man die Strukturgröße auf
Delphi-Quellcode:
ofn.lStructSize := OPENFILENAME_SIZE_VERSION_400; // die Konstante hat den Wert 76
ist Windows nicht so empfindlich und der Dialog wird auch bei nMaxFile := 0 erzeugt, aber es gibt eben auch keine Places-Bar.

Gruß, teebee

Olli 27. Sep 2005 15:37

Re: Paint-Messages abfangen
 
Zitat:

Zitat von teebee
Setzt man die Strukturgröße auf
Delphi-Quellcode:
ofn.lStructSize := OPENFILENAME_SIZE_VERSION_400; // die Konstante hat den Wert 76
ist Windows nicht so empfindlich und der Dialog wird auch bei nMaxFile := 0 erzeugt, aber es gibt eben auch keine Places-Bar.

Exakt das meinte ich. Man kann seinen Code ja so flexibel gestalten, daß er auf verschiedenen OS-Versionen läuft ;)

teebee 27. Sep 2005 16:13

Re: Paint-Messages abfangen
 
Zitat:

Zitat von Olli
Man kann seinen Code ja so flexibel gestalten, daß er auf verschiedenen OS-Versionen läuft ;)

Naja, ich habe schon ziemlich ungläubig geschaut, als derselbe Source, der mit D5 problemlos funktionierte, mit D6 auf dem selben OS nicht mehr lief...


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:53 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