SetWindowRgn函数应用--截图,绘制多边形窗体

3 篇文章 0 订阅

版权所有,转载请注明出处:http://guangboo.org/2013/02/04/setwindowrgn-application

SetWindowRgn函数用于设置窗体的绘制区域,该区域决定了窗口的形状,并且超出该区域的一切绘制工作都无效的,不会显示在屏幕上。

函数签名

int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw);

其中参数hWnd是要设置区域的窗口句柄;hRgn是区域句柄,该值可以是NULL;bRedraw表示设置完窗口区域后是否重新绘制窗口,True,表示重新绘制,否则不绘,如果窗口可见,bRedraw一般设为True。返回值为非零时表示设置成功,否则失败。

需要注意的是,这里的区域坐标是相对于窗口的左上角而言的,而不是窗口的工作区。一旦方法调用成功,那么系统就获取了这片区域的句柄,并可以在这片区域进行绘制。

C#函数声明

该函数定义在User32.dll中(参考http://msdn.microsoft.com/zh-cn/library/dd145102(v=VS.85).aspx),因此C#可以通过平台调用来引用该win32api,如下声明:

[DllImport("user32.dll")]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);

其中hWnd可以在Form中使用this.Handle获取,而hRgn则没有类似的定义,也没有对应的结构体。但是C#中有Region类(System.Drawing命名空间),并且该类提供了GetHrgn方法,用来获取Region类的句柄。并且如果你要绘制圆角矩形的窗体,还可以调用CreateRoundRectRgn方法来获取圆角矩形的区域句柄,该方法的在gdi32.dll中定义(参考http://msdn.microsoft.com/zh-cn/library/dd183516.aspx)。声明如下:

[DllImport("gdi32.dll")]
private static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy);

参数x1,y1表示圆角矩形左上角的坐标,x2,y2表示矩形的宽和高,cx, cy表示圆角所占椭圆的宽和高。如果调用成功,返回值为圆角矩形的区域句柄,否则为NULL。

截图应用

有了SetWindowRgn函数,我们就可以实现对窗口“挖洞”了。类似于QQ的截图功能,它的效果是,整个屏幕都变黑底半透明,然则在屏幕上选择一款矩形区域,并且选择的矩形区域是没有黑底半透明修饰的。那么这样的效果就像对一个全屏的,背景是黑色半透明的窗体,选择一块矩形区域,并将选择的矩形区域“挖空”一样。现在有了SetWindowRgn函数,我们就可以实现“挖空”效果了。一段测试代码,用来绘制“中空”的窗体,只有重写OnPaint方法或在WnProc方法中拦截WM_PAINT消息:

protected override void OnPaint(PaintEventArgs e) {
    System.Drawing.Region region = new System.Drawing.Region();
    region.Union(this.Bounds);
    region.Exclude(new Rectangle(40, 40, 100, 100));
    SetWindowRgn(this.Handle, region.GetHrgn(e.Graphics), true);
    base.OnPaint(e);
}

或者:

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case WM_PAINT:
            System.Drawing.Region region = new System.Drawing.Region();
            region.Union(this.Bounds);
            region.Exclude(new Rectangle(40, 40, 100, 100));
            IntPtr dc = GetWindowDC(m.HWnd);
            Graphics g = Graphics.FromHdc(dc);
            SetWindowRgn(m.HWnd, region.GetHrgn(g), true);
            break;
    }
    base.WndProc(ref m);
}

两个代码的效果是一样的,都在相对窗体的(40,40)的位置开始“挖”去一个长宽是100X100的矩形,运行效果如图:

“挖空”的效果已经实现,接着就是将窗体全屏,设置黑色背景,半透明化;然后将“挖空”的矩形改成屏幕选择的区域。这些代码可以参加《C#实现屏幕截图,这里不再贴出代码。

不过有一点需要说明,在选择区域时,应该调用Refresh方法,来刷新界面,否则是不会发出WM_PAINT消息的,也就没有了OnPaint事件了。

绘制多边形窗体

最常用的窗体样式就是圆角窗体了,如果使用SetWindowRgn方法就变的异常简单,只需要简单几行代码即可,如下:

const int WM_PAINT = 0x000F;
const int WM_SIZE = 0x0005;
protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case WM_PAINT:
        case WM_SIZE:
            SetWindowRgn(m.HWnd, CreateRoundRectRgn(0, 0, this.Width, this.Height, 20, 20), true);
            break;
    }
    base.WndProc(ref m);
}

这里用到了CreateRoundRectRgn函数,用于创建圆角区域,当然你也可以使用Region类来自己手动创建圆角区域。运行效果如下图:

这是在Window Classic主题下的效果。当然,如果希望Window XP主题下(本身就是圆角的窗体主题)使窗体没有圆角效果,只需要将CreateRoundRectRgn(0, 0, this.Width, this.Height, 20, 20)代码修改成CreateRoundRectRgn(0, 0, this.Width, this.Height, 0, 0)即可,运行效果如图:

但这里的示例仅仅用来演示修改窗体形状原理的,一般在实现一个窗体效果时,还需要很多的修饰,具体可以参考《C#重绘Windows窗体标题栏和边框》。上面主要演示了最常用的圆角或实角矩形窗体效果,当然有了Region类和 SetWindowRgn函数,我们可以实现更加丰富的窗体效果,只是这些效果不是很常用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值