TMenuItem mit onmousemove

Rund um die LCL und andere Komponenten
Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

TMenuItem mit onmousemove

Beitrag von Frank Ranis »

Hallo ,

gibt es irgendwie die Möglichkeit ein onmousemove für TMenuItem zu basteln ?

Ich habe schon gegooglet wie doof , aber werde nicht fündig.

Gruß

Frank
www.flz-vortex.de

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TMenuItem mit onmousemove

Beitrag von theo »

Bei solchen "Sonderwünschen" finde ich es immer hilfreich, wenn man kurz dazu schreibt, wozu das dienen soll.
Vielleicht gibt es ja einen einfacheren Weg zum (unbekannten) Ziel.

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: TMenuItem mit onmousemove

Beitrag von sstvmaster »

So wie hier im Beitrag #11: https://www.delphipraxis.net/100126-tme ... ver-2.html
steht, geht es nicht, da TMenuItem kein Nachfolger von TControl ist.
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TMenuItem mit onmousemove

Beitrag von Frank Ranis »

Hallo theo,
theo hat geschrieben:
Mi 2. Sep 2020, 10:01
Bei solchen "Sonderwünschen" finde ich es immer hilfreich, wenn man kurz dazu schreibt, wozu das dienen soll.
Vielleicht gibt es ja einen einfacheren Weg zum (unbekannten) Ziel.
meine Idee ist es , meine Programme mit einem neuen Hilfesystem auszurüsten .
Das derzeitige Hilfesystem , ähnlich dem Hilfesystem von Lazarus , funktioniert zwar , ist aber für einen Normal-User viel zu kompliziert .
Jeder User soll eine einfache Möglichkeit haben , in seiner Muttersprache die Hilfe (Programm-Beschriftung) zu erweitern / anzupassen.

Dazu soll man einfach mit der Maus auf ein beliebiges Bedienelement fahren , dann eine bestimmte Tasten-Kombination drücken und es soll dann der Hilfe-Editor (wird ein Eigenbau) aufmachen.
Im Hilfe-Editor gibt es dann für jede Sprache einen Reiter (wenn nicht vorhanden , dann kann einen neuer angelegt werden) .
Passend zum Bedienelement , soll man die Caption , das Hint ändern können.
Des weitern soll man dort auch einen LINK zur HTML-Hilfe-Seite eintragen können , ein im Programm eingebauter HTLM-Editor wäre da noch schick.
In jedem Sprachen-Reiter soll es dann auch eine Liste mit intern verwendeten Texten geben (Error-Meldungen , diverse Ausgabetexte).
Alle gesammelten Daten könnte man dann in eine XML-Datei schreiben und wenn jemand mit F1 die Hilfe ordert die passende Seite aufmachen.
Bei einer Sprachenänderung (auswählbar im Hauptmenü) soll dann auch die Oberfläche angepasst werden.
Alle Bestandteile der Hilfe sollen in einen DOC-Ordner abgelegt werden , so das man einfach durch austauschen des Ordners einen neue Hilfe hat.

So nun zum grundlegenden Problem :
Fast jede visuelle Lazarus-Komponente hat ein onmouseover-Ereignis mit dem ich einfach beim überfahren das entsprechende Bedienelement identifizieren kann und dann zusammen mit der Tasten-Kombination an meinen zukünftigen Hilfe-Editor senden kann.

Fast jede Komponente , außer Main- und Pop-Menus und dessen Items.
Deshalb meine Frage.

Gruß

Frank
www.flz-vortex.de

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TMenuItem mit onmousemove

Beitrag von theo »

Ohne in die Tiefe zu gehen: Über den Hint vielleicht?
Wenn du dafür sorgst, dass der Menu Hint in einem Statusbar angezeigt wird, kannst du den im geeigneten Moment aus dem Statusbar auslesen, über

Code: Alles auswählen

Statusbar1.SimpleText;  
Darüber sollte das MenuItem zu identifizieren sein.
Etwas anderes fällt mir auf die Schnelle nicht ein.

