首页 > REDM基础教程 > REDM基础教程18-换肤的几种方式
2016十二月29

REDM基础教程18-换肤的几种方式

[隐藏]

   MyTest下载–>  

MyTest.zip

  修改后的MyTest下载–>  

MyTest.zip

    

编译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.gif

      

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;

效果如下:

4.gif

代码解读:

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含义参考:

1.jpg

   

   

      下一节教程:REDM基础教程19-和MFC交互

   

  

     

    

文章作者:hgy413
本文地址:http://hgy413.com/3940.html
版权所有 © 转载时必须以链接形式注明作者和原始出处!

19 Responses to “REDM基础教程18-换肤的几种方式”

  1. #1 minecraft 回复 | 引用 Post:2018-10-05 08:00

    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?

  2. #2 minecraft 回复 | 引用 Post:2018-10-06 03:06

    I love it when folks get together and share views. Great blog, stick with
    it!

  3. #3 minecraft 回复 | 引用 Post:2018-10-06 15:55

    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..

  4. #4 minecraft 回复 | 引用 Post:2018-10-07 04:46

    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.

  5. 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…

  6. 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!

  7. 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.

  8. 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.

  9. #9 Coconut Oil Benefits 回复 | 引用 Post:2018-10-21 04:14

    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.

  10. #10 Coconut Oil Benefits 回复 | 引用 Post:2018-10-29 17:38

    Hi, I check your blog like every week. Your writing style is witty,
    keep up the good work!

  11. 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!

  12. #12 quest bars 回复 | 引用 Post:2018-11-06 05:04

    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!

  13. #13 Quest Protein Bars 回复 | 引用 Post:2018-11-06 05:41

    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

  14. #14 Sling TV 回复 | 引用 Post:2018-11-12 00:58

    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!

  15. 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!

  16. 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!

  17. 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

  18. 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.

  19. 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.

发表评论