#include "kncedlg.h" #include #include #include #ifdef UNICODE namespace std { typedef wstring tstring; } #else namespace std { typedef string tstring; } #endif using namespace std; enum { IDC_CHOOSE_FILE_FILE_LIST = 101, IDC_CHOOSE_FILE_CURRENT_DIRECTORY_LABEL = 102, IDC_CHOOSE_FILE_DIRECTORY_LIST = 103, IDC_CHOOSE_FILE_FILE_NAME_BOX = 104, IDC_CHOOSE_FILE_TYPE_COMBO = 105 }; static BOOL WINAPI dlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); static bool onInitDialog(HWND hDlg, void *createStruct); static void onOk(HWND hDlg); static void onCancel(HWND hDlg); static void onFileList(HWND hDlg, int event); static void onDirectoryList(HWND hDlg, int event); static void onTypeCombo(HWND hDlg, int event); static void onFileNameBox(HWND hDlg, int event); static void updateFileList(HWND hDlg); static void split(vector &result, const tstring &str, const tstring &delim); static tstring appendFileExtension(const tstring &fileName, const tstring &pat); extern HINSTANCE g_hInstance; struct KnceFileDlgData { KnceChooseFileParams *chooseFileParams; vector > filters; tstring currentPath; bool eventProcessing; }; bool showChooseFileDialog(HWND hOwnerWindow, KnceChooseFileParams *params) { int ret = DialogBoxParam(g_hInstance, _T("CHOOSE_FILE"), hOwnerWindow, (DLGPROC)dlgProc, (LPARAM)params); return ret == IDOK; } static BOOL WINAPI dlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: return onInitDialog(hDlg, (void *)lParam); case WM_COMMAND: { int id = LOWORD(wParam); int event = HIWORD(wParam); switch (id) { case IDOK: onOk(hDlg); break; case IDCANCEL: onCancel(hDlg); break; case IDC_CHOOSE_FILE_FILE_LIST: onFileList(hDlg, event); break; case IDC_CHOOSE_FILE_DIRECTORY_LIST: onDirectoryList(hDlg, event); break; case IDC_CHOOSE_FILE_FILE_NAME_BOX: onFileNameBox(hDlg, event); break; case IDC_CHOOSE_FILE_TYPE_COMBO: onTypeCombo(hDlg, event); break; default: return false; } return true; } } return false; } static bool onInitDialog(HWND hDlg, void *params) { int i; KnceFileDlgData *data = new KnceFileDlgData(); SetWindowLong(hDlg, GWL_USERDATA, (long)data); data->chooseFileParams = (KnceChooseFileParams *)params; data->eventProcessing = false; KnceUtil::adjustDialogLayout(hDlg); vector filterParts; split(filterParts, data->chooseFileParams->filters, _T("|")); int numFilters = filterParts.size() / 2; for (i = 0; i < numFilters; i++) { data->filters.push_back(make_pair(filterParts[i * 2], filterParts[i * 2 + 1])); } HWND hFileList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_LIST); HWND hFileNameBox = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_NAME_BOX); if (data->chooseFileParams->isSaveFile) { SetWindowText(hDlg, _T("Save File")); unsigned long style = GetWindowLong(hFileList, GWL_STYLE); SetWindowLong(hFileList, GWL_STYLE, style | LBS_NOSEL); SetWindowPos(hFileList, NULL, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED)); } else { ShowWindow(hFileNameBox, SW_HIDE); RECT nameRect; GetWindowRect(hFileNameBox, &nameRect); RECT listRect; GetWindowRect(hFileList, &listRect); SetWindowPos(hFileList, NULL, 0, 0, listRect.right - listRect.left, nameRect.bottom - listRect.top, SWP_NOMOVE | SWP_NOZORDER); } HWND hTypeCombo = GetDlgItem(hDlg, IDC_CHOOSE_FILE_TYPE_COMBO); for (i = 0; i < numFilters; i++) { SendMessage(hTypeCombo, CB_ADDSTRING, 0, (LPARAM)data->filters[i].first.c_str()); } if (numFilters > 0) SendMessage(hTypeCombo, CB_SETCURSEL, 0, 0); tstring fileName; tstring filePath = data->chooseFileParams->fileName; if (filePath.empty()) { data->currentPath = data->chooseFileParams->initialPath; if (data->currentPath.empty()) data->currentPath = _T("\\"); } else { int pos = filePath.rfind(_T('\\')); if (pos == 0) data->currentPath = _T("\\"); else data->currentPath = filePath.substr(0, pos); fileName = filePath.substr(pos + 1); } updateFileList(hDlg); ShowWindow(hDlg, SW_SHOW); if (data->chooseFileParams->isSaveFile) { if (fileName.empty()) SetWindowText(hFileNameBox, _T("untitled")); else SetWindowText(hFileNameBox, fileName.c_str()); SendMessage(hFileNameBox, EM_SETSEL, 0, -1); SetFocus(hFileNameBox); return false; } else return true; } static void onOk(HWND hDlg) { KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); HWND hDirList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_DIRECTORY_LIST); if (GetFocus() == hDirList) { onDirectoryList(hDlg, LBN_DBLCLK); return; } tstring fileName; if (data->chooseFileParams->isSaveFile) { HWND hFileNameBox = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_NAME_BOX); TCHAR fileNameCStr[MAX_PATH]; GetWindowText(hFileNameBox, fileNameCStr, MAX_PATH); fileName = fileNameCStr; HWND hTypeCombo = GetDlgItem(hDlg, IDC_CHOOSE_FILE_TYPE_COMBO); int typeIndex = SendMessage(hTypeCombo, CB_GETCURSEL, 0, 0); tstring pat = data->filters[typeIndex].second; vector exts; split(exts, pat, _T(";")); if (!exts.empty()) fileName = appendFileExtension(fileName, exts[0]); } else { HWND hFileList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_LIST); int selected = SendMessage(hFileList, LB_GETCURSEL, 0, 0); TCHAR fileNameCStr[MAX_PATH]; if (SendMessage(hFileList, LB_GETTEXTLEN, selected, 0) < MAX_PATH) { SendMessage(hFileList, LB_GETTEXT, selected, (LPARAM)fileNameCStr); fileName = fileNameCStr; } } tstring filePath; if (data->currentPath == _T("\\")) filePath = data->currentPath + fileName; else filePath = data->currentPath + _T("\\") + fileName; _tcsncpy(data->chooseFileParams->fileName, filePath.c_str(), MAX_PATH); if (data->chooseFileParams->isSaveFile) { FILE *file = _tfopen(filePath.c_str(), _T("r")); if (file != NULL) { fclose(file); tstring msg = _T("File ") + fileName + _T(" already exists. ") _T("Overwrite?"); if (MessageBox(hDlg, msg.c_str(), _T("Confirm"), MB_ICONEXCLAMATION | MB_YESNO) == IDNO) { return; } } } EndDialog(hDlg, IDOK); } static void onCancel(HWND hDlg) { KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); EndDialog(hDlg, IDCANCEL); } static void onFileList(HWND hDlg, int event) { KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); if (event != LBN_SELCHANGE || data->eventProcessing) return; HWND hFileList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_LIST); int selected = SendMessage(hFileList, LB_GETCURSEL, 0, 0); if (selected == -1) return; tstring fileName; TCHAR fileNameCStr[MAX_PATH]; if (SendMessage(hFileList, LB_GETTEXTLEN, selected, 0) < MAX_PATH) { SendMessage(hFileList, LB_GETTEXT, selected, (LPARAM)fileNameCStr); fileName = fileNameCStr; } HWND hFileNameBox = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_NAME_BOX); data->eventProcessing = true; SetWindowText(hFileNameBox, fileName.c_str()); data->eventProcessing = false; if (!data->chooseFileParams->isSaveFile) { HWND hOkButton = GetDlgItem(hDlg, IDOK); EnableWindow(hOkButton, true); } } static void onDirectoryList(HWND hDlg, int event) { const int dirDispLen = MAX_PATH + 2; KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); if (event != LBN_DBLCLK) return; HWND hDirList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_DIRECTORY_LIST); int selected = SendMessage(hDirList, LB_GETCURSEL, 0, 0); if (selected == -1) return; tstring dirDisp; TCHAR dirDispCStr[dirDispLen]; if (SendMessage(hDirList, LB_GETTEXTLEN, selected, 0) < dirDispLen) { SendMessage(hDirList, LB_GETTEXT, selected, (LPARAM)dirDispCStr); dirDisp = dirDispCStr; } if (dirDisp == _T("(Up...)")) { int pos = data->currentPath.rfind(_T('\\')); if (pos == 0) data->currentPath = _T("\\"); else data->currentPath = data->currentPath.substr(0, pos); } else { tstring dirName = dirDisp.substr(1, dirDisp.length() - 2); if (data->currentPath == _T("\\")) data->currentPath += dirName; else data->currentPath += _T("\\") + dirName; } updateFileList(hDlg); } static void onFileNameBox(HWND hDlg, int event) { KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); if (event != EN_CHANGE || data->eventProcessing) return; HWND hFileList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_LIST); data->eventProcessing = true; SendMessage(hFileList, LB_SETCURSEL, -1, 0); data->eventProcessing = false; } static void onTypeCombo(HWND hDlg, int event) { if (event == CBN_SELCHANGE) updateFileList(hDlg); } static void updateFileList(HWND hDlg) { KnceFileDlgData *data = (KnceFileDlgData *)GetWindowLong(hDlg, GWL_USERDATA); bool isRoot = data->currentPath == _T("\\"); tstring dirName; if (isRoot) dirName = _T("[My Device]"); else { dirName = _T("[") + data->currentPath.substr( data->currentPath.rfind(_T('\\')) + 1) + _T("]"); } HWND hDirLabel = GetDlgItem(hDlg, IDC_CHOOSE_FILE_CURRENT_DIRECTORY_LABEL); SetWindowText(hDirLabel, dirName.c_str()); HWND hTypeCombo = GetDlgItem(hDlg, IDC_CHOOSE_FILE_TYPE_COMBO); int typeIndex = SendMessage(hTypeCombo, CB_GETCURSEL, 0, 0); tstring pat = data->filters[typeIndex].second; HWND hFileList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_FILE_LIST); HWND hDirList = GetDlgItem(hDlg, IDC_CHOOSE_FILE_DIRECTORY_LIST); SendMessage(hFileList, LB_RESETCONTENT, 0, 0); SendMessage(hDirList, LB_RESETCONTENT, 0, 0); if (!isRoot) SendMessage(hDirList, LB_ADDSTRING, 0, (LPARAM)_T("(Up...)")); tstring findPath; if (isRoot) findPath = _T("\\*.*"); else findPath = data->currentPath + _T("\\*.*"); WIN32_FIND_DATA fd; HANDLE hFind = FindFirstFile(findPath.c_str(), &fd); if (hFind != INVALID_HANDLE_VALUE) { if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { tstring dirDisp = _T("[") + tstring(fd.cFileName) + _T("]"); SendMessage(hDirList, LB_ADDSTRING, 0, (LPARAM)dirDisp.c_str()); } else if (KnceUtil::matchMultiFileExtension(fd.cFileName, pat.c_str())) SendMessage(hFileList, LB_ADDSTRING, 0, (LPARAM)fd.cFileName); while (FindNextFile(hFind, &fd)) { if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { tstring dirDisp = _T("[") + tstring(fd.cFileName) + _T("]"); SendMessage(hDirList, LB_ADDSTRING, 0, (LPARAM)dirDisp.c_str()); } else if (KnceUtil::matchMultiFileExtension(fd.cFileName, pat.c_str())) { SendMessage(hFileList, LB_ADDSTRING, 0, (LPARAM)fd.cFileName); } } } FindClose(hFind); if (!data->chooseFileParams->isSaveFile) { HWND hOkButton = GetDlgItem(hDlg, IDOK); EnableWindow(hOkButton, false); } if (SendMessage(hFileList, LB_GETCOUNT, 0, 0) > 0) { SendMessage(hFileList, LB_SETCURSEL, 0, 0); onFileList(hDlg, LBN_SELCHANGE); } int numDirs = SendMessage(hDirList, LB_GETCOUNT, 0, 0); if (isRoot) SendMessage(hDirList, LB_SETCURSEL, 0, 0); else { if (numDirs > 1) SendMessage(hDirList, LB_SETCURSEL, 1, 0); else SendMessage(hDirList, LB_SETCURSEL, 0, 0); } } static void split(vector &result, const tstring &str, const tstring &delim) { tstring strWork = str; int cutAt = 0; while ((cutAt = strWork.find_first_of(delim)) != tstring::npos) { if (cutAt > 0) result.push_back(strWork.substr(0, cutAt)); strWork = strWork.substr(cutAt + 1); } if (strWork.length() > 0) result.push_back(strWork); } static tstring appendFileExtension(const tstring &fileName, const tstring &pat) { if (KnceUtil::matchFileExtension(fileName.c_str(), pat.c_str())) return fileName; if (pat.length() < 2 || pat.substr(0, 2) != _T("*.")) return fileName; return fileName + pat.substr(1); }