EDIT: Geht wahrsch. noch besser über

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnHint:=@ApplicationHint;
end;   

procedure TForm1.ApplicationHint(Sender: TObject);
begin
  Tuwas mit Application.Hint;
end;
Braucht so auch keinen Statusbar.

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TMenuItem mit onmousemove

Beitrag von Frank Ranis »

Hallo theo,
theo hat geschrieben:
Mi 2. Sep 2020, 11:37
Ohne in die Tiefe zu gehen: Über den Hint vielleicht?
Wenn du dafür sorgst, dass der Menu Hint in einem Statusbar angezeigt wird, kannst du den im geeigneten Moment aus dem Statusbar auslesen, über

Code: Alles auswählen

Statusbar1.SimpleText;  
Darüber sollte das MenuItem zu identifizieren sein.
Etwas anderes fällt mir auf die Schnelle nicht ein.

EDIT: Geht wahrsch. noch besser über

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnHint:=@ApplicationHint;
end;   

procedure TForm1.ApplicationHint(Sender: TObject);
begin
  Tuwas mit Application.Hint;
end;
Braucht so auch keinen Statusbar.
mit dem Hint bekommt man zwar eine Aktion , wenn man mit der Maus drüber fährt , aber.
1) Beim Mainmenu wird Hint erst geliefert , wenn man draufklickt und somit zum aufklappen motiviert.
Beim Popmenu ist klar , das muß ich erst mal öffnen und kann dann mit der Maus drüberfahren , dann wird Hint geliefert.
2) Alle Elemente bekommen ja ein Hint , in dem eine Kurzbeschreibung der Funktionsweise steht .
Zum identifizieren müßte man dann diesen Text mit einer zusätzlichen Kennung versehen (z.B. eine eindeutige Nummer des TMenuItems) .
Wird der Hint für den User angezeigt , dann müßte diesen Kennung irgendwie rausgeprüsselt werden , sonst wird ja die Kennung mitangezeigt , auch doof.
Nach jeder Änderung des Hints von außerhalb , muß man die Kennung wieder reinpacken , das wird ne frickelei.
Für den Notfall könnte man das aber nehmen.

Gibt es da nicht eventuell ne Möglichkeit mit einem Interface zu arbeiten.
Wobei ich von der Interface-Technik noch überhaupt keine Ahnung habe.
Und dort ansetzten , wo TMenuItem und alle anderen Komponenten getrennte Wege gehen , also ab der Klasse TLCLComponent.
Alle Standard-Komponenten (die onmousemove haben) stammen von TControl ab , ab dort gibt es ja das onmousemove.
TControl und auch TMenuItem stammen beide von TLCLComponent ab.

Ich bräuchte also als Basis ein TControl , welches dann noch die Methoden von TMenuItem bekommt .
TNewMenuitem = TControl + TMenuItem
Kann man das nicht irgendwie zusammenbauen ? , habe keine Ahnung vom Komponetenbau .

Gruß

Frank
www.flz-vortex.de

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TMenuItem mit onmousemove

Beitrag von theo »

1. Ja scheint so. Das ist wahrscheinlich schwer zu ändern.
2. Wenn die Hinttexte eindeutig sind, kann man die auch ohne zusätzliche Kennung vergleichen.
(Interface) Wenn schon, müsste man wohl an Windows Messages wie z.B. WM_MENUSELECT ran. Keine Ahnung, was das genau tut. Das ist wahrscheinlich nicht, was du suchst.

https://www.thoughtco.com/how-to-displa ... ts-1058397

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMenuItem mit onmousemove

Beitrag von Sieben »

Nicht ausprobiert, aber wie wäre es denn mit TApplication.OnShowHint? Da müsste eine THintInfo mitkommen, die auch ein Property HintControl hat. Vielleicht könnte man sogar das ganze System darauf aufbauen.

Edit: geht wohl leider nicht. Scheint erstens im fraglichen Fall nicht ausgelöst zu werden, zweitens ist auch HintControl wieder vom Typ TControl.

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TMenuItem mit onmousemove (So halbwegs gelöst , schön noch immer nicht!)

