`
444878909
  • 浏览: 635883 次
文章分类
社区版块
存档分类
最新评论

<Win32_9>SetWindowRgn函数的应用——绘制个性化形状的窗口

 
阅读更多

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);

……

我们还是来看看修改后的效果嘛:

呵呵,终于讲完了,希望鄙人的心得能给大家带来学习的方便^_^

点击下载完整代码和程序
分享到:
评论

相关推荐

    VB编程资源大全(英文源码 表单)

    Much more reliable than using INIs&lt;END&gt;&lt;br&gt;7 , Menubmp.zip&lt;br&gt;This demonstrates how to add images to a menu.&lt;END&gt;&lt;br&gt;8 , 3DBorders.zip&lt;br&gt;This bas lets you create 3D Borders on your form.&lt;END&gt;&lt;br&gt;9 ,...

    Win32个性化窗口形状

    本资源包含源代码和编译好的可执行程序 主要用于鄙人博文资源代码下载 http://blog.csdn.net/crocodile__/article/details/9873037

    QQ2006.rar_SetWindowRgn_resizing_对话框 大小_对话框 改变 大小_窗体

    创建异形窗体函数 SetWindowRgn 放到合适的位置,别让拖动窗体改变大小时出现用做 MASK 的紫色区域;再者与大家分享不指定窗体风格 WS_THICKFRAME(对于对话框,相当指定其属性 Border 为 Resizing ),用代码实现...

    SetWindowRgn

    SetWindowRgn对系统滚动条的影响

    API之网络函数---整理网络函数及功能

    SetHandleCount 这个函数不必在win32下使用;即使使用,也不会有任何效果 SetVolumeLabel 设置一个磁盘的卷标(Label) SystemTimeToFileTime 根据一个FILETIME结构的内容,载入一个SYSTEMTIME结构 UnlockFile ...

    VB SetWindowRgn创建椭圆形窗口.rar

    VB创建一个个性化的椭圆形窗口界面,使用 SetWindowRgn创建椭圆形窗口的例子。个性的窗口形状可增加程序的趣味性,可以使程序更具吸引力。见惯了方方正正的矩形窗体,椭圆形窗体更会使用户眼前一亮。本实例设计一个...

    VC++做异形窗口 透明效果

    2.改变窗口外形通过使用新的SDK函数SetWindowRgn(),可以将绘画和鼠标消息限定在窗口的一个指定的区域,因此实际上是使窗口成为指定的不规则形状(区域形状)。“区域”是Windows GDI中一种强有力的机制,区域是...

    MFC框架下简单异形窗口--SetWindowRgn

    一个简单的异形窗口的工程。 用VS2005编译的,使用了MFC做框架。

    设定不规则窗体 SetWindowRgn

    设定不规则窗体 SetWindowRgn 不规则窗体 SetWindowRgn

    透空窗口 GetGlyphOutline() SetWindowRgn() beginpath(),SetBkMode(),endpath(),StrokePath()

    3.讲解Win32 API函数:beginpath(),SetBkMode(),endpath(),StrokePath() SetWindowRgn() 有人用“GetGlyphOutline()”去实现,而这里用简单的方法就做到了。 使用“beginpath”可以打开画布的“path bracket”, ...

    易语言特殊形状按钮

    易语言特殊形状按钮源码,特殊形状按钮,窗口异型_正三角形,新函数,窗口异型_倒三角形,窗口异型_圆角矩形,窗口异型_平行四边形,画正三角焦点,DeleteObject,SetWindowRgn,CreateEllipticRgn,CreatePolygonRgn,...

    VC6.0 绘制多边形、圆角或椭圆形窗体的实例.rar

    一个VC 6.0个性化窗体设计实例,绘制矩形、多边形、圆角或椭圆形的窗体,没有了窗口的标题栏和任务栏,以及最大化、最小化按钮,一切看似很简洁,虽然是规则窗口吧,但不属于常规窗口,以后会与大家分享不规则的异型...

    易语言圆角化窗口

    易语言圆角化窗口源码,圆角化窗口,圆角化,CreateRoundRectRgn,SetWindowRgn,DeleteObject

    Delphi使用GDI+制作任意图片形状窗口

    Delphi使用GDI+制作任意图片形状(PGN图形)窗口

    win32下创建异形窗体

    异型窗口就是一些不规则的窗口,我们平时所见到的窗口如“画图”、word等,它们的窗口都是矩形的,然而,我们实际开发中,项目为了增加交互性和漂亮的UI来吸引用户,产品经理极有可能需要来做一些不规则的窗口。...

    e语言-易语言窗口windows 98风格

    .DLL命令 SetWindowRgn, 整数型, "user32", "SetWindowRgn", , 这是那些很难有人注意到的对编程者来说是个巨大的宝藏的隐含的API函数中的一个。本函数允许您改变窗口的区域。  .参数 hWnd, 整数型  ....

    一个窗口镂空程序(挖洞.zip)

    应网友要求,一个窗口镂空程序。说明 CreateRectRgn(0, 0, cx+A_BIT_MORE, cy+A_BIT_MORE); CombineRgn(&wndRgn;, &rgnTemp;, RGN_DIFF); SetWindowRgn(wndRgn,FALSE); 等CRgn函数的使用

    易语言窗口圆角效果

    易语言窗口圆角效果源码,窗口圆角效果,窗口圆角化,CreateRoundRectRgn,SetWindowRgn,DeleteObject

    字形窗口_sub_visualbasic_vb6_字形特效窗体_

    3 SelectObject dc OldFont EndPath dc '结束记录窗体轮廓路径 mw = PathToRegion(dc) '把所记录的路径转化为窗体轮廓句柄 SetWindowRgn Me.hWnd mw True '赋予窗体指定的轮廓形状 End Sub

    VC++界面编程之--使用分层窗口实现界面皮肤

    使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果。 在很多情况下,界面的漂亮与否,取决于PS的制作及创意,而界面...

Global site tag (gtag.js) - Google Analytics