|
|
| [ 2005-04-18 14:14:04
] |
作者:cobi
|
责任编辑:huangpeidan |
三、初步的实现 首先我们定义一个过程对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)之后还为什么一定要与Screen.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这个Windows 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; 这里的代码相对简单,不过值得指出的是对Form1的FormStyle属性的设置。FormStyle为fsStayOnTop时可保证了Form1始终位于最前显示。从效果角度看,当系统工具栏为“总在最前显示”时是最为明显的,因为若窗体移动到系统工具栏上时也不会被其所遮盖。
|