Beitrag von Frank Ranis »

Hallo ,

habe noch ein paar Stunden rumprobiert .
Mit dem TApplication.OnShowHint und THintInfo klappt nur mit den Standardkomponenten , die von TControl abstammen.
Und diese probiert und jenes , alles irgendwie nicht so toll .
Das mit dem WM_MENUSELECT (theo) war auch nicht so der Brüller.

Zum Schluß habe ich mich zum überschreiben von TMenuitem entschlossen.
Das funktioniert so halbwegs , man kann damit leben.
Also ich baue für die aktuelle Form ein neues TMenuItem , welches ich mit einer Behandlungsroutine (Fon_mouse_select_item) ausrüste.
Mit creator weise ich dem property on_mouse_select_item die over_object-Routine des Forms zu.
Das Orginal TMenuItem hat einen Methode IntfDoSelect , die den Item-Hint an die Application übergibt.
Dies war dann mein Angriffpunkt.
Funzt auch mit dem verwendeten PopUp-Menü .

Alle Standard-Komponenten senden bei onmouseenter ihren Pointer auch an die over_object-Routine des Forms.
Somit habe ich immer das aktuelle Objekt unter der Maus und kann dann meine Hilfe-Idee weiterspinnen.

Komplettes Testprog im Anhang.

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Menus,
  ComCtrls, StdCtrls ,LCLIntf ,LCLType, ExtCtrls;

type
  { TMenuItem }
  TMenuItem=class(menus.TMenuItem)
   private
    Fon_mouse_select_item:TNotifyEvent;
   protected
   public
    constructor Create(TheOwner: TComponent); override;
    procedure IntfDoSelect; override; // Beim Selektieren eines Menüitems
    property on_mouse_select_item:TNotifyEvent read Fon_mouse_select_item write Fon_mouse_select_item;
  end;

  { TForm1 }
  TForm1 = class(TForm)
    Button1: TButton;
    Label2: TLabel;
    MainMenu1: TMainMenu;
    Memo1: TMemo;
    MenuItem1: TMenuItem;
    MenuItem10: TMenuItem;
    MenuItem11: TMenuItem;
    MenuItem12: TMenuItem;
    MenuItem13: TMenuItem;
    MenuItem14: TMenuItem;
    MenuItem15: TMenuItem;
    MenuItem16: TMenuItem;
    MenuItem17: TMenuItem;
    MenuItem18: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    MenuItem4: TMenuItem;
    MenuItem5: TMenuItem;
    MenuItem6: TMenuItem;
    MenuItem7: TMenuItem;
    MenuItem8: TMenuItem;
    MenuItem9: TMenuItem;
    PopupMenu1: TPopupMenu;
    procedure over_object(o:tobject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TMenuItem }
constructor TMenuItem.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  self.Fon_mouse_select_item:=@form1.over_object;  // On Over_object des Forms zuweisen
end;

procedure TMenuItem.IntfDoSelect;
begin
 inherited IntfDoSelect;
 if assigned(Fon_mouse_select_item) then Fon_mouse_select_item(self);
end;

{ TForm1 }

procedure TForm1.over_object(o: tobject);
begin
 memo1.lines.add(tcomponent(o).Name);
end;

end.     


Gruß

Frank
Dateianhänge
Testprog.zip
(125.95 KiB) 86-mal heruntergeladen
www.flz-vortex.de

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMenuItem mit onmousemove

Beitrag von Sieben »

Oha. Hätte ich nicht gedacht, dass sich da so leicht was 'unterschieben' lässt. Keine side effects?
Alle Standard-Komponenten senden bei onmouseenter ihren Pointer auch an die over_object-Routine des Forms.
Blöde Frage: wo...?

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TMenuItem mit onmousemove

Beitrag von Frank Ranis »

