delphi之窗口变形记

概要

用delphi进行窗口外观设计的常规手段无外乎两种:

  • 一是在程序设计阶段用对象监视器对窗体(form)的有关属性进行设置;
  • 二是在程序运行的时候用代码来动态地修改有关的属性。

其实不管哪一种手段,传统上都只是修改象窗体的top、left、width、height、clientwidth、clientheight、color等常规的属性。针对规规矩矩的windows常规窗口是完全可行的,但假设我们由于某些特定的需要,要把窗体设置成一些古怪的形象,前面讲的两种手段就都不适用了。

在编写多媒体辅助教学软件时,经常碰到要把窗口的外形设计成椭圆、圆角矩形,甚至其它特别形状的情况。

delphi本身不能提供解决方案,但是windows呢?在windows api中有这样一些函数:

  • createellipticrgn 生成一个椭圆形状范围
  • createpolygonrgn 生成一个任意多边形形状范围
  • createrectrgn 生成一个矩形形状范围
  • createroundrectrgn 生成一个圆角矩形形状范围

用这些函数生成你指定的形状范围(region),然后将生成的形状范围交给另一个关键函数setwindowrgn,就可以将窗体设置成指定的形状了。

下面的程序片段演示了如何将窗体设置成椭圆形状:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure tform1.formcreate(sender: tobject);
  var rgn: hrgn;
  begin
   rgn:= createellipticrgn(0,0,300,100);
   setwindowrgn( handle, rgn, true );
   width:=300;
   height:=100;
  end;

运行上面的程序片段之前,还应当在对象监视器中将窗体form1的borderstyle属性设置成bsnone,以消除边框和标题栏。

以下的程序将显示一个三角形的窗体:

procedure tform1.formcreate(sender: tobject);

  var

   rgn: hrgn;

   p: array[0..2] of tpoint;

  begin

   p[0].x:=10; p[0].y:=10;

   p[1].x:=200; p[1].y:=100;

   p[2].x:=50; p[2].y:=300;//感觉就像坐标一样(10,10)(200,100)(50,300),大家自己动手试试呗!!!

   rgn:=createpolygonrgn(p, 3, winding);

   setwindowrgn( handle, rgn, true );

  end;

现在我们可以充分发挥想像力来设计满足任何形状要求的窗体了。接下来我们来设计一个非常漂亮的“我的时钟”:

我的时钟

首先将窗体form1的borderstyle属性设置为bsnone,formstyle实行设置为fsstayontop,然后在上面依次放置如下对象:image1、shape1、label1和timer1。

将image1的picture属性设置为你喜欢的一幅图片,并将strecth属性设置为true,以便在将来图片能自动适应窗口尺寸大小。

将shape1的style属性设置为bsclear,pen.color属性设置为你喜欢的颜色,pen.width设置为6,shape设置为stcircle,这样就出现一个粗边空心圆,我们把它作为将来“我的时钟”的边框。

将label1的font.color设置为你喜欢的文字颜色,将transparent属性设置为true,并将其移动到图片image1上合适的位置。

在程序编辑窗口中,找到implementation部分,然后输入以下变量定义:

1
2
const rc=90;
var p: array[0..359] of tpoint;

然后在form1的空白处双击,输入以下程序片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
procedure tform1.formcreate(sender: tobject);
var
x,y: real;
a: integer;
rgn: hrgn;
begin
for a:=0 to 359 do
begin
x:= rc*cos(a*pi/180)+rc;
y:= rc-rc*sin(a*pi/180);
p[a].x:=trunc(x);
p[a].y:=trunc(y);
end;
rgn:=createpolygonrgn(p, 360, winding);
setwindowrgn(handle, rgn, true);
clientwidth:=rc+rc;
clientheight:=rc+rc;
top:=10;
left:=screen.width-width-10;
showhint:=true;
hint:=′这是我的时钟!′+#13+′单击右键结束程序...′;
shape1.width:=rc+rc+1;
shape1.height:=rc+rc+1;
shape1.top:=-1;
shape1.left:=-1;
image1.width:=rc+rc div 2;
image1.height:=rc+rc div 2;
image1.top:=rc div 2;
image1.left:=rc div 2;
end;

在timer1上双击,然后输入以下程序片段:

1
2
3
4
5
6
7
procedure tform1.timer1timer(sender: tobject);
begin
label1.caption:=timetostr(time);
end;

在shape1上单击以选中它,然后在object inspector对象监视器中切换到events事件页,双击onmousedown右侧的空白处,然后输入以下程序片段:

1
2
3
4
5
6
7
8
9
procedure tform1.shape1mousedown(sender: tobject; button: tmousebutton;
shift: tshiftstate; x, y: integer);
begin
if button=mbright then close;
end;

好了,现在“我的时钟”完成了,你运行时将在桌面的右上角出现一个圆形的时钟,并且始终在所有窗口的前面。

有兴趣的读者可以进一步将时钟的形状改变为其它的样子,以适合自己的图片,并为这个程序增加更多的功能。

注意:这些特殊的程序运行时将不再出现窗口控制选单和关闭按钮,因此要结束程序,只能按alt-f4,或者在windows 95/98任务栏上右击该程序按钮,在快捷选单中选择“关闭”。 当然更好的办法是自己在窗体中提供一个“结束”按钮,或者其它结束程序的方式

热评文章