orm1 的 FormStyle 属性的设置。 FormStyle 为 fsStayOnTop 时可确保 Form1 始终位于最前显示。 从效果角度看, 当系统工具栏为“总在 最前显示”时是最为明显的,因为若窗体移动到系统工具栏上时也不会被其所遮盖。 四、进一步完善
上面的代码已基本实现了窗体的自动隐藏效果, 不过我在介绍代码的时候有两个问题是 被提出但没有被解答的。
首先是为什么触发隐藏时 Fanchors 中将至少有一个值而不多于两个值呢?注意代码中 对 Fanchors 的赋值是通过四个判断进行的, 那么如果触发隐藏的话,Fanchors 中将毫无 疑问会有一个值存在, 但这种情况是针对隐藏发生在
屏幕的四边而言。 当窗体被推入到屏幕 的四角时,那么 Fanchors 中便将会有两个值存在。那此时窗体会隐藏到什么地方呢?
实际的效果告诉我们, 窗体会被隐藏到屏幕的四角上。 此时若我们试图让窗体重新显示, 你便会发现窗体在不断的闪烁。 为什么呢?这就是第二个
问题提出的原因了。 因为对窗体显 示或隐藏的处理是根据 Fanchors 中的值作出的。 Fanchors 中有两个值的时候, 当 就将会引 发对窗体属性的两次设置。而因为设置语句只有顺序差异而没有优先级差异,那么 OnTimer 事件中每次都会对窗体进行两次的属性值设置,从而导致我们看到闪烁的显示效果。
怎么去解决这个问题呢?我们再观察一下 QQ 的处理。在 2003 II 版的 QQ 里面,窗体的 隐藏效果作了一定的调整: 当窗体在屏幕左右两边隐藏时, 他会自动充满屏幕的左右两边且 高度不可改动;当窗体脱离屏幕两边的隐藏区域后,窗体的大小会恢复为隐藏前的大小,如 图五所示。(注意:窗体并非是完全充满屏幕的两边。QQ 在处理这个效果时可能只注意了 系统工具栏总在最前显示且位于屏幕下方的情况, 所以其充满的区域也只是屏幕顶端到系统 工具栏上方的一段空间,如图六所示。)这样的处理能令窗体即使被推入到屏幕四角,也能 确保只会对其中的一个隐藏方向进行处理,从而避免了前面出现的闪烁现象。
图五 Q Q 窗体自动充满屏幕两边
图六 Q Q 窗体自动充满屏幕两边的漏洞
结合前面的分析,要实现如上的效果还是从拦截 WM_MOVING 消息入手。重写后的 WMMOVING 过程如下:
procedure TForm1.WMMOVING(var Msg: TMessage); begin inherited; with PRect(Msg.LParam)^ do begin if (akLeft in FAnchors) or (akRight in FAnchors) then begin if (Left > 0) and (Right < Screen.Width) then begin if rec_Position then begin Bottom := top + Lst_Height; Right := Left + Lst_Width; Height := Lst_Height; Width := Lst_Width; end; end else begin SetBarHeight; Top := Cur_Top; Bottom := Cur_Bottom; exit; end; end; Left := Min(Max(0, Left), Screen.Width - Width); ..
if not Rec_Position then begin Lst_Height := form1.Height; Lst_Width := form1.width; end; FAnchors := []; .. if (akLeft in FAnchors) or (akRight in FAnchors) then begin Rec_Position := True; SetBarHeight; Top := Cur_Top; Bottom := Cur_Bottom; end else Rec_Position := False; Timer1.Enabled := FAnchors <> []; end; end;
在新的代码中,我们首先使用了三个新定义的全局变量,分别是:
Lst_Height : Integer; //记录窗体隐藏前的高度 Lst_Width : Integer; //记录窗体隐藏前的宽度 Rec_Positi