SetWindowRgn这个函数比较好玩,它可以通过设定的区域(RGN)来制定该形状的窗口
先来看看函数原型:
int SetWindowRgn(
HWND hWnd, // handle to window
HRGN hRgn, // handle to region
BOOL bRedraw // window redraw option
);
由此可以看出我们需要先建立一个区域RGN,以此来设定窗口形状
这个不难,可以调用CreateEllipticRgn、CreatePolygonRgn等相关创建RGN的函数
关键是第三个参数bRedraw,它有点儿学问,我们先暂时放一下,待会儿细究……
今天写的程序,实现的功能为:
通过鼠标点击的次数来变换窗口的形状(为了简便起见,我只用了两种:椭圆形和五角形),同时变换窗口背景的颜色(待会儿你会看到奇怪的现象)
具体实现细节如下:
(1)首先建立两个自定义消息
//自定义消息
#define WM_ELLIPSEWND (WM_USER + 100)//椭圆窗口消息
#define WM_PENTAGONWND (WM_USER + 101)//五角形窗口消息
(2)在窗口过程设定以下静态变量:
static int iClick;//标记鼠标点击的次数
static HRGN hRgnWnd;//窗口区域
static POINT pt[5];//五角形的五个点
static HBRUSH hBr;//背景刷
(3)在WM_SIZE消息中初始化五角形的五个点
case WM_SIZE:
{
//获取客户区大小
int cxClient, cyClient;
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//初始化五角形的五个点
pt[0].x = cxClient / 2;
pt[0].y = 0;
pt[1].x = 50;
pt[1].y = cyClient / 2;
pt[2].x = cxClient / 3;
pt[2].y = cyClient;
pt[3].x = cxClient * 2 / 3;
pt[3].y = cxClient;
pt[4].x = cxClient - 50;
pt[4].y = cyClient / 2;
}
return 0;
(4)通过鼠标消息来控制窗口的形状和颜色
case WM_LBUTTONDOWN:
{
UINT msg;
COLORREF brColor;
iClick++;
//根据鼠标点击的次数来确定发送消息种类以及背景刷颜色
msg = iClick % 2 ? WM_ELLIPSEWND : WM_PENTAGONWND;
brColor = iClick % 2 ? RGB(36, 204, 40): RGB(254, 243, 39);//前者是绿色,后者是黄色
//创建背景刷
hBr = CreateSolidBrush(brColor);
//发送消息
SendMessage(hwnd, msg, wParam, lParam);
}
return 0;
不难推理出,当窗口形状为椭圆的时候应该为绿色,当窗口形状为五角形时就为黄色
(5)在自定义消息中绘制相应窗口形状
//绘制椭圆窗口
case WM_ELLIPSEWND:
hRgnWnd = CreateEllipticRgn(100, 100, 400, 400);
SetWindowRgn(hwnd, hRgnWnd, TRUE);
//绘制五角形窗口
case WM_PENTAGONWND:
hRgnWnd = CreatePolygonRgn(pt, 5, WINDING);
SetWindowRgn(hwnd, hRgnWnd, TRUE);
//重绘窗口背景
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
{
RECT rect;
GetClientRect(hwnd, &rect);
FillRect(hdc, &rect, hBr);
}
EndPaint(hwnd, &ps);
接下来,我们就来看看奇怪现象的产生(为了效果的显著,我一开始设定背景颜色为黑色):
(1)首先建立一个黑色背景的窗口
(2)点击一次鼠标后(你会发现,椭圆窗口颜色不是我们想要的绿色,而是原先的黑色)
(3)再点击一次鼠标(你会发现五角形窗口的颜色也有问题,虽然有黄色的部分,但左边一部分区域确是黑色)
(4)最后再来点击一次鼠标(这个和五角形的现象类似,你仔细瞧瞧,椭圆黑色的区域和五角形的黑色区域是同一个区域)
看到这儿,你一定会疑问了:是哪儿的代码出问题了吗?
其实不是代码的问题,主要是SetWindowRgn函数的特点决定的
还记得一开始说的这个函数最后一个参数吗——BOOL bRedraw
当为TRUE时,重绘窗口;否则,不重绘
而我们这里设定的是TRUE:
SetWindowRgn(hwnd, hRgnWnd, TRUE);
你可能还是会有疑问:对啊,重绘了的啊,怎么还是会出现这个问题呢?
经过本人仔细的思考和测试,我得出以下结论(虽然不能保证100%的正确,但至少能解释他的原因):
这里设定了第三个参数为TRUE,当调用该函数的时候,windows的确会重绘当前区域,但是:
它会依然保存当前区域和上一次区域的交集,仅仅重绘当前区域中除开这个交集的部分
我只解释第一个,之后的三个是相同的,大家通过我讲的第一个就能明白了:
首先建立窗口时,这个区域是该窗口的大小
当点击第一次鼠标时,当前区域是这个椭圆,由于这个椭圆在原始窗口内部,因此这个椭圆区域与初始窗口的交集就是这个椭圆区域,那么,按照我总结的结论,这个椭圆区域不会被重绘,依然是黑色
……
到此,你是不是应该明白了
当然,明白之后,你还会想知道解决方法,这个其实很简单,因为windows在调用SetWindowRgn函数时,并不是重绘完整的当前区域,那么我们寻找一种方式来迫使windows完全重绘该区域,一种很简单的方式就是设定无效区域为整个原始窗口:
//这里必须调用InvalidateRect和InvalidateRgn效果是一样的,只不过第二个参数要为NULL,因为我们希望整个窗口都会重绘
InvalidateRgn(hwnd, NULL, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
……
我们还是来看看修改后的效果嘛:
呵呵,终于讲完了,希望鄙人的心得能给大家带来学习的方便^_^
点击下载完整代码和程序
分享到:
相关推荐
Much more reliable than using INIs<END><br>7 , Menubmp.zip<br>This demonstrates how to add images to a menu.<END><br>8 , 3DBorders.zip<br>This bas lets you create 3D Borders on your form.<END><br>9 ,...
本资源包含源代码和编译好的可执行程序 主要用于鄙人博文资源代码下载 http://blog.csdn.net/crocodile__/article/details/9873037
创建异形窗体函数 SetWindowRgn 放到合适的位置,别让拖动窗体改变大小时出现用做 MASK 的紫色区域;再者与大家分享不指定窗体风格 WS_THICKFRAME(对于对话框,相当指定其属性 Border 为 Resizing ),用代码实现...
SetWindowRgn对系统滚动条的影响
SetHandleCount 这个函数不必在win32下使用;即使使用,也不会有任何效果 SetVolumeLabel 设置一个磁盘的卷标(Label) SystemTimeToFileTime 根据一个FILETIME结构的内容,载入一个SYSTEMTIME结构 UnlockFile ...
VB创建一个个性化的椭圆形窗口界面,使用 SetWindowRgn创建椭圆形窗口的例子。个性的窗口形状可增加程序的趣味性,可以使程序更具吸引力。见惯了方方正正的矩形窗体,椭圆形窗体更会使用户眼前一亮。本实例设计一个...
2.改变窗口外形通过使用新的SDK函数SetWindowRgn(),可以将绘画和鼠标消息限定在窗口的一个指定的区域,因此实际上是使窗口成为指定的不规则形状(区域形状)。“区域”是Windows GDI中一种强有力的机制,区域是...
一个简单的异形窗口的工程。 用VS2005编译的,使用了MFC做框架。
设定不规则窗体 SetWindowRgn 不规则窗体 SetWindowRgn
3.讲解Win32 API函数:beginpath(),SetBkMode(),endpath(),StrokePath() SetWindowRgn() 有人用“GetGlyphOutline()”去实现,而这里用简单的方法就做到了。 使用“beginpath”可以打开画布的“path bracket”, ...
易语言特殊形状按钮源码,特殊形状按钮,窗口异型_正三角形,新函数,窗口异型_倒三角形,窗口异型_圆角矩形,窗口异型_平行四边形,画正三角焦点,DeleteObject,SetWindowRgn,CreateEllipticRgn,CreatePolygonRgn,...
一个VC 6.0个性化窗体设计实例,绘制矩形、多边形、圆角或椭圆形的窗体,没有了窗口的标题栏和任务栏,以及最大化、最小化按钮,一切看似很简洁,虽然是规则窗口吧,但不属于常规窗口,以后会与大家分享不规则的异型...
易语言圆角化窗口源码,圆角化窗口,圆角化,CreateRoundRectRgn,SetWindowRgn,DeleteObject
Delphi使用GDI+制作任意图片形状(PGN图形)窗口
异型窗口就是一些不规则的窗口,我们平时所见到的窗口如“画图”、word等,它们的窗口都是矩形的,然而,我们实际开发中,项目为了增加交互性和漂亮的UI来吸引用户,产品经理极有可能需要来做一些不规则的窗口。...
.DLL命令 SetWindowRgn, 整数型, "user32", "SetWindowRgn", , 这是那些很难有人注意到的对编程者来说是个巨大的宝藏的隐含的API函数中的一个。本函数允许您改变窗口的区域。 .参数 hWnd, 整数型 ....
应网友要求,一个窗口镂空程序。说明 CreateRectRgn(0, 0, cx+A_BIT_MORE, cy+A_BIT_MORE); CombineRgn(&wndRgn;, &rgnTemp;, RGN_DIFF); SetWindowRgn(wndRgn,FALSE); 等CRgn函数的使用
易语言窗口圆角效果源码,窗口圆角效果,窗口圆角化,CreateRoundRectRgn,SetWindowRgn,DeleteObject
3 SelectObject dc OldFont EndPath dc '结束记录窗体轮廓路径 mw = PathToRegion(dc) '把所记录的路径转化为窗体轮廓句柄 SetWindowRgn Me.hWnd mw True '赋予窗体指定的轮廓形状 End Sub
使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果。 在很多情况下,界面的漂亮与否,取决于PS的制作及创意,而界面...