使用SetWindowRgn函数创建异形窗口 --简单异形窗口

 

写在正文前:

我是个初学者,很多程序员都说要多打代码,不要只是看看。所以我就将我的学习做一个记录,这些都是我搜索的,很多大家都见过了,我只是学习以后加入自己的理解编译出来,难免有错误,欢迎大家指出来共同提高。

SetWindowRgn()函数可以设定窗口的多种边界剪切域,而不是像SetWindowRect只能设置矩形的外包边界。

先用一个简单的实例直观的说明。

1、 用MFC的向导工具建立一个对话框工程,工程名为ShapedWindow1。

2、 在对话框类中增加窗口区域的数据成员

class CShapedWindow1Dlg : public CDialog
{ …
private:
CRgn m_rgn;//window region

…
};

3、 修改OnInitDialog()函数,建立一个圆角矩形区域,再调用SetWindowRgn()函数将区域分配给对话框。

BOOL CShapedWindow1Dlg::OnInitDialog()
{…

// 创建圆角矩形区域
CRect rc; // rounded rectangle 
GetWindowRect(&rc); // window rect in screen coords

m_rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,
    50,50); // rounded rect w/50 pixel corners

//设置这个区域
SetWindowRgn(m_rgn,TRUE); // set window region to make rounded window

return TRUE; // 除非将焦点设置到控件,否则返回TRUE
}

4、 编译运行程序,就可以完成一个最简单的圆角矩形窗口。(如图1)

tu1

这样一个简单的圆角矩形的对话框就完成了!

5、 下面让我们更近一步,创建更多不同的异形窗口。

利用CRgn类中的成员函数可以创建椭圆形、多边形和其它一些复杂的图形的窗口。

这里只介绍几种简单的异性窗口创建。

将上面3步骤中的代码行替换成不同的区域形状。

//替换的代码行
m_rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,
     50,50); // rounded rect w/50 pixel corners 

依次换成以下的代码。

//椭圆形替换代码
m_rgn.CreateEllipticRgn(rc.left,rc.top,rc.right,rc.bottom);

//多边形替换代码
//多边形的点的数组
CPoint ptVertex[5];

ptVertex[0].x = rc.left ;
ptVertex[0].y = rc.bottom;
ptVertex[1].x = rc.right;
ptVertex[1].y = rc.bottom;
ptVertex[2].x = rc.right;
ptVertex[2].y = (rc.top+rc.bottom)/2;
ptVertex[3].x = (rc.right+rc.left)/2;
ptVertex[3].y = rc.top;
ptVertex[4].x = rc.left;
ptVertex[4].y = (rc.top+rc.bottom)/2;
m_rgn.CreatePolygonRgn(ptVertex,5,ALTERNATE);

就可以实现椭圆形和多边形的异形窗口了。

6、 关于其它复杂图形可以参考MSDN的CRgn类中不同成员函数的说明,或者API的说明。

7、 注意:这里面使用的函数都是在CWnd类(CDialog类的父类)中的成员函数,而在Window GDI中也有API类似的函数,它们的拼写和参数列表都相同或相近。请不要用错。我在学习时候,搜索到一篇被广泛转载的文章。错误很多,其中一个就如下:

SetWindowRgn (GetSafeHwnd () , (HRGN) m_ rgn,TRUE );

这行代码编译的时候是不能通过的。从参数列表上看,这个函数是Window GDI中的函数。所以应该调用如下:

::SetWindowRgn (GetSafeHwnd () , (HRGN) m_rgn,TRUE );

加“:: ”域操作符调用的才是API函数,否则调用的是CWnd类(CDialog类的父类)中的成员函数,这样的话参数列表有不正确了。

调用成员函数的代码如下:

SetWindowRgn ( (HRGN) m_rgn,TRUE );

源代码下载链接:http://download.csdn.net/source/2301447

结束总结:

使用SetWindowRgn()函数创建异形窗口,首先创建一个CRgn对象,保存窗口形状的信息。

然后调用SetWindowRgn()函数设置成窗口边界剪切域。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个使用 GDI 和 PNG 图像创建异形窗口的完整 Demo: ```c++ #include <Windows.h> #include <gdiplus.h> #pragma comment(lib, "Gdiplus.lib") LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszClassName = TEXT("MyWindowClass"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); RegisterClassEx(&wc); HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST, TEXT("MyWindowClass"), TEXT("My Window"), WS_POPUP, 100, 100, 400, 300, NULL, NULL, hInstance, NULL); // 加载 PNG 图像 Gdiplus::Bitmap* bitmap = Gdiplus::Bitmap::FromFile(L"path/to/image.png"); Gdiplus::Rect rect(0, 0, bitmap->GetWidth(), bitmap->GetHeight()); Gdiplus::BitmapData bitmapData; bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bitmapData); // 创建位图 HDC hdc = GetDC(hwnd); HDC memdc = CreateCompatibleDC(hdc); HBITMAP hbitmap = CreateBitmap(bitmap->GetWidth(), bitmap->GetHeight(), 1, 32, bitmapData.Scan0); // 设置窗口透明度和形状 SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY); HRGN region = CreateRoundRectRgn(0, 0, bitmap->GetWidth(), bitmap->GetHeight(), 20, 20); SetWindowRgn(hwnd, region, TRUE); // 绘制位图到窗口 SelectObject(memdc, hbitmap); BITMAP bm; GetObject(hbitmap, sizeof(BITMAP), &bm); BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY); // 释放资源 DeleteObject(hbitmap); DeleteDC(memdc); ReleaseDC(hwnd, hdc); bitmap->UnlockBits(&bitmapData); delete bitmap; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } Gdiplus::GdiplusShutdown(gdiplusToken); return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } ``` 这个 Demo 首先使用 GDI+ 库加载 PNG 图像,然后创建位图并将其绘制到窗口上。其中,使用 `SetLayeredWindowAttributes` 函数设置窗口透明度和颜色键,使用 `CreateRoundRectRgn` 函数创建圆角矩形区域来设置窗口形状。最后,通过消息循环等待窗口被销毁。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值