procedure TfrmMain.CreateTabSheet( myFormClass: TFormClass;var Reference: TForm);  
var  
MyForm : TForm;  
begin  
tabsheet := TRzTabSheet.Create(RpgcMain);  
try  
tabsheet.Caption := Reference.Caption;  
tabsheet.PageControl := RpgcMain;  
tabsheet.Name := stabsheetname;  
MyForm := myFormClass.Create(tabsheet);  
try  
MyForm.Parent := tabsheet;  
MyForm.BorderStyle := bsnone;  
MyForm.WindowState := wsmaximized;  
RpgcMain.ActivePage := tabsheet;  
MyForm.Show;  
except  
FreeAndNil(MyForm);  
end;  
except  
FreeAndNil(tabsheet);  
end;  
end;  把窗体放入PageControl后,PageControl中Form内的快捷键处理。procedure TForm1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
  function GetMyParentForm(Control: TControl): TCustomForm;
  begin
    Result := nil;
    while Control.Parent <> nil do
    begin
      Control := Control.Parent;
      if Control is TCustomForm then
      begin
        Result := TCustomForm(Control);
        Break
      end
    end;
  end;
var
  ParentForm : TCustomForm;
begin
  ParentForm := GetMyParentForm(ActiveControl);
  if ParentForm <> nil then
  begin
    if (ParentForm is TCustomForm) and
     (ParentForm.Parent is TTabSheet) then
    begin
      ParentForm.IsShortCut(Msg);
    end;
  end;
问题来了,PageControl中Form输入操作会频繁出现失去焦点的问题。edit等不能输入,需要关闭窗口,重新开启后才能输入。请问问题出在那里,如何解决?

解决方案 »

  1.   

    你在TForm1中OnShortCut触发快捷键,为什么还要找父窗体的的快捷键事件?你这样就相当于触发父窗体的快捷键,导致焦点切换了。
      

  2.   

    我記得之前 有提供另外的方案解決這種 嵌入式窗體的快捷鍵問題——windows.SetParent。因為目前的做法,需要程序自己控制消息的走向,需要考慮的地方也比較多。所以建議你采用API來嵌入....
      

  3.   


    windows.SetParent 未能解决子窗体的快捷码的问题,请赐教!谢谢!
      

  4.   


    子窗放以主窗体的PageControl作为容器,子窗体上有快捷码,需触发快捷码。
      

  5.   

    procedure TfrmMain.CreateTabSheet( myFormClass: TFormClass;var Reference: TForm);   
    var   
    MyForm : TForm;   
    begin   
    tabsheet := TRzTabSheet.Create(RpgcMain);   
    try   
    tabsheet.Caption := Reference.Caption;   
    tabsheet.PageControl := RpgcMain;   
    tabsheet.Name := stabsheetname;   
    MyForm := myFormClass.Create(tabsheet);   
    try   
    MyForm.Parent := tabsheet;   
    MyForm.BorderStyle := bsnone;   
    MyForm.WindowState := wsmaximized;   
    RpgcMain.ActivePage := tabsheet; 
    MyForm.Show;   
    windows.SetParent(MyForm.Handle, tabsheet.Handle);  
    except   
    FreeAndNil(MyForm);   
    end;   
    except   
    FreeAndNil(tabsheet);   
    end;   
    end;  不行,快捷码不起作用。
      

  6.   

    是你的程序寫得有問題, 我還特地寫了小程序驗證了一下:
    1、FormA 有快捷鍵 Ctrl + A, FormB有快捷鍵 Ctrl + A;
    2、FormB嵌入FormA中的Panel——windows.SetParent;
    3、執行程序,焦點移到FormB,按 Ctrl + A, 執行的是FormB的動作,FORMA的不會被響應到由此說明,這種方式是可以解決你的問題的。
      

  7.   

    剛看了一下你貼的程序:
    MyForm := myFormClass.Create(tabsheet);   
    try   
    MyForm.Parent := tabsheet;   
    MyForm.BorderStyle := bsnone;   
    MyForm.WindowState := wsmaximized;   
    RpgcMain.ActivePage := tabsheet;  
    MyForm.Show;   
    windows.SetParent(MyForm.Handle, tabsheet.Handle);   
    except   
    FreeAndNil(MyForm);   
    end;   
    except   
    FreeAndNil(tabsheet);   
    end; 
    紅色部分去掉,改為procedure TfrmMain.CreateTabSheet( myFormClass: TFormClass;var Reference: TForm);   
    var   
      MyForm : TForm;   
    begin   
      tabsheet := TRzTabSheet.Create(RpgcMain);   
      try   
        tabsheet.Caption := Reference.Caption;   
        tabsheet.PageControl := RpgcMain;   
        tabsheet.Name := stabsheetname;   
        MyForm := myFormClass.Create(tabsheet);   
        try   
          MyForm.BorderStyle := bsnone;    
          MyForm.WindowState := wsmaximized;   
          RpgcMain.ActivePage := tabsheet;  
          windows.SetParent(MyForm.Handle, tabsheet.Handle);   
          MyForm.Show;   
        except   
          FreeAndNil(MyForm);   
        end;   
      except   
        FreeAndNil(tabsheet);   
      end;   
    end; 
      

  8.   

    源码如下:
    快捷方式没有题了,但不能完整显示frmBase2窗口的内容。program Project1;uses
      Forms,
      Unit1 in 'Unit1.pas' {frmMain},
      base in 'base.pas' {frmBase},
      Unit2 in 'Unit2.pas' {frmBase2};{$R *.res}begin
      Application.Initialize;
      Application.CreateForm(TfrmMain, frmMain);
      Application.CreateForm(TfrmBase2, frmBase2);
      Application.Run;
    end.unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, base, StdCtrls, RzTabs, ExtCtrls, RzPanel, RzSplit;   const WM_PCFORMCLOSE = WM_USER + 100;
    type
      TBaseFormClass = class of TfrmBase;
      TfrmMain = class(TForm)
        rzszpnl1: TRzSizePanel;
        rzszpnl2: TRzSizePanel;
        cMain: TRzPageControl;
        TabSheet1: TRzTabSheet;
        btn1: TButton;
        btn2: TButton;
        btn3: TButton;
        btn4: TButton;
        procedure btn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        tabsheet : TRzTabSheet;
        PageControlIndex:integer;
        function getPageControlSheetName(str: String):Boolean;
        procedure AddTabSheet(tabCaption:String;myFormClass: TBaseFormClass;ParentFrom: TForm; aID: Integer; aName: string; var Form: TForm);
        procedure FreePageControl;
        procedure PCFormClose(var msg:TMessage); message WM_PCFORMCLOSE;
        procedure SheetClose;
      end;var
      frmMain: TfrmMain;implementationuses Unit2;{$R *.dfm}function TfrmMain.getPageControlSheetName(str: String):Boolean;
    var i : Integer;
        strName : String;
    begin
      Result := False;
      For i := 0 to (Self.CMain.PageCount - 1) do begin
        strName := Trim(Self.CMain.Pages[i].Name);
        pagecontrolindex := Self.CMain.Pages[i].PageIndex;
        if strName = Trim(str) then
        begin
          Result := True;
          Break;
        end;
      end;
    end;procedure TfrmMain.AddTabSheet(tabCaption:String;myFormClass: TBaseFormClass;ParentFrom: TForm; aID: Integer; aName: string; var Form: TForm);
    procedure PageControlVisible;
    begin
      if CMain.Visible = false then
        CMain.Visible := true;
    end;
    begin
      if Self.getPageControlSheetName(aName) then //已经存在
      begin
        CMain.ActivePageIndex := PageControlIndex; //显示出来
        pagecontrolVisible;
      end
      else //创建
      begin
        tabsheet := TRzTabSheet.Create(CMain);
      try
        tabsheet.Caption := TabCaption;
        tabsheet.PageControl := CMain;
        tabsheet.Name := aName;
        Form := myFormClass.CreateWithFunction(ParentFrom, aID, aName);
        try
          cMain.ActivePage := tabsheet;
          Form.BorderStyle := bsnone;
          form.align:=alClient;
          windows.SetParent(Form.Handle, tabsheet.Handle);
          Form.Show;
        except
          FreeAndNil(Form);
        end;
      except
        FreeAndNil(tabsheet);
      end;
      pagecontrolVisible;
      end;
    end;
    procedure TfrmMain.FreePageControl;
    var ncount : Integer;
    begin
      ncount := Self.CMain.PageCount;
      try
        if ncount > 0 then begin
          Self.CMain.ActivePage.Free;
          if ncount > 1 then
            Self.CMain.ActivePageIndex := ncount - 2
          else
            Self.CMain.Visible := False;
        end;
      except  end;  
    end;procedure TfrmMain.PCFormClose(var msg: TMessage);
    begin
       FreePageControl;
    end; procedure TfrmMain.SheetClose;
     begin
       with CMain do begin
       if PageCount>0 then
         ActivePage.free;
         Visible:=PageCount>0;
       end;
     end;procedure TfrmMain.btn1Click(Sender: TObject);
    begin
      Self.AddTabSheet('单据1',TfrmBase2,Self,1,'tab1',TForm(frmBase2));
    end;end.
    unit base;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls, DBGridEh, DB;type
      TfrmBase = class(TForm)
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormKeyPress(Sender: TObject; var Key: Char);
      private
        { Private declarations }
      protected
         iID: Integer;
         sName: String;
         hand:string;
         function IsTEdit():Boolean; virtual;
         procedure StrToStringList(sStr, sFh : String; vLst : TStrings);
         procedure ExportDBGridEh(CustomDBGridEh:TDBGridEh);
      public
        Constructor CreateWithFunction(AOwner: TComponent; aID:Integer; aName:String);
        { Public declarations }
      end;var
      frmBase: TfrmBase;implementation
    uses DBGridEhImpExp;
    {$R *.dfm}
    Constructor TfrmBase.CreateWithFunction(AOwner: TComponent; aID:Integer; aName:String);
    begin
      iID:=aID;
      sName:=aName;
    Inherited Create(AOwner);
    end;function TfrmBase.IsTEdit: Boolean;
    begin
       if (ActiveControl is TCustomEdit) or
           (ActiveControl is TCustomComboBox) or
           (ActiveControl is TDateTimePicker)
           then Result:=True
       else
           Result:=False;
    end;
    procedure TfrmBase.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action:=cafree;
    end;procedure TfrmBase.StrToStringList(sStr, sFh : String; vLst : TStrings);
    var 
      Str : String;
    begin 
      Str := sStr;
      while Length(Str) >0 do
      begin
        if pos(sFh, Str) > 0 then
        begin
          vLst.Add(Copy(str, 1, Pos(sFh, Str) - 1));
          Str := Copy(Str, Pos(sFh, Str) + 1, Length(Str));
        end
        else begin
          vLst.Add(Str);
          Str :='';
        end;
      end;
    end;
    procedure TfrmBase.ExportDBGridEh(CustomDBGridEh:TDBGridEh);
    var
      ExpClass:TDBGridEhExportClass;
      Ext:string;
      SaveDlg:TSaveDialog;
    begin
      if CustomDBGridEh.DataSource.DataSet.IsEmpty then Exit;
      SaveDlg:=TSaveDialog.Create(nil);
      SaveDlg.Filter:='Microsoft Excel 工作簿 (*.xls)|*.xls|文本文档 (*.txt)|*.txt|CSV(逗号分隔) (*.csv)|*.csv|Web 页 (*.htm)|*.htm|RTF 格式 (*.rtf)|*.rtf';
      SaveDlg.FileName:='';
      SaveDlg.DefaultExt:='xls';
      if SaveDlg.Execute then
      begin
        case SaveDlg.FilterIndex of
          1: begin
               ExpClass:=TDBGridEhExportAsXLS;
               Ext:='xls';
             end;
          2: begin
               ExpClass:=TDBGridEhExportAsText;
               Ext:='txt';
             end;
          3: begin
               ExpClass:=TDBGridEhExportAsCSV;
               Ext:='csv';
             end;
          4: begin
               ExpClass:=TDBGridEhExportAsHTML;
               Ext:='htm';
             end;
          5: begin
               ExpClass:=TDBGridEhExportAsRTF;
               Ext:='rtf';
             end;
          else
             ExpClass:=nil;
        end;
        if ExpClass<>nil then
        begin
          if UpperCase(Copy(SaveDlg.FileName,Length(SaveDlg.FileName)-2,3))<>UpperCase(Ext) then
            SaveDlg.FileName:=SaveDlg.FileName+'.'+Ext;
          SaveDBGridEhToExportFile(ExpClass,CustomDBGridEh,SaveDlg.FileName,True);
        end;
      end;
      SaveDlg.Destroy;
    end;
    procedure TfrmBase.FormKeyPress(Sender: TObject; var Key: Char);
    begin
      if key = #13 then
      begin
      if IsTEdit then
        begin
          Key:= #0;
          Perform(WM_NEXTDLGCTL,0,0);
        end
      end;
    end;end.
    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, base, ActnList, StdCtrls, ExtCtrls, RzPanel, RzSplit, RzTabs;type
      TfrmBase2 = class(TfrmBase)
        rzpgcntrl1: TRzPageControl;
        rztbshtTabSheet1: TRzTabSheet;
        rztbshtTabSheet2: TRzTabSheet;
        rzszpnl1: TRzSizePanel;
        lbl1: TLabel;
        btn1: TButton;
        lbl2: TLabel;
        btn2: TButton;
        actlst1: TActionList;
        act1: TAction;
        act2: TAction;
        btn3: TButton;
        procedure act1Execute(Sender: TObject);
        procedure act2Execute(Sender: TObject);
        procedure btn3Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      frmBase2: TfrmBase2;implementationuses Unit1;{$R *.dfm}procedure TfrmBase2.act1Execute(Sender: TObject);
    begin
      inherited;
      ShowMessage('ok');
    end;procedure TfrmBase2.act2Execute(Sender: TObject);
    begin
      inherited;
      ShowMessage('ok地');
    end;procedure TfrmBase2.btn3Click(Sender: TObject);
    begin
      inherited;
      PostMessage(frmMain.Handle,WM_PCFORMCLOSE,Integer(TForm(Sender).Parent),Integer(TForm(self)));
    end;end.
      

  9.   

    子窗體大小變小時,超出的部分,不是會出現滾動條嗎?這種情況用VCL的Parent也一樣存在,與此問題無關....
      

  10.   

    測試了一下,在BorderStyle = bsnone時,滾動條不會自己出現。若非bsnone,則會自動出現滾動條。所以看你實際需要,是否要把BorderStyle 設為 bsnone
      

  11.   

    另一個解法是,設置bsnone之后,再設置AutoScroll:
      FormB.BorderStyle := bsNone;
      FormB.AutoScroll := True;
      

  12.   

    窗体部分的内容无论大小,左边与下边的都不能显示,但使用MyForm.Parent := tabsheet;语句后可以完整显示,且正常。我试了,感觉是把子窗体宽高设置为主窗体的宽度,导致右边与下边不能显示。(注:上边在工具条,左边有导航条。)
      

  13.   

    你又自己設置“子窗体宽高设置为主窗体的宽度”? 前面不是已設置了windowState 為max嗎?
      

  14.   

    没有,我是说现在出来的结果是那样子,我在左边放置panl,一部看不见,一部份看到!
      

  15.   

    使用MyForm.Parent := tabsheet;后可以正确显示
      

  16.   

    1、按前面的寫法scrollbar有沒有出來?
    2、windowState是否設置為max?
    3、請認真比對我說的寫法...