duilib把ZIP皮肤编译进EXE

From: http://www.duilibcn.com/ziliao/215.html

目前发现,压缩成zip的方式,不能使用图片资源的相对路径。

 

·duilib把ZIP皮肤编译进EXE

·    duilib的皮肤界面用的是XML和图片资源,发布duilib时需要带上XML和图片文件夹,

但是这样容易被别人修改,幸好duilib提供了一个函数

voidCPaintManagerUI::SetResourceZip(LPCTSTR pStrPath, bool bCachedResourceZip);

利用这个静态函数,可以把XML和图片资源压缩成一个zip包来供duilib使用。

但是这样仍然不是最好的解决方案,因为我们的程序有时候只是一个EXE程序,或则只是提供一个

使用duilib的DLL供别的程序调用,那么就有必要把所用到的皮肤文件放到EXE中去了,

duilib提供了一个函数来做这个事情

voidCPaintManagerUI::SetResourceZip(LPVOID pVoid, unsigned int len);

这个函数同样是静态函数,pVoid代表zip的数据,len是数据的长度,来实践一下吧。

先建立一个头文件 CMainWindow.h

 

#ifndefCMAINWINDOW_H

#defineCMAINWINDOW_H

 

#include

#include

#include

using namespaceDuiLib;

 

classCMainWindow : public WindowImplBase

{

public:

   CMainWindow(const CDuiString& sUiFolderName,const CDuiString&sUiFileName);

 

   virtual ~CMainWindow();

 

   void setWindowTitle(const CDuiString& sTitle);

   CLabelUI* m_titleLabel;

 

protected:

   virtual LPCTSTR GetWindowClassName() const;

 

   virtual CDuiString GetSkinFile();

 

   virtual void InitWindow();

   virtual CDuiString GetSkinFolder();

 

   void OnFinalMessage(HWND hwnd);

 

   virtual CControlUI* CreateControl(LPCTSTR pstrClass);

   void Notify(TNotifyUI& msg);

 

private:

   CDuiString m_uiFileName;

   CDuiString m_uiFolderName;

 

   CButtonUI* m_minBtn;

   CButtonUI* m_maxBtn;

   CButtonUI* m_restoreBtn;

   CButtonUI* m_closeBtn;

};

#endif //CMAINWINDOW_H

然后是源文件 CMainWindow.cpp

#include"CMainWindow.h"

 

CMainWindow::CMainWindow(constCDuiString& sUiFolderName,const CDuiString& sUiFileName)

    :WindowImplBase(),

     m_uiFolderName(sUiFolderName),

     m_uiFileName(sUiFileName)

{

   m_titleLabel = NULL;

   m_minBtn = NULL;

   m_maxBtn = NULL;

   m_closeBtn = NULL;

   m_restoreBtn = NULL;

}

 

CMainWindow::~CMainWindow()

{

 

}

 

 

CControlUI*CMainWindow::CreateControl(LPCTSTR pstrClass)

{

    //   if(_tcsicmp(pstrClass, L"Your custom clsss name") == 0)

    //   {

    //   }

   return NULL;

}

 

voidCMainWindow::OnFinalMessage(HWND hwnd)

{

   delete this;

}

 

LPCTSTRCMainWindow::GetWindowClassName() const

{

   return L"CMainWindow";

}

 

CDuiStringCMainWindow::GetSkinFile()

{

   return m_uiFolderName+CDuiString(L"\\")+m_uiFileName;

}

 

CDuiStringCMainWindow::GetSkinFolder()

{

   return m_uiFolderName;

}

 

voidCMainWindow::setWindowTitle(const CDuiString& sTitle)

{

   if(m_titleLabel)

    {

       m_titleLabel->SetText(sTitle.GetData());

    }

}

 

voidCMainWindow::InitWindow()

{

   CControlUI* pControlTitleLabel =m_PaintManager.FindControl(L"apptitle");

   if(pControlTitleLabel)

    {

       m_titleLabel = static_cast(pControlTitleLabel);

       WCHAR sTitle[500];

       memset(sTitle,0,sizeof(WCHAR)*500);

       ::GetWindowTextW(this->m_hWnd,sTitle,500);

       this->setWindowTitle(CDuiString(sTitle));

    }

 

   CControlUI* pControlMin = m_PaintManager.FindControl(L"minbtn");

   if(pControlMin)

       m_minBtn = static_cast(pControlMin);

 

   CControlUI* pControlMax = m_PaintManager.FindControl(L"maxbtn");

   if(pControlMax)

       m_maxBtn = static_cast(pControlMax);

 

   CControlUI* pControlRestore =m_PaintManager.FindControl(L"restorebtn");

   if(pControlRestore)

       m_restoreBtn = static_cast(pControlRestore);

 

   CControlUI*  pControlClose =m_PaintManager.FindControl(L"closebtn");

   if(pControlClose)

       m_closeBtn = static_cast(pControlClose);

}

 

 

voidCMainWindow::Notify(TNotifyUI &msg)

