于指明一个控件怎么锚定于其父类控件的位置, 我们在这里则借用来描述窗体对屏幕的 隐藏位置。
在 TAnchors 集合中也包含了四个值,其定义如下:
type TAnchorKind = (akTop, akLeft, akRight, akBottom); type TAnchors = set of TAnchorKind;
在代码的实现中, 我们将定义一个 TAnchors 类型的全局变量 FAnchors 去描述窗体隐藏 的位置。
三、初步的实现
首先我们定义一个过程对 WM_MOVING 消息进行拦截处理,代码如下:
.. private FAnchors: TAnchors; procedure WMMOVING(var Msg: TMessage); message WM_MOVING; .. uses Math,type; procedure TForm1.WMMOVING(var Msg: TMessage); begin inherited; with PRect(Msg.LParam)^ do begin Left := Min(Max(0, Left), Screen.Width - Width); Top := Min(Max(0, Top), Screen.Height - Height); Right := Min(Max(Width, Right), Screen.Width); Bottom := Min(Max(Height, Bottom), Screen.Height); FAnchors := []; if Left = 0 then Include(FAnchors, akLeft); if Right = Screen.Width then Include(FAnchors, akRight); if Top = 0 then Include(FAnchors, akTop); if Bottom = Screen.Height then Include(FAnchors, akBottom); Timer1.Enabled := FAnchors <> [];
end; end;
在该过程中,我们通过对矩形参数 Left、Top、Right、Bottom 的判断确定窗体所处位 置是否符合隐藏条件, 判断结果存放在全局变量 Fanchors 之中。 当触发隐藏时, Fanchors 在 中将至少有一个值而不多于两个值。(为什么呢?)
判断条件的设置似乎和我们一般的理解有点不同。以 Left 参数的判断为例,在判断了 Max(0, Left)之后还为什么一定要和 Scre
en.Width-Width 的值再作比较呢?这其实是为了 对一些较为极端的情况(例如窗体的宽度大于屏幕宽度)所作的伪处理,大家如果有兴趣的 可自己试验一下这些极端的效果。当然,如果我们的窗体限制了宽、高的最大值,那么判断 也就能简化为我们最初的理解。
最后需要注意的是,代码中出现的 Left、Top、Right、Bottom 都是 RECT 的参数,而 Width 和 Height 才是窗体 Form1 的属性。
接下来我们要处理 TTimer 的 OnTimer 事件了。在 WMMOVING 过程中,当 Fanchors 不为 空时,TTimer 启动;反之,TTimer 关闭。OnTimer 事件的代码如下:
procedure TForm1.Timer1Timer(Sender: TObject); const cOffset = 2; begin if WindowFromPoint(Mouse.CursorPos) = Handle then begin if akLeft in FAnchors then Left := 0; if akTop in FAnchors then Top := 0; if akRight in FAnchors then Left := Screen.Width - Width; if akBottom in FAnchors then Top := Screen.Height - Height; end else begin if akLeft in FAnchors then Left := -Width + cOffset; if akTop in FAnchors then Top := -Height + cOffset; if akRight in FAnchors then Left := Screen.Width - cOffset; if akBottom in FAnchors then Top := Screen.Height - cOffset; end; end;
在这里, 我们首先定义一个常量 cOffset 去表示窗体隐藏后显露部分的大小。 然后我们 利用 WindowFromPoint 这个视窗
系统 API 函数检测鼠标是否位于窗体之上。接下来的判断
就是处理在显示和隐藏状态下窗体 Left 和 Top 属性值的设置。注意,针对 Fanchors 中存 在不同值的情况,窗体 Left 和 Top 的设置是各不相同的,不过这些设置只有顺序上的差异 而并没有优先级别的差异。(为什么要提到这一点呢?)
最后需要注意的是: 在本事件中 Top、 Left、 Width 和 Height 都是窗体 Form1 的属性值。
好了,有关窗体隐藏的核心代码已介绍完毕了,不过要达到预期效果,窗体 Form1 在创 建时还必须做一些准备
工作,代码如下:
procedure TForm1.FormCreate(Sender: TObject); begin Timer1.Enabled := False; Timer1.Interval := 200; FormStyle := fsStayOnTop; end;
这里的代码相对简单, 不过值得指出的是对 F