📄 异形窗口1.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Delphi</title>
</head>
<body>
<!--webbot bot="Include" U-Include="../top.htm" TAG="BODY" startspan --><strong>[top.htm]</strong><!--webbot bot="Include" endspan i-checksum="11293" -->
<table border="0" width="80%" height="2211">
<tr>
<td width="100%" align="center" height="33" bgcolor="#99E3EA"><big><font color="#FF0000" face="幼圆"><big><big><strong>DELPHI 学 习 园 地</strong></big></big></font></big></td>
</tr>
<tr>
<td width="100%" height="33" bgcolor="#D6ED7A"><p align="center"><big><strong><font color="#0000FF" face="幼圆"><big><big>在Delphi中实现Windows异形窗口 </big></big></font></strong></big></td>
</tr>
<tr>
<td width="100%" height="2084" bgcolor="#FFFFFF" bordercolor="#FFFFFF"><p align="left"> WINDOWS图形界面应用程序都是基于窗口的。在Windows操作系统中,窗口是应用程序与用户之间的界面。微软对窗口的定义是:窗口是屏幕上的一块方形部分,用来显示输出和接受用户的输入。编写基于Windows
的GUI程序首先要做的事情之一便是创建一个或多个窗口。我们通常使用CreateWindow和CreateWindowEx这两个API函数创建窗口,此外通过DialogBox,CreateDialog和MessageBox等函数还可以创建特殊用途的窗口(如对话框、消息框等)。
<br>
不管是以上哪个函数,都将无一例外的得到矩形窗口。但是,有时为了实现特殊效果,有时希望使用不规则形状的窗口。而本文就将探讨怎样实现这些异形窗<br>
口,如圆形、椭圆形、星形等窗口。 <br>
为了实现不规则形状的窗口,需要用到“区域”(Region)这一概念。在微软<br>
Windows操作系统中,区域是指能对其进行填充、绘制、加边框、颜色翻转等操作<br>
的长方形、(椭)圆形、多边形,或者这些形状的叠加。 <br>
<font color="#0000FF"> <font face="隶书">区域的创建</font> </font><br>
通过以下API函数,我们可以创建区域,它们是:CreateRectRgn(长方形<br>
),CreateRoundRectRgn(圆角长方形),CreateEllipticRgn(圆形和椭圆<br>
形),以及CreatePolygonRgn和CreatePolyPolygonRgn。如果调用成功的话,<br>
它们都会返回一个指向新建区域的句柄。下面先简单地介绍CreatePolygonRgn和<br>
CreateEllipticRgn的用法: <br>
HRGN CreatePolygonRgn( //创建多边形区域 <br>
CONST POINT *lppt, //指向一个POINT类型的数组 <br>
int cPoints, //数组中元数的个数 <br>
int fnPolyFillMode //多边形填充模式 ); <br>
HRGN CreateEllipticRgn( //创建圆形或者椭圆形区域 <br>
int nLeftRect, //(椭)圆外切长方形左上角的X坐标 <br>
int nTopRect, //(椭)圆外切长方形左上角的Y坐标 <br>
int nRightRect, //(椭)圆外切长方形右下角的X坐标 <br>
int nBottomRect //(椭)圆外切长方形右下角的Y坐标 ); <br>
区域的一个非常重要的性质是:任意两个区域可以进行合成操作,进而生成一<br>
个新的区域。 <br>
<big><font face="隶书" color="#0000FF">区域的合成</font></big> <br>
利用已有的区域可以合成新的区域,这便是函数CombineRgn的作用。该函数<br>
的C语言原型声明如下: <br>
int CombineRgn( <br>
HRGN hrgnDest, // 指向目的区域 <br>
HRGN hrgnSrc1, // 指向源区域 <br>
HRGN hrgnSrc2, // 指向源区域 <br>
int fnCombineMode // 区域结合模式 ); <br>
在上述函数中,第二、三个参数为源区域;第一个参数hrgnDest指向的是目的<br>
区域,这块区域将用来盛放由hrgnSrc1和hrgnSrc2合成的新区域,所以必须保证<br>
hrgnDest所指向的区域在调用函数CombineRgn之前已经存在。 <br>
第四个参数,即fnCombineMode,指明了合成方式,它的取值及含义如下所<br>
示: </p>
<table border="1" width="100%">
<tr>
<td width="22%"><font face="幼圆" color="#FF0000"><strong>合成方式</strong></font> </td>
<td width="78%"><font face="幼圆" color="#FF0000"><strong>含 义</strong></font></td>
</tr>
<tr>
<td width="22%">RNG_AND</td>
<td width="78%">新区域为两块源区域的相交部分</td>
</tr>
<tr>
<td width="22%">RNG_COPY </td>
<td width="78%">新区域为第一块源区域的拷贝</td>
</tr>
<tr>
<td width="22%">RNG_DIFF</td>
<td width="78%">新区域为第一块源区域减去与第二块源区域共有的部分</td>
</tr>
<tr>
<td width="22%">RNG_OR</td>
<td width="78%">新区域为两块源区域的并集</td>
</tr>
<tr>
<td width="22%">RNG_XOR </td>
<td width="78%">新区域为两块源区域的非公共部分的并集</td>
</tr>
</table>
<p align="left"> <big><font face="隶书" color="#0000FF">区域的使用</font></big>
<br>
创建或者合成了一定形状的区域之后,并不能看到任何东西。区域要与具体的<br>
窗口结合才能起作用。把区域同窗口挂起钩来,要用到名为SetWindowRgn的API函<br>
数。它的原型如下: <br>
int SetWindowRgn( <br>
HWND hWnd, // 指向窗口区域已被设定好的窗口 <br>
HRGN hRgn, // 指向区域 <br>
BOOL bRedraw // 窗口重画标志 ); <br>
当成功地调用了此函数后,操作系统将拥有hRgn所指定的那块区域。区域的坐<br>
标是相对于窗口的左上角(包括标题区在内)。窗口中只有在区域内的那部分是可<br>
见的,对位于区域之外的窗口部分,系统将不予显示。也就是说,窗口表现出来的<br>
形状与区域的形状是一样的(当然这还有个条件,那就是窗口不得比区域小)。为<br>
了调整窗口的大小,可先用API函数GetRgnBox获取区域的大小(即长与宽),再<br>
根据获得的数据(在p2中)来相应地调整窗口的长和宽: <br>
function GetRgnBox(RGN: HRGN; var p2: TRect): Integer; stdcall;<br>
有了上面介绍的这些关于区域的知识,就足以实现这些异形窗口了。
<br>
异形窗口示例程序 <br>
笔者用Delphi编写了一个示例程序,它实现了5种形状的窗口(图1中列出了其<br>
中四种)。希望该示例程序能有助于读者加深对区域的理解和运用。
<br>
以下是程序的主单元代码: <br>
//Create windows in special shapes. <br>
//Press CTRL+S to exit this program. <br>
unit Shapes; <br>
interface <br>
uses <br>
Windows, Messages, SysUtils, Classes, Graphics, <br>
Controls, Forms, Dialogs, ExtCtrls, StdCtrls; <br>
const HOTKEYID=1; <br>
type <br>
TShape = class(TForm) <br>
Timer1: TTimer; <br>
procedure FormCreate(Sender: TObject); <br>
procedure FormDestroy(Sender: TObject); <br>
procedure Timer1Timer(Sender: TObject); <br>
private <br>
procedure WMHOTKEY(var Msg:TWMHotKey);message WM_HOTKEY; <br>
end; <br>
<br>
var <br>
Tick:Integer; <br>
Shape: TShape; <br>
Rgn, Rgn1:THandle; <br>
XX,YY:Integer; <br>
Triangle:array[0..2] of TPoint <br>
=((x:30;y:0),(x:0;y:60),(x:60;y:60)); <br>
Diamond:array[0..3] of TPoint <br>
=((x:30;y:0),(x:60;y:50),(x:30;y:100),(x:0;y:50)); <br>
Star:array[0..4]of TPoint=((x:34;y:0), (x:0;y:73), <br>
(x:75;y:28),(x:3;y:28),(x:64;y:73)); <br>
implementation <br>
{$R *.DFM} <br>
procedure TShape.FormCreate(Sender: TObject); <br>
begin <br>
Timer1.Interval:=99; <br>
BorderStyle:=bsNone; <br>
{ <br>
下条语句将Application窗口的扩展风格重新设 <br>
为WS_EX_TOOLWINDOW,这样程序运行时就不会在 <br>
任务栏上出现一个小图标。 <br>
} <br>
Timer1Timer(self); <br>
SetWindowLong(Application.Handle,GWL_ExStyle,WS_EX_ToolWindow); <br>
//为窗口注册Ctr+S 热键 <br>
RegisterHotKey(Handle,HOTKEYID,MOD_CONTROL,ord('S')); <br>
end; <br>
procedure TShape.FormDestroy(Sender: TObject); <br>
begin <br>
DeleteObject(Rgn); <br>
UnregisterHotKey(Handle,HOTKEYID); <br>
end; <br>
<br>
procedure TShape.WMHOTKEY(var Msg:TWMHotKey); <br>
begin <br>
//检测到Ctrl+S 热键时退出程序 <br>
if (Msg.HotKey=HOTKEYID) then Close <br>
else inherited; <br>
end; </td>
</tr>
<tr>
<td width="100%" height="37" bgcolor="#7CBDDC"><p align="right"><a href="Delphi2-2.htm"><img src="../images/goto.gif" alt="下一页" WIDTH="49" HEIGHT="23"><strong><big>下一页</big></strong></a></td>
</tr>
</table>
<!--webbot bot="Include" U-Include="../wei1.htm" TAG="BODY" startspan --><strong>[wei1.htm]</strong><!--webbot bot="Include" endspan i-checksum="9818" -->
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -