在一个项目中,因为多个窗体共用一个模板Form,但所有的窗体都是没有边框的,都是响应模板Form的AppMessage,代码如下所示,但在实际运行中,当两个窗体部分相叠时会出现响应鼠标消息错位,明明想移动当前窗口,却把后面的主窗体给移动了,如何解决?模板Form的代码如下:procedure TfrmShell.FormCreate(Sender: TObject);
var
HandleRoundRect: THandle;
begin
//设置初始化大小及最大化的长宽值
GetFormWidthHeigth; //画圆角矩形
HandleRoundRect := CreateRoundRectRgn(0, 0, Width, Height, 11, 11);
SetWindowRgn(Handle, HandleRoundRect, true); //设置控件初始状态
pnlTop.DoubleBuffered := true;
pnlBottom.DoubleBuffered := true;
pnlLeft.DoubleBuffered := true;
pnlRight.DoubleBuffered := true;
pnlMain.DoubleBuffered := true;
IsMax := False; //设置系统按钮
sbMin := TSkinButton.Create(pnlTop);
sbMin.Parent := pnlTop;
sbMin.Anchors := [akTop, akRight, akBottom];
sbMin.SkinButtonStyle := sbsMin;
sbMin.Top := 8;
sbMin.Left := pnlTop.Width - 48;
sbMin.OnClick := SkinButtonClick; sbMax := TSkinButton.Create(pnlTop);
sbMax.Parent := pnlTop;
sbMax.Anchors := [akTop, akRight, akBottom];
if WindowState = wsMaximized then
sbMax.SkinButtonStyle := sbsNormal;
if WindowState = wsNormal then
sbMax.SkinButtonStyle := sbsMax;
sbMax.Top := 8;
sbMax.Left := pnlTop.Width - 35;
sbMax.OnClick := SkinButtonClick; sbClose := TSkinButton.Create(pnlTop);
sbClose.Parent := pnlTop;
sbClose.Anchors := [akTop, akRight, akBottom];
sbClose.Top := 8;
sbClose.Left := pnlTop.Width - 22;
sbClose.OnClick := SkinButtonClick; //响应消息
Application.OnMessage := AppMessage;
Application.OnHint := DisplayHint;
end;
procedure TfrmShell.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
APoint: TPoint;
begin
if Msg.Message = WM_LBUTTONDOWN then
begin
APoint := ScreenToClient(Msg.pt); //响应鼠标动作移动窗口
//第一个按钮前面的区域
//最后一个按钮后面不含系统按钮的区域
if (APoint.Y < pnlTop.Height) and
(
(APoint.X < Width - 50) or (APoint.Y >= pnlTop.Height - 22)
) and
not (IsMax)
then
begin
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCaption, GetMessagePos);
Handled := true;
end; //缩放窗口的动作
if (APoint.X > Width - 15) and (APoint.Y > Height - 22) and not (IsMax) then
begin
SendMessage(Handle, WM_NCLBUTTONDOWN, HTBottomRight, GetMessagePos);
Handled := true;
end;
end;
end;
var
HandleRoundRect: THandle;
begin
//设置初始化大小及最大化的长宽值
GetFormWidthHeigth; //画圆角矩形
HandleRoundRect := CreateRoundRectRgn(0, 0, Width, Height, 11, 11);
SetWindowRgn(Handle, HandleRoundRect, true); //设置控件初始状态
pnlTop.DoubleBuffered := true;
pnlBottom.DoubleBuffered := true;
pnlLeft.DoubleBuffered := true;
pnlRight.DoubleBuffered := true;
pnlMain.DoubleBuffered := true;
IsMax := False; //设置系统按钮
sbMin := TSkinButton.Create(pnlTop);
sbMin.Parent := pnlTop;
sbMin.Anchors := [akTop, akRight, akBottom];
sbMin.SkinButtonStyle := sbsMin;
sbMin.Top := 8;
sbMin.Left := pnlTop.Width - 48;
sbMin.OnClick := SkinButtonClick; sbMax := TSkinButton.Create(pnlTop);
sbMax.Parent := pnlTop;
sbMax.Anchors := [akTop, akRight, akBottom];
if WindowState = wsMaximized then
sbMax.SkinButtonStyle := sbsNormal;
if WindowState = wsNormal then
sbMax.SkinButtonStyle := sbsMax;
sbMax.Top := 8;
sbMax.Left := pnlTop.Width - 35;
sbMax.OnClick := SkinButtonClick; sbClose := TSkinButton.Create(pnlTop);
sbClose.Parent := pnlTop;
sbClose.Anchors := [akTop, akRight, akBottom];
sbClose.Top := 8;
sbClose.Left := pnlTop.Width - 22;
sbClose.OnClick := SkinButtonClick; //响应消息
Application.OnMessage := AppMessage;
Application.OnHint := DisplayHint;
end;
procedure TfrmShell.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
APoint: TPoint;
begin
if Msg.Message = WM_LBUTTONDOWN then
begin
APoint := ScreenToClient(Msg.pt); //响应鼠标动作移动窗口
//第一个按钮前面的区域
//最后一个按钮后面不含系统按钮的区域
if (APoint.Y < pnlTop.Height) and
(
(APoint.X < Width - 50) or (APoint.Y >= pnlTop.Height - 22)
) and
not (IsMax)
then
begin
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCaption, GetMessagePos);
Handled := true;
end; //缩放窗口的动作
if (APoint.X > Width - 15) and (APoint.Y > Height - 22) and not (IsMax) then
begin
SendMessage(Handle, WM_NCLBUTTONDOWN, HTBottomRight, GetMessagePos);
Handled := true;
end;
end;
end;
procedure wmnchittest(var msg:twmnchittest);
message wm_nchittest;
在程序部分加入以下代码:
procedure TForm1.wmnchittest(var msg:twmnchittest);
begin
inherited;
if (htclient=msg.result) then msg.result:=htcaption;
end;
但我的窗体仅当鼠标在指定范围内单击并拖动窗体的,因为在无边框的窗体最上面用图片组成假边框,所以有
//响应鼠标动作移动窗口
//第一个按钮前面的区域
//最后一个按钮后面不含系统按钮的区域
if (APoint.Y < pnlTop.Height) and
(
(APoint.X < Width - 50) or (APoint.Y >= pnlTop.Height - 22)
) and
not (IsMax)
then
begin
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCaption, GetMessagePos);
Handled := true;
end;
这段代码,先判断坐标,再决定是否发消息,但这个消息是对整个application的,所以会有乱响应的错误,如何解决呢?我对消息这一方面不懂,这段代码只是从书上摘下来了的。
1。发送移动的消息让窗口移动,但这个方法在9X系统下会有一些小问题:
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
ReleaseCapture;
perform(WM_SysCommand, $F012, 0);
end;2。就是自己来实现了:
var
MPos:TPoint;
bMove:Boolean;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
MPos.X := X;
MPos.Y := Y;
end;procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if bMove then
begin
TForm(Sender).Left := TForm(Sender).Left - (MPos.X-X);
TForm(Sender).Top := TForm(Sender).Top - (MPos.Y-Y);
end;
end;procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
bMove :=False;
end;