请问有谁做过非规则的窗体,能说说原理或者例子吗? 请问有谁做过非规则的窗体,能说说原理或者例子吗? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 简单的,在主窗体Create。// 一个椭圆形窗体 OnResize中放同样的代码procedure TForm1.FormCreate(Sender: TObject);var hRegion: THandle;begin hRegion := CreateEllipticRgn(0, -Height, Width, Height); SetWindowRgn(Handle, hRegion, True);end; // 一个圆角矩形窗体 procedure TForm1.FormCreate(Sender: TObject);var hRegion: THandle;begin hRegion := CreateEllipticRgn(0,0,width,height,20,20); SetWindowRgn(Handle, hRegion, True);end; 主要就是两个API,举例procedure TForm1.Button1Click(Sender: TObject);var rgn: HRGN;begin rgn := CreateEllipticRgn(0, 0, 600, 300); SetWindowRgn(handle, rgn, true);end; 复杂的,你要进行Mask的编程,进行CombineRGN 透明和异形窗体 CoDelphi.com摘 要:创造透明的或非矩形的或同时有以上两种特性的窗体关键字:透明 形状 窗体类 别:用户界面 实际上,程序并不一定非要用Delphi来编。虽然我将提供Delphi的源代码,并且在Delphi环境中讨论问题,但是透明窗体程序是严格用winAPI实现的。因此,它可以被很容易的翻译为其他编程环境的代码。我将一步一步的把它解释清楚。 用这种方法可以将窗体的任意部分剪去。这些剪去的部分就是透明的。窗体的“透明”部分实际上已不属于窗体,用鼠标单击将会到达窗体下面。有一个很简单的方法能实现透明窗体,但是该方法也有它的弱点。 建立一个新的Application。 将BorderStyle设为bsNone。 保存并运行程序。它可以运行,但修改一下更好。因为它没有边缘部分,你的程序只显示一个简单的灰色矩形,你必须使用Alt-F4去关闭它。 为你的窗体的OnCreate事件添加处理函数:procedure TForm1.FormCreate(Sender: TObject); var NewRgn : HRGN; begin NewRgn := CreateEllipticRgn(10,10,width-10,height-10); SetWindowRgn(handle,NewRgn,false); end; 确定你的Uses子句含有"Windows"。 运行程序。你的窗口现在变成了一个灰色的椭圆形。你还是必须敲Alt-F4去关闭它。我已经告诉过你我将一步一步的把它解释清楚。 这里究竟发生了什么?Windows有一个称作“区域”的概念。我实际上对区域也不懂,现在我也只能猜了。区域是以边界定义的窗口的一部分。Windows为处理区域提供了几个函数,它提供给程序员区域句柄作为处理区域的主要接口。其中最基本函数的是关于建立区域的。在这个例子中,我使用CreateEllipticRgn来创建由其外接矩形定义的椭圆区域。我选择了一个比窗口小一些的矩形,这是因为在这一阶段一堆几何数据并不与什么窗口相联系。 最关键的区域函数是SetWindowRgn,它输入窗口的句柄、要设置的区域、窗体是否重画。区域的坐标是关于整个窗体的局部(而不是整个屏幕)坐标系。 实际上就这么简单。你先创建一个区域,然后把它设置为窗口的区域。 现在是开始解释细节的时候了。添加一个处理OnPaint事件的函数:procedure TForm1.FormPaint(Sender: TObject); begin canvas.pen.width := 10; canvas.Ellipse(10,10,width-10,height-10); end; 运行。我的程序现在填充了一个漂亮的黑边。我想除非你设定了不同的默认窗口颜色,你将得到相同的结果。 回到Object Inspector,将主窗体的BorderStyle设为bsSingle。 运行程序。现在椭圆向下了一些,你可以在上面看到一点标题栏。为什么?当你使用SetWindowRgn时,区域是相对窗口的整个部分的。把BorderStyle设为bsSingle就使所有的非客户区,包括边缘、标题栏和按钮都显示。这就是开始时我要你将BorderStyle设为bsNone的原因。如果你喜欢不同的边界样式,你可以利用CustomeForm.ClientRect、TCustomForm.ClientWidth、TCustomForm.ClientHeight、TControl.left和TControl.right,通过数学计算将所有的东西组合在一起。 请将BorderStyle重新设为bsNone。 呀,怎么来移动窗体呢?你可以自己用一些野路子,或是让Windows为你处理。当用户在一个窗口点击时,Windows先问窗口是否点击一个非客户区部分,如果是,是哪一种。我们可以在被问的时候,告诉Windows用户点击了标题栏。Windows然后对自己说:“好,我们开始移动窗口吧。”这样它就做了。 在你的窗体中添加一个私有方法,象这样声明:procedure WMNCHitTest(var Msg:TMessage); message WM_NCHITTEST; 象这样实现它:procedure TForm1.WMNCHitTest(var Msg:TMessage); begin msg.result := HTCAPTION; end; 运行程序。在窗口某处点击并拖拽窗体,窗体能够移动。 当用户点击时Windows发送wm_nchittest给程序。你可以回答说用户点击到了标题。Windows就想当然的认为要移动窗体了,就这么简单。我记不住非客户区测试的返回值,但是我记得它们在windows.pas中的某个地方。一般我找到了它们,或是查找"caption"。只要你找到那儿,你可以看到所有其他的玩意儿。更加复杂的区域 区域不一定非要是简单的矩形或椭圆形。他们可以是…… 坦率的说,他们可以是任意形状,凹的、不相连的、斑点状的。察看一下CreateXRgn样的函数(如在CreateEllipticRgn点F1,然后在帮助中点Group按钮)。其中有矩形、圆角矩形,还有任意多边形。更重要的是,还可以组合这些区域。OK,下面是一个组合区域的程序。我们用两个,而不是一个椭圆。 在你和更多区域打交道之前,你还需要知道一点其他的东西。看一下SetWindowRgn的帮助,你可以在底部看到它说你不能删去传给窗体的区域,Windows需要它。但当你组合两个区域时,你传给Windows其中的一个,另一个丢在一边。我们必须把它清除。下面是代码:procedure TForm1.FormCreate(Sender: TObject); var LeftRgn : HRGN; RightRgn : HRGN; NewRgn : HRGN; begin LeftRgn := CreateEllipticRgn(10,10,width div 2, height-10); RightRgn := CreateEllipticRgn(width div 2, 10, width-10, height-10); NewRgn := CreateRectRgn(0,0,0,0); CombineRgn(NewRgn,LeftRgn,RightRgn,RGN_OR); DeleteObject(LeftRgn); DeleteObject(RightRgn); SetWindowRgn(handle,NewRgn,false); end; 因为我们有两个椭圆,我们必须改FormPaint中的代码。你可以从FormCreate使工作简单一些。procedure TForm1.FormPaint(Sender: TObject); begin canvas.pen.width := 10; canvas.Ellipse(10,10,width div 2, height-10); canvas.Ellipse(width div 2, 10, width-10, height-10); end; 运行程序。将会出现两个椭圆。你可能看到过眼珠转动的程序,它也是用这样的方法。现在你明白了吧。 仔细看一下椭圆间的空间,有一个象素的间隔。注意在文档中,我想是在CreateRectRgn中,它指出建立的区域不包含右边缘和下边缘。这就解释了为什么有间隔。 但是我还有一点要解释。为什么要NewRegion := CreateRectRgn()? 非常简单。CombineRgn并不建立一新区域,目的区域必须存在。给它一个假的区域句柄,它会不高兴的,SetWindowRgn也会失败。你可以试一下,注释掉CreateRectRgn那一行,你可以看到会发生什么。我得到了一个没有变化的矩形窗口。这样我建立了一个任意区域,使Windows在CombineRgn时满意。注意,因为区域是(0,0,0,0),并且右边和下边被去除了,这将会产生一空的区域。 当然,看一下我在用完左右两个区域后将它们删除了。要记住除了你传给通过SetWindowRgn传给Windows的区域,你必须删除你创建的任何区域。 注意在CombineRgn中,组合方式是RGN_OR。它是关于位运算的,而不是英语概念的。如果用RGN_AND,结果区域是两个区域交叉部分。 如何建一个没有区域的窗口?很难发现一个没有作图部分的窗口。但是它能在工具条上显示,你可以在那里右击来关闭它。或者,如果你运行,你看不到它。但它是活动的,你可以用Alt-F4使它死亡。 现在是我能想到的最后一件事:太大的区域。潜入代码,把右边的椭圆改得比窗体还大: RightRgn := CreateEllipticRgn(width div 2, 10, width+60, height+60); 你将注意到椭圆正常并很大,但是Windows只使区域中在实际大小内的部分有效。如果你想使窗体增长到窗体之外,你必须改变窗体的实际大小使窗体增大。 所有的就是这些了。你可以从这个简单工具中得到不少创造性。 进行Mask的编程,进行CombineRGN,mask得编程有介绍吗?谢谢! 在WM_MOVE中如何判断负值 ? 如何修改本地时间,保持与服务器霎时间一致? 用程序来创建表? Delphi自己带的例子,看不明白,请大家指点!顶者有分!! 请问,哪里有比较好的数据库备份与恢复控件。 关于TreeView的使用 有谁告诉我TComponent.GetIDsOfNames怎么用啊 『每帖必结』请教:为什么我TRY了它还是要报错??? 如何得到文件的长度,很简单的问题 请问怎么将另一程序的窗口最小化? 怎么用Dephi创建数据库文件? 怎样解决扑克游戏中的一些问题?
// 一个椭圆形窗体 OnResize中放同样的代码
procedure TForm1.FormCreate(Sender: TObject);
var
hRegion: THandle;
begin
hRegion := CreateEllipticRgn(0, -Height, Width, Height);
SetWindowRgn(Handle, hRegion, True);
end; // 一个圆角矩形窗体
procedure TForm1.FormCreate(Sender: TObject);
var
hRegion: THandle;
begin
hRegion := CreateEllipticRgn(0,0,width,height,20,20);
SetWindowRgn(Handle, hRegion, True);
end;
var
rgn: HRGN;
begin
rgn := CreateEllipticRgn(0, 0, 600, 300);
SetWindowRgn(handle, rgn, true);
end;
CoDelphi.com
摘 要:创造透明的或非矩形的或同时有以上两种特性的窗体
关键字:透明 形状 窗体
类 别:用户界面
实际上,程序并不一定非要用Delphi来编。虽然我将提供Delphi的源代码,并且在Delphi环境中讨论问题,但是透明窗体程序是严格用winAPI实现的。因此,它可以被很容易的翻译为其他编程环境的代码。我将一步一步的把它解释清楚。 用这种方法可以将窗体的任意部分剪去。这些剪去的部分就是透明的。窗体的“透明”部分实际上已不属于窗体,用鼠标单击将会到达窗体下面。有一个很简单的方法能实现透明窗体,但是该方法也有它的弱点。 建立一个新的Application。 将BorderStyle设为bsNone。 保存并运行程序。它可以运行,但修改一下更好。因为它没有边缘部分,你的程序只显示一个简单的灰色矩形,你必须使用Alt-F4去关闭它。 为你的窗体的OnCreate事件添加处理函数:procedure TForm1.FormCreate(Sender: TObject);
var
NewRgn : HRGN;
begin
NewRgn := CreateEllipticRgn(10,10,width-10,height-10);
SetWindowRgn(handle,NewRgn,false);
end; 确定你的Uses子句含有"Windows"。 运行程序。你的窗口现在变成了一个灰色的椭圆形。你还是必须敲Alt-F4去关闭它。我已经告诉过你我将一步一步的把它解释清楚。 这里究竟发生了什么?Windows有一个称作“区域”的概念。我实际上对区域也不懂,现在我也只能猜了。区域是以边界定义的窗口的一部分。Windows为处理区域提供了几个函数,它提供给程序员区域句柄作为处理区域的主要接口。其中最基本函数的是关于建立区域的。在这个例子中,我使用CreateEllipticRgn来创建由其外接矩形定义的椭圆区域。我选择了一个比窗口小一些的矩形,这是因为在这一阶段一堆几何数据并不与什么窗口相联系。 最关键的区域函数是SetWindowRgn,它输入窗口的句柄、要设置的区域、窗体是否重画。区域的坐标是关于整个窗体的局部(而不是整个屏幕)坐标系。 实际上就这么简单。你先创建一个区域,然后把它设置为窗口的区域。 现在是开始解释细节的时候了。添加一个处理OnPaint事件的函数:procedure TForm1.FormPaint(Sender: TObject);
begin
canvas.pen.width := 10;
canvas.Ellipse(10,10,width-10,height-10);
end; 运行。我的程序现在填充了一个漂亮的黑边。我想除非你设定了不同的默认窗口颜色,你将得到相同的结果。 回到Object Inspector,将主窗体的BorderStyle设为bsSingle。 运行程序。现在椭圆向下了一些,你可以在上面看到一点标题栏。为什么?当你使用SetWindowRgn时,区域是相对窗口的整个部分的。把BorderStyle设为bsSingle就使所有的非客户区,包括边缘、标题栏和按钮都显示。这就是开始时我要你将BorderStyle设为bsNone的原因。如果你喜欢不同的边界样式,你可以利用CustomeForm.ClientRect、TCustomForm.ClientWidth、TCustomForm.ClientHeight、TControl.left和TControl.right,通过数学计算将所有的东西组合在一起。 请将BorderStyle重新设为bsNone。 呀,怎么来移动窗体呢?你可以自己用一些野路子,或是让Windows为你处理。当用户在一个窗口点击时,Windows先问窗口是否点击一个非客户区部分,如果是,是哪一种。我们可以在被问的时候,告诉Windows用户点击了标题栏。Windows然后对自己说:“好,我们开始移动窗口吧。”这样它就做了。 在你的窗体中添加一个私有方法,象这样声明:procedure WMNCHitTest(var Msg:TMessage); message WM_NCHITTEST; 象这样实现它:procedure TForm1.WMNCHitTest(var Msg:TMessage);
begin
msg.result := HTCAPTION;
end; 运行程序。在窗口某处点击并拖拽窗体,窗体能够移动。 当用户点击时Windows发送wm_nchittest给程序。你可以回答说用户点击到了标题。Windows就想当然的认为要移动窗体了,就这么简单。我记不住非客户区测试的返回值,但是我记得它们在windows.pas中的某个地方。一般我找到了它们,或是查找"caption"。只要你找到那儿,你可以看到所有其他的玩意儿。
更加复杂的区域 区域不一定非要是简单的矩形或椭圆形。他们可以是…… 坦率的说,他们可以是任意形状,凹的、不相连的、斑点状的。察看一下CreateXRgn样的函数(如在CreateEllipticRgn点F1,然后在帮助中点Group按钮)。其中有矩形、圆角矩形,还有任意多边形。更重要的是,还可以组合这些区域。OK,下面是一个组合区域的程序。我们用两个,而不是一个椭圆。 在你和更多区域打交道之前,你还需要知道一点其他的东西。看一下SetWindowRgn的帮助,你可以在底部看到它说你不能删去传给窗体的区域,Windows需要它。但当你组合两个区域时,你传给Windows其中的一个,另一个丢在一边。我们必须把它清除。下面是代码:procedure TForm1.FormCreate(Sender: TObject);
var
LeftRgn : HRGN;
RightRgn : HRGN;
NewRgn : HRGN;
begin
LeftRgn := CreateEllipticRgn(10,10,width div 2, height-10);
RightRgn := CreateEllipticRgn(width div 2, 10, width-10, height-10);
NewRgn := CreateRectRgn(0,0,0,0);
CombineRgn(NewRgn,LeftRgn,RightRgn,RGN_OR);
DeleteObject(LeftRgn);
DeleteObject(RightRgn);
SetWindowRgn(handle,NewRgn,false);
end; 因为我们有两个椭圆,我们必须改FormPaint中的代码。你可以从FormCreate使工作简单一些。procedure TForm1.FormPaint(Sender: TObject);
begin
canvas.pen.width := 10;
canvas.Ellipse(10,10,width div 2, height-10);
canvas.Ellipse(width div 2, 10, width-10, height-10);
end; 运行程序。将会出现两个椭圆。你可能看到过眼珠转动的程序,它也是用这样的方法。现在你明白了吧。 仔细看一下椭圆间的空间,有一个象素的间隔。注意在文档中,我想是在CreateRectRgn中,它指出建立的区域不包含右边缘和下边缘。这就解释了为什么有间隔。 但是我还有一点要解释。为什么要NewRegion := CreateRectRgn()? 非常简单。CombineRgn并不建立一新区域,目的区域必须存在。给它一个假的区域句柄,它会不高兴的,SetWindowRgn也会失败。你可以试一下,注释掉CreateRectRgn那一行,你可以看到会发生什么。我得到了一个没有变化的矩形窗口。这样我建立了一个任意区域,使Windows在CombineRgn时满意。注意,因为区域是(0,0,0,0),并且右边和下边被去除了,这将会产生一空的区域。 当然,看一下我在用完左右两个区域后将它们删除了。要记住除了你传给通过SetWindowRgn传给Windows的区域,你必须删除你创建的任何区域。 注意在CombineRgn中,组合方式是RGN_OR。它是关于位运算的,而不是英语概念的。如果用RGN_AND,结果区域是两个区域交叉部分。 如何建一个没有区域的窗口?很难发现一个没有作图部分的窗口。但是它能在工具条上显示,你可以在那里右击来关闭它。或者,如果你运行,你看不到它。但它是活动的,你可以用Alt-F4使它死亡。 现在是我能想到的最后一件事:太大的区域。潜入代码,把右边的椭圆改得比窗体还大: RightRgn := CreateEllipticRgn(width div 2, 10, width+60, height+60); 你将注意到椭圆正常并很大,但是Windows只使区域中在实际大小内的部分有效。如果你想使窗体增长到窗体之外,你必须改变窗体的实际大小使窗体增大。 所有的就是这些了。你可以从这个简单工具中得到不少创造性。