标签:
通过响应“wm_NCHitTest”消息来移动窗体。
Windows发送“wM_NCHitTest”消息来确定鼠标操作是否发生在窗体
的客户区,或边框的特殊区上(非客户区)。
如果Windows发现用户单击了窗体标题,系统将移动窗体,
单击了窗体边框,则系统将开始改变窗体大小。
例程如下:
//声明一自定义事件,拦截“WM_NCHITTEST”消息 Procedure MoveForm(var M:TWMNCHITTEST);Message WM_NCHITTEST; 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 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;
方法三:
直接向窗体发送一条“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; XY: 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”值等方法,在此不再详细举例.
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssleft in shift then releasecapture; perform(WM_SYSCOMMAND,$F012,0); end;
参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832063.html
标签:
原文地址:http://www.cnblogs.com/findumars/p/4801943.html