// Vance Thrift and Biller File Utility 2 // // Douglas Thrift // // $Id: DiscBrowse.cxx,v 1.12 2003/09/12 04:26:54 douglas Exp $ #include "DiscBrowse.h" DiscBrowse::DiscBrowse() { number = count++; browsers.insert(pair(number, this)); title = programName + " - Disc Browse"; popup = CreatePopupMenu(); MENUITEMINFO open, separator, properties; open.cbSize = sizeof(open); open.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE; open.fType = MFT_STRING; open.fState = MFS_DEFAULT; open.wID = 1; open.dwTypeData = "&Open"; open.cch = 5; separator.cbSize = sizeof(open); separator.fMask = MIIM_TYPE; separator.fType = MFT_SEPARATOR; properties.cbSize = sizeof(open); properties.fMask = MIIM_ID | MIIM_TYPE; properties.fType = MFT_STRING; properties.wID = 2; properties.dwTypeData = "P&roperties"; properties.cch = 11; InsertMenuItem(popup, 0, TRUE, &open); InsertMenuItem(popup, 1, TRUE, &separator); InsertMenuItem(popup, 2, TRUE, &properties); // start wizard[0].dwSize = sizeof(wizard[0]); wizard[0].dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; wizard[0].hInstance = gui.instance; wizard[0].pszTemplate = MAKEINTRESOURCE(IDD_BEGIN); wizard[0].pszTitle = title.c_str(); wizard[0].pfnDlgProc = start; wizard[0].lParam = number; wizard[0].pszHeaderTitle = "Start"; wizard[0].pszHeaderSubTitle = "Change any settings before browsing."; // browse wizard[1].dwSize = sizeof(wizard[1]); wizard[1].dwFlags = PSP_DEFAULT | PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; wizard[1].hInstance = gui.instance; wizard[1].pszTemplate = MAKEINTRESOURCE(IDD_BROWSE); wizard[1].pszTitle = title.c_str(); wizard[1].pfnDlgProc = browse; wizard[1].lParam = number; wizard[1].pszHeaderTitle = "Browse"; wizard[1].pszHeaderSubTitle = "View documents on the disc."; } DiscBrowse::~DiscBrowse() { DestroyMenu(popup); browsers.erase(number); } void DiscBrowse::run(void) { loadDir(); PROPSHEETHEADER header; // header header.dwSize = sizeof(header); header.dwFlags = PSH_DEFAULT | PSH_HEADER | PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_WIZARD97 | PSH_WIZARDHASFINISH; header.hwndParent = NULL; header.hInstance = gui.instance; header.pszIcon = MAKEINTRESOURCE(IDI_VTB_ICON); header.nPages = 2; header.nStartPage = 0; header.ppsp = wizard; header.pszbmHeader = MAKEINTRESOURCE(IDB_VTB_BMP); PropertySheet(&header); saveDir(); } unsigned DiscBrowse::count = 0; map DiscBrowse::browsers; map DiscBrowse::windows; void DiscBrowse::loadDir(void) { HKEY key; if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\DouglasThrift\\VTBFileUtil2", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { DWORD type; char data[MAX_PATH]; DWORD size = MAX_PATH; if (RegQueryValueEx(key, "DiscDir", NULL, &type, LPBYTE(data), &size) == ERROR_SUCCESS) { data[size - 1] = '\0'; switch (type) { case REG_EXPAND_SZ: { char folder[MAX_PATH]; ExpandEnvironmentStrings(data, folder, MAX_PATH); discDir = tail(folder); } break; case REG_SZ: discDir = tail(data); break; default: setDiscDir(); break; } } else { setDiscDir(); } RegCloseKey(key); } else { setDiscDir(); } if (debug) cerr << "discDir = " << discDir << "\n"; } void DiscBrowse::saveDir(void) { HKEY key; if (LONG code = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\DouglasThrift\\VTBFileUtil2", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &key, NULL) == ERROR_SUCCESS) { DWORD type; char data[MAX_PATH]; DWORD size = MAX_PATH; if (RegQueryValueEx(key, "DiscDir", NULL, &type, LPBYTE(data), &size) == ERROR_SUCCESS) { data[size - 1] = '\0'; } else { data[0] = '\0'; } if (discDir != data || type != REG_SZ) { if (code = RegSetValueEx(key, "DiscDir", 0, REG_SZ, LPBYTE(discDir.c_str()), discDir.length() + 1) != ERROR_SUCCESS) { error(NULL, code); } } RegCloseKey(key); } else { error(NULL, code); } } void DiscBrowse::setDiscDir(HWND parent) { char buffer[MAX_PATH]; SHGetFolderPath(parent, CSIDL_FLAG_CREATE | CSIDL_DESKTOPDIRECTORY, NULL, 0, buffer); BROWSEINFO info; info.hwndOwner = parent; info.pidlRoot = NULL; info.pszDisplayName = NULL; info.lpszTitle = "Select the Disc"; info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; info.lpfn = browse; info.lParam = MAKELPARAM(number, true); info.iImage = 0; do { LPITEMIDLIST id = SHBrowseForFolder(&info); if (id != NULL) { char folder[MAX_PATH]; if (SHGetPathFromIDList(id, folder)) discDir = tail(folder); LPMALLOC destruct; SHGetMalloc(&destruct); destruct->Free(id); destruct->Release(); } if (discDir == "") { switch (MessageBox(parent, "Disc needs to be selected.", title.c_str(), MB_ABORTRETRYIGNORE | MB_ICONERROR)) { case IDABORT: exit(1); break; case IDRETRY: break; case IDIGNORE: Beep(2200, 250); Beep(1100, 500); Beep(3300, 250); exit(2); break; } } } while (discDir == ""); if (debug) cerr << "discDir = " << discDir << "\n"; } void DiscBrowse::populate(HWND parent) { set clients; do { string client = discDir + "*_*." + IndividualClient::getExtension(); WIN32_FIND_DATA found; HANDLE finder = FindFirstFile(client.c_str(), &found); if (finder != INVALID_HANDLE_VALUE) { do { clients.insert(IndividualClient(found.cFileName)); } while (FindNextFile(finder, &found)); FindClose(finder); } if (clients.empty()) { if (MessageBox(parent, "No client documents found.", title.c_str(), MB_RETRYCANCEL | MB_ICONQUESTION) == IDCANCEL) break; } } while (clients.empty()); if (clients.empty()) { PropSheet_PressButton(GetParent(parent), PSBTN_BACK); } else { SHFILEINFO info; HIMAGELIST icons = HIMAGELIST(SHGetFileInfo((*clients.begin()).getFile().c_str(), 0, &info, sizeof(info), SHGFI_SMALLICON | SHGFI_SYSICONINDEX)); ListView_SetImageList(GetDlgItem(parent, IDC_BROWSE_DISC), icons, LVSIL_SMALL); if (debug) cerr << "clients = {\n"; for (set::iterator itor = clients.begin(); itor != clients.end(); itor++) { IndividualClient client = *itor; if (debug) cerr << " {\n" << " number = " << client.getNumber() << "\n" << " name = " << client.getName() << "\n" << " file = " << client.getFile() << "\n" << " }\n"; char clientFile[MAX_PATH], clientNumber[MAX_PATH], clientName[MAX_PATH], clientSize[MAX_PATH]; HANDLE fileSize = CreateFile(client.getFile().c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DWORD bytes = GetFileSize(fileSize, NULL); CloseHandle(fileSize); StringCchPrintf(clientFile, MAX_PATH, "%s", client.getFile().c_str()); StringCchPrintf(clientNumber, MAX_PATH, "%u", client.getNumber()); StringCchPrintf(clientName, MAX_PATH, "%s", client.getName().c_str()); StringCchPrintf(clientSize, MAX_PATH, "%.2f MB", FLOAT(bytes) / FLOAT(1024 * 1024)); LVITEM number, name, file, size; file.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT; file.iItem = 0; file.iSubItem = 0; file.pszText = clientFile; file.iImage = info.iIcon; file.lParam = bytes; int item = ListView_InsertItem(GetDlgItem(parent, IDC_BROWSE_DISC), &file); number.mask = LVIF_TEXT; number.iItem = item; number.iSubItem = 1; number.pszText = clientNumber; name.mask = LVIF_TEXT; name.iItem = item; name.iSubItem = 2; name.pszText = clientName; size.mask = LVIF_TEXT; size.iItem = item; size.iSubItem = 3; size.pszText = clientSize; ListView_SetItem(GetDlgItem(parent, IDC_BROWSE_DISC), &number); ListView_SetItem(GetDlgItem(parent, IDC_BROWSE_DISC), &name); ListView_SetItem(GetDlgItem(parent, IDC_BROWSE_DISC), &size); } if (debug) cerr << "}\n"; Thing thing; sortFile = true, sortNumber = true, sortName = true, sortSize = true; thing.index = 1; thing.order = sortNumber; thing.list = GetDlgItem(parent, IDC_BROWSE_DISC); sortNumber = !sortNumber; ListView_SortItemsEx(thing.list, sort, &thing); } } DiscBrowse* DiscBrowse::which(HWND window) { map::iterator itor = windows.find(window); return itor->second; } DiscBrowse* DiscBrowse::which(HWND window, LPARAM l) { LPPROPSHEETPAGE page = LPPROPSHEETPAGE(l); map::iterator itor = browsers.find(page->lParam); windows.insert(pair(window, itor->second)); return itor->second; } int DiscBrowse::browse(HWND dialog, UINT msg, LPARAM l, LPARAM d) { map::iterator itor = browsers.find(LOWORD(d)); DiscBrowse* data = itor->second; switch (msg) { case BFFM_INITIALIZED: center(dialog); SendMessage(dialog, BFFM_SETOKTEXT, 0, LPARAM(toWide("&Select").c_str())); SendMessage(dialog, BFFM_SETEXPANDED, FALSE, CSIDL_DRIVES); if (data->discDir != "") { IShellFolder* desktop; LPWSTR path = new WCHAR[data->discDir.length() + 1]; LPITEMIDLIST id; StringCchPrintfW(path, data->discDir.length() + 1, L"%s", toWide(data->discDir).c_str()); if (debug) cerr << "path = " << toAnsi(path) << "\n"; SHGetDesktopFolder(&desktop); desktop->ParseDisplayName(dialog, NULL, path, NULL, &id, NULL); if (id != NULL) { SendMessage(dialog, BFFM_SETSELECTION, FALSE, LPARAM(id)); LPMALLOC destruct; SHGetMalloc(&destruct); destruct->Free(id); destruct->Release(); } desktop->Release(); } break; case BFFM_SELCHANGED: { SHFILEINFO info; SHGetFileInfo(LPCSTR(l), 0, &info, sizeof(info), SHGFI_DISPLAYNAME | SHGFI_PIDL); SendMessage(dialog, BFFM_SETSTATUSTEXT, 0, LPARAM(info.szDisplayName)); char folder[MAX_PATH]; if (!SHGetPathFromIDList(LPCITEMIDLIST(l), folder)) { SendMessage(dialog, BFFM_ENABLEOK, 0, 0); } } break; } return 0; } int DiscBrowse::sort(LPARAM first, LPARAM second, LPARAM l) { Thing* thing = (Thing*)(l); switch (thing->index) { case 0: { char one[MAX_PATH], two[MAX_PATH]; ListView_GetItemText(thing->list, first, 0, one, MAX_PATH); ListView_GetItemText(thing->list, second, 0, two, MAX_PATH); string first = one, second = two; if (first < second) { return thing->order ? -1 : 1; } else if (first > second) { return thing->order ? 1 : -1; } } break; case 1: { char one[MAX_PATH], two[MAX_PATH]; ListView_GetItemText(thing->list, first, 0, one, MAX_PATH); ListView_GetItemText(thing->list, second, 0, two, MAX_PATH); IndividualClient first(one), second(two); if (first < second) { return thing->order ? -1 : 1; } else if (first > second) { return thing->order ? 1 : -1; } } break; case 2: { char one[MAX_PATH], two[MAX_PATH]; ListView_GetItemText(thing->list, first, 2, one, MAX_PATH); ListView_GetItemText(thing->list, second, 2, two, MAX_PATH); if (mcLess(one, two)) { return thing->order ? -1 : 1; } else if (mcGreater(one, two)) { return thing->order ? 1 : -1; } } break; case 3: if (first < second) { return thing->order ? -1 : 1; } else if (first > second) { return thing->order ? 1 : -1; } break; } return 0; } INT_PTR DiscBrowse::start(HWND dialog, UINT msg, WPARAM w, LPARAM l) { DiscBrowse* data = which(dialog); switch (msg) { case WM_INITDIALOG: center(GetParent(dialog)); SendMessage(GetParent(dialog), WM_SETICON, ICON_BIG, LPARAM(gui.icon)); data = which(dialog, l); break; case WM_NOTIFY: { LPNMHDR nm = LPNMHDR(l); switch (nm->code) { case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(dialog), PSWIZB_FINISH | PSWIZB_NEXT); { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_ICONLOCATION); HICON icon = ExtractIcon(gui.instance, info.szDisplayName, info.iIcon); SendDlgItemMessage(dialog, IDC_BEGIN_ICON, STM_SETIMAGE, IMAGE_ICON, LPARAM(icon)); } { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME); SetDlgItemText(dialog, IDC_BEGIN_TEXT, info.szDisplayName); } break; case PSN_WIZNEXT: SetCurrentDirectory(data->discDir.c_str()); break; } } break; case WM_COMMAND: switch (LOWORD(w)) { case IDC_BEGIN_BROWSE: data->setDiscDir(dialog); { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_ICONLOCATION); HICON icon = ExtractIcon(gui.instance, info.szDisplayName, info.iIcon); SendDlgItemMessage(dialog, IDC_BEGIN_ICON, STM_SETIMAGE, IMAGE_ICON, LPARAM(icon)); } { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME); SetDlgItemText(dialog, IDC_BEGIN_TEXT, info.szDisplayName); } break; } } return FALSE; } INT_PTR DiscBrowse::browse(HWND dialog, UINT msg, WPARAM w, LPARAM l) { DiscBrowse* data = which(dialog); int previous = -1; switch (msg) { case WM_INITDIALOG: data = which(dialog, l); ListView_SetExtendedListViewStyleEx(GetDlgItem(dialog, IDC_BROWSE_DISC), LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP); { LVCOLUMN file, number, name, size; file.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; file.fmt = LVCFMT_IMAGE; file.cx = 224; file.pszText = "File Name"; number.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; number.cx = 56; number.pszText = "Number"; number.iSubItem = 1; name.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; name.cx = 152; name.pszText = "Client Name"; name.iSubItem = 2; size.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; size.cx = 68; size.pszText = "Size"; size.iSubItem = 3; ListView_InsertColumn(GetDlgItem(dialog, IDC_BROWSE_DISC), 0, &file); ListView_InsertColumn(GetDlgItem(dialog, IDC_BROWSE_DISC), 1, &number); ListView_InsertColumn(GetDlgItem(dialog, IDC_BROWSE_DISC), 2, &name); ListView_InsertColumn(GetDlgItem(dialog, IDC_BROWSE_DISC), 3, &size); } { int columns[4]; columns[0] = 1; columns[1] = 2; columns[2] = 0; columns[3] = 3; ListView_SetColumnOrderArray(GetDlgItem(dialog, IDC_BROWSE_DISC), 4, columns); } break; case WM_NOTIFY: if (w == IDC_BROWSE_DISC) { LPNMITEMACTIVATE ni = LPNMITEMACTIVATE(l); switch (ni->hdr.code) { case LVN_COLUMNCLICK: { Thing thing; thing.index = ni->iSubItem; switch (thing.index) { case 0: thing.order = data->sortFile; data->sortFile = !data->sortFile; break; case 1: thing.order = data->sortNumber; data->sortNumber = !data->sortNumber; break; case 2: thing.order = data->sortName; data->sortName = !data->sortName; break; case 3: thing.order = data->sortSize; data->sortSize = !data->sortSize; break; } thing.list = GetDlgItem(dialog, IDC_BROWSE_DISC); if (ni->iSubItem == 3) { ListView_SortItems(thing.list, sort, &thing); } else { ListView_SortItemsEx(thing.list, sort, &thing); } } break; case LVN_ITEMCHANGED: if (ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), -1, LVNI_SELECTED) != -1) { EnableWindow(GetDlgItem(dialog, IDC_BROWSE_OPEN), TRUE); EnableWindow(GetDlgItem(dialog, IDC_BROWSE_PROP), TRUE); } else { EnableWindow(GetDlgItem(dialog, IDC_BROWSE_OPEN), FALSE); EnableWindow(GetDlgItem(dialog, IDC_BROWSE_PROP), FALSE); } break; case NM_DBLCLK: if (ni->iItem != -1) { char scan[MAX_PATH]; ListView_GetItemText(GetDlgItem(dialog, IDC_BROWSE_DISC), ni->iItem, 0, scan, MAX_PATH); ShellExecute(dialog, NULL, scan, NULL, NULL, SW_SHOWDEFAULT); } break; } } else { LPNMHDR nm = LPNMHDR(l); switch (nm->code) { case PSN_SETACTIVE: PropSheet_SetWizButtons(GetParent(dialog), PSWIZB_BACK | PSWIZB_FINISH); data->populate(dialog); { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_ICONLOCATION); HICON icon = ExtractIcon(gui.instance, info.szDisplayName, info.iIcon); SendDlgItemMessage(dialog, IDC_BROWSE_ICON, STM_SETIMAGE, IMAGE_ICON, LPARAM(icon)); } { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME); SetDlgItemText(dialog, IDC_BROWSE_TEXT, info.szDisplayName); } break; case PSN_WIZBACK: EnableWindow(GetDlgItem(dialog, IDC_BROWSE_OPEN), FALSE); EnableWindow(GetDlgItem(dialog, IDC_BROWSE_PROP), FALSE); ListView_DeleteAllItems(GetDlgItem(dialog, IDC_BROWSE_DISC)); break; } } break; case WM_COMMAND: switch (LOWORD(w)) { case IDC_BROWSE_REFRESH: EnableWindow(GetDlgItem(dialog, IDC_BROWSE_OPEN), FALSE); EnableWindow(GetDlgItem(dialog, IDC_BROWSE_PROP), FALSE); ListView_DeleteAllItems(GetDlgItem(dialog, IDC_BROWSE_DISC)); data->populate(dialog); { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_ICONLOCATION); HICON icon = ExtractIcon(gui.instance, info.szDisplayName, info.iIcon); SendDlgItemMessage(dialog, IDC_BROWSE_ICON, STM_SETIMAGE, IMAGE_ICON, LPARAM(icon)); } { SHFILEINFO info; SHGetFileInfo(data->discDir.c_str(), 0, &info, sizeof(info), SHGFI_DISPLAYNAME); SetDlgItemText(dialog, IDC_BROWSE_TEXT, info.szDisplayName); } break; case IDC_BROWSE_OPEN: do { char scan[MAX_PATH]; int index = ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), previous, LVNI_SELECTED); previous = index; if (previous == -1) continue; ListView_GetItemText(GetDlgItem(dialog, IDC_BROWSE_DISC), index, 0, scan, MAX_PATH); ShellExecute(dialog, NULL, scan, NULL, NULL, SW_SHOWDEFAULT); } while (previous != -1); break; case IDC_BROWSE_PROP: do { char scan[MAX_PATH]; int index = ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), previous, LVNI_SELECTED); previous = index; if (previous == -1) continue; ListView_GetItemText(GetDlgItem(dialog, IDC_BROWSE_DISC), index, 0, scan, MAX_PATH); SHELLEXECUTEINFO info; info.cbSize = sizeof(info); info.fMask = SEE_MASK_INVOKEIDLIST; info.hwnd = dialog; info.lpVerb = "properties"; info.lpFile = scan; info.lpParameters = NULL; info.lpDirectory = NULL; info.nShow = SW_SHOWDEFAULT; info.lpIDList = NULL; ShellExecuteEx(&info); } while (previous != -1); break; } break; case WM_CONTEXTMENU: if (ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), -1, LVNI_SELECTED) != -1) { POINT spot; LVHITTESTINFO test; test.pt.x = GET_X_LPARAM(l); test.pt.y = GET_Y_LPARAM(l); ScreenToClient(GetDlgItem(dialog, IDC_BROWSE_DISC), &test.pt); ListView_HitTest(GetDlgItem(dialog, IDC_BROWSE_DISC), &test); if (test.iItem != -1) { spot.x = test.pt.x; spot.y = test.pt.y; } else if (GET_X_LPARAM(l) == -1 && GET_Y_LPARAM(l) == -1) { int index = ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), -1, LVNI_SELECTED); RECT rect; ListView_EnsureVisible(GetDlgItem(dialog, IDC_BROWSE_DISC), index, FALSE); ListView_GetItemRect(GetDlgItem(dialog, IDC_BROWSE_DISC), index, &rect, LVIR_SELECTBOUNDS); spot.x = rect.left; spot.y = rect.top; } ClientToScreen(GetDlgItem(dialog, IDC_BROWSE_DISC), &spot); int code = TrackPopupMenuEx(data->popup, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON, spot.x, spot.y, GetDlgItem(dialog, IDC_BROWSE_DISC), NULL); switch (code) { case 1: do { char scan[MAX_PATH]; int index = ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), previous, LVNI_SELECTED); previous = index; if (previous == -1) continue; ListView_GetItemText(GetDlgItem(dialog, IDC_BROWSE_DISC), index, 0, scan, MAX_PATH); ShellExecute(dialog, NULL, scan, NULL, NULL, SW_SHOWDEFAULT); } while (previous != -1); break; case 2: do { char scan[MAX_PATH]; int index = ListView_GetNextItem(GetDlgItem(dialog, IDC_BROWSE_DISC), previous, LVNI_SELECTED); previous = index; if (previous == -1) continue; ListView_GetItemText(GetDlgItem(dialog, IDC_BROWSE_DISC), index, 0, scan, MAX_PATH); SHELLEXECUTEINFO info; info.cbSize = sizeof(info); info.fMask = SEE_MASK_INVOKEIDLIST; info.hwnd = dialog; info.lpVerb = "properties"; info.lpFile = scan; info.lpParameters = NULL; info.lpDirectory = NULL; info.nShow = SW_SHOWDEFAULT; info.lpIDList = NULL; ShellExecuteEx(&info); } while (previous != -1); break; } } break; } return FALSE; }