Hallo Sieben,
Sieben hat geschrieben:
Do 3. Sep 2020, 13:16
Oha. Hätte ich nicht gedacht, dass sich da so leicht was 'unterschieben' lässt. Keine side effects?
Alle Standard-Komponenten senden bei onmouseenter ihren Pointer auch an die over_object-Routine des Forms.
Blöde Frage: wo...?
Im Objekt-Inspektor zugewiesen.
z.B. für den Button -> Objekt-Inspektor ->Ereignisse -> OnMousEnter -> 'over_object' eintragen.

War zu faul , das im Code zu machen .
Deshalb habe ich ja das Zip mitgeschickt .

Gruß

Frank
www.flz-vortex.de

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMenuItem mit onmousemove

Beitrag von Sieben »

Ich wusste doch, es ist eine blöde Frage - also manchmal...

Danke.

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMenuItem mit onmousemove

Beitrag von Sieben »

Zur Strafe (und um deine Faulheit zu fördern :wink: ) hab ich auch noch mal ein bisschen damit rumgespielt. Mit folgendem Codeschnipsel lässt sich jeder Komponente, die ein Event-Property mit entsprechendem Namen hat, eine Methode zuweisen:

Code: Alles auswählen

procedure GrabEvents(AForm: TForm; AnEventName: string; AnEvent: TMethod);
var i: Integer;
begin
  with AForm do
    for i:=0 to pred(ComponentCount) do
      if Assigned(GetPropInfo(Components[i],AnEventName)) then
        SetMethodProp(Components[i],AnEventName,AnEvent);
end;                                                                       
Leider verfügt das untergeschobene TMenuItem aber nicht über die entsprechende RTTI, so dass man in dem Falle eine etwas weniger universelle Variante nehmen muss, dann auf TNotifyEvent bzw konkret OnMouseEnter beschränkt. Ich habe dein Beispiel mal entsprechend angepasst und dann auch das TMenuItem in eine eigene Unit ausgelagert. Sollte ich jetzt Eulen nach Athen getragen haben, dann ist das jedenfalls nicht bös gemeint... ich brauch zZt einfach ein paar Fingerübungen, um wieder reinzukommen...
Dateianhänge
OnMouseTest.zip
(127.88 KiB) 82-mal heruntergeladen
Zuletzt geändert von Sieben am Fr 4. Sep 2020, 11:47, insgesamt 2-mal geändert.

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: TMenuItem mit onmousemove

Beitrag von Frank Ranis »

Hallo Sieben,

cooler Code , auf so etwas wäre ich nicht gekommen , da die Methoden wie GetPropInfo oder SetMethodProp nicht in meiner Hirn-Pascal-Schublade gespeichert sind.
Und wat der Bauer nicht kennt , dat nutzt er nicht.

Was mich aber nun total verwirrt , ist , das das Verschieben unserer neuen TMenuItem-Klasse in die Unit MyItem funktioniert.
Ich dachte es müsste in der Formunit oberhalb der TForm1-Class-Deklaration eingebaut sein , damit sich die Form das neue TMenuItem schnappt und nicht generell auf das Orginal zugreift.

Einzige Erklärung für mich:
Die Unit MyItem ist lokal im Projekt-Ordner abgelegt und Lazarus durchsucht diesen Ordner zuerst , bevor es losgeht um die passende Class in der Lazarus-Installation zu suchen .
Also Vorrang hätten dann die lokalen Units und dann erst die aus der Installation.

Es wäre nun mal Interessant zu erfahren , wie die Unit-Zuriffsreihenfolge unter Lazarus überhaupt funktioniert.
Und ob eventuell die Reihenfolge in den USES-Einträgen auch ne Rolle spielt.
In diesem Fall wohl nicht , da die Unit MyItem ganz hinten eingetragen ist.
Kann dazu vielleicht mal einer der SUPER-Pascaller was sagen.

Gruß

Frank
www.flz-vortex.de

Sieben
Beiträge: 202
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: TMenuItem mit onmousemove

Beitrag von Sieben »

Soweit ich weiß bzw das in Erinnerung habe, ist die jeweils letzte (zuletzt gelesene?) Definition gültig, also das, was im uses-Clause weiter hinten steht.

Antworten