GDI+实现不规则窗体
2017-05-24 15:17
369 查看
先来看一下实现的效果,下图中那个娃娃就是我们要实现的不规则窗体啦~
VS2013上已经有了GDI+支持,不用单独下载安装包了。现在只需项目中引入gdiplus.lib和加入头文件即可。
为了在全工程使用GDI+,在stdafx.h中加入:
2
3
1
2
3
使用GDI+还需要进行初始化:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(1) 在CXXXDlg.h中添加成员变量:
2
1
2
(2) 在CXXXDlg.cpp中添加如下代码:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
用双缓冲的话还要再定义一个位图对象,然后用CreateCompatibleBitmap建立一个与屏幕显示兼容的位图,再用SelectObject将位图选入到内存显示设备中。
在绘制的时候有一个重要的函数叫做UpdateLayeredWindow,可以根据图像的透明度进行显示,函数原型是:
(官网定义)https://msdn.microsoft.com/en-us/library/windows/desktop/ms633556(v=vs.85).aspx
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
内存DC是很重要的一个概念,假如你要对屏幕进行比较多的GDI函数操作,如果每一步操作都直接对屏幕dc进行操作,那出现的大多数可能性都是屏幕的闪烁。一个很好的解决方法就是使用内存dc,将这些操作全部先在内存dc上操作,然后依次性在屏幕上进行操作。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
参考:
【VC++玩转炫酷悬浮窗3—GDI+完美实现不规则窗体】http://blog.csdn.net/lincyang/article/details/39078295
【CreateCompatibleDC】http://www.cnblogs.com/CBDoctor/archive/2012/12/09/2810447.html
1. GDI+配置及初始化(VS2013)
VS2013上已经有了GDI+支持,不用单独下载安装包了。现在只需项目中引入gdiplus.lib和加入头文件即可。 为了在全工程使用GDI+,在stdafx.h中加入:
#include <GdiPlus.h> #pragma comment(lib, "GdiPlus.lib") using namespace Gdiplus;1
2
3
1
2
3
使用GDI+还需要进行初始化:
//在应用初始化时,启动GDI+ BOOL CXXXApp::InitInstance() { ... //Initialize GDIplus ULONG_PTR m_gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); ... } //在程序退出时,关闭gdi+ int CXXXApp::ExitInstance() { //close gdiplus environment GdiplusShutdown(m_gdiplusToken); return CWinApp::ExitInstance(); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2. 动态载入png图片
png图片是实现不规则窗体的关键,因为它本身就是带透明效果的,把这种格式的图片作为窗体本身就是不规则的。首先我们需要载入这张图片,在这里我没有将其作为资源添加到项目中,这样对于更改图片不是很方便,所以用的是动态载入,将图片直接载入到内存中。(1) 在CXXXDlg.h中添加成员变量:
Gdiplus::Image *m_BkgImg;//不规则背景图片 BLENDFUNCTION m_Blend; //指定源和目标位图的透明混合参数1
2
1
2
(2) 在CXXXDlg.cpp中添加如下代码:
BOOL CXXXDlg::OnInitDialog() { ...... m_Blend.BlendOp = AC_SRC_OVER; m_Blend.BlendFlags = 0; m_Blend.AlphaFormat = AC_SRC_ALPHA; m_Blend.SourceConstantAlpha = 200;//255:src img在dest img上不透明 TCHAR lpImageFile[MAX_PATH]; swprintf_s(lpImageFile, TEXT("F:\\img\\region.png"));//图片存放位置 // load from file m_BkgImg = Image::FromFile(lpImageFile, TRUE); if (m_BkgImg == NULL || (m_BkgImg->GetLastStatus() != Ok)) { if (m_BkgImg != NULL) delete m_BkgImg; m_BkgImg = NULL; } ...... }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
3. 绘制不规则窗体
首先使用CreatCompatibleDC()创建了一个和当前屏幕的DC兼容的内存DC(DC就是设备上下文的意思,设备上下文就是当前的这个窗体的一些属性,譬如说他使用的画刷,画笔等等),在绘制位图的时候,你必须要在内存中建立这样的一个和当前设备的环境兼容的DC,这样你才能把位图加载到这块内存里,然后再将位图从内存复制到屏幕DC上,位图才能显示出来。用双缓冲的话还要再定义一个位图对象,然后用CreateCompatibleBitmap建立一个与屏幕显示兼容的位图,再用SelectObject将位图选入到内存显示设备中。
在绘制的时候有一个重要的函数叫做UpdateLayeredWindow,可以根据图像的透明度进行显示,函数原型是:
(官网定义)https://msdn.microsoft.com/en-us/library/windows/desktop/ms633556(v=vs.85).aspx
BOOL WINAPI UpdateLayeredWindow( _In_ HWND hwnd,//窗口句柄 _In_opt_ HDC hdcDst,//屏幕上下文DC _In_opt_ POINT *pptDst,//窗口相对于屏幕的位置的POINT结构的指针 _In_opt_ SIZE *psize,//显示窗口大小 _In_opt_ HDC hdcSrc,//窗口上下文DC _In_opt_ POINT *pptSrc,//窗口绘图表面在设备上下文位置的POINT结构的指针 _In_ COLORREF crKey, _In_opt_ BLENDFUNCTION *pblend,//透明混合参数 _In_ DWORD dwFlags );1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
内存DC是很重要的一个概念,假如你要对屏幕进行比较多的GDI函数操作,如果每一步操作都直接对屏幕dc进行操作,那出现的大多数可能性都是屏幕的闪烁。一个很好的解决方法就是使用内存dc,将这些操作全部先在内存dc上操作,然后依次性在屏幕上进行操作。
void CXXXDlg::OnPaint() { CClientDC clientdc(this); HDC hRgnDC; //Region窗口 HBITMAP hRgnBmp, hOldRgnBmp; int RgnWidth = 500; int RgnHeight = 400; // 创建一个内存DC 与当前屏幕DC兼容 hRgnDC = ::CreateCompatibleDC(clientdc.GetSafeHdc()); // 创建一个位图 与当前屏幕DC兼容 hRgnBmp = ::CreateCompatibleBitmap(clientdc.GetSafeHdc(), RgnWidth, RgnHeight); //将位图选入到内存DC中,只有选入了位图的内存DC才有地方绘图,画到指定的位图上 hOldRgnBmp = (HBITMAP)SelectObject(hRgnDC, hRgnBmp); if (m_BkgImg != NULL){ Graphics graph(hRgnDC); Point points[] = { Point(0, 0), Point(RgnWidth, 0), //width Point(0, RgnHeight)//height }; RECT rct; GetWindowRect(&rct); POINT ptWinPos = { rct.left, rct.top }; graph.DrawImage(m_BkgImg, points, 3); SIZE sizeWindow = { RgnWidth, RgnHeight }; POINT ptSrc = { 0, 0 }; DWORD dwExStyle = GetWindowLong(m_hWnd, GWL_EXSTYLE); if ((dwExStyle & 0x80000) != 0x80000) SetWindowLong(m_hWnd, GWL_EXSTYLE, dwExStyle ^ 0x80000); BOOL bRet = FALSE; bRet = ::UpdateLayeredWindow(m_hWnd, hRgnDC, &ptWinPos, &sizeWindow, hRgnDC, &ptSrc, 0, &m_Blend, 2); ::SelectObject(hRgnDC, hOldRgnBmp); ::DeleteObject(hRgnBmp); ::DeleteDC(hRgnDC); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
4. Done and done!
再来一张图,换图就是如此方便~~参考:
【VC++玩转炫酷悬浮窗3—GDI+完美实现不规则窗体】http://blog.csdn.net/lincyang/article/details/39078295
【CreateCompatibleDC】http://www.cnblogs.com/CBDoctor/archive/2012/12/09/2810447.html
相关文章推荐
- VC++玩转炫酷悬浮窗3---GDI+完美实现不规则窗体
- 使用GDI+实现漂亮的不规则窗体制作
- MFC界面编程1:GDI+实现不规则窗体
- SWT行,AWT/Swing也行系列(1)-实现半透明及不规则窗体
- SWT行,AWT/Swing也行系列(1)-实现半透明及不规则窗体
- Windows 中不规则窗体的编程实现
- Qt中不规则窗体和部件的实现
- Qt中不规则窗体和部件的实现
- 不规则窗体的实现
- QT中不规则窗体和部件的实现
- 用C#实现不规则窗体
- WPF实现不规则窗体(C#)
- Java实现带渐变字幕的不规则窗体
- Windows 中不规则窗体的编程实现
- wxWidgets实现不规则窗体
- Winform不规则窗体的实现心得
- C++BUILDER中一些实现界面效果的技巧。。不规则窗体等等。。
- Qt中不规则窗体和部件的实现
- 用PNG透明图片和GDI+做不规则透明窗体"异形窗口"
- Qt中不规则窗体和部件的实现