⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tmainfrm2.cpp

📁 mpq文件的格式就是一种压缩格式
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    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 + -