MFC创建不规则窗口

6 篇文章 0 订阅



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



最终运行效果:

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值