前言:
之前用Appface做VC皮肤,觉得很好用,但是该工具有试用期。由于此前学过逆向破解,后来就尝试破解软件,才发现其实是DLL里面加密了,惭愧无法破解,据说网上也无人破解。于是就改用了skinMagic,这个版本是2.2.1.1的,已被大牛破解,因此可以放心使用。
这个skinMagic包含了SkinMagicLib.h,SkinMagicLib.lib,SkinMagic.dll,通过静态库辅助方式导入动态库,这里出现了一个问题,就是SkinMagicLib.lib好像是VC6.0做的,于是上面的方法在VC6下面巨爽,VC2008却出现连接问题。
看来在VC2008下面就只有用动态导入dll了。这个是小问题。
一 修改skinMagic方法:
在SkinMagicLib.h头文件中的最后一个#endif前面添加了一个类Class MagicSkin,然后定义需要使用的相关函数。
代码如下。
#ifdef __cplusplus
class MagicSkin
{
public:
typedef int (__stdcall *MAGICSKIN_INIT)( HINSTANCE hInstance, LPCTSTR lpApplication,
LPCTSTR lpReserved1,LPCTSTR lpReserved2 );
typedef void (__stdcall *MAGICSKIN_EXIT)();
typedef int (__stdcall *MAGICSKIN_LOADSKINFILE)( char* lpSkinFile );
typedef int (__stdcall *MAGICSKIN_LOADSKINRESOURCE)( HMODULE hModule, char* lpSkinName ,char* lpType );
typedef int (__stdcall *MAGICSKIN_SETWIND)( HWND hWnd, char* lpSkinName );
typedef int (__stdcall *MAGICSKIN_SETDLG)( char* szSkinName );
#ifdef _UNICODE
MagicSkin(LPCTSTR DllPath = L"SkinMagic.dll")
#else
MagicSkin(LPCTSTR DllPath = "SkinMagic.dll")
#endif
{
m_bValid = FALSE;
m_hDll = NULL;
bInitSkinMagicLib = NULL;
bExitSkinMagicLib = NULL;
bLoadSkinFile = NULL;
bLoadSkinFromResource = NULL;
bSetWindowSkin = NULL;
bSetDialogSkin = NULL;
Init(DllPath);
};
~MagicSkin(){ Release(); };
BOOL Init(LPCTSTR DllPath)
{
if(m_hDll && m_bValid) return TRUE;
m_hDll = ::LoadLibrary(DllPath);
if(m_hDll == NULL) return FALSE ;
bInitSkinMagicLib = (MAGICSKIN_INIT) GetProcAddress(m_hDll, "InitSkinMagicLib");
if(!bInitSkinMagicLib) return FALSE;
bExitSkinMagicLib = (MAGICSKIN_EXIT) GetProcAddress(m_hDll, "ExitSkinMagicLib");
if(!bExitSkinMagicLib) return FALSE;
bLoadSkinFile = (MAGICSKIN_LOADSKINFILE) GetProcAddress(m_hDll, "LoadSkinFile");
if(!bLoadSkinFile) return FALSE;
bLoadSkinFromResource = (MAGICSKIN_LOADSKINRESOURCE) GetProcAddress(m_hDll, "LoadSkinFromResource");
if(!bLoadSkinFromResource) return FALSE;
bSetWindowSkin = (MAGICSKIN_SETWIND) GetProcAddress(m_hDll, "SetWindowSkin");
if(!bSetWindowSkin) return FALSE;
bSetDialogSkin = (MAGICSKIN_SETDLG) GetProcAddress(m_hDll, "SetDialogSkin");
if(!bSetDialogSkin) return FALSE;
m_bValid = TRUE;
return TRUE;
};
int InitSkin(HINSTANCE hInstance, LPCTSTR lpApplication, LPCTSTR lpReserved1,LPCTSTR lpReserved2)
{
return bInitSkinMagicLib(hInstance, lpApplication, lpReserved1, lpReserved2);
};
void ExitSkin()
{
bExitSkinMagicLib();
};
int LoadSkin(char* lpSkinFile)
{
return bLoadSkinFile(lpSkinFile);
};
int LoadSkin(HMODULE hModule, char* lpSkinName, char* lpType)
{
return bLoadSkinFromResource( hModule,lpSkinName,lpType );
};
int SetWindow(HWND hWnd, char* lpSkinName)
{
return bSetWindowSkin(hWnd,lpSkinName);
};
int SetDlg(char* lpSkinName)
{
return bSetDialogSkin(lpSkinName);
};
private:
BOOL m_bValid;
HMODULE m_hDll;
MAGICSKIN_INIT bInitSkinMagicLib;
MAGICSKIN_EXIT bExitSkinMagicLib;
MAGICSKIN_LOADSKINFILE bLoadSkinFile;
MAGICSKIN_LOADSKINRESOURCE bLoadSkinFromResource;
MAGICSKIN_SETWIND bSetWindowSkin;
MAGICSKIN_SETDLG bSetDialogSkin;
protected:
void Release()
{
try{
if(m_hDll)
{
FreeLibrary(m_hDll);
m_hDll = NULL;
m_bValid = false;
bInitSkinMagicLib = NULL;
bExitSkinMagicLib= NULL;
bLoadSkinFile = NULL;
bLoadSkinFromResource = NULL;
bSetWindowSkin = NULL;
bSetDialogSkin = NULL;
}
}catch(...){}
};
};
#endif //_cplusplus
二 使用方法
1. cpp中添加头文件#include "SkinMagicLib.h"
2. 定义全局的MagicSkin m_skin;
3. 在InitInstance中添加下面的代码
BOOL CTestMagicSkinApp::InitInstance()
{
VERIFY( 1 == m_skin.InitSkin(AfxGetInstanceHandle(), NULL, NULL, NULL));
WCHAR Tpath[256];
memset(Tpath,0,256);
GetModuleFileName(NULL,Tpath,256);
USES_CONVERSION;
char* path = W2A(Tpath);
char * p = strrchr(path,'//') ;
if(!p) return FALSE ;
strcpy(p,"///0/0");
strcat(path,"corona.smf");
VERIFY( 1 == m_skin.LoadSkin(path));
//************星号区域为MFC代码******************
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
....................
....................
....................
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
//********************************
VERIFY( 1 == m_skin.SetWindow( m_pMainWnd->m_hWnd , "MainFrame" ));
VERIFY( 1 == m_skin.SetDlg( "Dialog" ) );
// 仅当具有后缀时才调用 DragAcceptFiles
// 在 SDI 应用程序中,这应在 ProcessShellCommand 之后发生
return TRUE;
}
4.在ExitInstance中添加下面代码
int CTestMagicSkinApp::ExitInstance()
{
// TODO: Add your specialized code here and/or call the base class
m_skin.ExitSkin();
return CWinApp::ExitInstance();
}
5.VC6中也适用,只是GetModuleFileName可以直接赋值char数组
char path[256];
memset(path,0,256);
GetModuleFileName(NULL,path,256);
char * p = strrchr(path,'//') ;
if(!p) return FALSE ;
strcpy(p,"///0/0");
strcat(path,"corona.smf");
6.SkinMagicLib.h头文件放置工程目录下,SkinMagic.dll在exe相同目录下。皮肤也放在exe相同目录,也可以更改皮肤的path路径。
7.对于SkinMagicLib中声明了很多LPCTSTR类型,在VC6下没问题,在VC2008下感觉用起来一堆问题,于是我就把部分相关的改成了char *类型。
三、导入资源方式的问题
1. 有人跟我说不知道怎么用LoadSkin(HMODULE hModule, char* lpSkinName, char* lpType)。
这个其实是导入资源方式,将smf皮肤文件导入到资源中,选择全部文件,导入后设资源名为SKINTYPE,改资源ID为"IDR_SKINTYPE1",一定要有这个引号。
然后LoadSkin(AfxGetInstanceHandle(),"IDR_SKINTYPE1","SKINTYPE");就行了。
2. 后来我又发现一个问题,就是在VC6下LoadSkin资源是没问题,VC2008下又是无法更换皮肤,几经调查发现在VC2008下面导入资源后会在resource.h中有这么一句定义:#define IDR_SKINTYPE1 132
这就是关键了,skinMagic 的DLL中查资源是通过char*来查的,这个被定义成了数字,虽然我们引用的时候是"IDR_SKINTYPE1”,但还是发生了冲突。
解决方法:
1)将资源该名为"IDR_SKINTYPE2",注意一定要有引号。
2)也可以把#define IDR_SKINTYPE1 132这行注释掉。
以上内容及修改后的skinMagic我已上传到资源里面,有兴趣可以下载。
http://download.csdn.net/source/2889406