DragonNest/Third/XTToolkitPro/Samples/Utilities/ResourceEditor/ResourceImport.cpp
2024-12-19 09:48:26 +08:00

510 lines
12 KiB
C++

// ResourceImport.cpp: implementation of the CResourceImport class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ResourceImport.h"
#include "ResourceExport.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CResourceImport::CResourceImport()
{
m_pResources = NULL;
m_bDelete = TRUE;
}
CResourceImport::~CResourceImport()
{
if (m_bDelete)
{
SAFE_DELETE(m_pResources);
}
}
#pragma pack(push, 1)
typedef struct
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
} DLGTEMPLATEEX;
typedef struct
{
DWORD helpID;
DWORD exStyle;
DWORD style;
short x;
short y;
short cx;
short cy;
DWORD id;
} DLGITEMTEMPLATEEX;
#pragma pack(pop)
AFX_INLINE int REPLACEW_S(LPWSTR strReplace, LPCWSTR lpszOld, LPCWSTR lpszNew)
{
int nOldLength = (strReplace == NULL) ? 0 : (int)wcslen(strReplace);
int nSourceLen = (lpszOld == NULL) ? 0 : (int)wcslen(lpszOld);
if (nSourceLen == 0 || nOldLength == 0)
return 0;
int nReplacementLen = (lpszNew == NULL) ? 0 : (int)wcslen(lpszNew);
// loop once to figure out the size of the result string
int nCount = 0;
LPWSTR lpszStart = strReplace;
LPWSTR lpszTarget;
while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL)
{
nCount++;
lpszStart = lpszTarget + nSourceLen;
}
// if any changes were made, make them
if (nCount > 0)
{
int nNewLength = nOldLength + (nReplacementLen-nSourceLen)*nCount;
//ASSERT(nNewLength <= nOldLength); // not implemented
lpszStart = strReplace;
// loop again to actually do the work
while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL)
{
int nBalance = nOldLength - int(lpszTarget - strReplace + nSourceLen);
MEMMOVE_S(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
nBalance * sizeof(WORD));
MEMCPY_S(lpszTarget, lpszNew, nReplacementLen*sizeof(WORD));
lpszStart = lpszTarget + nReplacementLen;
lpszStart[nBalance] = '\0';
nOldLength += (nReplacementLen - nSourceLen);
}
ASSERT(strReplace[nNewLength] == '\0');
}
return nCount;
}
void PreformatString(LPWSTR strValue)
{
REPLACEW_S(strValue, L"\\", L"\\\\");
REPLACEW_S(strValue, L"\n", L"\\n");
REPLACEW_S(strValue, L"\r", L"\\r");
REPLACEW_S(strValue, L"\t", L"\\t");
}
AFX_INLINE ULONG_PTR AlignDWord(ULONG_PTR uLong) { return ((uLong + 3) & ~3); }
void PX_StringW(CXTPPropExchange* pPX, LPCTSTR pszPropName, LPWSTR str, LPWSTR lpDefault = 0)
{
if (!str || str[0] == 0)
return;
WORD dwLength = (WORD)wcslen(str);
LPWSTR lpwString = new WCHAR[(dwLength + 1) * 2 * 2];
memcpy(lpwString, str, (dwLength + 1) * 2);
PreformatString(lpwString);
BSTR bstrValue = (BSTR)lpwString;
PX_Bstr(pPX, pszPropName, bstrValue, (BSTR)lpDefault);
delete[] lpwString;
}
void PutDialogTemplate(CXTPPropExchange* pPX, DLGTEMPLATE* pTemplate)
{
DLGTEMPLATEEX* pTemplateEx = (DLGTEMPLATEEX*)pTemplate;
BOOL bTemplateEx = pTemplateEx->signature == 0xFFFF;
int style, styleex, x, y, cx, cy, id;
LPWORD pItems;
if (bTemplateEx)
{
style = pTemplateEx->style;
styleex = pTemplateEx->exStyle;
x = pTemplateEx->x;
y = pTemplateEx->y;
cx = pTemplateEx->cx;
cy = pTemplateEx->cy;
pItems = (LPWORD)((LPBYTE)pTemplate + sizeof(DLGTEMPLATEEX));
}
else
{
style = pTemplate->style;
styleex = pTemplate->dwExtendedStyle;
x = pTemplate->x;
y = pTemplate->y;
cx = pTemplate->cx;
cy = pTemplate->cy;
pItems = (LPWORD)((LPBYTE)pTemplate + sizeof(DLGTEMPLATE));
}
ASSERT(*pItems == 0);
ASSERT(*(pItems + 1) == 0);
pItems += 2;
if (pItems)
{
PX_StringW(pPX, _T("caption"), (LPWSTR)pItems);
pItems += wcslen((LPWSTR)pItems);
}
pItems += 1;
if (style & DS_SETFONT)
{
int nHeight = *pItems;
PX_Int(pPX, _T("fontsize"), nHeight, 8);
pItems += bTemplateEx? 3: 1;
PX_StringW(pPX, _T("fontface"), (LPWSTR)pItems, L"MS Sans Serif");
pItems += wcslen((LPWSTR)pItems) + 1;
}
CString strPos;
strPos.Format(_T("%i, %i, %i, %i"), x, y, cx, cy);
PX_Int(pPX, _T("style"), style);
PX_Int(pPX, _T("styleex"), styleex, 0);
PX_String(pPX, _T("position"), strPos);
pItems = LPWORD((LPBYTE)pTemplate + AlignDWord((LPBYTE)pItems - (LPBYTE)pTemplate));
CXTPPropExchangeEnumeratorPtr secControl(pPX->GetEnumerator(_T("control")));
POSITION pos = secControl->GetPosition(32000);
int nCount = bTemplateEx? pTemplateEx->cDlgItems: pTemplate->cdit;
for (int i = 0; i < nCount; i++)
{
DLGITEMTEMPLATE* pItemTemplate = (DLGITEMTEMPLATE*)pItems;
DLGITEMTEMPLATEEX* pItemTemplateEx = (DLGITEMTEMPLATEEX*)pItems;
CXTPPropExchangeSection sec(secControl->GetNext(pos));
if (bTemplateEx)
{
style = pItemTemplateEx->style;
styleex = pItemTemplateEx->exStyle;
x = pItemTemplateEx->x;
y = pItemTemplateEx->y;
cx = pItemTemplateEx->cx;
cy = pItemTemplateEx->cy;
id = pItemTemplateEx->id;
pItems = LPWORD((LPBYTE)pItemTemplate + sizeof(DLGITEMTEMPLATEEX));
}
else
{
style = pItemTemplate->style;
styleex = pItemTemplate->dwExtendedStyle;
x = pItemTemplate->x;
y = pItemTemplate->y;
cx = pItemTemplate->cx;
cy = pItemTemplate->cy;
id = pItemTemplate->id;
pItems = LPWORD((LPBYTE)pItemTemplate + sizeof(DLGITEMTEMPLATE));
}
CString strPos;
strPos.Format(_T("%i, %i, %i, %i"), x, y, cx, cy);
if (id == 65535 || id == -1) id = 0;
PX_Int(&sec, _T("id"), id, 0);
CString strClass;
if (*pItems == 0xFFFF)
{
switch (*(pItems + 1))
{
case 0x0080: strClass = _T("BUTTON"); break;
case 0x0081: strClass = _T("EDIT"); break;
case 0x0082: strClass = _T("STATIC"); break;
case 0x0083: strClass = _T("LISTBOX"); break;
case 0x0084: strClass = _T("SCROLLBAR"); break;
case 0x0085: strClass = _T("COMBOBOX"); break;
}
pItems += 2;
}
else
{
strClass = (LPWSTR)pItems;
pItems += strClass.GetLength() + 1;
}
PX_String(&sec, _T("class"), strClass, _T("STATIC"));
if (*pItems == 0xFFFF)
{
int nResource = *(pItems + 1);
PX_Int(&sec, _T("resource"), nResource);
pItems += 2;
}
else
{
PX_StringW(&sec, _T("caption"), (LPWSTR)pItems);
pItems += wcslen((LPWSTR)pItems) + 1;
}
PX_Int(&sec, _T("style"), style, WS_CHILD | WS_VISIBLE | WS_GROUP);
PX_Int(&sec, _T("styleex"), styleex, 0);
PX_String(&sec, _T("position"), strPos);
ASSERT(*pItems == 0);
pItems += 1;
pItems = LPWORD((LPBYTE)pItemTemplate + AlignDWord((LPBYTE)pItems - (LPBYTE)pItemTemplate));
}
}
void PutMenuItems(CXTPPropExchange* pPX, MENUITEMTEMPLATE*& pItem)
{
CXTPPropExchangeEnumeratorPtr secMenuItem(pPX->GetEnumerator(_T("menuitem")));
POSITION posMenuItem = secMenuItem->GetPosition(32000);
while (TRUE)
{
CXTPPropExchangeSection sec(secMenuItem->GetNext(posMenuItem));
BOOL bPopup = (pItem->mtOption & MF_POPUP) != 0;
BOOL bEnd = (pItem->mtOption & MF_END) != 0;
int nID = !bPopup? (int)pItem->mtID: 0;
PX_Int(&sec, _T("id"), nID, 0);
int nCaptionSize = (int)wcslen(bPopup? pItem->mtString - 1: pItem->mtString);
WCHAR* pCaption = !bPopup? pItem->mtString: (WCHAR*)&pItem->mtID;
if (pCaption)
{
PX_StringW(&sec, _T("caption"), pCaption);
}
pItem = (MENUITEMTEMPLATE*)((LPBYTE)pItem + (pItem->mtOption & MF_POPUP? sizeof(WORD) * 2: sizeof(WORD) * 3) + (nCaptionSize) * 2);
if (bPopup)
{
PutMenuItems(&sec, pItem);
}
if (bEnd) break;
}
}
struct PROPEXCHANGEENUM
{
CXTPPropExchangeEnumerator* pEnumerator;
POSITION pos;
};
BOOL CALLBACK EnumResStringProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam;
ASSERT(pxEnum);
if (!pxEnum)
return FALSE;
HRSRC hRsrc = FindResource(hModule, lpszName, lpszType);
if (!hRsrc)
return FALSE;
HGLOBAL hRsrcData = LoadResource(hModule, hRsrc);
LPWSTR lpszData = (LPWSTR)LockResource(hRsrcData);
for (int i = 0; i < 16; i++)
{
if (*lpszData)
{
CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos));
WORD dwLength = *lpszData;
LPWSTR lpwString = new WCHAR[(dwLength + 1) * 2 * 2];
memcpy(lpwString, lpszData + 1, dwLength * 2);
lpwString[dwLength] = 0;
PreformatString(lpwString);
BSTR bstrString = (BSTR)lpwString;
int nResource = (((UINT)(UINT_PTR)lpszName - 1) * 16 + i);
PX_Int(&sec, _T("id"), nResource);
PX_Bstr(&sec, _T("value"), bstrString, 0);
delete[] lpwString;
lpszData = lpszData + dwLength + 1;
}
else
{
lpszData += 1;
}
}
return TRUE;
}
void ConvertStrings(HMODULE hModule, CXTPPropExchange* pPX)
{
PROPEXCHANGEENUM pxenum;
pxenum.pEnumerator = pPX->GetEnumerator(_T("string"));
pxenum.pos = pxenum.pEnumerator->GetPosition(32000);
::EnumResourceNames(hModule, RT_STRING, &EnumResStringProc, (LONG_PTR)&pxenum);
delete pxenum.pEnumerator;
}
BOOL CALLBACK EnumResMenuProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam;
ASSERT(pxEnum);
if (!pxEnum)
return FALSE;
HRSRC hRsrc = FindResource(hModule, lpszName, lpszType);
if (!hRsrc)
return FALSE;
HGLOBAL hRsrcData = LoadResource(hModule, hRsrc);
LPBYTE lpszData = (LPBYTE)LockResource(hRsrcData);
CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos));
int nResource = (UINT)(UINT_PTR)lpszName;
PX_Int(&sec, _T("id"), nResource);
lpszData += 4;
MENUITEMTEMPLATE* pItem = (MENUITEMTEMPLATE*)lpszData;
PutMenuItems(&sec, pItem);
return TRUE;
}
void ConvertMenus(HMODULE hModule, CXTPPropExchange* pPX)
{
PROPEXCHANGEENUM pxenum;
pxenum.pEnumerator = pPX->GetEnumerator(_T("menu"));
pxenum.pos = pxenum.pEnumerator->GetPosition(32000);
::EnumResourceNames(hModule, RT_MENU, &EnumResMenuProc, (LONG_PTR)&pxenum);
delete pxenum.pEnumerator;
}
BOOL CALLBACK EnumResDialogProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
PROPEXCHANGEENUM* pxEnum = (PROPEXCHANGEENUM*)lParam;
ASSERT(pxEnum);
if (!pxEnum)
return FALSE;
HRSRC hRsrc = FindResource(hModule, lpszName, lpszType);
if (!hRsrc)
return FALSE;
HGLOBAL hRsrcData = LoadResource(hModule, hRsrc);
LPBYTE lpszData = (LPBYTE)LockResource(hRsrcData);
CXTPPropExchangeSection sec(pxEnum->pEnumerator->GetNext(pxEnum->pos));
int nResource = (UINT)(UINT_PTR)lpszName;
PX_Int(&sec, _T("id"), nResource);
DLGTEMPLATE* pItem = (DLGTEMPLATE*)lpszData;
PutDialogTemplate(&sec, pItem);
return TRUE;
}
void ConvertDialogs(HMODULE hModule, CXTPPropExchange* pPX)
{
PROPEXCHANGEENUM pxenum;
pxenum.pEnumerator = pPX->GetEnumerator(_T("dialog"));
pxenum.pos = pxenum.pEnumerator->GetPosition(32000);
::EnumResourceNames(hModule, RT_DIALOG, &EnumResDialogProc, (LONG_PTR)&pxenum);
delete pxenum.pEnumerator;
}
BOOL CResourceImport::Import(LPCTSTR lpszFileName)
{
HMODULE hModule = LoadLibrary(lpszFileName);
if (!hModule)
return FALSE;
m_pResources = new CXTPPropExchangeXMLNode(FALSE, 0, _T("resource"));
if (!m_pResources->OnBeforeExchange())
return FALSE;
long wLanguage = CXTPResourceManager::GetResourceLanguage(hModule);
if (wLanguage == 0)
return FALSE;
XTP_RESOURCEMANAGER_LANGINFO* lan = CXTPResourceManager::GetLanguageInfo(wLanguage);
if (!lan)
return FALSE;
m_pResources->SetEncoding(lan->lpszEncoding);
CString strCaption(lan->lpszCaption);
PX_String(m_pResources, _T("Language"), strCaption);
PX_Long(m_pResources, _T("LANGID"), wLanguage);
ConvertStrings(hModule, m_pResources);
ConvertMenus(hModule, m_pResources);
ConvertDialogs(hModule, m_pResources);
FreeLibrary(hModule);
return TRUE;
}