Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi TabSheet "freistellen" (https://www.delphipraxis.net/185788-tabsheet-freistellen.html)

Sugar 6. Jul 2015 17:12

TabSheet "freistellen"
 
Hallo Forum,

ich muss eine Anwendung etwas anpassen und die Oberfläche optimieren. Dazu würde ich am liebsten den Anwendern die Möglichkeit geben - wie bei einigen Browsern - einzelne Tabs aus dem aktiven Fenster zu "ziehen" um sie auf weiteren Bildschirmen zu platzieren.

Wie stelle ich sowas am besten an? Ich habe derzeit nicht mal den Anflug einer Idee dazu...

Uwe Raabe 6. Jul 2015 17:21

AW: TabSheet "freistellen"
 
Dockable Forms?

Perlsau 6. Jul 2015 17:29

AW: TabSheet "freistellen"
 
Zitat:

Zitat von Sugar (Beitrag 1307845)
... den Anwendern die Möglichkeit geben - wie bei einigen Browsern - einzelne Tabs aus dem aktiven Fenster zu "ziehen" um sie auf weiteren Bildschirmen zu platzieren.

Du könntest in diesen TabSheets mit Frames arbeiten, die du dann bei Bedarf auch in eigenen Fenstern anzeigen kannst.

Sugar 6. Jul 2015 17:35

AW: TabSheet "freistellen"
 
Ja, so ähnlich wie in dem Beispiel stelle ich mir das vor. Ich stelle mir das aber per Drag vor. Also der Benutzer zieht das Tab auf den Desktop oder einfach nur aus der Anwendung. Ich muss also eine Form "neben" meiner Hauptansicht ertellen und mit dem Tabsheet bestücken. In dem Beispiel gibt es die Form ja schon..

Sailor 7. Jul 2015 10:07

AW: TabSheet "freistellen"
 
Du mußt dem TabSheet ein neues Fensterhandle unterjubeln. Geht grob etwa so:

Delphi-Quellcode:
UNIT Floating;

 INTERFACE

  USES Windows,
       Messages,
       SysUtils,Variants,
       Classes,Graphics,Controls,ComCtrls,Forms,Dialogs;

  TYPE
   TFloatingForm = CLASS(TForm)
                    PROCEDURE FormCloseQuery(sender:TObject; VAR can_close:Boolean);
                    PROCEDURE FormClose(sender:TObject; VAR action:TCloseAction);

                    PRIVATE
                       FNoFloatParent: TWinControl;

                        FOnBeforeDock: TNotifyEvent;
                         FOnAfterDock: TNotifyEvent;
                       FOnBeforeFloat: TNotifyEvent;
                        FOnAfterFloat: TNotifyEvent;

                    PUBLIC
                     CONSTRUCTOR Create(an_owner:TComponent; CONST tab_sheet:TWinControl); REINTRODUCE;
                     PROCEDURE CreateParams(VAR params:TCreateParams);                    OVERRIDE;

                     PROCEDURE Float(x:Integer; y:Integer; wdt:Integer; hgt:Integer);

                     PROPERTY OnBeforeDock:TNotifyEvent
                              READ FOnBeforeDock
                              WRITE FOnBeforeDock;
                     PROPERTY OnAfterDock:TNotifyEvent
                              READ FOnAfterDock
                              WRITE FOnAfterDock;
                     PROPERTY OnBeforeFloat:TNotifyEvent
                              READ FOnBeforeFloat
                              WRITE FOnBeforeFloat;
                     PROPERTY OnAfterFloat:TNotifyEvent
                              READ FOnAfterFloat
                              WRITE FOnAfterFloat;
                   END;

 IMPLEMENTATION

{$R *.dfm}

  CONSTRUCTOR TFloatingForm.Create(an_owner:TComponent; CONST tab_sheet:TWinControl);
   BEGIN
    INHERITED Create(an_owner);
    FNoFloatParent := tab_sheet
   END; {OF CONSTRUCTOR TFloatingForm.Create}

  PROCEDURE TFloatingForm.CreateParams(VAR params:TCreateParams);
   BEGIN
    INHERITED CreateParams(params);
// Desktop button
    params.ExStyle := params.ExStyle OR ws_Ex_AppWindow
   END; {OF PROCEDURE TFloatingForm.CreateParams}

  PROCEDURE TFloatingForm.Float(x:Integer; y:Integer; wdt:Integer; hgt:Integer);
   VAR
    ind: Integer;

   BEGIN
    IF Visible = True
     THEN Exit; //Already floating

    IF Assigned(FOnBeforeFloat)
     THEN FOnBeforeFloat(Self);

    FOR ind:=FNoFloatParent.ControlCount-1 DOWNTO 0
     DO FNoFloatParent.Controls[ind].Parent := Self; // That' s the trick
    Left := x;
    Width := wdt;
    Top := y;
    Height := hgt;

    IF Assigned(FOnAfterFloat)
     THEN FOnAfterFloat(Self);

    Visible := True;
    SetCursorPos(Left+30,Top+10);
    Mouse_Event(MouseEventF_Absolute OR MouseEventF_LeftDown,Left+30,Top+10,0,0)
   END; {OF PROCEDURE TFloatingForm.Float}

  PROCEDURE TFloatingForm.FormCloseQuery(sender:TObject; VAR can_close:Boolean);
   VAR
    ind: Integer;

   BEGIN
    can_close := True;

    IF Assigned(FOnBeforeDock)
     THEN FOnBeforeDock(Self);

    FOR ind:=ControlCount-1 DOWNTO 0
     DO Controls[ind].Parent := FNoFloatParent; // Reset to old parent window

    IF Assigned(FOnAfterDock)
     THEN FOnAfterDock(Self)
   END; {OF PROCEDURE TFloatingForm.FormCloseQuery}

  PROCEDURE TFloatingForm.FormClose(sender:TObject; VAR action:TCloseAction);
   BEGIN
    action := caFree
   END; {OF PROCEDURE TFloatingForm.FormClose}

 END
 .


Aufruf:

 PROCEDURE TShellForm.PageControlMouseMove(sender:TObject; shift:TShiftState; x:Integer; y:Integer);
   CONST
    CMinMove = 3;

   VAR
    tab: Integer;
      p: TPoint;

   BEGIN
    WITH PageControl
     DO BEGIN
         tab := IndexOfTabAt(x,y);
         IF tab <> Undefined
          THEN BEGIN
                IF (FMouseDown = True)
                  AND
                   (
                     (Abs(FMouseX-x) > CMinMove)
                    OR
                     (Abs(FMouseY-y) > CMinMove)
                   )
                 THEN BEGIN
                       IF VisibleTabs > 1
                        THEN BEGIN
                              p := ClientToScreen(Point(x,GetSystemMetrics(sm_CyCaption)+TabHeight DIV 2));
                              FFloatingForm := TFloatingForm.Create(Self,PageControl.Pages[tab]);
                              WITH FFloatingForm
                               DO BEGIN
                                   OnBeforeDock := FloatingBeforeDock;
                                   OnBeforeFloat := FloatingBeforeFloat;
                                   OnAfterDock := FloatingAfterDock;
                                   OnAfterFloat := FloatingAfterFloat
                                  END;
                              FFloatingForm.Float(p.X,p.Y,Width,Height)
                             END;
                       FMouseDown := False
                      END
               END
        END
   END; {OF PROCEDURE TShellForm.PageControlMouseMove}

Uwe Raabe 7. Jul 2015 11:58

AW: TabSheet "freistellen"
 
Zitat:

Zitat von Sugar (Beitrag 1307849)
Ja, so ähnlich wie in dem Beispiel stelle ich mir das vor. Ich stelle mir das aber per Drag vor. Also der Benutzer zieht das Tab auf den Desktop oder einfach nur aus der Anwendung.

In dem Beispiel zeigt Alister leider nur die eine Richtung - Form in Tab-Control ziehen und fallen lassen. Es geht aber auch anders herum, in dem man den Tab aus dem Tab-Control herauszieht. Da die Tabs ja aus gedockten Forms bestehen, kann jedes dieser Forms natürlich auch allein (undocked) existieren.

Ebenso ist es möglich, per Programmcode ein Form in ein Tab-Control zu docken. Der Befehl dazu heißt ManualDock.

Bei den Beispielen bis XE6 war auch eines namens "Docking" dabei, daß diesen Vorgang zumindest ansatzweise darstellt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:50 Uhr.

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