我做了一个不规则窗体(form1),上面有一个image1,窗体的borderstyle我设为bsNone,现在我想通过拖动image1实现整个form1的拖动,请问如何实现?

解决方案 »

  1.   

    如何创建异形窗体
    在Windows中有时因为需要需创建一个异形窗体,我们可以利用Windows API函数SetWindowRgn()达到目的,在Window单元中它是这样声明的:
    int SetWindowRgn(
    HWND hWnd, // 要改变窗口的句柄 
    HRGN hRgn, // 窗口的显示区域 
    BOOL bRedraw //指明窗口在被改变显示区域之后是否需要重绘(一般设为True)
    );
     SetWindowRgn函数能够将窗口设定成任意形状。现在我们来建立一个小太阳的窗体。先创建一空白窗体,没置窗体的Color属性为clRed(红色),BorderStyle为:bsNone(去掉标题栏).在FormCreate事件中添加如下代码:
    procedure TForm1.FormCreate(Sender: TObject);
    var
     hRgn:LongInt;
    begin
     //建立一圆形窗体,如要创建其他形状的窗体,只需调用不同的建立区域的函数
     hRgn:=CreateRoundRectRgn(0,0,200,200,200,200);
     SetWindowRgn(Handle,hRgn,True);
    end;
     现在我们再添加代码实现无标题窗体的移动,这里我们要拦截WM_NCHITTEST消息,这个消息是当光标移动、鼠标按下或释放时发生的。当在客户区按下Mouse时,我们欺骗Windows认为是标题栏被按下:
    procedure TForm1.WMNcHitTest(var Msg: TWmNcHitTest);message WM_NCHITTEST;
    begin
     inherited;
     //如果Mouse按下是窗体的客户区,将值赋为标题区
     if (Msg.Result=HTClient) then
     Msg.Result:=HTCaption;
    end;
     这样我们就实现了无标题的异常窗体的创建及移动问题,再加上若干码,我们就可创建一个实用的小时钟程序。
      

  2.   

    转载
    无标题窗口的移动 无标题窗口的移动 
    天津纺织工学院 
    姚佩云 
    ---- 在Delphi 编程中有时要对无标题窗体进行移动,以下就结合本 
    人的经验介绍几种对无标题窗体移动的方法。 ---- 方法一: ---- 通过响应“wm_NCHitTest" 消息来移动窗体。Windows 发送
    “wM_NCHitTest" 消息来确定鼠标操作是否发生在窗体的客户区, 
    或边框的特殊区上(非客户区)。如果Windows 发现用户单击了窗体 
    标题,系统将移动窗体,单击了窗体边框,则系统将开始改变窗 
    体大小。 ---- 例程如下:   .
      .
      private
    { Private declarations }
    Procedure MoveForm(var M:TWMNCHITTEST);
    Message WM_NCHITTEST;
        //声明一自定义事件,拦截“WM_NCHITTEST"消息
      public
      .
      .
    {$R *.DFM}Procedure TForm1.MoveForm (var M:TWMNCHITTEST);
    begin
      inHerited;//继承,窗体可以继续处理以后的事件
      if (M.Result=HTCLIENT) //如果发生在客户区
    and ((GetKeyState(vk_CONTROL) < 0) 
     //检测“Ctrl"键是否按下
      then   M.Result:=HTCAPTION;
      //更改“.Result"域的值
    end;
    ---- 方法二: ---- 通过为Application.OnMessage 创建一个处理程序获得Windows 消息, 
    可以调整应用程序对不同消息的响应或为不能正常识别的消 
    息提供服务。这里受到窗体客户区的鼠标按下的消息后,发送一 
    条在标题栏内按下的消息。 ---- 例程如下: .
      .
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        procedure AppMessage(var Msg:TMsg;var Handled:Boolean);
      .
      .{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
    begin
        Application.OnMessage:=AppMessage;
       //捕捉消息:将程序的收到消息事件与消息过滤过程关联起来
    end;procedure TForm1.AppMessage(var Msg:TMsg;var Handled:Boolean);
    begin
      if (Msg.message=WM_LButtonDown) and 
      //如果鼠标左键按下的话
    (DefWindowProc(Handle,WM_NCHitTest,
    0,GetMessagePos)=HTClient) and
          //判断光标是否在客户区内
    ((GetKeyState(vk_CONTROL) < 0) 
    //检测“Ctrl"键是否按下
        then
          begin
            SendMessage(Handle,WM_NCLButtonDown,
               HTCaption,GetMessagePos);
             //发送鼠标在标题栏内按下的消息
            Handled:=true;
          end;
    end;
    ---- 方法三: ---- 直接向窗体发送一条“wm_SysCommand" 消息,需要使用未归档的
    “sc_DragMove" 标志,定义如下:             const
                  sc_DragMove:LongInt=$F012;
    ---- 我们只能向TWinControl 派生组件发送该消息,而且只能响应鼠 
    标按下事件,因为系统会在此时捕获鼠标(当释放鼠标键时,拖 
    动操作是没有意义的)。 ---- 例程如下:   .
      . 
    const
      sc_DragMove:longint=$F012;implementation{$R *.DFM}procedure TForm1.FormMouseDown
    (Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if ssCtrl in Shift then
      //判断“Ctrl"键是否按下
      Begin
    ReleaseCapture;
    //释放鼠标事件的对象
        (Sender as TWinControl).PerForm(wm_SysCommand,
           sc_DragMove,0);
           //发送消息
      end;
    end;
    ---- 这种方法适用与窗体与组件,如想移动组件,将其
    “OnMouseDown" 事件写成与Form 的“OnMouseDown" 事件一样即可。如只 
    想移动窗体可按以下方法编写代码:   .
      .
    procedure TForm1.FormMouseDown
    (Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if SsCtrl in Shift then
      Begin
        ReleaseCapture;
        SendMessage(handle,wm_SysCommand,
          sc_DragMove,0);
      end;
    end;
    ---- 运行结果: ---- 按下“Ctrl" 键拖动鼠标即可移动窗体。 ---- 总结: ---- 要实现无标题窗体的移动有很多种方法,还可以通过检测鼠 
    标的位置(坐标)来确定Form 的“left" 与“top" 值等方法,在此不再详 
    细举例.