{

   if(msg.sType == DUI_MSGTYPE_CLICK)

    {

       //(*

       if(msg.pSender == m_minBtn)

       {this->SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, NULL);}

       if(msg.pSender == m_maxBtn)

       {this->SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, NULL);}

       if(msg.pSender == m_restoreBtn)

       {this->SendMessage(WM_SYSCOMMAND, SC_RESTORE, NULL);}

       if(msg.pSender == m_closeBtn)

       {::PostQuitMessage(0L);}

       //*)

 

       if(msg.pSender->GetName() == L"button1")

       {

           ::MessageBoxW(NULL,L"你好 DuiLib",L"ok",MB_OK);

       }

    }

}

然后是resource.h定义资源类型

#ifndef RESOURCE

#define RESOURCE

#defineIDR_SKIN1   10001

#endif //RESOURCE

 

定义一个ID为IDR_SKIN1的SKIN文件

要为这个EXE程序定义一个资源文件,好把ZIP文件添加进去,就叫app.rc吧

#include"winver.h"

#include"resource.h"

 

IDI_ICON1              ICON    DISCARDABLE    "app.ico"

 

IDR_SKIN1              SKIN                    "skin.zip"

 

VS_VERSION_INFOVERSIONINFO

 FILEVERSION1,0,0,1

 PRODUCTVERSION1,0,0,1

 FILEFLAGSMASK0x3fL

#ifdef _DEBUG

 FILEFLAGS0x1L

#else

 FILEFLAGS0x0L

#endif

 FILEOS0x40004L

 FILETYPE0x1L

 FILESUBTYPE0x0L

BEGIN

   BLOCK "StringFileInfo"

   BEGIN

       BLOCK "080404B0"

       BEGIN

           VALUE "CompanyName","duilibcn.com"

           VALUE "FileDescription", "DuiLibApp"

           VALUE "FileVersion", "1.0.0.1"

           VALUE "InternalName", ""

           VALUE "LegalCopyright","DuiLibcn.com"

           VALUE "OriginalFilename", ""

           VALUE "ProductName", "DuiLibApp"

           VALUE "ProductVersion","1.0.0.1"

       END

   END

   BLOCK "VarFileInfo"

   BEGIN

       VALUE "Translation", 0x804, 1200

   END

END

下面就是关键的main.cpp函数了,看如何把zip编译进EXE吧

#defineWIN32_LEAN_AND_MEAN

#define_CRT_SECURE_NO_SEPRECATE

 

#include"resource.h"

#include"cmainwindow.h"

 

 

DWORDg_func_GetResourceDataLength(HINSTANCE hInstance,

                           UINT dwResourceId,

                           const WCHAR* sResourceType)

{

   if(hInstance == NULL)

       return 0;

 

   HRSRC hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(dwResourceId),sResourceType);

   if(!hRsrc)

    {

       return 0;

    }

   DWORD dwResSize = SizeofResource(hInstance,hRsrc);

   FreeResource(hRsrc);

   return dwResSize;

}

 

voidg_func_GetResourceData(HINSTANCE hInstance,

                          UINT dwResourceId,

                          const WCHAR* sResourceType,

                          char* pRetData,

                          DWORD pRetLength)

{

   if(hInstance == NULL)

       return;

 

   HRSRC hRsrc =FindResourceW(hInstance,MAKEINTRESOURCEW(dwResourceId),sResourceType);

   if(!hRsrc)

    {

       return;

    }

 

   HGLOBAL hGlobal = (char*)LoadResource(hInstance,hRsrc);

 

   char* pData = (char*)LockResource(hGlobal);

   memcpy(pRetData,pData,pRetLength);

 

   FreeResource(hRsrc);

}

 

int APIENTRYWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,intnCmdShow)

{

   CPaintManagerUI::SetInstance(hInstance);

   CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());

 

   DWORD iLength =g_func_GetResourceDataLength(hInstance,IDR_SKIN1,L"SKIN");

   if(iLength > 0)

    {

       char* pData = (char*)malloc(iLength);

       memset(pData,0,iLength);

      g_func_GetResourceData(hInstance,IDR_SKIN1,L"SKIN",pData,iLength);

 

       CPaintManagerUI::SetResourceZip(pData,iLength);

free(pData); // 不应该在这里释放。需要在使用结束后,程序退出前释放。

    }

   else

    {

       ::MessageBoxA(NULL,"Load Skin fail zip in rc size is0","fail",0);

       return 0;

    }

 

 

   CMainWindow* pFrame = newCMainWindow(L"skin",L"CMainWindow.xml");

 

   pFrame->Create(NULL,L" 你好DuiLib",UI_WNDSTYLE_FRAME,WS_EX_WINDOWEDGE);

    pFrame->CenterWindow();

   pFrame->ShowWindow();

 

   CPaintManagerUI::MessageLoop();

   delete pFrame;

   return 0;

}

 

首先用g_func_GetResourceDataLength获取RC内ZIP文件的长度,然后

用g_func_GetResourceData来填充ZIP数据,最后用

CPaintManagerUI::SetResourceZip(pData,iLength);来设置ZIP资源数据,这个是关键。

但是这样以后我发现了一个问题,右上角的自定义按钮图片不见了,不知道是路径问题还是duilib的BUG,

如果直接用路径的方式加载ZIP文件倒是能显示。

工程和编译后的EXE可以在这里下载http://download.csdn.net/detail/hats8888/9346953

可以用DuiCreator/QtCreator编译,或则自己用cl.exe编译也行。

你可能感兴趣的:(c++,duilib)