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, wenn ImageIndex sich ändert? (https://www.delphipraxis.net/193803-menuitem-neu-zeichnen-wenn-imageindex-sich-aendert.html)

SearchBot 11. Sep 2017 14:05

MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Hallo,

ich habe ein optisches Problem.
Im MainMenu habe ich sowas wie Status-Anzeigen angelegt.

Mit der ImageList habe ich 4 "LEDs" (grau, grün, gelb, rot), die ich je nach Situation einschalte.

Startet die Anwendung, werden die "LED" grau gezeigt.
Setze ich jetzt ImageIndex:=1 , soll neben dem MenuItem.Caption die Grüne "LED" angezeigt werden.

Das funktioniert auch intern ganz gut - nur wird das Menü erst dann neu gezeichnet, wenn ich mit dem Mauszeiger drüberfahre.

Ich kann ja von Anwender nicht erwarten, immer mit dem Mauszeiger drüber zu gehen, um die Anzeige zu aktualisieren.

Es gibt irgendwie kein Event dafür, auch mit Update, Refresh, Invalidate funktioniert es nicht. Einzig beim komplett neu zeichnen der Anwendung wird auch das Menü neu gezeichnet, aber das flackert blöd...

Wie kann ich das Menü bei Änderung des ImageIndex selbst neu zeichnen lassen?

himitsu 12. Sep 2017 08:42

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Nunja, die Setter von z.B. Caption und ImageIndex machen rein garnichts, um der der Componente die Änderung mitzuteilen. :wall:

Im Allgemeinem sucht daher man zuerst nach so einer Methode, hier im Item oder im Menü,
aber finden wirst du sowas nur in der Form. (ganze Form neu zeichnen lassen dürfte dein Problem also lösen)
> Repaint, Refresh, Update oder Invalidate heißen die meistens.

Falls garnichs funktionier:
Es gibt im TMenuItem ein RebuildHandle, was eigentlich das Gewünschte bewirken würde, aber da kommst du nicht direkt ran. (ist Private)
Aufgerufen wird es z.B. beim Add/Remove, also wenn du mal kurz ein MenuItem im Root einfügst und gleich wieder löschst.

SearchBot 12. Sep 2017 12:06

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Ne, nix geht.

Aber wenn man mit der Maus drüber fährt, malt es ein Hover um das Item, dadurch wird dann auch die "LED" korrekt gezeichnet.
Wenn man nun irgendwie dies durch ein Postmessage oder so auslösen könnte?

Ich hab irgendwoher sowas eingebaut:
Delphi-Quellcode:
type
  THackedMenuItem = class(TMenuItem);
Dann kann ich auch schreiben
Delphi-Quellcode:
 THackedMenuItem(myMenuItem).MenuChanged(true);
und das True sollte ein Rebuid auslösen. Macht es aber trotzdem nicht, zumindest hat es keine Auswirkung. Hab ich was übersehen?

EWeiss 12. Sep 2017 12:21

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Zitat:

Wie kann ich das Menü bei Änderung des ImageIndex selbst neu zeichnen lassen?
Gar nicht.. so lange es geöffnet ist.

Es sei denn du erstellst ein eigenes das als Basis ein Normales Fenster erzeugt.
Das ist einer der gründe warum ich ein eigenes PopUpMenu erstellt habe wegen diverser Einschränkungen.

Es ist nun mal so das ein Menu kein Handle hat somit kannst du auch keine Messagen an das NICHT vorhandene Fenster(Handle) schicken.
Da kannst du versuchen zu zaubern wie du willst.

gruss

himitsu 12. Sep 2017 12:50

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Zitat:

Zitat von EWeiss (Beitrag 1380923)
Gar nicht.. so lange es geöffnet ist.

MainMenu, nicht PopupMenu
und da ist die erste Ebene immer sichtbar. :zwinker:


Unqualifizierte alternative Antwort: Schmeiß das TMainMenu weg und nimm ein Ribbon. :stupid:

Uwe Raabe 12. Sep 2017 14:19

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Das funktioniert doch ganz hervorragend (sowohl im obersten Level, als auch in den Subleveln):

Delphi-Quellcode:
type
  TForm210 = class(TForm)
    MainMenu1: TMainMenu;
    ImageList1: TImageList;
    Test1: TMenuItem;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
  end;

var
  Form210: TForm210;

implementation

{$R *.dfm}

procedure TForm210.Timer1Timer(Sender: TObject);
{ ImageList hat nur zwei Bitmaps }
begin
  Test1.ImageIndex := 1 - Test1.ImageIndex;
end;

himitsu 12. Sep 2017 14:33

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Haben die da was geändert?

Im XE sieht es so aus:
Delphi-Quellcode:
procedure TMenuItem.SetImageIndex(Value: TImageIndex);
begin
  if Value <> FImageIndex then
  begin
    FImageIndex := Value;
    MenuChanged(True);
  end;
end;

procedure TMenuItem.MenuChanged(Rebuild: Boolean);
var
  Source: TMenuItem;
begin
  if (Parent = nil) and (Owner is TMenu) then
    Source := nil else
    Source := Self;
  if Assigned(FOnChange) then FOnChange(Self, Source, Rebuild);
end;
Demnach bekommt niemand mit, wenn sich der ImageIndex ändert.

Der Teil wird hierbei leider nicht ausgeführt.
Delphi-Quellcode:
procedure TMainMenu.MenuChanged(Sender: TObject; Source: TMenuItem; Rebuild: Boolean);
var
  NeedUpdate: Boolean;
begin
  if (FWindowHandle <> 0) then
  begin
    NeedUpdate := UpdateImage; // check for changes before CM_MENUCHANGED does
    if Source = nil then
      SendMessage(FWindowHandle, CM_MENUCHANGED, 0, 0);
    if NeedUpdate then
      DrawMenuBar(FWindowHandle);
  end;
  inherited MenuChanged(Sender, Source, Rebuild);
end;
Nach der Änderung manuell das Protected MenuChanged aufrufen oder direkt
Delphi-Quellcode:
//MainMenu.UpdateImage; // ist Private, aber geht vielleicht auch ohne
SendMessage(MainMenu.WindowHandle, CM_MENUCHANGED, 0, 0);
DrawMenuBar(MainMenu.WindowHandle);

Uwe Raabe 12. Sep 2017 14:38

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Zitat:

Zitat von himitsu (Beitrag 1380927)
Demnach bekommt niemand mit, wenn sich der ImageIndex ändert.

In Tokyo ist das FOnChange verlinkt auf das SubItemChanged des Parent (ist ja auch private). Kann man leicht sehen, wenn man im Debugger durchstept.

EWeiss 12. Sep 2017 16:53

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Zitat:

MainMenu, nicht PopupMenu
und da ist die erste Ebene immer sichtbar.
Oh.. Entschuldige.

gruss

SearchBot 13. Sep 2017 08:57

AW: MenuItem neu zeichnen, wenn ImageIndex sich ändert?
 
Aah cool, so gehts (in Berlin).

Hab im MainMenu1.OnChange gesetzt und da drin geschrieben:
Delphi-Quellcode:
procedure TForm1.MainMenu1Change(Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);
begin
 SendMessage(MainMenu1.WindowHandle, CM_MENUCHANGED, 0, 0);
 DrawMenuBar(MainMenu1.WindowHandle);
end;
Jetzt geht es ohne weiteres Herumgetrickse... :thumb:
Danke für Eure Hilfe!!


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