声明:原始方法部分已经废弃,现在有更好的办法来实现DUILIB加载PNG图片,为保持学习的渐进性,我还是保留了原始方法部分的博文与代码,大家没有必要看原始部分了,直接看新方法部分吧;
新方法
前言:上周我研究了一周如何在DUILIB中加载PNG不规则背景图,但毕竟还是新接触GDI绘图,难度还是挺大的,一直没能找到一种方法在DUILIB中不大规模修改代码的情况下,能实现PNG图片加载,正在绝望之时,一位大牛出现了,就在前一天,他发表了一篇BLOG,修改了WM_PAINT消息响应,成功的实现了加载PNG图片,具体代码我还没有看,但成功加载是一点问题都没有的,这里我就把他的代码贴出来给大家,还有这位大牛写的几个小例子,相当不错。
修改源文件及示例下载地址(不要分,仅供分享):http://download.csdn.net/detail/harvic880925/5457661
问题及解决(一定要看):
1、关键问题,在修改了WM_PAINT后,文字都变成了透明的了,很蛋疼,下面是解决方案
将下面的代码覆盖UIRender.cpp里的DrawText, 注意添加头文件和命名空间
- #include <gdiplus.h>
- #include <windowsx.h>
- #include <locale.h>
- using namespace Gdiplus;
- #pragma comment(lib, "gdiplus.lib")
-
- void DrawText( HDC hDC, CPaintManagerUI* pManager,
- RECT& rc, LPCTSTR pstrText, DWORD dwTextColor, int iFont, UINT uStyle )
- {
- ASSERT(::GetObjectType(hDC)==OBJ_DC || ::GetObjectType(hDC)==OBJ_MEMDC);
- if( pstrText == NULL || pManager == NULL ) return;
- ::SetBkMode(hDC, TRANSPARENT);
- BYTE alphaValue = (dwTextColor)>>24;
-
- Gdiplus::Graphics graphics(hDC);
- Font myFont(hDC,pManager->GetFont(iFont));
- RectF layoutRect(
- static_cast<REAL>(rc.left),
- static_cast<REAL>(rc.top),
- static_cast<REAL>(rc.right - rc.left),
- static_cast<REAL>(rc.bottom - rc.top));
- StringFormat format;
- StringAlignment align=StringAlignmentCenter;
- int i=uStyle%16;
- if(i==0){
- align=StringAlignmentNear;
- }else if(i==1){
- align=StringAlignmentCenter;
- }else if(i==2){
- align=StringAlignmentFar;
- }
-
- format.SetAlignment(align);
- format.SetLineAlignment(StringAlignmentCenter);
-
- if(uStyle & DT_END_ELLIPSIS)format.SetTrimming( StringTrimmingEllipsisCharacter );
- if(uStyle & DT_SINGLELINE) format.SetFormatFlags( StringFormatFlagsNoWrap );
- Color textcolor(dwTextColor);
-
-
-
- BYTE R=GetBValue(dwTextColor);
- BYTE B=GetRValue(dwTextColor);
- BYTE G=GetGValue(dwTextColor);
- SolidBrush textBrush(Color(255,R,G,B));
- graphics.DrawString(pstrText,
- -1,
- &myFont,
- layoutRect,
- &format,
- &textBrush);
- }
添加字体:
showHtml一定要设置成FALSE,不然不会进入我们的函数,字体仍然会透明,如果想使用加粗啥啥的怎么办呢,这里我们使用设置字体的办法。
先点中XXX.XML,在属性里,选择“字体管理”,然后添加字体,比如我的:
注意第一列的“Index”,然后到控件里,设置font属性,值就是要设置的字体的Index值。
如:
2、创建DLG时,会出现控件与背景对不齐的现象,,有时还会出现,当鼠标移动到按钮时,对话框会从右边自动消失,
如图:,红框的部分原来也是背景的一部分的,但当我移动到按钮或其它控件的时候,背景会一点点的消失掉,解决办法:
在handleMessage()里加上对WM_NCCALCSIZE和WM_NCHITTEST的响应代码!
在HandleMessage()中加上如下两句代码:
- case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
- case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
OnNcCalcSize和OnNcHitTest的具体实现
- LRESULT CBaseWnd::OnNcCalcSize(UINT , WPARAM , LPARAM , BOOL& )
- {
- return 0;
- }
- LRESULT CBaseWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
- ::ScreenToClient(*this, &pt);
-
- RECT rcClient;
- ::GetClientRect(*this, &rcClient);
-
- if( !::IsZoomed(*this) ) {
- RECT rcSizeBox = paint_manager_.GetSizeBox();
- if( pt.y < rcClient.top + rcSizeBox.top ) {
- if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;
- if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
- return HTTOP;
- }
- else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) {
- if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;
- if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
- return HTBOTTOM;
- }
- if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;
- if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
- }
-
- RECT rcCaption = paint_manager_.GetCaptionRect();
- if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
- && pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
- CControlUI* pControl = static_cast<CControlUI*>(paint_manager_.FindControl(pt));
- if( pControl && _tcsicmp(pControl->GetClass(), _T("ButtonUI")) != 0 &&
- _tcsicmp(pControl->GetClass(), _T("OptionUI")) != 0
- )
- return HTCAPTION;
- }
-
- return HTCLIENT;
- }
最后:感谢ku625的分享,现在DUILIB还处于不成熟的阶段,我们大家只有联合起来共同努力,乐于分享,才能让DUILIB更强大,我们开发起来也更容易,还有这个方法的作者建了个群:322701541,供大家交流DUILIB技术,ku625非常热心,技术也很高,很有耐心地解答了我一些问题,在此表示感谢!!!!。
此方法的原出处:http://www.yutent.com/article-68.html
原始方法
前言:在一篇中,我们讲了怎么加载XML界面,这篇文章我们将讲解怎么创建不规则窗体也就是异形窗体。我们是在上一篇工程的基础上讲解,如果大家对基本加载XML还不清楚的话,还是先看前一篇吧
先看看效果:
下面讲解实现方法:
先打开上一篇的工程,跟我一步步做;
一、准备工作
1、准备一张.png的图片(名称我们叫做bg.png),如上,注意,如果你在图片中设置不透明度为30%的话,显示出来的也将是不透明度为30%的
2、将其放在debug目录下,如图
3.用UIDesigner设计一个XML文档,按钮啥啥的我都不加了,只加一个背景,背景色为:#ffff00ff,将XML文档放在debug中的skin目录下
4、准备文件IrregularWindow.h和IrregularWindow.cpp,并将它们加载到工程中
二、写代码
1、MainFrame类中添加一个成员变量:
- CIrregularWindow *m_pBackWnd;
2、在CMainFrame::CMainFrame(void)函数中添加如下代码:
- CMainFrame::CMainFrame(void)
- {
- CStdString strResourcePath=CPaintManagerUI::GetInstancePath();
- CIrregularWindow::InitGDIplus();
-
- m_pBackWnd = new CIrregularWindow(strResourcePath + _T("bg.png"));
-
- assert(m_pBackWnd != NULL && _T("new CIrregularWindow() 失败!"));
-
- if(m_pBackWnd)
- {
- HWND hBkWnd = m_pBackWnd->GetHandle();
- }
- }
意思是,在创建的时候调用CirregularWindow来初始化背景,注意这里会有一个HWND产生,也就是会有一个窗体产生,所以仅仅是这一个背景图片就会在运行的时候,在任务栏产生一个任务图标!!!!
3、在CMainFrame::OnCreate的最后添加上如下代码
- if(m_pBackWnd)
- {
- m_pBackWnd->AttachWindow(m_hWnd);
- };
一定要添加上这句,如果不添加上这句,前面搞的背景图片不会有任何效果,有兴趣大家看看这句的实现就会知道这句的作用了。这就不讲了
4、CMainFrame::HandleMessage中,添加上对WM_DESTROY的响应,在销毁窗口时,释放资源:
- case WM_DESTROY:
- ::PostQuitMessage(0L);
- CIrregularWindow::UnInitGDIplus();
- delete m_pBackWnd;
- m_pBackWnd = NULL;
- return 0;
5、对_tWinMain的修改
最后就是入口函数了,这里有几个地方要修改下,先看代码吧:
- int APIENTRY _tWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine,
- int nCmdShow)
- {
- CPaintManagerUI::SetInstance(hInstance);
- CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()
- + _T("skin"));
-
- HRESULT Hr = ::CoInitialize(NULL);
- if( FAILED(Hr) )
- return 0;
-
- CMainFrame* pMainFrame = new CMainFrame();
- if( pMainFrame == NULL )
- return 0;
-
- pMainFrame->Create(pMainFrame->m_pBackWnd->GetHandle(), _T("AdderCalc"), UI_WNDSTYLE_DIALOG, 0);
-
- pMainFrame->m_pBackWnd->CenterWindow();
-
- pMainFrame->ShowWindow(true);
- CPaintManagerUI::MessageLoop();
-
- ::CoUninitialize();
- return 0;
- }
这里更改了几个地方:
5.1:
- pMainFrame->Create(pMainFrame->m_pBackWnd->GetHandle(), _T("AdderCalc"), UI_WNDSTYLE_DIALOG,0);
看一个参数,以前是NULL,现在是pMainFrame->m_pBackWnd->GetHandle(),也就是将背景图片产生的窗体作为父窗口产生DLG,如果不这样在任务栏会产生两个窗体,不信,你就把下面create的第一个参数改成NULL试试,你就懂了
5.2:
- pMainFrame->m_pBackWnd->CenterWindow();
因为现在的主HWND是背景图片产生的窗体所以要以背景图片居中,直接pMainFrame ->CenterWindow();居中是无效的!!!
好了,到这就全部实现了,大家可以自己去添加自定义的按钮啥啥的,然后添加响应,嘿嘿
与往常一样,源码地址:http://download.csdn.net/detail/harvic880925/5374535
转载要标明出处哦:http://blog.csdn.net/harvic880925/article/details/8925650
声明:感谢金山影音漂亮的图片,该图片来源于网络,如果有任何侵权问题,请及时联系我,我会删除,谢谢!!