📄 tmainfrm2.cpp
字号:
HANDLE hMpq = NULL;
int nError = ERROR_SUCCESS;
ASSERT(pWork->pFileList != NULL);
// Open the MPQ Archive
if(nError == ERROR_SUCCESS)
{
if(!pSFileOpenArchive(pWork->szMpqName, 0, 0, &hMpq))
nError = GetLastError();
}
// If no items selected, do nothing
if(nError == ERROR_SUCCESS)
{
POSITION pos = pWork->pFileList->GetHeadPosition();
while(pos != NULL && WorkStopped(pWork) == FALSE)
{
CString strLoc;
pInfo = (TFileInfo *)pWork->pFileList->GetNext(pos);
strLoc = GetLocalFileName(pInfo->szFullName, pWork->bKeepPath);
// Extract the file
nError = ExtractFile(pWork, hMpq, pInfo->szFullName, strLoc, pInfo->lcLocale);
if(nError != ERROR_SUCCESS)
break;
}
}
// Close the MPQ archive
if(hMpq != NULL)
pSFileCloseArchive(hMpq);
return nError;
}
int TMainFrame::WTRenameFile(TWorkInfo * pWork)
{
TFileInfo * pInfo = pWork->Ren.pInfo;
CString str;
HANDLE hMpq = NULL;
int nError = ERROR_SUCCESS;
// Update the status text
SetStatusText(IDS_RENAMINGFILE);
// Open the MPQ archive for renaming
if(nError == ERROR_SUCCESS)
{
if(!SFileCreateArchiveEx(pWork->szMpqName, OPEN_EXISTING, 0, &hMpq))
nError = GetLastError();
}
// Then rename the file
if(nError == ERROR_SUCCESS)
{
SFileSetLocale(pInfo->lcLocale);
if(!SFileRenameFile(hMpq, pInfo->szFullName, pWork->Ren.szNewName))
nError = GetLastError();
}
// Close the archive and return
if(hMpq != NULL)
SFileCloseArchive(hMpq);
if(nError == ERROR_SUCCESS)
strcpy(pInfo->szFullName, pWork->Ren.szNewName);
else
{
str.Format(IDS_ERENAMEFILE, pInfo->szFullName, nError);
AfxMessageBox(str, MB_OK | MB_ICONERROR);
}
// Reload the list view
m_pListView->LoadListView(TreeView_GetSelection(m_pTreeView->GetHwnd()));
return nError;
}
// Remove the selected files and directories
int TMainFrame::WTRemoveFiles(TWorkInfo * pWork)
{
TFileInfo * pInfo = NULL;
HTREEITEM hItem = TreeView_GetSelection(m_pTreeView->GetHwnd());
CString str;
HANDLE hMpq = NULL;
int nError = ERROR_SUCCESS;
// Open the archive for writing
if(nError == ERROR_SUCCESS)
{
if(!SFileCreateArchiveEx(pWork->szMpqName, OPEN_EXISTING, 0, &hMpq))
nError = GetLastError();
}
// Remove all files from the archive
if(nError == ERROR_SUCCESS)
{
POSITION pos = pWork->pFileList->GetHeadPosition();
while(pos != NULL && WorkStopped(pWork) == FALSE)
{
pInfo = (TFileInfo *)pWork->pFileList->GetNext(pos);
SetStatusText(IDS_REMOVINGFILE, pInfo->szFullName);
SFileSetLocale(pInfo->lcLocale);
if(!SFileRemoveFile(hMpq, pInfo->szFullName))
{
nError = GetLastError();
str.Format(IDS_EDELETEFILE, pInfo->szFullName, nError);
AfxMessageBox(str, MB_OK | MB_ICONERROR);
break;
}
else
pInfo->bDeleted = TRUE;
}
}
// Close the archive, reload the list view and return
if(hMpq != NULL)
SFileCloseArchive(hMpq);
// Remove all items deleted from view
m_pTreeView->FreeRemovedFiles(hItem);
m_pListView->LoadListView(hItem);
return nError;
}
// Adds one or more files
int TMainFrame::WTAddFiles(TWorkInfo * pWork)
{
char szArchName[MAX_PATH];
HANDLE hMpq = NULL;
HANDLE hFile;
char * szFilePos;
int nError = ERROR_SUCCESS;
// Open the archive
if(nError == ERROR_SUCCESS)
{
if(!SFileCreateArchiveEx(pWork->szMpqName, OPEN_EXISTING, 0, &hMpq))
nError = GetLastError();
}
// Test if there is enough space for adding all files
if(nError == ERROR_SUCCESS)
{
DWORD dwMaxFiles = SFileGetFileInfo(hMpq, SFILE_INFO_HASH_TABLE_SIZE);
DWORD dwFiles = SFileGetFileInfo(hMpq, SFILE_INFO_NUM_FILES);
if(dwFiles + pWork->pFileList->GetCount() > dwMaxFiles)
{
AfxMessageBox(IDS_CANTADDALLFILES, MB_OK | MB_ICONERROR);
nError = ERROR_DISK_FULL;
}
}
if(nError == ERROR_SUCCESS)
{
CPtrList * pFileList = m_pTreeView->GetCurrentMpqDir(szArchName);
POSITION pos = pWork->pFileList->GetHeadPosition();
// Get the current "folder" within MPQ archive
szFilePos = szArchName + strlen(szArchName);
while(pos != NULL && nError == ERROR_SUCCESS && WorkStopped(pWork) == FALSE)
{
char * szAddedFile = (char *)pWork->pFileList->GetNext(pos);
BOOL bReplaced = FALSE;
// Update status text
SetStatusText(IDS_ADDINGFILE, szAddedFile);
strcpy(szFilePos, szAddedFile + pWork->New.nRelPathStart);
// Add the file into archive
nError = AddFileToArchive(pWork, hMpq, szAddedFile, szArchName, &bReplaced);
// If added or replaced, open the file and get size, csize and locale
if(nError == ERROR_SUCCESS)
{
if(SFileOpenFileEx(hMpq, szArchName, 0, &hFile))
{
DWORD dwFSize = SFileGetFileInfo(hFile, SFILE_INFO_FILE_SIZE);
DWORD dwFlags = SFileGetFileInfo(hFile, SFILE_INFO_FLAGS);
if(bReplaced == TRUE)
UpdateFileInfo(pFileList, szArchName, pWork->lcLocale, dwFSize, dwFlags);
else
AddFileToTree(szArchName, pWork->lcLocale, dwFSize, dwFlags);
SFileCloseFile(hFile);
}
}
}
}
// Close the archive and return
if(hMpq != NULL)
SFileCloseArchive(hMpq);
// Reload the list view
m_pListView->LoadListView(TreeView_GetSelection(m_pTreeView->GetHwnd()));
return nError;
}
// Extracts the file list, attributes list etc
int TMainFrame::WTExtractSpecialFile(TWorkInfo * pWork)
{
char * szExtractPath = cfg.szWorkPath;
char * szFileName = NULL;
char szLocalFile[MAX_PATH];
int nError = ERROR_SUCCESS;
if(pWork->dwWorkType == WORK_EXTRACT_LISTFILE)
{
szExtractPath = cfg.szFileListsPath;
szFileName = LISTFILE_NAME;
}
if(pWork->dwWorkType == WORK_EXTRACT_ATTRIBUTES)
szFileName = ATTRIBUTES_NAME;
if(pWork->dwWorkType == WORK_EXTRACT_SIGNATURE)
szFileName = SIGNATURE_NAME;
if(szFileName != NULL)
{
sprintf(szLocalFile, "%s\\%s.txt", szExtractPath, GetPlainName(pWork->szMpqName));
if((nError = ExtractFile(pWork, NULL, szFileName, szLocalFile, LANG_NEUTRAL)) == ERROR_SUCCESS)
AfxMessageBox(IDS_LISTFILE_EXTRACTED, MB_OK | MB_ICONINFORMATION);
}
return nError;
}
int TMainFrame::WTCompactArchive(TWorkInfo * pWork)
{
CString str;
HANDLE hMpq = NULL;
int nError = ERROR_SUCCESS;
// Open the archive
if(nError == ERROR_SUCCESS)
{
if(!SFileCreateArchiveEx(pWork->szMpqName, OPEN_EXISTING, 0, &hMpq))
{
nError = GetLastError();
str.Format(IDS_EOPEN_MPQ, (const char *)pWork->szMpqName, nError);
AfxMessageBox(str, MB_OK | MB_ICONERROR);
}
}
// Set the compact callback
if(nError == ERROR_SUCCESS)
{
if(!SFileSetCompactCallback(hMpq, CompactCB, this))
nError = GetLastError();
}
// Compact the archive
if(nError == ERROR_SUCCESS)
{
if(!SFileCompactArchive(hMpq, pWork->Cmpct.szFileList, 0))
{
nError = GetLastError();
AfxMessageBox(IDS_ECOMPACTERROR, MB_OK | MB_ICONERROR);
}
}
// Close the archive
if(hMpq != NULL)
SFileCloseArchive(hMpq);
return nError;
}
DWORD WINAPI TMainFrame::WorkThreadProc(VOID * pParam)
{
TWorkInfo * pWork = (TWorkInfo *)pParam;
TMainFrame * pMainFrame = pWork->pMainFrame;
int nError = ERROR_SUCCESS;
if(pMainFrame->IsKindOf(RUNTIME_CLASS(TMainFrame)))
{
switch(pWork->dwWorkType)
{
case WORK_NEW_MPQ_ARCHIVE:
nError = pMainFrame->WTNewMpqArchive(pWork);
break;
case WORK_LOAD_MPQ_ARCHIVE:
nError = pMainFrame->WTLoadMPQArchive(pWork);
break;
case WORK_OPEN_FILE:
nError = pMainFrame->WTOpenFile(pWork);
break;
case WORK_EXTRACT_FILES:
nError = pMainFrame->WTExtractFiles(pWork);
break;
case WORK_RENAME_FILE:
nError = pMainFrame->WTRenameFile(pWork);
break;
case WORK_REMOVE_FILES:
nError = pMainFrame->WTRemoveFiles(pWork);
break;
case WORK_ADD_FILES:
nError = pMainFrame->WTAddFiles(pWork);
break;
case WORK_EXTRACT_LISTFILE:
case WORK_EXTRACT_ATTRIBUTES:
case WORK_EXTRACT_SIGNATURE:
nError = pMainFrame->WTExtractSpecialFile(pWork);
break;
case WORK_COMPACT_ARCHIVE:
nError = pMainFrame->WTCompactArchive(pWork);
break;
// case WORK_RUN_SCRIPT:
// nError = pMainFrame->WTRunMPQ2000Script(pWork);
// break;
}
// If the thread was not terminated, cleanup
if(WaitForSingleObject(pMainFrame->m_hStopEvent, 0) == WAIT_TIMEOUT)
{
// Tell the main window that we are complete with the work
::PostMessage(pMainFrame->m_hWnd, WM_WORKCOMPLETE, pWork->dwWorkType, nError);
pMainFrame->FreeWorkInfo(pWork);
}
}
return nError;
}
int TMainFrame::StartWorkThread(TWorkInfo * pWork)
{
DWORD dwThreadID;
int nError = ERROR_SUCCESS;
// Disable all dialog bars
EnableDialogBars(FALSE);
// Start the thread in suspended state
if(nError == ERROR_SUCCESS)
{
ResetEvent(m_hStopEvent);
m_hWorkThread = CreateThread(NULL, 0, WorkThreadProc, pWork, CREATE_SUSPENDED, &dwThreadID);
}
// Set AutoDelete to FALSE and start the work
if(nError == ERROR_SUCCESS)
{
SetThreadPriority(m_hWorkThread, THREAD_PRIORITY_BELOW_NORMAL);
ResumeThread(m_hWorkThread);
}
// If an error, we have to let us know that the work ended
if(nError != ERROR_SUCCESS)
PostMessage(WM_WORKCOMPLETE, pWork->dwWorkType, ERROR_SUCCESS);
return nError;
}
// Message function that is called when the work is complete
void TMainFrame::OnWorkComplete(WPARAM wParam, LPARAM lParam)
{
int nResult = (int)lParam;
// Close the handles.
if(m_hWorkThread != NULL)
{
// Before deleting, we have to wait until the thread really terminates.
WaitForSingleObject(m_hWorkThread, 1000);
CloseHandle(m_hWorkThread);
m_hWorkThread = NULL;
}
// Set status text to "Idle"
SetStatusText(AFX_IDS_IDLEMESSAGE);
// Do action corresponding to the kind of work thread
switch(wParam)
{
case WORK_LOAD_MPQ_ARCHIVE:
if(nResult != ERROR_SUCCESS)
{
CloseMpqArchive();
AfxMessageBox(IDS_CANTLOADMPQ, MB_OK | MB_ICONERROR);
}
break;
}
// Must enable dialog bar after sending WM_WORKCOMPLETE
if(m_bNameless == FALSE)
EnableDialogBars(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -