如何移动没有标题栏的窗口?(100分)

  • 主题发起人 主题发起人 abc2003
  • 开始时间 开始时间
A

abc2003

Unregistered / Unconfirmed
GUEST, unregistred user!
我用过wmnchittest的方法,但我还要在窗口了响应其它的mouse事件
如mouse的click.
所以用wmnchittest可能不行,有没有别的方法。
 
用wmnchittest效果最好,
不然也可以这样,
在mouse的移动事件中先判断mouse左键是否按下,如按下就让form随之移动。
这样效果不是很好。
 
这是"ExtraPack" Components Library中的TepMoveForm元件,放置在
Form上后就能用鼠标拖动窗体
TepMoveForm = class(TGraphicControl)
private
FDown: Boolean;
FOldX, FOldY: Integer;
protected
procedure MouseDown(Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
override;
procedure MouseMove(Shift: TShiftState;
X, Y: Integer);
override;
procedure MouseUp(Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
override;
public
procedure Paint;
override;
constructor Create(AOwner: TComponent);
override;
published
property Align;
end;

{TepMoveForm}
constructor TepMoveForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 100;
Height := 100;
end;

procedure TepMoveForm.Paint;
begin
if csDesigning in ComponentState
then
with Canvasdo
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
end
end;

procedure TepMoveForm.MouseMove;
begin
if FDown
then
with TForm(Owner)do
SetBounds(Left + X - FOldX, Top + Y - FOldY, Width, Height);
end;

procedure TepMoveForm.MouseUp;
begin
FDown := False;
end;

procedure TepMoveForm.MouseDown;
begin
if (Button = mbleft) and not FDown then
FDown := True;
FOldX := X;
FOldy := Y;
end;
 
那里有这样的控件TepMoveForm元件?
 
<a href=http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=162574>请看这个问题</a>
 
不好意思,刚才出了点错,Sorry.
你可以到cAkk的
http://202.97.166.10/files/delphi/delphi.htm
去下载。
 
天哪,没有那么麻烦吧!
我以为该解决了,还是让我出手吧 :)
const SC_DRAGMOVE = $F017;
在MOURSEMOVE的时候
begin

ReleaseCapture;
perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0);
end;

 
唐晓锋的方法不一定灵。有时鼠标移到窗体就使窗体移动了。
如下写FORM的OnMouseDown事件处理程序,就像通过标题栏移动:
procedure TForm1.FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
begin
POSTMESSAGE(form1.handle,WM_LBUTTONUP,0,0);
POSTMESSAGE(form1.handle,274,61458,0);
end;
 
也可以在某个范围内移动窗体:
if (x<x2) and(x>x1) and (y<y2) and (y>y1) then
//在矩形(x1,y1,x2,y2)内
begin
POSTMESSAGE(form1.handle,WM_LBUTTONUP,0,0);
POSTMESSAGE(form1.handle,274,61458,0);

end;

 
TForm4 = class(TForm)
procedure FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
private
{ Private declarations }
public
procedure wm(var msg:Twmnchittest);message wm_nchittest;
end;

procedure TForm4.wm(var msg: Twmnchittest);
begin
inherited;
msg.Result:=htcaption;
end;
 
在控件的OnMouseDown事件中记录鼠标的位置
lastx:=x;
lasty:=y;
在OnMouseMove事件中加入:
form1.left:=form1.left+x-lastx;
form1.top:=form1.top+y-lasty;
下面为源程序:
Unit Unit1;
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
Type
TForm1 = class(TForm)
procedure FormMouseDown(Sender: TObject;
Button: TmouseButton;
Shift: TShiftState;
X, Y: Integer);
procedure FormMouseMove(Sender: TObject;
Shift: TshiftState;
X,
Y: Integer);
Private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Ylx,yly:integer;
//定义一个全局变量
Implementation
{$R *.DFM}
procedure TForm1.FormMouseDown(Sender: TObject;
Button: TmouseButton;
Shift: TShiftState;
X, Y: Integer);
begin
Ylx:=x;
//记录鼠标原来的坐标值
Yly:=y;
end;

procedure TForm1.FormMouseMove(Sender: TObject;
Shift: TshiftState;
X,
Y: Integer);
begin
If ssleft in shift then
begin
//按下鼠标左键拖动form1
form1.left:=form1.left+x-ylx;
form1.top:=form1.top+y-yly;
end;
end;

end.
 
删除处理wm_nchittestan消息的所有代码
const
sc_drag:Longint=$f012;
procedure TForm4.FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
begin
releasecapture;
sendmessage(handle,wm_syscommand,SC_drag,0);
//用perform(wm_syscommand,sc_drag,0);也行
end;
 

从计算机世界上看到的,顺便就转到这里来了。
无 标 题 窗 口 的 移 动
天 津 纺 织 工 学 院104#
姚 佩 云
---- 在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”
值 等 方 法, 在 此 不 再 详 细 举 例.
---- 以 上 程 序 均 在Delphi 3.0 下 编 译 通
过。
 
DreamTiger没错,我以前实现的方法就是响应wm_lbuttondown事件,
然后欺骗系统,送过去wm_nclbuttondown的消息,让系统以为是在标题
区按下的,非常简单,好像数行代码就解决了问题,只是现在找不到那段
代码了.
 
// 哥们,真遗憾,我上次发的东西你们原来没收到
// 看你放一个panel在form上在用下面这段代码;
// 呵呵,不错吧,
// 把panel替换成form就成了。
// 呵呵,很容易的,delphi拖动元件就是这么拖的。
// 呵呵,没想到吧。
// 呵呵,可喜,上次没发上来。
// 呵呵,真遗憾
// 呵呵。
procedure TForm1.Panel1MouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
const
SC_DragMove = $F012;
begin
ReleaseCapture;
panel1.perform(WM_SysCommand, SC_DragMove, 0);
end;
 
时间太久,强制结束。 wjiachun
 
后退
顶部