在一个项目中,因为多个窗体共用一个模板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;

解决方案 »

  1.   

    在private部分加入下列代码:
    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;
      

  2.   

    to jinjazz(三个小时上下班)
    但我的窗体仅当鼠标在指定范围内单击并拖动窗体的,因为在无边框的窗体最上面用图片组成假边框,所以有
        //响应鼠标动作移动窗口
        //第一个按钮前面的区域
        //最后一个按钮后面不含系统按钮的区域
        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的,所以会有乱响应的错误,如何解决呢?我对消息这一方面不懂,这段代码只是从书上摘下来了的。
      

  3.   

    有两种方法:
    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;