AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Tastatureingabe an Formularen

Ein Thema von Tom65 · begonnen am 7. Sep 2006 · letzter Beitrag vom 8. Sep 2006
Antwort Antwort
Tom65

Registriert seit: 25. Jan 2005
15 Beiträge
 
#1

Tastatureingabe an Formularen

  Alt 7. Sep 2006, 07:43
Ich möchte auf dem Hauptformular des Programmes (Form1) ein zweites Formular (Form2) ohne sichtbaren Rahmen (BorderStyle = bsNone) anzeigen. Dabei soll Form2 auch sichtbar bleiben, wenn mit der Maus auf Form1 geklickt wird. Die Titelleiste von Form1 soll blau bleiben wenn Form2 angezeigt wird und Form2 soll im OnKeyDown-Ereignis auf die Tastatureingaben reagieren. Aber an einem dieser Punkte scheitert es immer.
Bei

Form2.FormStyle = fsStayOnTop und
Form2.KeyPreview = true

lässt sich Form2 mit der Tastatur bedienen aber die Titelleiste von Form1 wird grau.
Bei

Form2.Parent:= Form1

wird Form2 angezeigt und die Titelzeile von Form1 bleibt blau aber Form2 lässt sich nicht mit der Tastatur bedienen.
Wie kann man dieses Problem lösen?
  Mit Zitat antworten Zitat
Benutzerbild von Mackhack
Mackhack

Registriert seit: 29. Nov 2003
Ort: San Diego, CA/USA
1.446 Beiträge
 
Delphi 2006 Architect
 
#2

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 08:04
Brauchst du vlt. Delphi-Referenz durchsuchenWindows.SetParent?
Um etwas Neues zu schaffen muss man seine Ohren vor den Nein-sagern verschliessen um seinen Geist öffnen zu können.
(George Lukas)
  Mit Zitat antworten Zitat
Tom65

Registriert seit: 25. Jan 2005
15 Beiträge
 
#3

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 08:31
Soweit ich das sehe ist

Form2.SetParent(Form1);

das gleiche wie

Form2.Parent:= Form1;
  Mit Zitat antworten Zitat
Benutzerbild von Mackhack
Mackhack

Registriert seit: 29. Nov 2003
Ort: San Diego, CA/USA
1.446 Beiträge
 
Delphi 2006 Architect
 
#4

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 08:54
I hab ja auch Windows.SetParent geschrieben und net FormX.Parent. Dann hast du 2 Argumente die du uebergeben musst.
Kann mich aber auch taeuschen! Ist schon spaet hier!
Um etwas Neues zu schaffen muss man seine Ohren vor den Nein-sagern verschliessen um seinen Geist öffnen zu können.
(George Lukas)
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#5

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 09:32
Hallo.

Wenn aus irgendeinem Grund Frames keine akzeptable Lösung sind, dann darf es natürlich auch eine embedded form sein. Ich habe ein Demo-Projekt dazu angehängt. Wenn man die beispielhaften Controls nebst dem event handler ButtonClick() aus der ChildForm entfernt, dann kann man diese ChildForm als Template ins Object Repository stellen.

Grüße vom marabu
Angehängte Dateien
Dateityp: zip childdemo_141.zip (2,7 KB, 47x aufgerufen)
  Mit Zitat antworten Zitat
Tom65

Registriert seit: 25. Jan 2005
15 Beiträge
 
#6

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 12:29
Ich habe mir das Beispiel von Marabu angeschaut und es entsprechend modifiziert. Wenn das ChildFrm aktiv ist werden trotzdem alle Tastatureingaben, die im OnKeyDown-Ereignis definiert sind, vom DemoFrm(Hauptformular) abgefangen. Die Befehle im OnKeyDown-Ereignis vom ChildFrm werden nicht ausgeführt.

Viele Grüße

Tom
  Mit Zitat antworten Zitat
Benutzerbild von dataspider
dataspider

Registriert seit: 9. Nov 2003
Ort: 04539 Groitzsch
1.351 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 12:45
Hi Tom,

das liegt an der VCL. Ich habe mir an dem Problem auch schon die Zähne ausgebissen.
Jetzt mach ich es so, dass ich über einen Keyboardhook das Form ermittle und eine eigene Nachricht sende.
Dann gibt es noch die Möglichkeit, nicht mit Parent sondern wie schon beschrieben mit Windows.SetParent zu arbeiten. So hab ich mir mal ein FormPanel erstellt.

Delphi-Quellcode:
unit RW_FormPanel;

interface

uses
  Forms, Windows, Messages, Classes, Controls, ExtCtrls;

type
  TRWFormPanel = class(TCustomPanel)
  private
    FForm: TCustomForm;
    FFormSaveParent: THandle;
    FFormSavePosition: TPosition;
    FFormSaveStyle: Integer;
    FFormSaveStyleEx: Integer;
    FFormSaveVisible: Boolean;
    FFormSaveWindowPlacement: TWindowPlacement;
    procedure SetForm(Value:TCustomForm);
  protected
    procedure Notification(AComponent : TComponent; Operation : TOperation);
        override;
    procedure SizeChanged;
    procedure WMSize(var Message:TMessage); message WM_SIZE;
  public
    constructor Create(AOwner:TComponent); override;
    property Form: TCustomForm read FForm write SetForm;
  published
    property Align;
    property Alignment;
    property Anchors;
    property AutoSize;
    property BevelInner;
    property BevelOuter default bvNone;
    property BevelWidth;
    property BiDiMode;
    property BorderStyle;
    property BorderWidth;
    property Caption;
    property Color;
    property Constraints;
    property Ctl3D;
    property DockSite;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property Font;
    property FullRepaint;
    property OnCanResize;
    property OnClick;
    property OnConstrainedResize;
    property OnDblClick;
    property OnDockDrop;
    property OnDockOver;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetSiteInfo;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnStartDock;
    property OnStartDrag;
    property OnUnDock;
    property ParentBiDiMode;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property UseDockManager default True;
    property Visible;
  end;

implementation

procedure TRWFormPanel.Notification(AComponent : TComponent; Operation :
    TOperation);
begin
  inherited Notification( AComponent, Operation);
  if Assigned(FForm) then
    if (Operation = opRemove) and (AComponent = FForm) then
    begin
      // RemoveFreeNotification(AComponent);
      FForm := nil;
    end;
end;

procedure TRWFormPanel.SetForm(Value:TCustomForm);
begin
  try
    if (FForm = Value) then
      Exit;
    if csDesigning in ComponentState then
      Exit;

    // hat schon ein Form, also wiederherstellen
    if (FForm<>nil) and FForm.HandleAllocated then
    begin
      FForm.Visible := False;
      if not FFormSaveVisible then
        FFormSaveWindowPlacement.showCmd:=SW_HIDE;
      Windows.SetParent(FForm.Handle,FFormSaveParent);
      SetWindowPlacement(FForm.Handle,@FFormSaveWindowPlacement);
      SetWindowLong(FForm.Handle,GWL_STYLE,FFormSaveStyle);
      SetWindowLong(FForm.Handle,GWL_EXSTYLE,FFormSaveStyleEx);
      SetWindowPos(FForm.Handle,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE or
                   SWP_NOZORDER or SWP_FRAMECHANGED or SWP_NOACTIVATE);
      FForm.Visible := FFormSaveVisible;
      TForm(FForm).Position := FFormSavePosition;
    end;

    FForm:=Value;

    if FForm<>nil then
    begin
      FFormSaveStyle := GetWindowLong(FForm.Handle,GWL_STYLE);
      FFormSaveStyleEx := GetWindowLong(FForm.Handle,GWL_EXSTYLE);
      FFormSaveVisible := FForm.Visible;
      FFormSaveParent := GetParent(FForm.Handle);
      FFormSavePosition := TForm(FForm).Position;
      TForm(FForm).Position := poDesigned;

      GetWindowPlacement(FForm.Handle,@FFormSaveWindowPlacement);

      SetWindowLong(FForm.Handle,GWL_STYLE,(FFormSaveStyle or WS_CHILD)
          and not WS_OVERLAPPED and not WS_OVERLAPPEDWINDOW and not WS_CAPTION);
      SetWindowLong(FForm.Handle,GWL_EXSTYLE,FFormSaveStyleEx and not WS_EX_MDICHILD);
      Windows.SetParent(FForm.Handle,self.Handle);
      SetWindowPos(FForm.Handle,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE or
                   SWP_NOZORDER or SWP_FRAMECHANGED or SWP_NOACTIVATE);
      FForm.Left:=0;
      FForm.Top:=0;
      SizeChanged;
      // FForm.Visible:=True;
      // FForm.SetFocus;
      // Application.ProcessMessages;
      FForm.FreeNotification(Self);
    end;
  except
    FForm := nil;
    if csLoading in ComponentState then
      Application.HandleException(Self)
    else
      raise;
  end;
end;

procedure TRWFormPanel.SizeChanged;
begin
  FForm.Width := ClientWidth;
  FForm.Height := ClientHeight;
end;

procedure TRWFormPanel.WMSize(Var Message:TMessage);
begin
  inherited;
  if FForm <> nil then
    SizeChanged;
end;

constructor TRWFormPanel.Create(AOwner:TComponent);
begin
  inherited;
// BevelOuter := bvNone;
  Caption := '';
end;

end.
Vielleicht hilft es dir ja weiter.

Cu, Frank
Frank Reim
  Mit Zitat antworten Zitat
Tom65

Registriert seit: 25. Jan 2005
15 Beiträge
 
#8

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 15:59
@Dataspider

Vielen Dank für Deine Hilfe. Ich werde es testen.

Viele Grüße

Thomas
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#9

Re: Tastatureingabe an Formularen

  Alt 7. Sep 2006, 19:17
Hallo.

In meiner Demo bin ich aus Schusseligkeit nicht auf die Sache mit dem KeyPreview eingegangen. Hier eine erweiterte Demo, die etwas Licht auf dieses Problem wirft.

Dazu muss man wissen, dass Borland die ParentForm eines Controls für die Überprüfung der Eigenschaft KeyPreview ermittelt, indem es den Top-Level-Parent des Controls sucht. Dadurch arbeitet KeyPreview bei ChildForms nicht auf die übliche Weise. KeyPreview muss bei der ParentForm von ChildForm gesetzt werden und nur dort wird die Eigenschaft von den VCL-Machern auch ausgewertet.

Es gibt jetzt zwei Strategien zum Umgang mit der Misere - neben dem Ansatz von Frank, den ich mangels Zeit jetzt nicht nachvollzogen habe: Man berücksichtigt die Designschwäche und gestaltet die event handler OnKeyDown() etc. entsprechend (siehe Demo) oder man verkettet die event handler im Ereignis OnCreate() der ChildForm.

Man beachte die von mir überschriebene Funktion GetParentForm():

Delphi-Quellcode:
function GetParentForm(Control: TControl): TCustomForm;
begin
  Result := nil;
  while Assigned(Control.Parent) do
  begin
    Control := Control.Parent;
    if Control is TCustomForm then
    begin
      Result := TCustomForm(Control);
      Break;
    end;
  end;
end;
So erkenne ich im event handler der DemoForm, ob ein Tastendruck auf einem eigenen Control oder einem Control der ChildForm ausgelöst wurde.

marabu
Angehängte Dateien
Dateityp: zip childdemo_204.zip (3,0 KB, 17x aufgerufen)
  Mit Zitat antworten Zitat
Tom65

Registriert seit: 25. Jan 2005
15 Beiträge
 
#10

Re: Tastatureingabe an Formularen

  Alt 8. Sep 2006, 07:55
@ marabu

Vielen Dank für Deine Hilfe. Jetzt habe ich es verstanden.

Grüße!

Tom
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:01 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