Mercurial > vba-clojure
diff src/win32/7zip/OpenArchive.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/OpenArchive.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,713 @@ 1.4 +#include "../stdafx.h" 1.5 +#include "../resource.h" 1.6 +#include <windows.h> 1.7 +#include <mmsystem.h> 1.8 +#include <cstdio> 1.9 +#include <cerrno> 1.10 +#include <cassert> 1.11 +#include <cstring> 1.12 +#include <map> 1.13 +#include <vector> 1.14 +#include <algorithm> 1.15 +#include "7zip.h" 1.16 +//#include "G_main.h" 1.17 +//#include "G_dsound.h" 1.18 +#include "OpenArchive.h" 1.19 + 1.20 +LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 1.21 +static int s_archiveFileChooserResult = -1; 1.22 + 1.23 +static HWND s_parentHWND = NULL; 1.24 +void SetArchiveParentHWND(void* hwnd) { s_parentHWND = (HWND)hwnd; } 1.25 +static HWND GetArchiveParentHWND() { return s_parentHWND ? s_parentHWND : AfxGetApp()->m_pMainWnd->GetSafeHwnd(); } 1.26 + 1.27 +static char Str_Tmp [2048]; 1.28 + 1.29 +struct ArchiveFileChooserInfo 1.30 +{ 1.31 + ArchiveFileChooserInfo(ArchiveFile& theArchive, const char** ignoreExtensions, int& numIgnoreExtensions) : archive(theArchive) 1.32 + { 1.33 +tryagain: 1.34 + int numItems = archive.GetNumItems(); 1.35 + for(int i = 0; i < numItems; i++) 1.36 + { 1.37 + if(archive.GetItemSize(i)) 1.38 + { 1.39 + const char* name = archive.GetItemName(i); 1.40 + const char* ext = strrchr(name, '.'); 1.41 + bool ok = true; 1.42 + if(ext++) 1.43 + { 1.44 + for(int j = 0; j < numIgnoreExtensions; j++) 1.45 + { 1.46 + const char* ext2 = ignoreExtensions[j]; 1.47 + const char* wild = strchr(ext2, '*'); 1.48 + if(!wild) 1.49 + { 1.50 + if(!_stricmp(ext, ext2)) 1.51 + { 1.52 + ok = false; 1.53 + break; 1.54 + } 1.55 + } 1.56 + else // very limited (end only) wildcard support 1.57 + { 1.58 + if(!_strnicmp(ext, ext2, wild - ext2)) 1.59 + { 1.60 + ok = false; 1.61 + break; 1.62 + } 1.63 + } 1.64 + } 1.65 + } 1.66 + if(ok) 1.67 + { 1.68 + ArchiveFileChooserInfo::FileInfo fi = { name, i }; 1.69 + files.push_back(fi); 1.70 + } 1.71 + } 1.72 + } 1.73 + 1.74 + if(files.empty() && numIgnoreExtensions) 1.75 + { 1.76 + // try again without any exclusions if we excluded everything in the archive 1.77 + numIgnoreExtensions = 0; 1.78 + goto tryagain; 1.79 + } 1.80 + 1.81 + // strip away prefix paths that are common to all the files 1.82 + bool stripping = !files.empty(); 1.83 + while(stripping) 1.84 + { 1.85 + const char* firstName = files[0].name.c_str(); 1.86 + const char* slash = strchr(firstName, '\\'); 1.87 + const char* slash2 = strchr(firstName, '/'); 1.88 + slash = max(slash, slash2); 1.89 + if(!slash++) 1.90 + break; 1.91 + for(size_t i = 1; i < files.size(); i++) 1.92 + if(strncmp(firstName, files[i].name.c_str(), slash - firstName)) 1.93 + stripping = false; 1.94 + if(stripping) 1.95 + for(size_t i = 0; i < files.size(); i++) 1.96 + files[i].name = files[i].name.substr(slash - firstName, files[i].name.length() - (slash - firstName)); 1.97 + } 1.98 + 1.99 + // sort by filename 1.100 + std::sort(files.begin(), files.end(), FileInfo::Sort); 1.101 + } 1.102 + 1.103 +//protected: 1.104 + 1.105 + struct FileInfo 1.106 + { 1.107 + std::string name; 1.108 + int itemIndex; 1.109 + 1.110 + static bool Sort(const FileInfo& elem1, const FileInfo& elem2) 1.111 + { 1.112 + int comp = elem1.name.compare(elem2.name); 1.113 + return comp ? (comp < 0) : (elem1.itemIndex < elem2.itemIndex); 1.114 + } 1.115 + }; 1.116 + 1.117 + ArchiveFile& archive; 1.118 + std::vector<FileInfo> files; 1.119 +}; 1.120 + 1.121 +static void ClearLayoutStates(); 1.122 + 1.123 +int ChooseItemFromArchive(ArchiveFile& archive, bool autoChooseIfOnly1, const char** ignoreExtensions, int numIgnoreExtensions) 1.124 +{ 1.125 + int prevNumIgnoreExtensions = numIgnoreExtensions; 1.126 + archive.m_userMadeSelection = false; 1.127 + 1.128 + // prepare a list of files to choose from the archive 1.129 + ArchiveFileChooserInfo info (archive, ignoreExtensions, numIgnoreExtensions); 1.130 + 1.131 + // based on our list, decide which item in the archive to choose 1.132 + 1.133 + // check if there's nothing 1.134 + if(info.files.size() < 1) 1.135 + { 1.136 + MessageBox(GetArchiveParentHWND(), "The archive is either empty or encrypted.", "Nothing to load!", MB_OK | MB_ICONWARNING); 1.137 + return -1; 1.138 + } 1.139 + 1.140 + // warn if all the files in the archive have extensions we should ignore 1.141 + if(numIgnoreExtensions != prevNumIgnoreExtensions) 1.142 + { 1.143 + CString msg; 1.144 + msg.Format("The archive appears to only contain the wrong type of files.\n\n(in \"%s\")", archive.GetArchiveFileName()); 1.145 + int answer = MessageBox(GetArchiveParentHWND(), msg, "Warning", MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2); 1.146 + if(answer == IDCANCEL) 1.147 + return -1; 1.148 + } 1.149 + 1.150 + // if there's only 1 item, choose it 1.151 + if(info.files.size() == 1 && autoChooseIfOnly1 && numIgnoreExtensions == prevNumIgnoreExtensions) 1.152 + return info.files[0].itemIndex; 1.153 + 1.154 + // bring up a dialog to choose the index if there's more than 1 1.155 + DialogBoxParam(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDD_ARCHIVEFILECHOOSER), GetArchiveParentHWND(), (DLGPROC) ArchiveFileChooser,(LPARAM) &info); 1.156 + archive.m_userMadeSelection = (s_archiveFileChooserResult != -1); 1.157 + return s_archiveFileChooserResult; 1.158 +} 1.159 + 1.160 + 1.161 + 1.162 + 1.163 +#define DEFAULT_EXTENSION ".tmp" 1.164 +#define DEFAULT_CATEGORY "vba" 1.165 + 1.166 +static struct TempFiles 1.167 +{ 1.168 + struct TemporaryFile 1.169 + { 1.170 + TemporaryFile(const char* cat, const char* ext) 1.171 + { 1.172 + if(!ext || !*ext) ext = DEFAULT_EXTENSION; 1.173 + if(!cat || !*cat) cat = DEFAULT_CATEGORY; 1.174 + category = cat; 1.175 + 1.176 + char tempPath [2048]; 1.177 + GetTempPath(2048, tempPath); 1.178 + //GetTempFileName(tempPath, cat, 0, filename, ext); // alas 1.179 + 1.180 + char*const fname = tempPath + strlen(tempPath); 1.181 + unsigned short start = (unsigned short)(timeGetTime() & 0xFFFF); 1.182 + unsigned short n = start + 1; 1.183 + while(n != start) 1.184 + { 1.185 + _snprintf(fname, 2048 - (fname - tempPath), "%s%04X%s", cat, n, ext); 1.186 + FILE* file = fopen(tempPath, "wb"); 1.187 + if(file) 1.188 + { 1.189 + // mark the temporary file as read-only and (whatever this does) temporary 1.190 + DWORD attributes = GetFileAttributes(tempPath); 1.191 + attributes |= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_TEMPORARY; 1.192 + SetFileAttributes(tempPath, attributes); 1.193 + 1.194 + fclose(file); 1.195 + 1.196 + // add it to our registry of files that need to be deleted, in case we fail to terminate properly 1.197 + TempFiles::AddEntryToGarbageRegistry(tempPath); 1.198 + 1.199 + break; 1.200 + } 1.201 + n++; 1.202 + } 1.203 + strcpy(filename, tempPath); 1.204 + } 1.205 + TemporaryFile(const TemporaryFile& copy) 1.206 + { 1.207 + strcpy(filename, copy.filename); 1.208 + category = copy.category; 1.209 + } 1.210 + TemporaryFile() 1.211 + { 1.212 + filename[0] = 0; 1.213 + // category[0] = 0; // error 1.214 + } 1.215 + bool Delete(bool returnFalseOnRegistryRemovalFailure=false) 1.216 + { 1.217 + if(!*filename) 1.218 + return true; // guess it already didn't exist 1.219 + 1.220 + // remove read-only attribute so Windows will let us delete it 1.221 + // (our temporary files are read-only to discourage other apps from tampering) 1.222 + DWORD attributes = GetFileAttributes(filename); 1.223 + if(attributes & FILE_ATTRIBUTE_READONLY) 1.224 + SetFileAttributes(filename, attributes & ~FILE_ATTRIBUTE_READONLY); 1.225 + 1.226 + if(_unlink(filename) == 0 || errno != EACCES) 1.227 + { 1.228 + // remove it from our registry of files that need to be deleted, to reduce accumulation 1.229 + bool removed = TempFiles::RemoveEntryFromGarbageRegistry(filename); 1.230 + 1.231 + *filename = '\0'; 1.232 + return removed || !returnFalseOnRegistryRemovalFailure; // successfully deleted or already didn't exist, return true unless registry removal failure notification was requested and that failed 1.233 + } 1.234 + 1.235 + // restore read-only if we couldn't delete it (not sure if this ever succeeds or matters though) 1.236 + if(attributes & FILE_ATTRIBUTE_READONLY) 1.237 + SetFileAttributes(filename, attributes); 1.238 + 1.239 + return false; // failed to delete read-only or in-use file 1.240 + } 1.241 + char filename [MAX_PATH]; 1.242 + std::string category; 1.243 + }; 1.244 + 1.245 + std::vector<TemporaryFile> tempFiles; 1.246 + 1.247 + const char* GetFile(const char* category, const char* extension) 1.248 + { 1.249 + tempFiles.push_back(TemporaryFile(category, extension)); 1.250 + return tempFiles.back().filename; 1.251 + } 1.252 + 1.253 + void ReleaseFile(const char* filename) 1.254 + { 1.255 + for(int i = (int)tempFiles.size()-1; i >= 0; i--) 1.256 + { 1.257 + if(!strcmp(filename, tempFiles[i].filename)) 1.258 + { 1.259 + if(tempFiles[i].Delete()) 1.260 + tempFiles.erase(tempFiles.begin() + i); 1.261 + } 1.262 + } 1.263 + } 1.264 + 1.265 + void ReleaseCategory(const char* cat, const char* exceptionFilename) 1.266 + { 1.267 + for(int i = (int)tempFiles.size()-1; i >= 0; i--) 1.268 + { 1.269 + if(!strcmp(cat, tempFiles[i].category.c_str()) && 1.270 + (!exceptionFilename || 1.271 + strcmp(exceptionFilename, tempFiles[i].filename))) 1.272 + { 1.273 + if(tempFiles[i].Delete()) 1.274 + tempFiles.erase(tempFiles.begin() + i); 1.275 + } 1.276 + } 1.277 + } 1.278 + 1.279 + // delete all temporary files on shutdown 1.280 + ~TempFiles() 1.281 + { 1.282 + for(size_t i = 0; i < tempFiles.size(); i++) 1.283 + { 1.284 + tempFiles[i].Delete(); 1.285 + } 1.286 + 1.287 + TempFiles::CleanOutGarbageRegistry(); 1.288 + } 1.289 + 1.290 + // run this on startup to delete any files that we failed to delete last time 1.291 + // in case we crashed or were forcefully terminated 1.292 + TempFiles() 1.293 + { 1.294 + TempFiles::CleanOutGarbageRegistry(); 1.295 + } 1.296 + 1.297 + static void AddEntryToGarbageRegistry(const char* filename) 1.298 + { 1.299 + char gbgFile[2048]; 1.300 + GetTempPath(2048, gbgFile); 1.301 + strcat(gbgFile, "VBATempFileRecords"); 1.302 + char key[64]; 1.303 + int i = 0; 1.304 + while(true) 1.305 + { 1.306 + sprintf(key, "File%d", i); 1.307 + GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); 1.308 + if(!*Str_Tmp) 1.309 + break; 1.310 + i++; 1.311 + } 1.312 + WritePrivateProfileString("Files", key, filename, gbgFile); 1.313 + } 1.314 + static bool RemoveEntryFromGarbageRegistry(const char* filename) 1.315 + { 1.316 + char gbgFile[2048]; 1.317 + GetTempPath(2048, gbgFile); 1.318 + strcat(gbgFile, "VBATempFileRecords"); 1.319 + char key[64]; 1.320 + int i = 0; 1.321 + int deleteSlot = -1; 1.322 + while(true) 1.323 + { 1.324 + sprintf(key, "File%d", i); 1.325 + GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); 1.326 + if(!*Str_Tmp) 1.327 + break; 1.328 + if(!strcmp(Str_Tmp, filename)) 1.329 + deleteSlot = i; 1.330 + i++; 1.331 + } 1.332 + --i; 1.333 + if(i >= 0 && deleteSlot >= 0) 1.334 + { 1.335 + if(i != deleteSlot) 1.336 + { 1.337 + sprintf(key, "File%d", i); 1.338 + GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); 1.339 + sprintf(key, "File%d", deleteSlot); 1.340 + WritePrivateProfileString("Files", key, Str_Tmp, gbgFile); 1.341 + } 1.342 + sprintf(key, "File%d", i); 1.343 + if(0 == WritePrivateProfileString("Files", key, NULL, gbgFile)) 1.344 + return false; 1.345 + } 1.346 + if(i <= 0 && deleteSlot == 0) 1.347 + _unlink(gbgFile); 1.348 + return true; 1.349 + } 1.350 + 1.351 +private: 1.352 + static void CleanOutGarbageRegistry() 1.353 + { 1.354 + char gbgFile[2048]; 1.355 + GetTempPath(2048, gbgFile); 1.356 + strcat(gbgFile, "VBATempFileRecords"); 1.357 + 1.358 + char key[64]; 1.359 + int i = 0; 1.360 + while(true) 1.361 + { 1.362 + sprintf(key, "File%d", i); 1.363 + GetPrivateProfileString("Files", key, "", Str_Tmp, 2048, gbgFile); 1.364 + if(!*Str_Tmp) 1.365 + break; 1.366 + TemporaryFile temp; 1.367 + strcpy(temp.filename, Str_Tmp); 1.368 + if(!temp.Delete(true)) 1.369 + i++; 1.370 + } 1.371 + } 1.372 + 1.373 +} s_tempFiles; 1.374 + 1.375 + 1.376 +const char* GetTempFile(const char* category, const char* extension) 1.377 +{ 1.378 + return s_tempFiles.GetFile(category, extension); 1.379 +} 1.380 +void ReleaseTempFile(const char* filename) 1.381 +{ 1.382 + s_tempFiles.ReleaseFile(filename); 1.383 +} 1.384 +void ReleaseTempFileCategory(const char* cat, const char* exceptionFilename) 1.385 +{ 1.386 + if(!cat || !*cat) cat = DEFAULT_CATEGORY; 1.387 + s_tempFiles.ReleaseCategory(cat, exceptionFilename); 1.388 +} 1.389 + 1.390 + 1.391 + 1.392 +// example input Name: "C:\games.zip" 1.393 +// example output LogicalName: "C:\games.zip|Metroid.gba" 1.394 +// example output PhysicalName: "C:\Documents and Settings\User\Local Settings\Temp\VBA\rom7A37.gba" 1.395 +// assumes arguments are character buffers with 2048 bytes each 1.396 +bool ObtainFile(const char* Name, char *const & LogicalName, char *const & PhysicalName, const char* category, const char** ignoreExtensions, int numIgnoreExtensions) 1.397 +{ 1.398 +restart: 1.399 + char ArchivePaths [2048]; 1.400 + strcpy(LogicalName, Name); 1.401 + strcpy(PhysicalName, Name); 1.402 + strcpy(ArchivePaths, Name); 1.403 + char* bar = strchr(ArchivePaths, '|'); 1.404 + if(bar) 1.405 + { 1.406 + PhysicalName[bar - ArchivePaths] = 0; // doesn't belong in the physical name 1.407 + LogicalName[bar - ArchivePaths] = 0; // we'll reconstruct the logical name as we go 1.408 + *bar++ = 0; // bar becomes the next logical archive path component 1.409 + } 1.410 + 1.411 + bool userSelected = false; 1.412 + 1.413 + while(true) 1.414 + { 1.415 + ArchiveFile archive (PhysicalName, LogicalName); 1.416 + if(!archive.IsCompressed()) 1.417 + { 1.418 + if(archive.GetNumItems() > 0) 1.419 + return true; 1.420 + else 1.421 + { 1.422 + // failed or cancelled... backtrack to outermost archive if not already there 1.423 + char* div = NULL; 1.424 + if(LogicalName[strlen(LogicalName)-1] == '|') 1.425 + { 1.426 + LogicalName[strlen(LogicalName)-1] = '\0'; 1.427 + div = strrchr(LogicalName, '|'); 1.428 + } 1.429 + if(div && userSelected) 1.430 + goto restart; 1.431 + else 1.432 + return false; 1.433 + } 1.434 + } 1.435 + else 1.436 + { 1.437 + int item = -1; 1.438 + bool forceManual = false; 1.439 + if(bar && *bar) // try following the in-archive part of the logical path 1.440 + { 1.441 + char* bar2 = strchr(bar, '|'); 1.442 + if(bar2) *bar2++ = 0; 1.443 + int numItems = archive.GetNumItems(); 1.444 + for(int i = 0; i < numItems; i++) 1.445 + { 1.446 + if(archive.GetItemSize(i)) 1.447 + { 1.448 + const char* itemName = archive.GetItemName(i); 1.449 + if(!_stricmp(itemName, bar)) 1.450 + { 1.451 + item = i; // match found, now we'll auto-follow the path 1.452 + break; 1.453 + } 1.454 + } 1.455 + } 1.456 + if(item < 0) 1.457 + { 1.458 + forceManual = true; // we don't want it choosing something else without user permission 1.459 + bar = NULL; // remaining archive path is invalid 1.460 + } 1.461 + else 1.462 + bar = bar2; // advance to next archive path part 1.463 + } 1.464 + if(item < 0) 1.465 + item = ChooseItemFromArchive(archive, !forceManual, ignoreExtensions, numIgnoreExtensions); 1.466 + 1.467 + userSelected |= archive.m_userMadeSelection; 1.468 + 1.469 + const char* TempFileName = s_tempFiles.GetFile(category, strrchr(archive.GetItemName(item), '.')); 1.470 + if(!archive.ExtractItem(item, TempFileName)) 1.471 + s_tempFiles.ReleaseFile(TempFileName); 1.472 + s_tempFiles.ReleaseFile(PhysicalName); 1.473 + strcpy(PhysicalName, TempFileName); 1.474 + _snprintf(LogicalName + strlen(LogicalName), 2048 - (strlen(LogicalName)+1), "|%s", archive.GetItemName(item)); 1.475 + } 1.476 + } 1.477 +} 1.478 + 1.479 + 1.480 + 1.481 +struct ControlLayoutInfo 1.482 +{ 1.483 + int controlID; 1.484 + 1.485 + enum LayoutType // what to do when the containing window resizes 1.486 + { 1.487 + NONE, // leave the control where it was 1.488 + RESIZE_END, // resize the control 1.489 + MOVE_START, // move the control 1.490 + }; 1.491 + LayoutType horizontalLayout; 1.492 + LayoutType verticalLayout; 1.493 +}; 1.494 +struct ControlLayoutState 1.495 +{ 1.496 + int x,y,width,height; 1.497 + bool valid; 1.498 + ControlLayoutState() : valid(false) {} 1.499 +}; 1.500 + 1.501 +static ControlLayoutInfo controlLayoutInfos [] = { 1.502 + {IDC_LIST1, ControlLayoutInfo::RESIZE_END, ControlLayoutInfo::RESIZE_END}, 1.503 + {IDOK, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, 1.504 + {ID_CANCEL, ControlLayoutInfo::MOVE_START, ControlLayoutInfo::MOVE_START}, 1.505 +}; 1.506 +static const int numControlLayoutInfos = sizeof(controlLayoutInfos)/sizeof(*controlLayoutInfos); 1.507 + 1.508 +static ControlLayoutState s_layoutState [numControlLayoutInfos]; 1.509 +static int s_windowWidth = 182, s_windowHeight = 113; 1.510 + 1.511 + 1.512 +LRESULT CALLBACK ArchiveFileChooser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 1.513 +{ 1.514 + RECT r, r2; 1.515 + int dx1, dy1, dx2, dy2; 1.516 + static std::map<int,int> s_listToItemsMap; 1.517 + 1.518 + switch(uMsg) 1.519 + { 1.520 + case WM_INITDIALOG: 1.521 + { 1.522 + //Clear_Sound_Buffer(); 1.523 + 1.524 + //if(Full_Screen) 1.525 + //{ 1.526 + // while (ShowCursor(false) >= 0); 1.527 + // while (ShowCursor(true) < 0); 1.528 + //} 1.529 + 1.530 + for(int i = 0; i < numControlLayoutInfos; i++) 1.531 + s_layoutState[i].valid = false; 1.532 + 1.533 + GetWindowRect(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), &r); 1.534 + dx1 = (r.right - r.left) / 2; 1.535 + dy1 = (r.bottom - r.top) / 2; 1.536 + 1.537 + GetWindowRect(hDlg, &r2); 1.538 + dx2 = (r2.right - r2.left) / 2; 1.539 + dy2 = (r2.bottom - r2.top) / 2; 1.540 + 1.541 + //SetWindowPos(hDlg, NULL, max(0, r.left + (dx1 - dx2)), max(0, r.top + (dy1 - dy2)), NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); 1.542 + SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); 1.543 + 1.544 + ArchiveFileChooserInfo& info = *(ArchiveFileChooserInfo*)lParam; 1.545 + std::vector<ArchiveFileChooserInfo::FileInfo>& files = info.files; 1.546 + ArchiveFile& archive = info.archive; 1.547 + 1.548 + std::string title = "Choose File in "; 1.549 + title += archive.GetArchiveTypeName(); 1.550 + title += " Archive"; 1.551 + SetWindowText(hDlg, title.c_str()); 1.552 + 1.553 + // populate list 1.554 + for(size_t i = 0; i < files.size(); i++) 1.555 + { 1.556 + int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_ADDSTRING, (WPARAM) 0, (LONG) (LPTSTR) files[i].name.c_str()); 1.557 + s_listToItemsMap[listIndex] = files[i].itemIndex; 1.558 + } 1.559 + 1.560 + SendDlgItemMessage(hDlg, IDC_LIST1, LB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); 1.561 + 1.562 + { 1.563 + RECT r3; 1.564 + GetClientRect(hDlg, &r3); 1.565 + s_windowWidth = r3.right - r3.left; 1.566 + s_windowHeight = r3.bottom - r3.top; 1.567 + } 1.568 + 1.569 + return true; 1.570 + } break; 1.571 + 1.572 + case WM_SIZING: 1.573 + { 1.574 + // enforce a minimum window size 1.575 + 1.576 + LPRECT r = (LPRECT) lParam; 1.577 + int minimumWidth = 281; 1.578 + int minimumHeight = 117; 1.579 + if(r->right - r->left < minimumWidth) 1.580 + if(wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT || wParam == WMSZ_BOTTOMLEFT) 1.581 + r->left = r->right - minimumWidth; 1.582 + else 1.583 + r->right = r->left + minimumWidth; 1.584 + if(r->bottom - r->top < minimumHeight) 1.585 + if(wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT) 1.586 + r->top = r->bottom - minimumHeight; 1.587 + else 1.588 + r->bottom = r->top + minimumHeight; 1.589 + return TRUE; 1.590 + } 1.591 + 1.592 + case WM_SIZE: 1.593 + { 1.594 + // resize or move controls in the window as necessary when the window is resized 1.595 + 1.596 + int prevDlgWidth = s_windowWidth; 1.597 + int prevDlgHeight = s_windowHeight; 1.598 + 1.599 + int dlgWidth = LOWORD(lParam); 1.600 + int dlgHeight = HIWORD(lParam); 1.601 + 1.602 + int deltaWidth = dlgWidth - prevDlgWidth; 1.603 + int deltaHeight = dlgHeight - prevDlgHeight; 1.604 + 1.605 + for(int i = 0; i < numControlLayoutInfos; i++) 1.606 + { 1.607 + ControlLayoutInfo layoutInfo = controlLayoutInfos[i]; 1.608 + ControlLayoutState& layoutState = s_layoutState[i]; 1.609 + 1.610 + HWND hCtrl = GetDlgItem(hDlg,layoutInfo.controlID); 1.611 + 1.612 + int x,y,width,height; 1.613 + if(layoutState.valid) 1.614 + { 1.615 + x = layoutState.x; 1.616 + y = layoutState.y; 1.617 + width = layoutState.width; 1.618 + height = layoutState.height; 1.619 + } 1.620 + else 1.621 + { 1.622 + RECT r; 1.623 + GetWindowRect(hCtrl, &r); 1.624 + POINT p = {r.left, r.top}; 1.625 + ScreenToClient(hDlg, &p); 1.626 + x = p.x; 1.627 + y = p.y; 1.628 + width = r.right - r.left; 1.629 + height = r.bottom - r.top; 1.630 + } 1.631 + 1.632 + switch(layoutInfo.horizontalLayout) 1.633 + { 1.634 + case ControlLayoutInfo::RESIZE_END: width += deltaWidth; break; 1.635 + case ControlLayoutInfo::MOVE_START: x += deltaWidth; break; 1.636 + default: break; 1.637 + } 1.638 + switch(layoutInfo.verticalLayout) 1.639 + { 1.640 + case ControlLayoutInfo::RESIZE_END: height += deltaHeight; break; 1.641 + case ControlLayoutInfo::MOVE_START: y += deltaHeight; break; 1.642 + default: break; 1.643 + } 1.644 + 1.645 + SetWindowPos(hCtrl, 0, x,y, width,height, 0); 1.646 + 1.647 + layoutState.x = x; 1.648 + layoutState.y = y; 1.649 + layoutState.width = width; 1.650 + layoutState.height = height; 1.651 + layoutState.valid = true; 1.652 + } 1.653 + 1.654 + s_windowWidth = dlgWidth; 1.655 + s_windowHeight = dlgHeight; 1.656 + 1.657 + RedrawWindow(hDlg, NULL, NULL, RDW_INVALIDATE); 1.658 + } 1.659 + break; 1.660 + 1.661 + case WM_COMMAND: 1.662 + switch(LOWORD(wParam)) 1.663 + { 1.664 + case IDC_LIST1: 1.665 + if(HIWORD(wParam) == LBN_DBLCLK) 1.666 + { 1.667 + POINT pos; 1.668 + GetCursorPos(&pos); 1.669 + int clickedItem = LBItemFromPt(GetDlgItem(hDlg, IDC_LIST1), pos, FALSE); 1.670 + if(clickedItem != -1) 1.671 + { 1.672 + SendMessage(hDlg, WM_COMMAND, IDOK, 0); 1.673 + } 1.674 + } 1.675 + return TRUE; 1.676 + 1.677 + case IDOK: 1.678 + { 1.679 + int listIndex = SendDlgItemMessage(hDlg, IDC_LIST1, LB_GETCURSEL, (WPARAM) 0, (LPARAM) 0); 1.680 + s_archiveFileChooserResult = s_listToItemsMap[listIndex]; 1.681 + s_listToItemsMap.clear(); 1.682 + //if(Full_Screen) 1.683 + //{ 1.684 + // while (ShowCursor(true) < 0); 1.685 + // while (ShowCursor(false) >= 0); 1.686 + //} 1.687 + EndDialog(hDlg, false); 1.688 + } return TRUE; 1.689 + 1.690 + case ID_CANCEL: 1.691 + case IDCANCEL: 1.692 + s_archiveFileChooserResult = -1; 1.693 + s_listToItemsMap.clear(); 1.694 + //if(Full_Screen) 1.695 + //{ 1.696 + // while (ShowCursor(true) < 0); 1.697 + // while (ShowCursor(false) >= 0); 1.698 + //} 1.699 + EndDialog(hDlg, false); 1.700 + return TRUE; 1.701 + } 1.702 + 1.703 + case WM_CLOSE: 1.704 + s_archiveFileChooserResult = -1; 1.705 + s_listToItemsMap.clear(); 1.706 + //if(Full_Screen) 1.707 + //{ 1.708 + // while (ShowCursor(true) < 0); 1.709 + // while (ShowCursor(false) >= 0); 1.710 + //} 1.711 + EndDialog(hDlg, false); 1.712 + return TRUE; 1.713 + } 1.714 + 1.715 + return false; 1.716 +}