Delphi-PRAXiS
Seite 1 von 3  1 23   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Menu Ownerdraw (https://www.delphipraxis.net/199974-menu-ownerdraw.html)

EWeiss 7. Mär 2019 09:23

Menu Ownerdraw
 
Kann mir jemand sagen wie ich das Menu ändern kann? bzw. wie ich da dran komme.
Die einzige Message die ich ermitteln kann ist WM_PRINTCLIENT.

Nur was hat diese mit dem Menu zu tun.
Habe leider keine Mail um Rodrigo Ruz mal zu kontaktieren

gruss

TiGü 7. Mär 2019 10:49

AW: Menu Ownerdraw
 
Wenn man sich den Dialog mithilfe des Tools Window Detective anschaut, dann erkennt man beim Aufklappen des Ansichtsbuttons, dass dynamisch zwei Sachen erzeugt werden (unter Windows 10 1809):
Einmal
Delphi-Quellcode:
#32768 (Menu)
und
Delphi-Quellcode:
SysShadow
. Letzteres stellt den Schatten am rechten und unteren Rand dar.
Ersteres ist wiederum interessant, weil es das Menü ist, wonach du suchst.

Wenn wir in den Quelltexten der VCL.Styles.Utils suchen, finden wir in Vcl.Styles.Utils.Menus.pas die Anmeldung des StyleHooks für dieses Menü.
https://github.com/RRUZ/vcl-styles-u...tils.Menus.pas

Am Ende der Unit unter initialization befindet sich:
Delphi-Quellcode:
TSysStyleManager.RegisterSysStyleHook('#32768', TSysPopupStyleHook);


In den folgenden Methoden der Hook-Klasse befinden sich wahrscheinlich die Dinge, die du wissen möchtest:
Delphi-Quellcode:
procedure MNSELECTITEM(var Message: TMessage); message MN_SELECTITEM;
procedure WMPRINT(var Message: TMessage); message WM_PRINT;
procedure WndProc(var Message: TMessage); override;
Die Definitionen für die von Microsoft undokumentierten Messages befinden sich als Konstanten ganz oben in der Unit.

EWeiss 7. Mär 2019 10:57

AW: Menu Ownerdraw
 
Zitat:

In den folgenden Methoden der Hook-Klasse befinden sich wahrscheinlich die Dinge, die du wissen möchtest:
Danke für das heraussuchen.. Habe selber leider den richtigen Punkt nicht gefunden. :duck:
Werde es damit mal versuchen und melde mich dann wieder hoffentlich mit einer Erfolgsmeldung. :)

gruss

TiGü 7. Mär 2019 11:23

AW: Menu Ownerdraw
 
Was genau willst du denn wissen?

EWeiss 7. Mär 2019 11:37

AW: Menu Ownerdraw
 
Zitat:

Zitat von TiGü (Beitrag 1427181)
Was genau willst du denn wissen?

Ich möchte das Menu Ownerdrawn damit es so aussieht wie mein Window also der Hintergrund..
Ich Subclass im Moment meine Toolbar auf diesem weg.

Delphi-Quellcode:
{$REGION 'procedure ToolBarSubClass'}

procedure ToolBarSubClass(WinHandle: HWND);
begin

  FToolBarInstance := MakeObjectInstance(OpenDialog.ToolBarSubClassProc);

  FPrevToolBarProc := Pointer(GetWindowLongPtr(WinHandle, GWL_WNDPROC));
  SetWindowLongPtr(WinHandle, GWL_WNDPROC, LPARAM(FToolBarInstance));
end;
{$ENDREGION}
{$REGION 'procedure ToolBarUnSubClass'}

procedure ToolBarUnSubClass(WinHandle: HWND);
begin

  SetWindowLongPtr(WinHandle, GWL_WNDPROC, LPARAM(FPrevToolBarProc));
  FreeObjectInstance(FToolBarInstance);
end;
{$ENDREGION}
{$REGION 'procedure ToolBarSubClassProc'}

procedure TSkinOpenSaveDialog.ToolBarSubClassProc(var Message: TMessage);
begin

  with Message do
  begin
    case Msg of
      WM_DESTROY:
        Result := ToolBarProc(hToolbar, LRESULT(Msg), Message.WPARAM, Message.LPARAM);
      WM_PAINT:
        Result := ToolBarProc(hToolbar, LRESULT(Msg), Message.WPARAM, Message.LPARAM);
      WM_PRINTCLIENT:
        Result := ToolBarProc(hToolbar, LRESULT(Msg), Message.WPARAM, Message.LPARAM);      
      WM_ERASEBKGND:
        Result := ToolBarProc(hToolbar, LRESULT(Msg), Message.WPARAM, Message.LPARAM);
    end;
    if (Result = 0) then
      Result := CallWindowProc(FPrevToolBarProc, hToolbar, Msg, WPARAM, LPARAM)

  end;
end;
{$ENDREGION}
{$REGION 'function ToolBarProc'}

function ToolBarProc(WinHandle: HWND; Msg: UINT; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;
var
  hDCTemp: HDC;
  rc, rw: TRect;
  ps: TPaintStruct;
  lpt: TPoint;
  DC: HDC;
  hDCBack: HDC;

begin
  Result := 0;

  case Msg of

    WM_ERASEBKGND:
      begin
        RedrawWindow(WinHandle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
        Result := 1;
        Exit;
      end;

    WM_PAINT, WM_PRINTCLIENT:
      begin
        GetClientRect(WinHandle, rc);

        if (wp = 0) then
        begin
          BeginPaint(WinHandle, ps);
          DC := ps.HDC;
        end
        else
          DC := wp;

        // Double Buffer erstellen
        hDCTemp := SkinEngine.DoubleBuffer(DC, rc.Right, rc.Bottom, CreateBuffer);

        // Dimensionen der ToolBar auslesen
        GetWindowRect(WinHandle, rw);
        lpt.x := rw.Left;
        lpt.y := rw.Top;
        ScreenToClient(SKDialogHandle, lpt);

        // Hintergrund Kopieren
        hDCBack := CreateCompatibleDC(hDCTemp);
        SelectObject(hDCBack, SkinEngine.GetBackBitmap(SKDialogHandle));
        // Toolbar Hintergrund mit dem Parent Hintergrund füllen
        BitBlt(hDCTemp, 0, 0, rc.Right, rc.Bottom, hDCBack, lpt.x, lpt.y, SRCCOPY);
        // Resourcen freigeben
        DeleteDC(hDCBack);
        // Double Buffer freigeben
        SkinEngine.DoubleBuffer(0, 0, 0, DestroyBuffer);
        DeleteDC(hDCTemp);

        if (wp = 0) then
          EndPaint(WinHandle, ps);

        Result := 0;
        Exit;
      end;

    WM_DESTROY:
      begin
        ToolBarUnSubClass(WinHandle);
        Result := 1;
        Exit;
      end;

  end;
  if (Result = 0) then
    Result := CallWindowProc(FPrevToolBarProc, WinHandle, Msg, wp, lp);
end;
{$ENDREGION}
Was ich jetzt wissen muss wann bekomme ich das Window Handle um das Menu zu subclassen das ist ja erst bei WM_LBUTTONDOWN bzw. UP sichtbar.
Vorher kann ich das Handle nicht erreichen.

Etwas kompliziert. (Umständlich)
Das zeichnen selbst ist das kleinste Problem sobald ich das Handle habe.

PS:
Überlege noch ob ich diese Subclass verwenden kann oder für das Menu eine neue erstellen muss.
Muss es testen. ;)

gruss

TiGü 7. Mär 2019 12:14

AW: Menu Ownerdraw
 
Guck dir mal GetMenuFromHandle an und die Stellen wo es verwendet wird.

EWeiss 7. Mär 2019 12:36

AW: Menu Ownerdraw
 
Zitat:

Zitat von TiGü (Beitrag 1427192)
Guck dir mal GetMenuFromHandle an und die Stellen wo es verwendet wird.

Danke.. Ist etwas komplizierter muss mich da durchbeißen.

Delphi-Quellcode:
    WM_PAINT, WM_PRINTCLIENT:
      begin
        HToolBarMenu := HMENU(SendMessage(GetParent(WinHandle), MN_GETHMENU, 0, 0));
        if HToolBarMenu <> 0 then
            ToolBarSubClass(hToolbarMenu);
Innerhalb der ToolbarProc.
Handle ist immer 0.

GetParent(WinHandle) und nur WinHandle immer 0.
Kann ich mit den VCL Styles nicht vergleichen. Hmmm...

gruss

EWeiss 7. Mär 2019 13:27

AW: Menu Ownerdraw
 
Messagen die ich bekomme und das Menu siehe im Anhang.. hat bei den VCL Styles nichts mit einem Popupmenu zu tun.
Deshalb scheint MN_GETHMENU nicht das richtige zu sein.

gruss

TiGü 7. Mär 2019 13:28

AW: Menu Ownerdraw
 
Wo kommt denn der Wert für hToolbar in procedure TSkinOpenSaveDialog.ToolBarSubClassProc(var Message: TMessage); her?

EWeiss 7. Mär 2019 13:32

AW: Menu Ownerdraw
 
Zitat:

Zitat von TiGü (Beitrag 1427201)
Wo kommt denn der Wert für hToolbar in procedure TSkinOpenSaveDialog.ToolBarSubClassProc(var Message: TMessage); her?

Delphi-Quellcode:
  hToolbar := FindWindowEx(hMain, 0, 'ToolBarWindow32', nil);
  GetWindowRect(hToolbar, rc);
  lpt.x := rc.Left;
  lpt.y := rc.Top;
  ScreenToClient(hMain, lpt);

  MoveWindow(hToolbar, lpt.x, lpt.y, (rc.Right - rc.Left) + 3, rc.Bottom - rc.Top, false);

  ExStyle := GetWindowLongPtr(hToolbar, GWL_EXSTYLE);
  ExStyle := ExStyle or WS_EX_TRANSPARENT;
  SetWindowLongPtr(hToolbar, GWL_EXSTYLE, ExStyle);
  ToolBarSubClass(hToolbar);
hMain = Handle der Class #32700 Dialog Box

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 Uhr.
Seite 1 von 3  1 23   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz