Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen (https://www.delphipraxis.net/196205-menuitem-neu-zeichnen-ohne-ganzes-menue-neu-zu-zeichnen.html)

StephanR 1. Mai 2018 11:51

MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Hallo DPler,

in meinem aktuellen Projekt muss ich während ein PopUpMenü bereits geöffnet ist und dargestellt wird den Caption mehrerer MenuItems ändern.
Die Änderung selbst ist weiters unproblematisch, allerdings löst das Ändern der Caption das Kommando MenuChanged(true) aus, welches dann das
ganze Menü neuzeichnet. Dabei wird aber bei jeder Änderung das PopUp geschlossen und neu geöffnet, was ganz nervig "flackert".
Ich habe daraufhin eine Childklasse erstellt (ThackedMenuItem) und darin die SetCaption-Funktion so überschrieben, dass ich MenuChanged blockieren kann.

Leider habe ich bislang keinen Weg gefunden, trotzdem das Neuzeichnen des jeweiligen MenuItem auszulösen (und nur dieses). Erst wenn der Nutzer mit der Maus darüberfährt wird über das Hover-Ereignis der Menüeintrag neu gezeichnet.

Gibt es irgend einen anderen Weg, das Neuzeichnen auch ohne Mausereignis auszulösen? Invalidate etc. gibt es ja leider nicht, da TMenuItem kein zeichenbares Control ist... Kann man Hover oder Mouseleave an ein MenuItem senden, so dass dann neu gezeichnet wird?

Alternativ habe ich versucht, in der SetCaption-Funktion die Routine DrawItem aufzurufen (ist OwnerDraw). Dabei habe ich es aber bislang nicht geschafft den dazugehörigen Canvas des Menüfensters zu ermitteln. Somit klappt das neu selber darüber zeichnen bislang nicht.

Es wäre toll, wenn Ihr für eine der beiden Varianten eine Lösung kennen solltet und diese hier posten könntet.

Vielen Dank
Stephan

EWeiss 2. Mai 2018 06:53

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Delphi-Quellcode:
if (PDis.itemAction and ODA_DRAWENTIRE) <> 0 then


und vielleicht noch etwas mit dem DC rumspielen.
Delphi-Quellcode:
GetClipBox(PDis.HDC, Rect);


Aber ohne WM_DRAWITEM geht wohl gar nichts.

gruss

hoika 2. Mai 2018 09:25

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Hallo,
hilft vielleicht EnableMenuItem (oder MnuItem.Enabled)?
Das einmal auf False und dann wieder auf True zurück.
Das müsste ja eigentlich das Neuzeichnen aufrufen.

Das Popupmenu wird zumindestens schon mal nicht neu aufgebaut.

Mavarik 2. Mai 2018 09:44

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Nur mal aus Neugier:
Warum Items neu zeichnen?

Was hat sich den geändert, was nicht in der MS vor dem öffnen nicht schon bekannt war?

StephanR 2. Mai 2018 10:04

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Zitat:

Zitat von EWeiss (Beitrag 1401018)
Delphi-Quellcode:
if (PDis.itemAction and ODA_DRAWENTIRE) <> 0 then


und vielleicht noch etwas mit dem DC rumspielen.
Delphi-Quellcode:
GetClipBox(PDis.HDC, Rect);


Aber ohne WM_DRAWITEM geht wohl gar nichts.

gruss

Hallo EWeiss,

um ein WM_DRAWITEM manuell auszulösen benötige ich aber wenigstens das Handle des Canvas, auf dem das Menü(item) gezeichnet werden soll. Und genau das habe ich bislang nicht herausgefunden. Nächstes Problem wäre dann die genaue Position des Rect, indem das Menuitem gezeichnet werden soll. Aber das könnte ich zur not noch ausrechnen...

Viele Grüße
Stephan

StephanR 2. Mai 2018 10:06

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Zitat:

Zitat von hoika (Beitrag 1401027)
Hallo,
hilft vielleicht EnableMenuItem (oder MnuItem.Enabled)?
Das einmal auf False und dann wieder auf True zurück.
Das müsste ja eigentlich das Neuzeichnen aufrufen.

Das Popupmenu wird zumindestens schon mal nicht neu aufgebaut.

Hallo hoika,

leider löst das Ändern von Enabled wieder MenuChanged aus und das schließt und öffnet das PopUp zur Aktualisierung.
Genau das möchte ich umgehen...

VG
Stephan

StephanR 2. Mai 2018 10:14

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Zur Erläuterung, warum ich denn einzelne Menuitems aktualisieren möchte/muss.

Bei meinem Projekt handelt es sich um eine Software für Sportwettbewerbe, die auf mehreren Clients im Netzwerk parallel betrieben wird. Die Daten liegen dabei zentral auf einem Fileserver.
Das Menü, welches zum Öffnen der einzelnen Wettbewerbe verwendet wird, soll neben dem Namen des einzelnen Wettbewerbs zu jedem Wettbewerb den aktuellen Status anzeigen (x Starter gemeldet, Wettbewerb in der x. Runde mit y Startern,...). Das Sammeln dieser Daten ist jedoch im Netzwerkbetrieb so langsam, dass der Nutzer ziemlich lange auf das Öffnen des Menüs warten müsste (sollte ich diese Daten erst Sammeln und dann das Menü anzeigen).
Deshalb habe ich das Zusammenstellen dieser Daten in einen parallelen Thread ausgelagert, der noch läuft während das Menü bereits geöffnet ist. Das Menü ist somit zunächst nur mit den Namen der Wettbewerbe bestückt und wenn dann die Statusdaten bereitstehen sollen diese mit angezeigt werden.
Aktuell geschieht diese Aktualisierung/das Neuzeichnen des MenuItems durch die Bewegung der Maus über die einzelnen Menüpunkte (Hover-Ereignis).
Dies ist aber nicht sonderlich intuitiv... Deshalb möchte ich gerne das Neuzeichnen der MenuItems anstoßen, sobald die jeweilige Info verfügbar wurde.

VG
Stephan

EWeiss 2. Mai 2018 10:14

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Zitat:

Zitat von StephanR (Beitrag 1401033)
Zitat:

Zitat von EWeiss (Beitrag 1401018)
Delphi-Quellcode:
if (PDis.itemAction and ODA_DRAWENTIRE) <> 0 then


und vielleicht noch etwas mit dem DC rumspielen.
Delphi-Quellcode:
GetClipBox(PDis.HDC, Rect);


Aber ohne WM_DRAWITEM geht wohl gar nichts.


gruss

Hallo EWeiss,

um ein WM_DRAWITEM manuell auszulösen benötige ich aber wenigstens das Handle des Canvas, auf dem das Menü(item) gezeichnet werden soll. Und genau das habe ich bislang nicht herausgefunden. Nächstes Problem wäre dann die genaue Position des Rect, indem das Menuitem gezeichnet werden soll. Aber das könnte ich zur not noch ausrechnen...

Viele Grüße
Stephan

Delphi-Quellcode:
hMenuWnd := WindowFromDC(PDis.HDC);

und

Delphi-Quellcode:
PDis.hwndItem

Bei dem Rect musst du gar nichts berechnen diesen gibt dir
GetClipBox zurück.. und zwar den vom selektierten HDC


gruss

StephanR 2. Mai 2018 10:48

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Delphi-Quellcode:
hMenuWnd := WindowFromDC(PDis.HDC);

und

Delphi-Quellcode:
PDis.hwndItem

Bei dem Rect musst du gar nichts berechnen diesen gibt dir
GetClipBox zurück.. und zwar den vom selektierten HDC


gruss[/QUOTE]

Hallo EWeiss,

Danke für Deine schnelle Antwort. Kannst Du mir bitte noch erklären, worauf genau sich "PDis" bezieht?
Ich steh da nämlich gerade etwas auf dem Schlauch...
Aktuell hatte ich vor, in meiner Child-Routine des SetCaption eine WM_DRAW-Message zusammenzubauen beziehungsweise DrawItem direkt aufzurufen.
Dort habe ich zwar Zugriff auf das Handle des TMenuItem aber PDis und sein HDC sind mir dort nicht bekannt.
Vielleicht kannst Du mir etwas mehr Info rund um Deinen Tipp geben :-)

Vielen Dank
Stephan

EWeiss 2. Mai 2018 10:55

AW: MenuItem neu zeichnen ohne ganzes Menü neu zu zeichnen
 
Sollte selbst erklärend sein.

Delphi-Quellcode:
  PDis: PDrawItemStruct absolute lP;
Initialisierung..

Delphi-Quellcode:
    WM_DRAWITEM:
      begin
        PDis := Pointer(lP);
        case PDis^.CtlType of
          ODT_MENU: // 1 Ownerdrawn menu item
            begin
              hMenuWnd := WindowFromDC(PDis.HDC);

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:38 Uhr.
Seite 1 von 2  1 2   

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