用DSkinLite实现QQ界面

来源:互联网 发布:失败项目管理分析 知乎 编辑:程序博客网 时间:2024/05/07 01:34

 相信已经有很多人用过QQ2009了,自然也对其中的UI设计很感兴趣,觉得设计很是完美。但是这是怎么设计的呢?下面我介绍一个用来实现这种效果的设计库——DSkinLite(源于CodeProject)。下面通过一个演示程序来介绍使用过程:

程序中,我主要对主窗口和两个通用对话框(打开对话框和浏览对话框)进行了换肤,这里我所有的窗口都使用了同一个皮肤(定义在XML文件中),通常应该为每个对话框都定义自己的皮肤。下面我简要描述一下使用过程:

1、 将头文件和库文件放在你的工程目录下:

(1)    头文件路径

…\FileCutterTool\include,其中包含DskinDef.hDSkinDLL.h两个文件

(2)    库文件路径

…\FileCutterTool\lib,其中dskinlite.lib为多字节编码,dskinliteu.libUnicode编码

(3)    在工程的属性中添加附加依赖项路径,保证.lib库导入到工程中。

2、 stdafx.h中导入库文件:

#ifdef DSKINDLL_EXPORTS

#define DSKINDLL_API extern "C" __declspec(dllexport)

#else

#define DSKINDLL_API extern "C" __declspec(dllimport)

#endif

 

#include "..\include\dskindll.h"

#include "..\include\dskindef.h"

#include <afxdlgs.h>

3、 FileCutterTool.cpp文件中添加初始化库和结束库的代码:

(1)    InitInstance()中添加初始化库代码

//Load the skin theme

dsLoadSkin( _T("SkinQQ"));

(2)    Existance()中添加结束库的代码(也可放在InitInstance()的最后)

dsExitSkin();

4、 XML文件中定义皮肤(略)

5、 在对话框的OnInitDialog()中添加换肤的代码

dsSkinWindow( GetSafeHwnd(), SKIN_TYPE_DIALOG, _T("mfctestdialog"), FALSE);

    

     dsSkinWindow( GetDlgItem( IDC_SOURCEBROWSER)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("button"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_DESTBROWSER)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("button"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_START)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("button"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_STOP)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("button"), FALSE);

     dsSkinWindow( GetDlgItem( IDCANCEL)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("button"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_STATIC_1)->GetSafeHwnd(), SKIN_TYPE_STATIC, NULL, FALSE);

     dsSkinWindow( GetDlgItem( IDC_STATIC_2)->GetSafeHwnd(), SKIN_TYPE_STATIC, NULL, FALSE);

     dsSkinWindow( GetDlgItem( IDC_EDITSOURCE)->GetSafeHwnd(), SKIN_TYPE_EDIT, _T("edit"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_EDITDEST)->GetSafeHwnd(), SKIN_TYPE_EDIT, _T("edit"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_STATUSTEXT)->GetSafeHwnd(), SKIN_TYPE_EDIT, _T("edit"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_SELECTSPLIT)->GetSafeHwnd(), SKIN_TYPE_RADIOBUTTON, _T("radiobutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_SELECTMERGE)->GetSafeHwnd(), SKIN_TYPE_RADIOBUTTON, _T("radiobutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_COMBO1)->GetSafeHwnd(), SKIN_TYPE_COMBOBOX, _T("combobox"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_STATIC)->GetSafeHwnd(), SKIN_TYPE_GROUPBOX, _T("groupbox"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_PROGRESS1)->GetSafeHwnd(), SKIN_TYPE_PROGRESS, _T("progress"), FALSE);

 

     dsSkinWindow( GetDlgItem( IDC_BUTTON1)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("mainmenubutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON2)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("messagebutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON3)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("smsbutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON4)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("appcenterbutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON5)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("petbutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON6)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("gamebutton"), FALSE);

     dsSkinWindow( GetDlgItem( IDC_BUTTON7)->GetSafeHwnd(), SKIN_TYPE_BUTTON, _T("chatbutton"), FALSE);

6、 为打开对话框添加换肤代码

要为打开对话框添加换肤代码,首先要自定义一个类,在类中实现,详细代码如下:

头文件:

#pragma once

 

 

// CMyFileDialog

 

class CMyFileDialog

{

// 接口

public:

     // 构造函数

     CMyFileDialog(void);

 

     // 获取文件全名(含路径)

     LPCTSTR GetFile() { return m_szFile; }

 

     // 显示打开对话框

     BOOL OpenFileDialog(HWND hWndParent);

 

// 内部实现

protected:

     // 文件名

     WCHAR m_szFile[MAX_PATH];

 

     OPENFILENAME m_openFile;

 

     // CALLBACK function

     static UINT_PTR CALLBACK OFNHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam);

};

实现文件:

// MyFileDialog.cpp : 实现文件

//

 

#include "stdafx.h"

#include "FileCutterTool.h"

#include "MyFileDialog.h"

#include "windows.h"

 

 

// CMyFileDialog

 

CMyFileDialog::CMyFileDialog()

{

     memset(m_szFile,0,MAX_PATH);

     ::ZeroMemory(&m_openFile,sizeof(OPENFILENAME));

     m_openFile.lStructSize = sizeof(OPENFILENAME);

     m_openFile.hwndOwner = NULL;

     m_openFile.lpstrFile = m_szFile;

     m_openFile.nMaxFile = MAX_PATH;

     m_openFile.lpstrFilter = _T("All Files(*.*)\0*.*\0\0");

//   m_openFile.Flags =  OFN_ENABLEHOOK | OFN_EXPLORER;

     m_openFile.Flags =  OFN_ENABLEHOOK;

     m_openFile.lpfnHook = OFNHookProc;

}

 

BOOL CMyFileDialog::OpenFileDialog(HWND hWndParent)

{

     m_openFile.hwndOwner = hWndParent;

     if(GetOpenFileName(&m_openFile))

     {

         return TRUE;

     }

     return FALSE;

}

 

UINT_PTR CALLBACK CMyFileDialog::OFNHookProc(HWND hdlg,UINT uiMsg,WPARAM wParam,LPARAM lParam)

{

     if (uiMsg==WM_INITDIALOG)

     {

         dsSkinWindow( hdlg, SKIN_TYPE_DIALOG, _T("mfctestdialog"), TRUE);

     }

 

     return 0;

}

调用代码:

// 打开文件对话框

         CMyFileDialog sourceDlg;

         if (sourceDlg.OpenFileDialog(m_hWnd))

         {

              // 获取源文件名

              strSourceText = sourceDlg.GetFile();

         }

7、 为浏览对话框添加换肤代码

要实现为浏览对话框换肤,也需要自定义一个类,详细实现代码如下:

头文件:

#ifndef _DIRDIALOG_H_

#define _DIRDIALOG_H_

 

#include <shlobj.h>

 

class CDirDialog

{

// 接口

public:

     CDirDialog(void);

 

     // 显示浏览对话框

     BOOL DoBrowser(HWND hWndParent,LPCTSTR pszTitle = NULL);

 

     // 取得用户选择的目录名称

     LPCTSTR GetPath() { return m_szPath; }

 

protected:

     // 浏览对话框所需的结构体,详见MSDN

     BROWSEINFO m_info;

 

     // 用来接受用户选择目录的缓冲区

     WCHAR m_szDisplay[MAX_PATH];

     WCHAR m_szPath[MAX_PATH];

 

     // CALLBACK function

     static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData);

};

#endif // _DIRDIALOG_H_

实现文件:

#include "stdafx.h"

#include "windows.h"

#include "DirDialog.h"

 

CDirDialog::CDirDialog()

{

     memset(&m_info,0,sizeof(m_info));

     m_info.hwndOwner = NULL;

     m_info.pidlRoot = NULL;

     m_info.pszDisplayName = m_szDisplay;

     m_info.lpszTitle = NULL;

     m_info.ulFlags = BIF_RETURNONLYFSDIRS;

     m_info.lpfn = BrowseCallbackProc;

     m_szPath[0] = '\0';

}

 

BOOL CDirDialog::DoBrowser(HWND hWndParent, LPCTSTR pszTitle)

{

     if (pszTitle == NULL)

     {

         m_info.lpszTitle = _T("选择目标文件夹");

     }

     else

     {

         m_info.lpszTitle = pszTitle;

     }

     m_info.hwndOwner = hWndParent;

     LPITEMIDLIST pItem = ::SHBrowseForFolder(&m_info);

     if (pItem != 0)

     {

         ::SHGetPathFromIDList(pItem,m_szPath);

         return TRUE;

     }

     return FALSE;

}

 

int CALLBACK CDirDialog::BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)

{

     if (uMsg==BFFM_INITIALIZED)

     {

         dsSkinWindow( hwnd, SKIN_TYPE_DIALOG, _T("mfctestdialog"), TRUE);

     }

     return 0;

}

调用代码:

// 浏览目录对话框

         CDirDialog sourceDlg;

         if (sourceDlg.DoBrowser(m_hWnd))

         {

              // 获取源文件目录

              strSourceText = sourceDlg.GetPath();

         }

上面的代码即可实现换肤,在这里我要强调一个函数dsSkinWindow(),当最后一个参数为TRUE时,则整个窗口可实现全部换肤;当为FALSE时,只是对窗口框架进行换肤,而其中的控件则不做修改,需要自己逐个换肤,详细代码可以参照上面代码。