[梦幻心得-2]如何不用MDI方式在Form1上显示Form2(0分)

  • 主题发起人 主题发起人 DreamTiger
  • 开始时间 开始时间
D

DreamTiger

Unregistered / Unconfirmed
GUEST, unregistred user!
假设你需要在TForm1的Panel1上显示TForm2,最简单的方法是改写TForm2.
TForm2=class(TForm)
private
...
public
constructor Create(AOwner: TComponent); override;
end;

implementation

constructor TForm2.Create(AOwner: TComponent);
begin
inherited;
Parent := (AOwner as TWinControl);
ParentWindow := (AOwner as TWinControl).Handle;
end;

同时设置TForm2的BorderStyle为bsNone,WindowState为wsMaximized。

在TForm1的调用时候:
procedure TForm1.FormCreate(Sender: TObject);
begin
with TForm2.Create(Panel1) do
Show;
end;

或许有人要问,为什么不直接用TFrame,而要这么费事用TForm。其实,
最早我也用TFrame实现一些功能,但是,后来发现如果TForm2中需要用
到一些消息控制,用TFrame方式,就无法接受消息,具体原因还没有查
过。不过,我觉得这种方式还是蛮不错的。
 
不错,不过有个问题:在form2(子窗口)上的按键似乎会激活form1(主窗口)上的菜单热键。
比如,form1上有菜单: 文件(&F) ,在form2的memo1里面按F,就会调出form1的[文件]菜单,
而不是输入字符F

如果这个问题能解决就完美了!
 
这个我倒是没有遇到过。不清楚怎么回事,如果你寄给我你的代码,我可以看看。
shengqh@263.net
 
入坞出坞可不可以呀?
 
学习了。
 
>入坞出坞可不可以呀?
什么意思?
 
那如何才能检测form2已经有了,我用了几种方法都不行
如果有了就不用再创建了
 
检测窗体实例是否存在:
if not Assigned(form2) then
form2:=Tform.create......
 
很简单啊,就这样好了——
var form2:tform2;
begin
form2:=tform2.Create(application);
form2.Parent:=panel1; //就是这一句啊。
form2.Align:=alclient;
form2.Show;
end;
 
doxpix的方法最好,DreamTiger, 好象如果主窗体如果也是动态生成的就不行了,
我是菜鸟,试了一下是这样!
 
我用d6,下面是三个unit,unit2,unit3都是动态创建,
同时unit3会创建在unit2的panel1上,测试没问题。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
with TForm2.Create(Self) do
Show;
end;

end.

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Unit3;

type
TForm2 = class(TForm)
Panel1: TPanel;
procedure FormCreate(Sender: TObject);
private
FForm3:TForm3;
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
FForm3 := TForm3.Create(Panel1);
FForm3.Show;
end;

end.


unit Unit3;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm3 = class(TForm)
Label1: TLabel;
private
{ Private declarations }
public
constructor Create(AOwner: TComponent); override;
end;

var
Form3: TForm3;

implementation

{$R *.dfm}

constructor TForm3.Create(AOwner: TComponent);
begin
inherited;
Parent := (AOwner as TWinControl);
ParentWindow := (AOwner as TWinControl).Handle;
end;

end.
 
可以利用窗体和控件的停泊功能实现。
这是主窗体:
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Buttons, ComCtrls;

type
TForm1 = class(TForm)
LeftDockPanel: TPanel;
LeftSplitter: TSplitter;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
SpeedButton1: TSpeedButton;
StatusBar1: TStatusBar;
BitBtn3: TBitBtn;
procedure LeftDockPanelDockOver(Sender: TObject;
Source: TDragDockObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
procedure LeftDockPanelDockDrop(Sender: TObject;
Source: TDragDockObject; X, Y: Integer);
procedure BitBtn1Click(Sender: TObject);
procedure LeftDockPanelUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean);
procedure BitBtn2Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
HOLDCURSOR:HCURSOR;// Cursor temp Var
implementation

uses DocUnit;

{$R *.dfm}

procedure TForm1.LeftDockPanelDockOver(Sender: TObject;
Source: TDragDockObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
var
ARect: TRect;
begin
Accept := Source.Control is TDockableForm;
if Accept then
begin
//修改预览停靠位置
ARect.TopLeft := LeftDockPanel.ClientToScreen(Point(0, 0));
ARect.BottomRight := LeftDockPanel.ClientToScreen(
Point(Self.ClientWidth div 4, LeftDockPanel.Height));
Source.DockRect := ARect;
end;
end;

procedure TForm1.LeftDockPanelDockDrop(Sender: TObject;
Source: TDragDockObject; X, Y: Integer);
begin
LeftDockPanel.Width := ClientWidth div 4;
LeftSplitter.Left := LeftDockPanel.Width + LeftSplitter.Width;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
Var
DockMe:Boolean;
begin
DockableForm.show;
DockableForm.Visible:=true;
DockMe:=DockableForm.ManualDock(Form1.LeftDockPanel,nil,alleft);
if not DockMe then
ShowMessage('Don''t Dock Form2 to LeftPanel');
end;

procedure TForm1.LeftDockPanelUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean);
begin
LeftDockPanel.Width:=0;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
form1.ScaleBy(4,3);
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
form1.ScaleBy(3,4);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
HNEWCURSOR:HCURSOR; // Cursor Temp var
begin
BitBtn3.Caption:='关闭光标';
HNEWCURSOR:=LOADCURSORFROMFILE('D:/WINNT/Cursors/horse.ani');
{调用API函数装载动画光标文件,ANI文件路径请根据自己的实际情况进行调整}
HOLDCURSOR:=SETCLASSLONG(FORM1.Handle,GCL_HCURSOR,HNEWCURSOR);
{把原光标储存起来以备以后的恢复}
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
begin
HOLDCURSOR:=SETCLASSLONG(FORM1.HANDLE,GCL_HCURSOR,HOLDCURSOR);
end;
end.

这个第二个窗体
unit DocUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;

type
TDockableForm = class(TForm)
Image1: TImage;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
DockableForm: TDockableForm;

implementation

uses MainUnit;

{$R *.dfm}

procedure TDockableForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Form1.LeftDockPanel.Width := 0;
Action := caHide
end;
end.


运行时第二个窗体自动被放到第一个窗体中停泊。
我们还可以利用TabControl和PageControl等控件停泊多个窗体,就像delphi的代码编辑器一样了
 
奇怪,我好像回答过这个贴子,名字呢?
我是说你指定Parent试过没有啊?

好奇怪。你把你的小例子弄过来,把要求说说
我帮你调调吧

Nizvoo@etang.com
 
我按你的方法试了,可是在语句
Parent := (AOwner as TWinControl);
出现错误提示“project project1.exe raised exception class InValidcast with message '
invalid class typecast'.” 怎么会出现这样的问题?其实,我先前按《Delphi5开发人员指南》
中的例题做,也没成功。它是利用如下方法的,在form2中:
constructor Create(Aowner:Tcomponent;Aparent:Twincontrol);override;
begin
inherited Create(Aowner,Aparent);
end;
在form1中调用form2时:
if not assigned(Form2) then
Form2:=Tform2.Create(application,panel1);
可是,也不行,在语句:
form2:=tform2.create(application,panel1);
提示:
Too many actual parameters
不知为什么!
 
这样做是有问题的,Form2是没可能真正获得焦点的,
另外Parent := (AOwner as TWinControl);
下面一句:ParentWindow := (AOwner as TWinControl).Handle;就不用了;

在inherited前最好判断一下
begin
if (AOwner is TWinControl) then
begin
inherited;
Parent := (AOwner as TWinControl);
end else
Raise exception.create('Error');
end;
 
后退
顶部