三种方法实现Delphi无标题窗体的拖动

来源:互联网 发布:js钩子函数 编辑:程序博客网 时间:2024/06/07 10:18
方 法 一:

通 过 响 应“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” 值 等 方 法, 在 此 不 再 详 细 举 例.

========================
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
begin
if ssleft in shift then
      releasecapture;
perform(WM_SYSCOMMAND,$F012,0);
end;
原创粉丝点击