Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
628 lines
18 KiB
C++
628 lines
18 KiB
C++
// ItemViewerDlg.cpp : 구현 파일
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "ItemViewer.h"
|
|
#include "ItemViewerDlg.h"
|
|
#include ".\itemviewerdlg.h"
|
|
|
|
#include <Item/ItemMgr.h>
|
|
|
|
#include <d3dx9.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
|
|
// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.
|
|
|
|
class CAboutDlg : public CDialog
|
|
{
|
|
public:
|
|
CAboutDlg();
|
|
|
|
// 대화 상자 데이터
|
|
enum { IDD = IDD_ABOUTBOX };
|
|
|
|
protected:
|
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원
|
|
|
|
// 구현
|
|
protected:
|
|
DECLARE_MESSAGE_MAP()
|
|
};
|
|
|
|
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
|
{
|
|
}
|
|
|
|
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
// CItemViewerDlg 대화 상자
|
|
|
|
|
|
|
|
CItemViewerDlg::CItemViewerDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CItemViewerDlg::IDD, pParent)
|
|
, m_szItemScriptName(_T(""))
|
|
, m_szSpriteFolderName(_T(""))
|
|
, m_lpD3D(0), m_lpd3dDevice(0)
|
|
{
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
void CItemViewerDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
DDX_Text(pDX, IDC_ITEMSCRIPT_PATH, m_szItemScriptName);
|
|
DDX_Text(pDX, IDC_SPRITE_PATH, m_szSpriteFolderName);
|
|
DDX_Control(pDX, IDC_VIEWER_LOG, m_messageDlg);
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CItemViewerDlg, CDialog)
|
|
ON_WM_SYSCOMMAND()
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
//}}AFX_MSG_MAP
|
|
ON_BN_CLICKED(IDC_LOAD_ITEMSCRIPT, OnBnClickedLoadItemscript)
|
|
ON_BN_CLICKED(IDC_SET_SPRITE_FOLDER, OnBnClickedSetSpriteFolder)
|
|
ON_BN_CLICKED(IDC_SAVE_ALL_ITEM, OnBnClickedSaveAllItem)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
// CItemViewerDlg 메시지 처리기
|
|
|
|
BOOL CItemViewerDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.
|
|
|
|
// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
|
|
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
|
|
ASSERT(IDM_ABOUTBOX < 0xF000);
|
|
|
|
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
|
if (pSysMenu != NULL)
|
|
{
|
|
CString strAboutMenu;
|
|
strAboutMenu.LoadString(IDS_ABOUTBOX);
|
|
if (!strAboutMenu.IsEmpty())
|
|
{
|
|
pSysMenu->AppendMenu(MF_SEPARATOR);
|
|
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
|
|
}
|
|
}
|
|
|
|
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
|
|
// 프레임워크가 이 작업을 자동으로 수행합니다.
|
|
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
|
|
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
|
|
|
|
// TODO: 여기에 추가 초기화 작업을 추가합니다.
|
|
|
|
if(NULL == (m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
D3DPRESENT_PARAMETERS d3dpp;
|
|
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
|
d3dpp.Windowed = TRUE;
|
|
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
|
|
|
|
if(FAILED(m_lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetSafeHwnd(),
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_lpd3dDevice)))
|
|
{
|
|
if(m_lpD3D != 0)
|
|
{
|
|
m_lpD3D->Release();
|
|
m_lpD3D = 0;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
char szFileName[MAX_PATH];
|
|
char szDir[MAX_PATH];
|
|
char szPath[MAX_PATH];
|
|
char szName[MAX_PATH];
|
|
char szExtension[MAX_PATH];
|
|
|
|
GetModuleFileName(NULL, szFileName, MAX_PATH);
|
|
_splitpath(szFileName, szDir, szPath, szName, szExtension);
|
|
_snprintf(m_szRegFileName, MAX_PATH - 1, "%s%sItemViewer.ini", szDir, szPath);
|
|
_snprintf(m_szCurrentFolderName, MAX_PATH - 1, "%s%s", szDir, szPath);
|
|
|
|
char szItemScriptName[MAX_PATH];
|
|
char szDDSFilePath[MAX_PATH];
|
|
|
|
GetPrivateProfileString("Ryl_ItemViewer", "LastItemScriptName", "",
|
|
szItemScriptName, MAX_PATH, m_szRegFileName);
|
|
|
|
GetPrivateProfileString("Ryl_ItemViewer", "LastDDSFilePath", "",
|
|
szDDSFilePath, MAX_PATH, m_szRegFileName);
|
|
|
|
m_szItemScriptName = szItemScriptName;
|
|
m_szSpriteFolderName = szDDSFilePath;
|
|
|
|
int nFind = m_szItemScriptName.ReverseFind('.');
|
|
if(0 < nFind)
|
|
{
|
|
bool bResult = false;
|
|
|
|
if(0 == strcmp(m_szItemScriptName.GetBuffer() + nFind + 1, "gsf"))
|
|
{
|
|
bResult = Item::CItemMgr::GetInstance().LoadItemProtoTypeBinary(m_szItemScriptName);
|
|
}
|
|
else if(0 == strcmp(m_szItemScriptName.GetBuffer() + nFind + 1, "txt"))
|
|
{
|
|
bResult = Item::CItemMgr::GetInstance().LoadItemProtoType(m_szItemScriptName);
|
|
}
|
|
|
|
if(!bResult)
|
|
{
|
|
m_szItemScriptName = "";
|
|
}
|
|
else
|
|
{
|
|
LoadSurfaces();
|
|
}
|
|
|
|
m_messageDlg.SetTopIndex(
|
|
m_messageDlg.AddString(bResult ? "ItemScript load success" : "ItemScript load failed."));
|
|
|
|
}
|
|
else
|
|
{
|
|
m_szItemScriptName.Empty();
|
|
}
|
|
|
|
UpdateData(false);
|
|
return TRUE; // 컨트롤에 대한 포커스를 설정하지 않을 경우 TRUE를 반환합니다.
|
|
}
|
|
|
|
void CItemViewerDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|
{
|
|
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
|
|
{
|
|
CAboutDlg dlgAbout;
|
|
dlgAbout.DoModal();
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnSysCommand(nID, lParam);
|
|
}
|
|
}
|
|
|
|
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
|
|
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
|
|
// 프레임워크에서 이 작업을 자동으로 수행합니다.
|
|
|
|
void CItemViewerDlg::OnPaint()
|
|
{
|
|
if (IsIconic())
|
|
{
|
|
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트
|
|
|
|
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
|
|
|
|
// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
|
|
int cxIcon = GetSystemMetrics(SM_CXICON);
|
|
int cyIcon = GetSystemMetrics(SM_CYICON);
|
|
CRect rect;
|
|
GetClientRect(&rect);
|
|
int x = (rect.Width() - cxIcon + 1) / 2;
|
|
int y = (rect.Height() - cyIcon + 1) / 2;
|
|
|
|
// 아이콘을 그립니다.
|
|
dc.DrawIcon(x, y, m_hIcon);
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnPaint();
|
|
}
|
|
}
|
|
|
|
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
|
|
// 이 함수를 호출합니다.
|
|
HCURSOR CItemViewerDlg::OnQueryDragIcon()
|
|
{
|
|
return static_cast<HCURSOR>(m_hIcon);
|
|
}
|
|
|
|
void CItemViewerDlg::OnOK()
|
|
{
|
|
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
|
|
|
// CDialog::OnOK();
|
|
}
|
|
|
|
void CItemViewerDlg::OnBnClickedLoadItemscript()
|
|
{
|
|
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
|
|
|
|
OPENFILENAME openFileName;
|
|
|
|
memset(&openFileName, 0, sizeof(OPENFILENAME));
|
|
|
|
char szFileName[MAX_PATH];
|
|
char szFilePathName[MAX_PATH];
|
|
|
|
memset(szFileName, 0, sizeof(char) * MAX_PATH);
|
|
memset(szFilePathName, 0, sizeof(char) * MAX_PATH);
|
|
|
|
openFileName.lStructSize = sizeof(OPENFILENAME);
|
|
|
|
openFileName.hwndOwner = GetSafeHwnd();
|
|
openFileName.lpstrFilter = "ItemScript file\0*.gsf;*.txt";
|
|
openFileName.nMaxFile = MAX_PATH;
|
|
openFileName.nMaxFileTitle = MAX_PATH;
|
|
openFileName.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER;
|
|
|
|
openFileName.lpstrFile = szFileName;
|
|
openFileName.lpstrFileTitle = szFilePathName;
|
|
|
|
if(GetOpenFileName(&openFileName))
|
|
{
|
|
UpdateData(true);
|
|
|
|
m_szItemScriptName = szFileName;
|
|
|
|
// 아이템 스크립트를 로딩한다.
|
|
int nFind = m_szItemScriptName.ReverseFind('.');
|
|
if(0 < nFind)
|
|
{
|
|
bool bResult = false;
|
|
|
|
if(0 == strcmp(m_szItemScriptName.GetBuffer() + nFind + 1, "gsf"))
|
|
{
|
|
bResult = Item::CItemMgr::GetInstance().LoadItemProtoTypeBinary(m_szItemScriptName);
|
|
}
|
|
else if(0 == strcmp(m_szItemScriptName.GetBuffer() + nFind + 1, "txt"))
|
|
{
|
|
bResult = Item::CItemMgr::GetInstance().LoadItemProtoType(m_szItemScriptName);
|
|
}
|
|
|
|
if(!bResult)
|
|
{
|
|
m_szItemScriptName = "";
|
|
}
|
|
else
|
|
{
|
|
LoadSurfaces();
|
|
}
|
|
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString(
|
|
bResult ? "ItemScript load success" : "ItemScript load failed."));
|
|
}
|
|
else
|
|
{
|
|
m_szItemScriptName.Empty();
|
|
}
|
|
|
|
WritePrivateProfileString("Ryl_ItemViewer", "LastItemScriptName", m_szItemScriptName, m_szRegFileName);
|
|
UpdateData(false);
|
|
}
|
|
}
|
|
|
|
void CItemViewerDlg::OnBnClickedSetSpriteFolder()
|
|
{
|
|
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
|
|
|
|
OPENFILENAME openFileName;
|
|
|
|
memset(&openFileName, 0, sizeof(OPENFILENAME));
|
|
|
|
char szFileName[MAX_PATH];
|
|
char szFilePathName[MAX_PATH];
|
|
|
|
memset(szFileName, 0, sizeof(char) * MAX_PATH);
|
|
memset(szFilePathName, 0, sizeof(char) * MAX_PATH);
|
|
|
|
openFileName.lStructSize = sizeof(OPENFILENAME);
|
|
|
|
openFileName.hwndOwner = GetSafeHwnd();
|
|
openFileName.lpstrFilter = "\0";
|
|
openFileName.nMaxFile = MAX_PATH;
|
|
openFileName.nMaxFileTitle = MAX_PATH;
|
|
openFileName.Flags = OFN_PATHMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER;
|
|
|
|
openFileName.lpstrFile = szFileName;
|
|
openFileName.lpstrFileTitle = szFilePathName;
|
|
|
|
if(GetOpenFileName(&openFileName))
|
|
{
|
|
UpdateData(true);
|
|
|
|
m_szSpriteFolderName = szFileName;
|
|
int nFind = m_szSpriteFolderName.ReverseFind('\\');
|
|
if(0 < nFind)
|
|
{
|
|
m_szSpriteFolderName.GetBuffer()[nFind + 1] = 0;
|
|
LoadSurfaces();
|
|
}
|
|
else
|
|
{
|
|
m_szSpriteFolderName.Empty();
|
|
}
|
|
|
|
WritePrivateProfileString("Ryl_ItemViewer", "LastDDSFilePath", m_szSpriteFolderName, m_szRegFileName);
|
|
UpdateData(false);
|
|
}
|
|
}
|
|
|
|
void CItemViewerDlg::PostNcDestroy()
|
|
{
|
|
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
|
ClearSurfaces();
|
|
|
|
if(m_lpd3dDevice != 0)
|
|
{
|
|
m_lpd3dDevice->Release();
|
|
m_lpd3dDevice = 0;
|
|
}
|
|
|
|
if(m_lpD3D != 0)
|
|
{
|
|
m_lpD3D->Release();
|
|
m_lpD3D = 0;
|
|
}
|
|
|
|
CDialog::PostNcDestroy();
|
|
}
|
|
|
|
bool CItemViewerDlg::LoadSurfaces()
|
|
{
|
|
ClearSurfaces();
|
|
|
|
if(m_szItemScriptName.IsEmpty() || m_szSpriteFolderName.IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
DWORD nBufferSize = 512 * 1024;
|
|
char* szBuffer = new char[nBufferSize];
|
|
|
|
if(0 == szBuffer)
|
|
{
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString("Insufficient memory"));
|
|
return false;
|
|
}
|
|
|
|
CString szDDSFileName;
|
|
CString szErrorMessage;
|
|
|
|
std::string spriteName;
|
|
|
|
|
|
for(unsigned short usID = 0; usID < USHRT_MAX; ++usID)
|
|
{
|
|
const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(usID);
|
|
if(0 != lpItemInfo)
|
|
{
|
|
spriteName.assign(lpItemInfo->m_SpriteData.m_szSpriteName);
|
|
szDDSFileName.Format("%s%s.dds", m_szSpriteFolderName, lpItemInfo->m_SpriteData.m_szSpriteName);
|
|
|
|
LPDIRECT3DSURFACE9 lpItemSprite = 0;
|
|
|
|
SurfaceMap::iterator pos = m_surfaceMap.find(spriteName);
|
|
if(pos == m_surfaceMap.end())
|
|
{
|
|
// Surface생성 및 Load
|
|
const char* szErrorReason = 0;
|
|
|
|
// 파일 열기
|
|
HANDLE hFile = CreateFile(szDDSFileName, GENERIC_READ, FILE_SHARE_READ, 0,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
|
|
if(INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
DWORD dwHighSize = 0;
|
|
DWORD dwLowSize = GetFileSize(hFile, &dwHighSize);
|
|
|
|
if(0 == dwHighSize)
|
|
{
|
|
if(nBufferSize < dwLowSize)
|
|
{
|
|
nBufferSize = dwLowSize;
|
|
delete [] szBuffer;
|
|
|
|
szBuffer = new char[nBufferSize];
|
|
}
|
|
|
|
if(0 != szBuffer)
|
|
{
|
|
DWORD dwTotalReadSize = 0;
|
|
|
|
do
|
|
{
|
|
DWORD dwReadSize = 0;
|
|
|
|
if(ReadFile(hFile, szBuffer,
|
|
dwLowSize - dwTotalReadSize, &dwReadSize, 0))
|
|
{
|
|
dwTotalReadSize += dwReadSize;
|
|
}
|
|
|
|
} while(dwTotalReadSize < dwLowSize);
|
|
|
|
szBuffer[0] = 'D';
|
|
szBuffer[1] = 'D';
|
|
szBuffer[2] = 'S';
|
|
szBuffer[3] = ' ';
|
|
|
|
D3DXIMAGE_INFO imageInfo;
|
|
memset(&imageInfo, 0, sizeof(D3DXIMAGE_INFO));
|
|
|
|
HRESULT hr = D3DXGetImageInfoFromFileInMemory(szBuffer, dwLowSize, &imageInfo);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_lpd3dDevice->CreateOffscreenPlainSurface(imageInfo.Width, imageInfo.Height,
|
|
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &lpItemSprite, NULL);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
RECT srcRect;
|
|
SetRect(&srcRect, 0, 0, imageInfo.Width, imageInfo.Height);
|
|
|
|
// 파일 로드가 끝났수.
|
|
hr = D3DXLoadSurfaceFromFileInMemory(lpItemSprite,
|
|
NULL, NULL, szBuffer, dwLowSize, &srcRect,
|
|
D3DX_DEFAULT, 0xFF000000, NULL);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_surfaceMap.insert(std::make_pair(spriteName, lpItemSprite));
|
|
}
|
|
else
|
|
{
|
|
lpItemSprite->Release();
|
|
lpItemSprite = 0;
|
|
|
|
szErrorReason = "LoadSurface failed";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szErrorReason = "Create offscreenBuffer failed";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szErrorReason = "Get imageInfo failed";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szErrorReason = "Buffer is NULL";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szErrorReason = "Too large sprite file";
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
else
|
|
{
|
|
szErrorReason = "File open failed";
|
|
}
|
|
|
|
if(0 != szErrorReason)
|
|
{
|
|
szErrorMessage.Format("%s : %s.dds (%6d : %s)",
|
|
szErrorReason, lpItemInfo->m_SpriteData.m_szSpriteName,
|
|
usID, lpItemInfo->m_SpriteData.m_szName);
|
|
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString(szErrorMessage));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [] szBuffer;
|
|
return true;
|
|
}
|
|
|
|
|
|
void CItemViewerDlg::ClearSurfaces()
|
|
{
|
|
SurfaceMap::iterator pos = m_surfaceMap.begin();
|
|
SurfaceMap::iterator end = m_surfaceMap.end();
|
|
|
|
for(; pos != end; ++pos)
|
|
{
|
|
pos->second->Release();
|
|
}
|
|
|
|
m_surfaceMap.clear();
|
|
}
|
|
|
|
|
|
void CItemViewerDlg::OnBnClickedSaveAllItem()
|
|
{
|
|
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
|
|
|
|
if(0 == m_lpd3dDevice)
|
|
{
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString("Invalid D3D Device"));
|
|
return;
|
|
}
|
|
|
|
// 폴더 생성
|
|
|
|
CString szCurrentFolderName;
|
|
szCurrentFolderName.Format("%sSavedItems\\", m_szCurrentFolderName);
|
|
|
|
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(szCurrentFolderName))
|
|
{
|
|
if (!CreateDirectory(szCurrentFolderName, 0))
|
|
{
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString("Folder create failed"));
|
|
return;
|
|
}
|
|
}
|
|
|
|
CString szBMPFileName;
|
|
CString szDDSFileName;
|
|
CString szErrorMessage;
|
|
|
|
std::string spriteName;
|
|
|
|
for(unsigned short usID = 0; usID < USHRT_MAX; ++usID)
|
|
{
|
|
const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(usID);
|
|
if(0 != lpItemInfo)
|
|
{
|
|
spriteName.assign(lpItemInfo->m_SpriteData.m_szSpriteName);
|
|
szBMPFileName.Format("%s%6d - %s.bmp", szCurrentFolderName, usID, lpItemInfo->m_SpriteData.m_szName);
|
|
|
|
SurfaceMap::iterator pos = m_surfaceMap.find(spriteName);
|
|
if(pos != m_surfaceMap.end())
|
|
{
|
|
LPDIRECT3DSURFACE9 lpItemSprite = pos->second;
|
|
|
|
if(0 != lpItemSprite)
|
|
{
|
|
RECT srcRect;
|
|
SetRect(&srcRect,
|
|
lpItemInfo->m_SpriteData.m_nSpriteMinX,
|
|
lpItemInfo->m_SpriteData.m_nSpriteMinY,
|
|
lpItemInfo->m_SpriteData.m_nSpriteMaxX,
|
|
lpItemInfo->m_SpriteData.m_nSpriteMaxY);
|
|
|
|
HRESULT hr = D3DXSaveSurfaceToFile(szBMPFileName, D3DXIFF_BMP, lpItemSprite, 0, &srcRect);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
szErrorMessage.Format("Save sprite failed : failed to save %6d:%s",
|
|
usID, lpItemInfo->m_SpriteData.m_szName);
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString(szErrorMessage));
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
szErrorMessage.Format("Save sprite failed : failed to find %6d:%s",
|
|
usID, lpItemInfo->m_SpriteData.m_szName);
|
|
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString(szErrorMessage));
|
|
}
|
|
}
|
|
}
|
|
|
|
m_messageDlg.SetTopIndex(m_messageDlg.AddString("Save sprite complete."));
|
|
}
|