MFC不规则窗口
1. 准备工作
1.1 新建一个基于对话框的MFC程序Test
运行后,界面单调乏味。本文介绍如何通过一张png图片实现一个不规则窗口。
1.2 初始化和注销GDI+
在stdafx.h中加入
#include<gdiplus.h>
usingnamespaceGdiplus;
#pragma comment(lib,"gdiplus.lib")
在 CTestApp theApp;下添加一行:
ULONG_PTR g_GDIPlusToken;
在 CTestApp::InitInstance中添加:
GdiplusStartupInputgdiplusStartupInput;
GdiplusStartup(&g_GDIPlusToken,&gdiplusStartupInput,NULL);
在 CTestApp::ExitInstance中添加
GdiplusShutdown(g_GDIPlusToken);
2. 将主对话框不规则化
进入CTestDlg::OnInitDialog。
2.1 设置该窗口为LayeredWindow
即给窗口的WS_EX_LAYERED属性添加WS_EX_LAYERED值。
使用LayeredWindows可以提高性能,并能使用一些视觉效果,如Alpha混合等。
// 设置窗口为LayeredWindows
DWORDdwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE);
SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^WS_EX_LAYERED);
2.2 用png图片来更新这个Layered Window
// 加载png图片
Image image(L"loading.png",TRUE); //GDI+中的类
int nPngWidth = image.GetWidth();
int nPngHeight = image.GetHeight();
//绘制内存位图
HDC hdcTemp = GetDC()->m_hDC;
HDC hdcMemory =CreateCompatibleDC(hdcTemp);
HBITMAP hBitMap= CreateCompatibleBitmap( hdcTemp, nPngWidth,nPngHeight );
SelectObject( hdcMemory,hBitMap );
//使用GDI+载入PNG图片
HDC hdcScreen=::GetDC(m_hWnd);
RECT rct;
GetWindowRect(&rct);
POINT ptWinPos={rct.left,rct.top};
Graphics graph(hdcMemory);
graph.DrawImage(&image,0,0,nPngWidth,nPngHeight); //后面两个参数要设置成跟图片一样大小,否则会失真
//使用UpdateLayerWindow进行窗口透明处理
BLENDFUNCTION blendFun;
blendFun.BlendOp= 0;
blendFun.BlendFlags= 0;
blendFun.AlphaFormat= 1;
blendFun.SourceConstantAlpha= 255;
HMODULE hFuncInst=LoadLibrary(L"User32.DLL");
typedef BOOL (WINAPI *MYFUNC)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
MYFUNC UpdateLayeredWindow;
UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst,"UpdateLayeredWindow");
SIZE sizeWindow={nPngWidth,nPngHeight};
POINT ptSrc={0,0};
UpdateLayeredWindow( m_hWnd,hdcScreen,&ptWinPos,&sizeWindow,hdcMemory,&ptSrc,0,&blendFun,2);
下面就是运行效果:
至此已经实现了不规则的窗口,但是还需要添加各种控件,这里以一个静态文本控件为例。
3. 添加控件
添加文字或控件必须是先添加到子窗口中,然后加到这个窗口上。我们直接在子窗口上写文字。
3.1 添加子窗口对象
在classCTestDlg定义中加入成员
CCtrlsDlg *m_pCtrlsDlg;//子窗体
3.2 为CTestDlg添加WM_CREATE消息响应
CTestDlg::OnCreate
在此添加子对话框的创建:
m_pCtrlsDlg =new CUpdateDlg(this);
m_pCtrlsDlg->Create(IDD_UPDATE_DIALOG);
m_pCtrlsDlg->ShowWindow(SW_SHOW);
3.3 为CTestDlg添加WM_MOVE消息响应
CTestDlg::OnMove
在此添加对子对话位置的调整:
CRectrcDlg;
GetWindowRect(rcDlg);
CRectrcCtrlsDlg;
m_pCtrlsDlg->GetWindowRect(&rcCtrlsDlg);
CRectrc;
rc.left=rcDlg.left+ 30;
rc.top =rcDlg.top+ 75;
rc.right =rc.left +rcCtrlsDlg.Width();
rc.bottom =rc.top +rcCtrlsDlg.Height();
m_pCtrlsDlg->MoveWindow(&rc);
3.4 子窗口透明设置
3.4.1创建画刷
在classCCtrlsDlg定义中添加成员
CBrush m_Brush; // 背景画刷
在CCtrlsDlg::OnInitDialog中添加
m_Brush.CreateSolidBrush(RGB(255,0,255));
3.4.2设置该窗口为LayeredWindow
DWORDdwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE);
SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^WS_EX_LAYERED);
用上面创建的画刷来更新这个Layered Window
HMODULEhInst=LoadLibrary(L"User32.DLL");
typedefBOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNCSetLayeredWindowAttributes= NULL;
SetLayeredWindowAttributes=(MYFUNC)GetProcAddress(hInst,"SetLayeredWindowAttributes");
SetLayeredWindowAttributes(this->GetSafeHwnd(),0xff00ff,0,1);
FreeLibrary(hInst);
3.4 修改字体
在classCCtrlsDlg定义中添加成员
CFont m_Font; //提示文字
创建字体
m_Font.CreateFont(14,0, 0, 0,FW_NORMAL,
FALSE,FALSE, FALSE, 0,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH |FF_ROMAN,L"宋体");
3.4 向窗口上写字
CDC *pDC=GetDC();
::SendMessage(m_hWnd,WM_ERASEBKGND,(WPARAM)pDC->GetSafeHdc(), 0 );
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(0xffffff);
pDC->SelectObject(&m_Font);
pDC->TextOut(50,20,strUpdateInfo,strUpdateInfo.GetLength());
ReleaseDC(pDC);
最终运行效果: