REDM基础教程18-换肤的几种方式
MyTest下载–>
修改后的MyTest下载–>
编译MyTest时如果报错误:
.\..\Test\inc\Test.rc(57) : error RC2135 : file not found: I:\MyTest\Test\inc\qq.ico
把它改成
IDI_ICON1 ICON "inc\\qq.ico"
就OK了
1.增加换肤的菜单项
首先我们来打开MyRes\layout\xml\dui_exitmenu.xml,增加两项换肤菜单
<menu clrbg="pbgra(f8,fc,e9,ff)" clrselbg="pbgra(33,99,ff,ff)" clrText="pbgra(00,00,00,ff)" clrTextSel="pbgra(fe,fe,fe,ff)" alpha="0x80" bshadow="1" itemhei="24" textoffset="13" font="face:微软雅黑,size:13"><!--id必须不为0,,在1到65535之间,0在菜单TrackPopupMenu中表示fail--> <item text="官方支持(禁用态)" bdisable="1" /> <item text="多语言切换"><!--三个子项--> <item id="100" text="英语"/> <item id="101" text="俄语"/> <item id="102" text="中文"/> </item> <item text="换肤方式">//--------------------------------------------------> 增加两项换肤菜单 <item id="103" text="主题包换肤"/> item id="104" text="外部载入换肤"/> <item id="105" text="SetAttribute换肤"/> </item> <sep/> <item text="自定高度" height="40"/> <item id="200" text="退出"/> </menu>
以前面同样的方式,在MyTest\Test\inc\MainWnd.h中加入
enum QQMenuId { QQMENU_LANG_EN = 100,// QQMENU_LANG_RN = 101, QQMENU_LANG_CH = 102, QQMENU_THEMESKIN = 103, QQMENU_OUTSKIN = 104, QQMENU_SETATTRSKIN = 105, QQMENU_EXIT = 200, }; };
在MyTest\Test\inc\MainWnd.cpp中加入
void CMainWnd::OnCommand(UINT uNotifyCode, int nID, HWND wndCtl) { switch (nID) { ..... case QQMENU_THEMESKIN: {// 通过主题包换肤 } break; case QQMENU_OUTSKIN: {// 通过外部加载图片 } break; case QQMENU_SETATTRSKIN: {// 通过SetAttribut换肤 } break; default: break; } }
2.主题包换肤
主题包可以是预先已被加载到内存中,也可以是从外部加载,参考代码在:
DMDemo\src\SkinWnd.cpp->CSkinWnd::OnChangeSkin1() DMDemo\src\SkinWnd.cpp->CSkinWnd::OnChangeSkin2()// 外部加载 或 QQDemo\src\SkinPreview.cpp-->SkinPreview::OnLButtonUp(UINT nFlags,CPoint pt)
关键函数:
DMSmartPtrT<IDMRes> pRes; g_pDMApp->GetDefRegObj((void**)&pRes, DMREG_Res);// 取得内部正在使用的Res对象 virtual DMCode LoadTheme(WPARAM wp, LPARAM lp);// 从外部加载新的主题包 virtual DMCode SetCurTheme(LPCWSTR lpszName, LPCWSTR lpszOldName=NULL);// 设置当前主题包
我们来增加主题包换肤示例,前面一节我们已增加了一个叫theme1的主题包,这里加入换肤代码
case QQMENU_THEMESKIN: {// 通过主题包换肤 DMSmartPtrT<IDMRes> pRes; g_pDMApp->GetDefRegObj((void**)&pRes, DMREG_Res); if (pRes) { static wchar_t szOldThemeName[50]={0}; static bool bNew = false; if (false == bNew) { pRes->SetCurTheme(L"theme1",szOldThemeName);// 返回原始theme的名字,即theme0 bNew = true; } else { pRes->SetCurTheme(szOldThemeName); bNew = false; } } } break;
效果如下:
3.外部图片换肤
这里介绍几个关键函数:
DMApp中的GetSkin
IDMSkin* GetSkin(LPCWSTR lpszSkin);// 取得指定的skin对象
IDMSkin中的GetBitmap、SetBitmap
virtual DMCode GetBitmap(IDMBitmap** ppBitmap) = 0;///<取得bitmap virtual DMCode SetBitmap(LPBYTE pBuf,size_t szLen,LPCWSTR pszType) = 0; ///<通过内存设置bitmap
OK,一种换肤的方式出来了,取得原始的Skin,把Skin对应图片的内存换成新的,再刷新一下,就实现了换肤,具体可参考
QQDemo\src\SkinWnd.cpp—>DMCode CSkinWnd::OnOutSkin()
我们来尝试为关闭按钮换肤,它的name为closebtn,skin名为png:close
<Button name="closebtn" pos="-30,0,@30,@27" text="" clrnc="pbgra(00,00,00,ff)" clrbg="pbgra(dd,dd,dd,ff)" skin="png:close" />
这里加入换肤代码:
case QQMENU_OUTSKIN: {// 通过外部加载图片 wchar_t szFileTitle[_MAX_FNAME] = {0}; wchar_t szFileName[_MAX_PATH] = {0}; OPENFILENAMEW ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = szFileName; ofn.nMaxFile = _MAX_PATH; ofn.lpstrDefExt = L"gif"; ofn.lpstrInitialDir = NULL; ofn.lpstrFileTitle = (LPTSTR)szFileTitle; ofn.nMaxFileTitle = _MAX_FNAME; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING| OFN_NOCHANGEDIR; ofn.lpstrFilter = L"图像文件(*.bmp;*.jpg;*.png)\0*.bmp;*.jpg;*.png\0\0"; ofn.hwndOwner = m_hWnd; if (::GetOpenFileNameW(&ofn)) {// todo.hgy413 note:GetOpenFileNameW点击后WM_LBUTTTONUP消息会发送给dui,所以不要随意只处理WM_LBUTTONUP DMSmartPtrT<IDMSkin> pSkin = g_pDMApp->GetSkin(L"png:close"); if (pSkin) { DMSmartPtrT<IDMBitmap> pBitmap; pSkin->GetBitmap(&pBitmap); if (pBitmap) { DWORD dwSize = DM::GetFileSizeW(szFileName); if (dwSize!=0) { DMBufT<byte>pBuf;pBuf.Allocate(dwSize); DWORD dwRead = 0; DM::GetFileBufW(szFileName,(void**)&pBuf,dwSize,dwRead); pBitmap->LoadFromMemory(pBuf,dwSize,L""); } FindChildByNameT<DUIButton>(L"closebtn")->DM_Invalidate(); } } } } break;
效果如下:
代码解读:
1.从Skin池里取得类型为png名字为close的skin对象IDMSkin(你也可以直接写close,因为内部默认为png)
DMSmartPtrT<IDMSkin> pSkin = g_pDMApp->GetSkin(L"png:close");
2.取得skin对象对应的图元对象IDMBitmap
DMSmartPtrT<IDMBitmap> pBitmap; pSkin->GetBitmap(&pBitmap);
3.图元对象IDMBitmap重新加载内存(从外部传入的图片中加载)
DWORD dwSize = DM::GetFileSizeW(szFileName); if (dwSize!=0) { DMBufT<byte>pBuf;pBuf.Allocate(dwSize); DWORD dwRead = 0; DM::GetFileBufW(szFileName,(void**)&pBuf,dwSize,dwRead); pBitmap->LoadFromMemory(pBuf,dwSize,L""); }
4.最后刷新自己的控件即可
FindChildByNameT<DUIButton>(L"closebtn")->DM_Invalidate();
注意,这种方式只是改了skin对应图元的内存,并不能改变skin的类型:http://hgy413.com/3506.html
如果要改变skin的类型,就只能把skin先移除,再添加了,对应DMApp的RemoveSkin和AddSkin
DMCode RemoveSkin(LPCWSTR lpszKey,LPCWSTR lpszName,bool bLoopFind = true); DMCode AddSkin(void *pBuf,size_t bufLen,LPCWSTR pszType, LPCWSTR lpszXml,LPCWSTR lpszPoolName=NULL);
在下面的方式里介绍了RemoveSkin和AddSkin的用法
4.SetAttribute换肤
前面提到过,SetAttribute是万能的,所有的属性都可以通过SetAttribute去动态设置,那么我们当然可以Add一个Skin,然后把某个控件SetAttribute过去,从而实现换肤
case QQMENU_SETATTRSKIN: {// 通过SetAttribut换肤 wchar_t szFileTitle[_MAX_FNAME] = {0}; wchar_t szFileName[_MAX_PATH] = {0}; OPENFILENAMEW ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.lpstrFile = szFileName; ofn.nMaxFile = _MAX_PATH; ofn.lpstrDefExt = L"gif"; ofn.lpstrInitialDir = NULL; ofn.lpstrFileTitle = (LPTSTR)szFileTitle; ofn.nMaxFileTitle = _MAX_FNAME; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING| OFN_NOCHANGEDIR; ofn.lpstrFilter = L"图像文件(*.bmp;*.jpg;*.png)\0*.bmp;*.jpg;*.png\0\0"; ofn.hwndOwner = m_hWnd; if (::GetOpenFileNameW(&ofn)) {// todo.hgy413 note:GetOpenFileNameW点击后WM_LBUTTTONUP消息会发送给dui,所以不要随意只处理WM_LBUTTONUP DWORD dwSize = DM::GetFileSizeW(szFileName); if (dwSize!=0) { DMBufT<byte>pBuf;pBuf.Allocate(dwSize); DWORD dwRead = 0; DM::GetFileBufW(szFileName,(void**)&pBuf,dwSize,dwRead); DMSmartPtrT<IDMSkin> pSkin = g_pDMApp->GetSkin(L"todo"); if (pSkin) {// 如果skin存在,则直接删除 #if 0// 如果skin存在,则直接改内存 DMSmartPtrT<IDMBitmap> pBitmap; pSkin->GetBitmap(&pBitmap); if (pBitmap) { pBitmap->LoadFromMemory(pBuf,dwSize,L""); FindChildByNameT<DUIButton>(L"closebtn")->DM_Invalidate(); } break; #else g_pDMApp->RemoveSkin(L"todo",L"ccskinpool"); #endif } // 如果skin不存在,则创建skin CStringW strWXml = L"<imglist id=\"todo\" states=\"3\" />";// xml中不要配src了 g_pDMApp->AddSkin(pBuf,dwSize,L"png",strWXml,L"ccskinpool");// 加入到ccskinpool这个skin池 FindChildByNameT<DUIButton>(L"closebtn")->SetAttribute(L"skin",L"todo");// 强制把skin属性设置为todo的skin } } } break;
效果图和前面的一样,所以不再发了,上面我们创建了一个todo的skin,并放在ccskinpool池中(自动创建),第二次加入时,先从ccskinpool池中移除todo,再加入,当然,最后是第二次加入时,直接改变skin对应的图片内存,如我上面#if0所示
SetAttribute的第一个参数skin含义参考:
文章作者:hgy413
本文地址:https://hgy413.com/3940.html
版权所有 © 转载时必须以链接形式注明作者和原始出处!
magnificent points altogether, you simply received a
new reader. What could you recommend about your publish
that you simply made some days ago? Any certain?
I love it when folks get together and share views. Great blog, stick with
it!
I am really impressed along with your writing talents and also
with the layout to your blog. Is this a paid topic or did you customize it your
self? Anyway keep up the excellent high quality writing,
it is uncommon to see a great weblog like this one nowadays..
Hey There. I found your blog using msn. This is a really well written article.
I will make sure to bookmark it and come back to read
more of your useful info. Thanks for the post. I will definitely return.
I want to to thank you for this good read!! I definitely loved every little bit of it.
I have got you book marked to check out new stuff you post…
It is the best time to make some plans for the future and it is
time to be happy. I’ve read this post and
if I could I desire to suggest you some interesting things or advice.
Perhaps you could write next articles referring to this
article. I desire to read more things about it!
I’m gone to convey my little brother, that he should also pay a visit this
web site on regular basis to get updated from most recent information.
I really like what you guys tend to be up too. This sort of clever work and reporting!
Keep up the amazing works guys I’ve added you guys to our blogroll.
Pretty section of content. I just stumbled upon your blog and in accession capital to assert that I acquire actually enjoyed
account your blog posts. Anyway I will be subscribing to your augment and even I achievement you access consistently fast.
Hi, I check your blog like every week. Your writing style is witty,
keep up the good work!
Everything is very open with a really clear clarification of the issues.
It was definitely informative. Your website is very helpful.
Thank you for sharing!
Someone necessarily assist to make severely articles I’d state.
That is the very first time I frequented your website page and so far?
I surprised with the research you made to create this particular post amazing.
Fantastic task!
Undeniably imagine that that you said. Your favourite justification appeared to be at
the internet the easiest factor to be mindful of.
I say to you, I certainly get irked whilst folks think about concerns that they just don’t recognize about.
You controlled to hit the nail upon the top and also defined out the whole thing without having side
effect , people can take a signal. Will probably be again to get more.
Thank you
Please let me know if you’re looking for a writer for your site.
You have some really great articles and I think I would be a good asset.
If you ever want to take some of the load off, I’d love to write some articles for your blog in exchange for a link back
to mine. Please shoot me an e-mail if interested. Kudos!
excellent post, very informative. I’m wondering why the other experts of
this sector don’t realize this. You must proceed your writing.
I am confident, you have a huge readers’ base already!
Thanks for a marvelous posting! I seriously enjoyed reading it, you are
a great author.I will be sure to bookmark your blog and will eventually come back down the
road. I want to encourage yourself to continue your great writing,
have a nice weekend!
I don’t know if it’s just me or if perhaps everybody else experiencing problems with your website.
It appears as if some of the written text within your posts are
running off the screen. Can somebody else please provide feedback and let me
know if this is happening to them too? This may be
a problem with my web browser because I’ve had this happen before.
Thanks
You made some really good points there. I looked on the internet for additional information about the issue and found
most individuals will go along with your views on this site.
Hey There. I found your weblog the usage of msn.
This is a really smartly written article. I’ll make
sure to bookmark it and return to read extra of your
useful info. Thank you for the post. I will certainly return.
Hi, this weekend is good in favor of me, for the reason that this time i
am reading this impressive informative piece
of writing here at my house.
Hi there everybody, here every one is sharing such
experience, therefore it’s nice to read this website, and I used to visit this webpage daily.