rlm@1: #include "../stdafx.h" rlm@1: #include "../resource.h" rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include "7zip.h" rlm@1: //#include "G_main.h" rlm@1: //#include "G_dsound.h" rlm@1: #include "OpenArchive.h" rlm@1: rlm@1: LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); rlm@1: static int s_archiveFileChooserResult = -1; rlm@1: rlm@1: static HWND s_parentHWND = NULL; rlm@1: void SetArchiveParentHWND(void* hwnd) { s_parentHWND = (HWND)hwnd; } rlm@1: static HWND GetArchiveParentHWND() { return s_parentHWND ? s_parentHWND : AfxGetApp()->m_pMainWnd->GetSafeHwnd(); } rlm@1: rlm@1: static char Str_Tmp [2048]; rlm@1: rlm@1: struct ArchiveFileChooserInfo rlm@1: { rlm@1: ArchiveFileChooserInfo(ArchiveFile& theArchive, const char** ignoreExtensions, int& numIgnoreExtensions) : archive(theArchive) rlm@1: { rlm@1: tryagain: rlm@1: int numItems = archive.GetNumItems(); rlm@1: for(int i = 0; i < numItems; i++) rlm@1: { rlm@1: if(archive.GetItemSize(i)) rlm@1: { rlm@1: const char* name = archive.GetItemName(i); rlm@1: const char* ext = strrchr(name, '.'); rlm@1: bool ok = true; rlm@1: if(ext++) rlm@1: { rlm@1: for(int j = 0; j < numIgnoreExtensions; j++) rlm@1: { rlm@1: const char* ext2 = ignoreExtensions[j]; rlm@1: const char* wild = strchr(ext2, '*'); rlm@1: if(!wild) rlm@1: { rlm@1: if(!_stricmp(ext, ext2)) rlm@1: { rlm@1: ok = false; rlm@1: break; rlm@1: } rlm@1: } rlm@1: else // very limited (end only) wildcard support rlm@1: { rlm@1: if(!_strnicmp(ext, ext2, wild - ext2)) rlm@1: { rlm@1: ok = false; rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: if(ok) rlm@1: { rlm@1: ArchiveFileChooserInfo::FileInfo fi = { name, i }; rlm@1: files.push_back(fi); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: if(files.empty() && numIgnoreExtensions) rlm@1: { rlm@1: // try again without any exclusions if we excluded everything in the archive rlm@1: numIgnoreExtensions = 0; rlm@1: goto tryagain; rlm@1: } rlm@1: rlm@1: // strip away prefix paths that are common to all the files rlm@1: bool stripping = !files.empty(); rlm@1: while(stripping) rlm@1: { rlm@1: const char* firstName = files[0].name.c_str(); rlm@1: const char* slash = strchr(firstName, '\\'); rlm@1: const char* slash2 = strchr(firstName, '/'); rlm@1: slash = max(slash, slash2); rlm@1: if(!slash++) rlm@1: break; rlm@1: for(size_t i = 1; i < files.size(); i++) rlm@1: if(strncmp(firstName, files[i].name.c_str(), slash - firstName)) rlm@1: stripping = false; rlm@1: if(stripping) rlm@1: for(size_t i = 0; i < files.size(); i++) rlm@1: files[i].name = files[i].name.substr(slash - firstName, files[i].name.length() - (slash - firstName)); rlm@1: } rlm@1: rlm@1: // sort by filename rlm@1: std::sort(files.begin(), files.end(), FileInfo::Sort); rlm@1: } rlm@1: rlm@1: //protected: rlm@1: rlm@1: struct FileInfo rlm@1: { rlm@1: std::string name; rlm@1: int itemIndex; rlm@1: rlm@1: static bool Sort(const FileInfo& elem1, const FileInfo& elem2) rlm@1: { rlm@1: int comp = elem1.name.compare(elem2.name); rlm@1: return comp ? (comp < 0) : (elem1.itemIndex < elem2.itemIndex); rlm@1: } rlm@1: }; rlm@1: rlm@1: ArchiveFile& archive; rlm@1: std::vector files; rlm@1: }; rlm@1: rlm@1: static void ClearLayoutStates(); rlm@1: rlm@1: int ChooseItemFromArchive(ArchiveFile& archive, bool autoChooseIfOnly1, const char** ignoreExtensions, int numIgnoreExtensions) rlm@1: { rlm@1: int prevNumIgnoreExtensions = numIgnoreExtensions; rlm@1: archive.m_userMadeSelection = false; rlm@1: rlm@1: // prepare a list of files to choose from the archive rlm@1: ArchiveFileChooserInfo info (archive, ignoreExtensions, numIgnoreExtensions); rlm@1: rlm@1: // based on our list, decide which item in the archive to choose rlm@1: rlm@1: // check if there's nothing rlm@1: if(info.files.size() < 1) rlm@1: { rlm@1: MessageBox(GetArchiveParentHWND(), "The archive is either empty or encrypted.", "Nothing to load!", MB_OK | MB_ICONWARNING); rlm@1: return -1; rlm@1: } rlm@1: rlm@1: // warn if all the files in the archive have extensions we should ignore rlm@1: if(numIgnoreExtensions != prevNumIgnoreExtensions) rlm@1: { rlm@1: CString msg; rlm@1: msg.Format("The archive appears to only contain the wrong type of files.\n\n(in \"%s\")", archive.GetArchiveFileName()); rlm@1: int answer = MessageBox(GetArchiveParentHWND(), msg, "Warning", MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2); rlm@1: if(answer == IDCANCEL) rlm@1: return -1; rlm@1: } rlm@1: rlm@1: // if there's only 1 item, choose it rlm@1: if(info.files.size() == 1 && autoChooseIfOnly1 && numIgnoreExtensions == prevNumIgnoreExtensions) rlm@1: return info.files[0].itemIndex; rlm@1: rlm@1: // bring up a dialog to choose the index if there's more than 1 rlm@1: DialogBoxParam(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_ARCHIVEFILECHOOSER), GetArchiveParentHWND(), (DLGPROC) ArchiveFileChooser,(LPARAM) &info); rlm@1: archive.m_userMadeSelection = (s_archiveFileChooserResult != -1); rlm@1: return s_archiveFileChooserResult; rlm@1: } rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: #define DEFAULT_EXTENSION ".tmp" rlm@1: #define DEFAULT_CATEGORY "vba" rlm@1: rlm@1: static struct TempFiles rlm@1: { rlm@1: struct TemporaryFile rlm@1: { rlm@1: TemporaryFile(const char* cat, const char* ext) rlm@1: { rlm@1: if(!ext || !*ext) ext = DEFAULT_EXTENSION; rlm@1: if(!cat || !*cat) cat = DEFAULT_CATEGORY; rlm@1: category = cat; rlm@1: rlm@1: char tempPath [2048]; rlm@1: GetTempPath(2048, tempPath); rlm@1: //GetTempFileName(tempPath, cat, 0, filename, ext); // alas rlm@1: rlm@1: char*const fname = tempPath + strlen(tempPath); rlm@1: unsigned short start = (unsigned short)(timeGetTime() & 0xFFFF); rlm@1: unsigned short n = start + 1; rlm@1: while(n != start) rlm@1: { rlm@1: _snprintf(fname, 2048 - (fname - tempPath), "%s%04X%s", cat, n, ext); rlm@1: FILE* file = fopen(tempPath, "wb"); rlm@1: if(file) rlm@1: { rlm@1: // mark the temporary file as read-only and (whatever this does) temporary rlm@1: DWORD attributes = GetFileAttributes(tempPath); rlm@1: attributes |= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_TEMPORARY; rlm@1: SetFileAttributes(tempPath, attributes); rlm@1: rlm@1: fclose(file); rlm@1: rlm@1: // add it to our registry of files that need to be deleted, in case we fail to terminate properly rlm@1: TempFiles::AddEntryToGarbageRegistry(tempPath); rlm@1: rlm@1: break; rlm@1: } rlm@1: n++; rlm@1: } rlm@1: strcpy(filename, tempPath); rlm@1: } rlm@1: TemporaryFile(const TemporaryFile& copy) rlm@1: { rlm@1: strcpy(filename, copy.filename); rlm@1: category = copy.category; rlm@1: } rlm@1: TemporaryFile() rlm@1: { rlm@1: filename[0] = 0; rlm@1: // category[0] = 0; // error rlm@1: } rlm@1: bool Delete(bool returnFalseOnRegistryRemovalFailure=false) rlm@1: { rlm@1: if(!*filename) rlm@1: return true; // guess it already didn't exist rlm@1: rlm@1: // remove read-only attribute so Windows will let us delete it rlm@1: // (our temporary files are read-only to discourage other apps from tampering) rlm@1: DWORD attributes = GetFileAttributes(filename); rlm@1: if(attributes & FILE_ATTRIBUTE_READONLY) rlm@1: SetFileAttributes(filename, attributes & ~FILE_ATTRIBUTE_READONLY); rlm@1: rlm@1: if(_unlink(filename) == 0 || errno != EACCES) rlm@1: { rlm@1: // remove it from our registry of files that need to be deleted, to reduce accumulation rlm@1: bool removed = TempFiles::RemoveEntryFromGarbageRegistry(filename); rlm@1: rlm@1: *filename = '\0'; rlm@1: return removed || !returnFalseOnRegistryRemovalFailure; // successfully deleted or already didn't exist, return true unless registry removal failure notification was requested and that failed rlm@1: } rlm@1: rlm@1: // restore read-only if we couldn't delete it (not sure if this ever succeeds or matters though) rlm@1: if(attributes & FILE_ATTRIBUTE_READONLY) rlm@1: SetFileAttributes(filename, attributes); rlm@1: rlm@1: return false; // failed to delete read-only or in-use file rlm@1: } rlm@1: char filename [MAX_PATH]; rlm@1: std::string category; rlm@1: }; rlm@1: rlm@1: std::vector tempFiles; rlm@1: rlm@1: const char* GetFile(const char* category, const char* extension) rlm@1: { rlm@1: tempFiles.push_back(TemporaryFile(category, extension)); rlm@1: return tempFiles.back().filename; rlm@1: } rlm@1: rlm@1: void ReleaseFile(const char* filename) rlm@1: { rlm@1: for(int i = (int)tempFiles.size()-1; i >= 0; i--) rlm@1: { rlm@1: if(!strcmp(filename, tempFiles[i].filename)) rlm@1: { rlm@1: if(tempFiles[i].Delete()) rlm@1: tempFiles.erase(tempFiles.begin() + i); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void ReleaseCategory(const char* cat, const char* exceptionFilename) rlm@1: { rlm@1: for(int i = (int)tempFiles.size()-1; i >= 0; i--) rlm@1: { rlm@1: if(!strcmp(cat, tempFiles[i].category.c_str()) && rlm@1: (!exceptionFilename || rlm@1: strcmp(exceptionFilename, tempFiles[i].filename))) rlm@1: { rlm@1: if(tempFiles[i].Delete()) rlm@1: tempFiles.erase(tempFiles.begin() + i); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: // delete all temporary files on shutdown rlm@1: ~TempFiles() rlm@1: { rlm@1: for(size_t i = 0; i < tempFiles.size(); i++) rlm@1: { rlm@1: tempFiles[i].Delete(); rlm@1: } rlm@1: rlm@1: TempFiles::CleanOutGarbageRegistry(); rlm@1: } rlm@1: rlm@1: // run this on startup to delete any files that we failed to delete last time rlm@1: // in case we crashed or were forcefully terminated rlm@1: TempFiles() rlm@1: { rlm@1: TempFiles::CleanOutGarbageRegistry(); rlm@1: } rlm@1: rlm@1: static void AddEntryToGarbageRegistry(const char* filename) rlm@1: { rlm@1: char gbgFile[2048]; rlm@1: GetTempPath(2048, gbgFile); rlm@1: strcat(gbgFile, "VBATempFileRecords"); rlm@1: char key[64]; rlm@1: int i = 0; rlm@1: while(true) rlm@1: { rlm@1: sprintf(key, "File%d", i); rlm@1: GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); rlm@1: if(!*Str_Tmp) rlm@1: break; rlm@1: i++; rlm@1: } rlm@1: WritePrivateProfileString("Files", key, filename, gbgFile); rlm@1: } rlm@1: static bool RemoveEntryFromGarbageRegistry(const char* filename) rlm@1: { rlm@1: char gbgFile[2048]; rlm@1: GetTempPath(2048, gbgFile); rlm@1: strcat(gbgFile, "VBATempFileRecords"); rlm@1: char key[64]; rlm@1: int i = 0; rlm@1: int deleteSlot = -1; rlm@1: while(true) rlm@1: { rlm@1: sprintf(key, "File%d", i); rlm@1: GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); rlm@1: if(!*Str_Tmp) rlm@1: break; rlm@1: if(!strcmp(Str_Tmp, filename)) rlm@1: deleteSlot = i; rlm@1: i++; rlm@1: } rlm@1: --i; rlm@1: if(i >= 0 && deleteSlot >= 0) rlm@1: { rlm@1: if(i != deleteSlot) rlm@1: { rlm@1: sprintf(key, "File%d", i); rlm@1: GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); rlm@1: sprintf(key, "File%d", deleteSlot); rlm@1: WritePrivateProfileString("Files", key, Str_Tmp, gbgFile); rlm@1: } rlm@1: sprintf(key, "File%d", i); rlm@1: if(0 == WritePrivateProfileString("Files", key, NULL, gbgFile)) rlm@1: return false; rlm@1: } rlm@1: if(i <= 0 && deleteSlot == 0) rlm@1: _unlink(gbgFile); rlm@1: return true; rlm@1: } rlm@1: rlm@1: private: rlm@1: static void CleanOutGarbageRegistry() rlm@1: { rlm@1: char gbgFile[2048]; rlm@1: GetTempPath(2048, gbgFile); rlm@1: strcat(gbgFile, "VBATempFileRecords"); rlm@1: rlm@1: char key[64]; rlm@1: int i = 0; rlm@1: while(true) rlm@1: { rlm@1: sprintf(key, "File%d", i); rlm@1: GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); rlm@1: if(!*Str_Tmp) rlm@1: break; rlm@1: TemporaryFile temp; rlm@1: strcpy(temp.filename, Str_Tmp); rlm@1: if(!temp.Delete(true)) rlm@1: i++; rlm@1: } rlm@1: } rlm@1: rlm@1: } s_tempFiles; rlm@1: rlm@1: rlm@1: const char* GetTempFile(const char* category, const char* extension) rlm@1: { rlm@1: return s_tempFiles.GetFile(category, extension); rlm@1: } rlm@1: void ReleaseTempFile(const char* filename) rlm@1: { rlm@1: s_tempFiles.ReleaseFile(filename); rlm@1: } rlm@1: void ReleaseTempFileCategory(const char* cat, const char* exceptionFilename) rlm@1: { rlm@1: if(!cat || !*cat) cat = DEFAULT_CATEGORY; rlm@1: s_tempFiles.ReleaseCategory(cat, exceptionFilename); rlm@1: } rlm@1: rlm@1: rlm@1: rlm@1: // example input Name: "C:\games.zip" rlm@1: // example output LogicalName: "C:\games.zip|Metroid.gba" rlm@1: // example output PhysicalName: "C:\Documents and Settings\User\Local Settings\Temp\VBA\rom7A37.gba" rlm@1: // assumes arguments are character buffers with 2048 bytes each rlm@1: bool ObtainFile(const char* Name, char *const & LogicalName, char *const & PhysicalName, const char* category, const char** ignoreExtensions, int numIgnoreExtensions) rlm@1: { rlm@1: restart: rlm@1: char ArchivePaths [2048]; rlm@1: strcpy(LogicalName, Name); rlm@1: strcpy(PhysicalName, Name); rlm@1: strcpy(ArchivePaths, Name); rlm@1: char* bar = strchr(ArchivePaths, '|'); rlm@1: if(bar) rlm@1: { rlm@1: PhysicalName[bar - ArchivePaths] = 0; // doesn't belong in the physical name rlm@1: LogicalName[bar - ArchivePaths] = 0; // we'll reconstruct the logical name as we go rlm@1: *bar++ = 0; // bar becomes the next logical archive path component rlm@1: } rlm@1: rlm@1: bool userSelected = false; rlm@1: rlm@1: while(true) rlm@1: { rlm@1: ArchiveFile archive (PhysicalName, LogicalName); rlm@1: if(!archive.IsCompressed()) rlm@1: { rlm@1: if(archive.GetNumItems() > 0) rlm@1: return true; rlm@1: else rlm@1: { rlm@1: // failed or cancelled... backtrack to outermost archive if not already there rlm@1: char* div = NULL; rlm@1: if(LogicalName[strlen(LogicalName)-1] == '|') rlm@1: { rlm@1: LogicalName[strlen(LogicalName)-1] = '\0'; rlm@1: div = strrchr(LogicalName, '|'); rlm@1: } rlm@1: if(div && userSelected) rlm@1: goto restart; rlm@1: else rlm@1: return false; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int item = -1; rlm@1: bool forceManual = false; rlm@1: if(bar && *bar) // try following the in-archive part of the logical path rlm@1: { rlm@1: char* bar2 = strchr(bar, '|'); rlm@1: if(bar2) *bar2++ = 0; rlm@1: int numItems = archive.GetNumItems(); rlm@1: for(int i = 0; i < numItems; i++) rlm@1: { rlm@1: if(archive.GetItemSize(i)) rlm@1: { rlm@1: const char* itemName = archive.GetItemName(i); rlm@1: if(!_stricmp(itemName, bar)) rlm@1: { rlm@1: item = i; // match found, now we'll auto-follow the path rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: if(item < 0) rlm@1: { rlm@1: forceManual = true; // we don't want it choosing something else without user permission rlm@1: bar = NULL; // remaining archive path is invalid rlm@1: } rlm@1: else rlm@1: bar = bar2; // advance to next archive path part rlm@1: } rlm@1: if(item < 0) rlm@1: item = ChooseItemFromArchive(archive, !forceManual, ignoreExtensions, numIgnoreExtensions); rlm@1: rlm@1: userSelected |= archive.m_userMadeSelection; rlm@1: rlm@1: const char* TempFileName = s_tempFiles.GetFile(category, strrchr(archive.GetItemName(item), '.')); rlm@1: if(!archive.ExtractItem(item, TempFileName)) rlm@1: s_tempFiles.ReleaseFile(TempFileName); rlm@1: s_tempFiles.ReleaseFile(PhysicalName); rlm@1: strcpy(PhysicalName, TempFileName); rlm@1: _snprintf(LogicalName + strlen(LogicalName), 2048 - (strlen(LogicalName)+1), "|%s", archive.GetItemName(item)); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: rlm@1: rlm@1: struct ControlLayoutInfo rlm@1: { rlm@1: int controlID; rlm@1: rlm@1: enum LayoutType // what to do when the containing window resizes rlm@1: { rlm@1: NONE, // leave the control where it was rlm@1: RESIZE_END, // resize the control rlm@1: MOVE_START, // move the control rlm@1: }; rlm@1: LayoutType horizontalLayout; rlm@1: LayoutType verticalLayout; rlm@1: }; rlm@1: struct ControlLayoutState rlm@1: { rlm@1: int x,y,width,height; rlm@1: bool valid; rlm@1: ControlLayoutState() : valid(false) {} rlm@1: }; rlm@1: rlm@1: static ControlLayoutInfo controlLayoutInfos [] = { rlm@1: {IDC_LIST1, ControlLayoutInfo::RESIZE_END, ControlLayoutInfo::RESIZE_END}, rlm@1: {IDOK, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, rlm@1: {ID_CANCEL, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, rlm@1: }; rlm@1: static const int numControlLayoutInfos = sizeof(controlLayoutInfos)/sizeof(*controlLayoutInfos); rlm@1: rlm@1: static ControlLayoutState s_layoutState [numControlLayoutInfos]; rlm@1: static int s_windowWidth = 182, s_windowHeight = 113; rlm@1: rlm@1: rlm@1: LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) rlm@1: { rlm@1: RECT r, r2; rlm@1: int dx1, dy1, dx2, dy2; rlm@1: static std::map s_listToItemsMap; rlm@1: rlm@1: switch(uMsg) rlm@1: { rlm@1: case WM_INITDIALOG: rlm@1: { rlm@1: //Clear_Sound_Buffer(); rlm@1: rlm@1: //if(Full_Screen) rlm@1: //{ rlm@1: // while (ShowCursor(false) >= 0); rlm@1: // while (ShowCursor(true) < 0); rlm@1: //} rlm@1: rlm@1: for(int i = 0; i < numControlLayoutInfos; i++) rlm@1: s_layoutState[i].valid = false; rlm@1: rlm@1: GetWindowRect(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), &r); rlm@1: dx1 = (r.right - r.left) / 2; rlm@1: dy1 = (r.bottom - r.top) / 2; rlm@1: rlm@1: GetWindowRect(hDlg, &r2); rlm@1: dx2 = (r2.right - r2.left) / 2; rlm@1: dy2 = (r2.bottom - r2.top) / 2; rlm@1: rlm@1: //SetWindowPos(hDlg, NULL, max(0, r.left + (dx1 - dx2)), max(0, r.top + (dy1 - dy2)), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); rlm@1: SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); rlm@1: rlm@1: ArchiveFileChooserInfo& info = *(ArchiveFileChooserInfo*)lParam; rlm@1: std::vector& files = info.files; rlm@1: ArchiveFile& archive = info.archive; rlm@1: rlm@1: std::string title = "Choose File in "; rlm@1: title += archive.GetArchiveTypeName(); rlm@1: title += " Archive"; rlm@1: SetWindowText(hDlg, title.c_str()); rlm@1: rlm@1: // populate list rlm@1: for(size_t i = 0; i < files.size(); i++) rlm@1: { rlm@1: int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_ADDSTRING, (WPARAM) 0, (LONG) (LPTSTR) files[i].name.c_str()); rlm@1: s_listToItemsMap[listIndex] = files[i].itemIndex; rlm@1: } rlm@1: rlm@1: SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); rlm@1: rlm@1: { rlm@1: RECT r3; rlm@1: GetClientRect(hDlg, &r3); rlm@1: s_windowWidth = r3.right - r3.left; rlm@1: s_windowHeight = r3.bottom - r3.top; rlm@1: } rlm@1: rlm@1: return true; rlm@1: } break; rlm@1: rlm@1: case WM_SIZING: rlm@1: { rlm@1: // enforce a minimum window size rlm@1: rlm@1: LPRECT r = (LPRECT) lParam; rlm@1: int minimumWidth = 281; rlm@1: int minimumHeight = 117; rlm@1: if(r->right - r->left < minimumWidth) rlm@1: if(wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT) rlm@1: r->left = r->right - minimumWidth; rlm@1: else rlm@1: r->right = r->left + minimumWidth; rlm@1: if(r->bottom - r->top < minimumHeight) rlm@1: if(wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT) rlm@1: r->top = r->bottom - minimumHeight; rlm@1: else rlm@1: r->bottom = r->top + minimumHeight; rlm@1: return TRUE; rlm@1: } rlm@1: rlm@1: case WM_SIZE: rlm@1: { rlm@1: // resize or move controls in the window as necessary when the window is resized rlm@1: rlm@1: int prevDlgWidth = s_windowWidth; rlm@1: int prevDlgHeight = s_windowHeight; rlm@1: rlm@1: int dlgWidth = LOWORD(lParam); rlm@1: int dlgHeight = HIWORD(lParam); rlm@1: rlm@1: int deltaWidth = dlgWidth - prevDlgWidth; rlm@1: int deltaHeight = dlgHeight - prevDlgHeight; rlm@1: rlm@1: for(int i = 0; i < numControlLayoutInfos; i++) rlm@1: { rlm@1: ControlLayoutInfo layoutInfo = controlLayoutInfos[i]; rlm@1: ControlLayoutState& layoutState = s_layoutState[i]; rlm@1: rlm@1: HWND hCtrl = GetDlgItem(hDlg,layoutInfo.controlID); rlm@1: rlm@1: int x,y,width,height; rlm@1: if(layoutState.valid) rlm@1: { rlm@1: x = layoutState.x; rlm@1: y = layoutState.y; rlm@1: width = layoutState.width; rlm@1: height = layoutState.height; rlm@1: } rlm@1: else rlm@1: { rlm@1: RECT r; rlm@1: GetWindowRect(hCtrl, &r); rlm@1: POINT p = {r.left, r.top}; rlm@1: ScreenToClient(hDlg, &p); rlm@1: x = p.x; rlm@1: y = p.y; rlm@1: width = r.right - r.left; rlm@1: height = r.bottom - r.top; rlm@1: } rlm@1: rlm@1: switch(layoutInfo.horizontalLayout) rlm@1: { rlm@1: case ControlLayoutInfo::RESIZE_END: width += deltaWidth; break; rlm@1: case ControlLayoutInfo::MOVE_START: x += deltaWidth; break; rlm@1: default: break; rlm@1: } rlm@1: switch(layoutInfo.verticalLayout) rlm@1: { rlm@1: case ControlLayoutInfo::RESIZE_END: height += deltaHeight; break; rlm@1: case ControlLayoutInfo::MOVE_START: y += deltaHeight; break; rlm@1: default: break; rlm@1: } rlm@1: rlm@1: SetWindowPos(hCtrl, 0, x,y, width,height, 0); rlm@1: rlm@1: layoutState.x = x; rlm@1: layoutState.y = y; rlm@1: layoutState.width = width; rlm@1: layoutState.height = height; rlm@1: layoutState.valid = true; rlm@1: } rlm@1: rlm@1: s_windowWidth = dlgWidth; rlm@1: s_windowHeight = dlgHeight; rlm@1: rlm@1: RedrawWindow(hDlg, NULL, NULL, RDW_INVALIDATE); rlm@1: } rlm@1: break; rlm@1: rlm@1: case WM_COMMAND: rlm@1: switch(LOWORD(wParam)) rlm@1: { rlm@1: case IDC_LIST1: rlm@1: if(HIWORD(wParam) == LBN_DBLCLK) rlm@1: { rlm@1: POINT pos; rlm@1: GetCursorPos(&pos); rlm@1: int clickedItem = LBItemFromPt(GetDlgItem(hDlg, IDC_LIST1), pos, FALSE); rlm@1: if(clickedItem != -1) rlm@1: { rlm@1: SendMessage(hDlg, WM_COMMAND, IDOK, 0); rlm@1: } rlm@1: } rlm@1: return TRUE; rlm@1: rlm@1: case IDOK: rlm@1: { rlm@1: int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); rlm@1: s_archiveFileChooserResult = s_listToItemsMap[listIndex]; rlm@1: s_listToItemsMap.clear(); rlm@1: //if(Full_Screen) rlm@1: //{ rlm@1: // while (ShowCursor(true) < 0); rlm@1: // while (ShowCursor(false) >= 0); rlm@1: //} rlm@1: EndDialog(hDlg, false); rlm@1: } return TRUE; rlm@1: rlm@1: case ID_CANCEL: rlm@1: case IDCANCEL: rlm@1: s_archiveFileChooserResult = -1; rlm@1: s_listToItemsMap.clear(); rlm@1: //if(Full_Screen) rlm@1: //{ rlm@1: // while (ShowCursor(true) < 0); rlm@1: // while (ShowCursor(false) >= 0); rlm@1: //} rlm@1: EndDialog(hDlg, false); rlm@1: return TRUE; rlm@1: } rlm@1: rlm@1: case WM_CLOSE: rlm@1: s_archiveFileChooserResult = -1; rlm@1: s_listToItemsMap.clear(); rlm@1: //if(Full_Screen) rlm@1: //{ rlm@1: // while (ShowCursor(true) < 0); rlm@1: // while (ShowCursor(false) >= 0); rlm@1: //} rlm@1: EndDialog(hDlg, false); rlm@1: return TRUE; rlm@1: } rlm@1: rlm@1: return false; rlm@1: }