Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Rund um die LCL und andere Komponenten
kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von kirchfritz »

Hallo,
ich verzichte in meiner Windows-Application auf eine Titelleiste.
Das habe ich realisiert mit

Code: Alles auswählen

borderstyle := bsNone.
Da meine Windows-Application auch ein MainMenu enthält, habe ich mir in den Kopf gesetzt, das Verschieben der Application durch Mausklick in das MainMenu zu realisieren.
Leider hat die MainMenu-Komponente kein MouseDown, MouseUp oder MouseMove Event.

Irgendwie kann man bestimmt mit Hilfe von WinMessages herausfinden, dass der Anwender in das Hauptmenu geklickt hat. Leider kenne ich mich auf diesem Gebiet nicht so gut aus.

Kann mir da jemand helfen?
Dateianhänge
RahmenlosesFenster_mit_MainMenu.png
RahmenlosesFenster_mit_MainMenu.png (46.38 KiB) 3236 mal betrachtet
Zuletzt geändert von kirchfritz am Sa 30. Dez 2023, 13:00, insgesamt 1-mal geändert.

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: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Sieben »

Dein Ansatz verstößt mE gegen die GUI-Richtlinien der Zielplattform. Nun kann man in Bezug auf diese Richtlinien durchaus eine eigene, auch gut begründete abweichende Meinung haben, aber letztlich verfolgen diese Richtlinien ein sinnvolles Ziel - den User mit einer einheitlichen Vorgehensweise hinsichtlich grundlegender Aufgaben wie eben dem Verschieben eines Fensters auszustatten. Ich würde dir daher schlicht vorschlagen, dir das in den Kopf Gesetzte wieder aus demselben zu schlagen. Zugegeben nicht sonderlich originell oder 'problemorientiert' - aber warum nicht nur dir sondern auch dem User Probleme bereiten, für dessen Bewältigung nicht nur du sondern auch er erst neue Strategien erlernen muss?

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von kirchfritz »

Du hast natürlich irgendwie schon recht, aber wenn ich mir auf der Zielplattform verschiedene Titelleisten so anschaue, dann wird dem Anwender ziemlich viel "Neues" zugemutet. Vorallem im Microsoft Browser Edge finden sich Buttons und Tabs in der Titelleiste. Ich dachte mir halt, wenn ich das irgendwie mit Lazarus nachbauen könnte, dann wäre ich sehr zufrieden damit. Für "Buttons oder Tabs in die Titelleiste einbauen" habe ich bisher unter Lazarus noch keine Lösungen gefunden, außer sich mit einem Panel selbst eine eigene Titelleiste zu bauen. Und genau dieses Panel lässt sich dann gut zum Verschieben der Application "umfunktionieren". Sieht aus wie eine Titelleiste, funktioniert wie eine Titelleiste, Anwender braucht sich nicht "umgewöhnen". Alles soweit gut.

Und gerade diese Titelleisten-Panel-Technik wollte ich umgehen, in dem ich die Titelleiste gleich durch ein MainMenu ersetze.
MenuItems anstatt Buttons, "Minimize,Maximize,Restore,Close-Buttons durch rechtsausgerichtete MenuItems ersetzen, müsste alles aussehen wie eine gewöhnliche Titelleiste, nur das Verschieben der Application durch Klick auf diese "Pseudo-Titelleiste" will ebenhalt noch als ungelöstes Problem im Raum stehen bleiben.

Vielleicht hat ja jemand eine Lösung für mich.
Wie man den Clientbereich einer Anwendung mit Titelleiste so erweitert, dass man auch Buttons oder Tabs in die normale Titelleiste "reinzeichnet", würde mich natürlich auch interessieren, fall jemand "Nebenlösungen" für meine Titelleisten-Herausforderungen anbieten will.
Verschiedene_Titelleisten.png
(103.53 KiB) Noch nie heruntergeladen

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Mathias »

Dein Ansatz verstößt mE gegen die GUI-Richtlinien der Zielplattform.
Genau solche Sachen nerven. Dazumal unter DOS war alles so chaotisch. Mit Win3 wurde endlich mal eine einheitliche Oberfläche eingeführt, welche mit Win2000 den Höhepunkt erreichte. Nachher ging alles wieder Bach ab. Angefangen hat M$ mit diesem Mist, ab Win8 wurde alles unübersichtlicher und un-bedienbarer. Nachher zogen leider auch viele andere mit, vor allem Browser Hersteller.
Chrome ist auch so idiotisch verbaut worden. Total verbastelte Menü, bei denen die Zeilen viel zu weit auseinander sind.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von af0815 »

Bezüglich GUI gebe ich den anderen Recht, aber man hat für Abweichungen manchmal Gründe.

Normalerweise sollte das Formular ja Keyevents zur Verfügung stellen OnKey... mit KeyPreview und wenn alle Stricke reissen, im Hintergrund gibt es immer eine Messageloop in die du dich einklinken kannst.

Bin gerade auf einem Tablett und kann deswegen kein Beispiel posten, aber vielleicht helfen dir die Keyworte bei der Suche.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Mathias »

Meinst du die wm... Komandos ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von af0815 »

Mathias hat geschrieben:
Sa 30. Dez 2023, 09:26
Meinst du die wm... Komandos ?
Ja, über dieMessagequece geht im Endeffekt alles drüber, es wird nur sehr gut durch die komfortablen Events gut versteckt. Man hat damit meistens nur zu tun, wenn man eigene Botschaften ins System einschleusen muss. Oder halt für so Spezialfälle so wie hier.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von theo »

@kirchfritz: Ich würde so etwas nicht machen, auch wegen der Platzformunterschiede.
Erfahrungsgemäß verbrät man viel Zeit damit und ist am Ende doch nicht zufrieden.
Wahrsch. müsstest du deine eigene Ableitung von TMainMenu machen.

Auf Linux (mind. KDE) ist z.B. das gewünschte Verhalten gratis.
Dort wird immer das Fenster verschoben, wenn man an einem freien Bereich des Hauptmenüs "zieht".

Bei KDE lässt sich übrigens auch beim laufenden Fenster die Titelleiste ausschalten. Bei Windows weiss ich es nicht.
Dateianhänge
kde_desk.png
kde_desk.png (87.66 KiB) 3155 mal betrachtet

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von siro »

Ich hab grad mal was probiert, aber da treten VIELE Probleme auf.... :roll:
funktioniert so leider nicht richtig, aber dient evtl. als Ansatzpunkt:

Ohne Die Unit Windowes geht das eh nicht,
Die Messages Non Client .... kommen aber auch, wenn ich auf die Menüeinträge klicke,
ist also so nicht wirklich brauchbar.

Code: Alles auswählen


var
  PrevWndProc: WNDPROC;
  FlagDown:Boolean;

var sx,sy,x,y:Integer;

{ TForm1 }
  function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam; lParam: LParam): LRESULT; stdcall;
  begin

    if uMsg =  WM_NCLBUTTONUP then begin 
      FlagDown:=FALSE;
    end;

    if uMsg =  WM_NCLBUTTONDOWN then begin
      sx:=GET_X_LPARAM(lParam);        // Startpunkt X
      sy:=GET_Y_LPARAM(lParam);        // Startpunkt Y
      FlagDown:=TRUE;
    end;

    if uMsg = WM_NCMOUSEMOVE then begin 
      x:=GET_X_LPARAM(lParam);         // aktuelle Position X
      y:=GET_Y_LPARAM(lParam);         // aktuelle Position Y
      if FlagDown then begin
        Form1.left:=Form1.left-sx+x;   // horizontal verschieben
      end;
    end;

    Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);    // Das Original aufrufen
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Die WndProc umleiten auf die neue WndCallback Funktion
  PrevWndProc := Windows.WNDPROC(SetWindowLongPtr(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback)));
end;           
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Mathias »

Ohne Die Unit Windowes geht das eh nicht,
Ich habe da mal etwas probiert, was auch auf Linux funktioniert.
Dateianhänge
LM_Message.zip
(69.96 KiB) 50-mal heruntergeladen
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von kirchfritz »

@siro: Vom Ansatz her scheint das schon in die richtige Richtung zu gehen. Ich kann leider noch nicht erkennen, wo die umgeleitete WndProc auf das MainMenu Bezug nicht.

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

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von theo »

Mathias hat geschrieben:
Sa 30. Dez 2023, 13:57
Ohne Die Unit Windowes geht das eh nicht,
Ich habe da mal etwas probiert, was auch auf Linux funktioniert.
Das reagiert aber auf dem MainMenu genauso wenig wie WndProc des Formulars.

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von kirchfritz »

ChatGPT will mir folgenden Sourcecode schmackhaft machen:

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Menus;

type

  { TForm1 }

  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    FileMenu: TMenuItem;
    OpenItem: TMenuItem;
    SaveItem: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { private declarations }
    FDragging: Boolean;
    FDeltaX, FDeltaY: Integer;
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Initialize variables
  FDragging := False;
  FDeltaX := 0;
  FDeltaY := 0;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  // Check if the mouse is over the MainMenu
  if MainMenu1.ClientRect.Contains(Point(X, Y)) then
  begin
    // Start dragging
    FDragging := True;

    // Record the initial mouse position relative to the form
    FDeltaX := X;
    FDeltaY := Y;
  end;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  // Check if dragging is in progress
  if FDragging then
  begin
    // Calculate the new position of the form
    Left := Left + (X - FDeltaX);
    Top := Top + (Y - FDeltaY);
  end;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  // Stop dragging
  FDragging := False;
end;

end.
Leider läßt sich dieser Sourcecode nicht kompilieren, weil im FormMouseDown die if Bedingung nicht funktioniert

Code: Alles auswählen

 if MainMenu1.ClientRect.Contains(Point(X, Y)) 
MainMenu hat dummerweise kein ClientRect und weil das FormMouseDown-Event überhaupt nicht ausgelöst wird, wenn man im MainMenu mit der Maus klickt.
Typisch ChatGPT: Schöner SourceCode, funktioniert nur nicht.
Bitte jetzt keine Diskussion über ChatGPT weiterführen. Ich stelle meine Fragen immerhin diesen von mir sehr geschätzten Forum, Die Grenzen und die Sinnhaftigkeit der künstlichen Intelligenz sind mir vollauf bewußt.
Zuletzt geändert von kirchfritz am Sa 30. Dez 2023, 14:56, insgesamt 1-mal geändert.

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: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Sieben »

Vielleicht hilft der in diesem Thread verfolgte Ansatz weiter...?

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Rahmenloses Fenster mit Hilfe des MainMenus verschieben

Beitrag von Mathias »

Da meine Windows-Application auch ein MainMenu enthält, habe ich mir in den Kopf gesetzt, das Verschieben der Application durch Mausklick in das MainMenu zu realisieren.
Ich habe gerade eine neue Anwendung erstellt und BorderStyle auf bsNone gesetzt.
Ein kleines Menu eingefügt, und mein Form macht genau das was du willst, ich kann es rechts-oben verschieben. Nur vergrössern geht nicht.

Ist dies etwa Linux-Usern vorbehalten ?
Dateianhänge
Bildschirmfoto vom 2023-12-30 16-10-02.png
Bildschirmfoto vom 2023-12-30 16-10-02.png (3.67 KiB) 3096 mal betrachtet
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten