关于窗体移动 ( 积分: 100 )

  • 主题发起人 主题发起人 tuorx
  • 开始时间 开始时间
T

tuorx

Unregistered / Unconfirmed
GUEST, unregistred user!
目前我在做控件时遇到了一个问题,描述如下:
我编写了一个类似于TEdit的控件,放到窗体Form1上,名字叫TEdit1,当焦点进入时,会弹出另外一个窗体Form2,离开时关闭Form2;但Form1在移动位置时,Form2的位置不移动。如果不考虑自定义控件,在Form1里通过消息对移动事件进行捕获,可以将Form2一起移动。但要考虑在控件里做,如何实现?
不在控件里做,捕获代码如下:
procedure WMMOVE(var msg: TWMMOVE);message WM_MOVE;

procedure TForm1.WMMOVE(var msg: TWMMOVE);
begin
Form2移动的计算....
end;

检索功能也不能用,请大家帮助解决一下,谢谢。
 
Form1移动时,其中的控件也会收到相应的消息,至少有两个

WM_WINDOWPOSCHANGING //位置即将改变
WM_WINDOWPOSCHANGED //位置改变完成

procecdure TMyEdit.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
// Form2移动的计算....
end;
 
我做了个测试程序,发现不行,
捕获WM_WINDOWPOSCHANGING 和 WM_WINDOWPOSCHANGED 消息,
在Form1 显示时,会有消息传出,但是显示结束后,
再移动Form1的位置,就不会有消息传出了,不知道怎么回事。
请指点。
 
控件? 你是想把form封装成一个控件?
给他一个onmove事件,再事件里调用其他窗体的移动
我的测试例子:
{unit1是form控件
unit2是主窗体,生成Tform1的实例
unit3是始终在最上面的跟随Tform1实例移动的窗体}

unit Unit1;

interface

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

type
TFrmMove=procedure(Sender:TObject;IncX,IncY:integer) of Object;

TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
ox,oy:integer;
FOnMove:TFrmMove;
procedure WMMove(var Message: TWMMove); message WM_MOVE;
public
{ Public declarations }
property OnMove:TFrmMove read FOnMove write FOnMove;
end;


implementation

{$R *.dfm}

procedure TForm1.WMMove(var Message: TWMMove);
begin
inherited;
if assigned(FOnMove) then
FOnMove(self,message.XPos-ox,message.YPos-oy);
ox:=message.XPos;
oy:=message.YPos;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ox:=Left;
oy:=Top;
end;

end.
//-------------------------------------------------------
unit Unit2;

interface

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

type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure FrmDblClick(Sender: TObject);
procedure frmmove(Sender:TObject;IncX,IncY:integer);
public
{ Public declarations }

end;

var
Form2: TForm2;

implementation
uses unit1,unit3;
{$R *.dfm}

procedure TForm2.frmmove(Sender:TObject;IncX,IncY:integer);
begin
if form3.Showing then
form3.SetBounds(form3.Left+incx,form3.Top+incy,form3.Width,form3.Height);
end;

procedure TForm2.Button1Click(Sender: TObject);
var
frm:tform1;
begin
frm:=tform1.Create(self);
frm.OnMove:=frmmove;
frm.OnDblClick:=FrmDblClick;
frm.Show;
end;

procedure TForm2.FrmDblClick(Sender: TObject);
begin
form3.Show;
end;

end.
//-------------------------------------------------------
unit Unit3;

interface

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

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

var
Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.FormCreate(Sender: TObject);
begin
self.FormStyle:=fsStayOnTop;
end;

end.
 
我的意思是这样:
我从TCustomEdit继承了一个自定义类:TEditInfo,
重写了TEditInfo的DoEnter事件,在进入时,调用窗体Form2,FormStyle属性为fsStayOnTop。

在使用TEditInfo时,新建Form1,在上面放上TEditInfo控件,名字为EditInfo1,
在EditInfo1获得焦点时,Form2可以正常弹出,但是Form1移动时,Form2的位置还在
原位置,我想让Form2的位置跟着Form1的移动而变化,Form2是在TEditInfo里创建的,
在Form1里看不到,而且也不能对每一个使用TEditInfo的Form进行单独捕获移动消息,
我想怎么从TEditInfo里捕获到其父窗体的移动,通过捕获WM_WINDOWPOSCHANGING 和 WM_WINDOWPOSCHANGED 消息,在Form1 显示时,会有消息传出,但是显示结束后,
再移动Form1的位置,就不会有消息传出了,不知道怎么做,请指点。
 
......这样啊.......我建议你 别费事去截什么消息了,如果你的form2是TEditInfo创建出来的话,那么只需要加一句话:

假设你的TEditInfo控件弹出的窗体名为frm,创建form2时这样:
var
frm:tform;
begin
frm:=tform.Create(self);
// frm.SetBounds(Left+100,Top+100,100,100); 定位和大小
frm.Parent:=self.parent; //加上这个 frm就自己跟着窗口走了
frm.Show;
end;
 
这样做可以跟着走,
但是Form2创建后,窗体上的控件就接收不到焦点了。
不知道有什么高招?
 
哦........看到了.....暂时找不到解决办法......

你为什么一定要用个form? 既然要跟随着走,用个panel不就行了?
让panel.parent:=EditInfo.parent;
 
主要是要把TEditInfo做成一个控件,而且Form2上有好多
控件,而且只有当TEditInfo进入的时候才需要调入Form2,
所以考虑用Form实现,离开时释放。
 
恩.....如果form本身不移动的话,可以考虑用这个:form.ManualDock(self);
 
好象达不到跟随移动的效果,
郁闷了。
 
在産生FORM2時你可以設置其的TOP和LEFT跟隨FORM1變化而變化。這樣就會移動了。
 
怎么设置?
而且Form2是在自定义控件里创建的,
自定义组件是放在Form1上,
现在想让Form1移动时,Form2跟着动
 
真不好意思,上次没测试清楚
重新测试一下,真的不行,窗体移动后,Edit不会收到任何消息
只有接管Form1的消息了

type
TEditInfo = class(TCustomEdit)
private
FForm: TForm;
FSaveFormProc: TWndMethod;
procedure NewFormProc(var Message: TMessage);
procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
procedure CMExit(var Message: TCMExit); message CM_EXIT;
protected
procedure AdjustPosition;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

implementation

{ TEditInfo }

procedure TEditInfo.AdjustPosition;
begin
if FForm = nil then Exit;
FForm.Left := ClientOrigin.X;
FForm.Top := ClientOrigin.Y + Height;
end;

constructor TEditInfo.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if AOwner is TCustomForm then //如果AOnwer是Form就接管消息
with TCustomForm(AOwner) do
begin
FSaveFormProc := WindowProc; //保存Form的消息处理过程
WindowProc := NewFormProc; //设置Form新的消息处理过程
end;
FForm := TForm.Create(nil);
FForm.FormStyle := fsStayOnTop;
FForm.Visible := False;
FForm.FreeNotification(Self);
end;

destructor TEditInfo.Destroy;
begin
if FForm <> nil then
FForm.Free;
inherited Destroy;
end;

procedure TEditInfo.NewFormProc(var Message: TMessage);
begin
FSaveFormProc(Message); //用保存的过程处理消息
if Message.Msg = WM_MOVE then //如果是移动消息,再处理
AdjustPosition;
end;

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

procedure TEditInfo.CMExit(var Message: TCMExit);
begin
inherited;
if FForm <> nil then
FForm.Visible := False;
end;

procedure TEditInfo.CMEnter(var Message: TCMEnter);
begin
inherited;
if FForm <> nil then
begin
FForm.Visible := True;
AdjustPosition;
end;
end;
 
谢谢 问题解决了,
高手还是挺多的啊。
 
这种写法好像不太符合OO标准......
 
后退
顶部