Entry tags:
Выбор каталога
В виндах есть диалог для выбора каталога SHBrowseForFolder. В работе сие позорище выглядит так:

Не буду объяснять, насколько оно неудобно - если разок столкнетесь, то поймете на опыте.
Вместо этого хотелось бы иметь диалог, подобный тем, что дают функции GetSaveFileName/GetOpenFileName. Что-то в таком роде:

Осталось понять, как этого добиться - ведь те функции позволяют выбрать файл, а не фолдер. Под катом решение, опробованное на работоспособность под Win XP и Win 7. Можно прямо копипастить.

Не буду объяснять, насколько оно неудобно - если разок столкнетесь, то поймете на опыте.
Вместо этого хотелось бы иметь диалог, подобный тем, что дают функции GetSaveFileName/GetOpenFileName. Что-то в таком роде:

Осталось понять, как этого добиться - ведь те функции позволяют выбрать файл, а не фолдер. Под катом решение, опробованное на работоспособность под Win XP и Win 7. Можно прямо копипастить.
//ага, просто static, без выпендрежа static WNDPROC wProcBase; static char getFolderNameResult[_MAX_PATH]; //функция для субклассинга LRESULT CALLBACK wProcNew(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) { //сохраняем путь в lpstrFile и выходим SendMessage(hwnd, CDM_GETFILEPATH, _MAX_PATH, (LPARAM)getFolderNameResult); //здесь можно проверить getFolderNameResult если надо чтобы это был существующий каталог, например так: struct _stat buffer; if (0 == _stat(fname, &buffer) && 0 != (buffer.st_mode & _S_IFDIR)) EndDialog(hwnd, IDOK); return 0; } //вызов прежнего обработчика return CallWindowProc(wProcBase, hwnd, msg, wParam, lParam); } //Hook-функция для диалога static UINT_PTR CALLBACK OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { if (uiMsg == WM_INITDIALOG) { //hdlg - это не сам диалог, а его child, так что на шаг вверх HWND par= (HWND)GetWindowLong(hdlg, GWL_HWNDPARENT); //субклассинг wProcBase= (WNDPROC)GetWindowLong(par, GWL_WNDPROC); SetWindowLong(par, GWL_WNDPROC, (LONG)wProcNew); //скрываем лишние контролы, на некоторых меняем надпейси SendMessage(par, CDM_HIDECONTROL, cmb1, NULL); SendMessage(par, CDM_HIDECONTROL, stc2, NULL); SendMessage(par, CDM_SETCONTROLTEXT, stc3, (LPARAM)"Folder:"); SendMessage(par, CDM_SETCONTROLTEXT, IDOK, (LPARAM)"Accept"); SendMessage(par, CDM_SETCONTROLTEXT, stc4, (LPARAM)"In folder:"); return 0; } return 0; } //на входе надо заполнить ofn так, как будто хотим сохранить файл //в каталоге. на выходе результат будет в ofn->lpstrFile. int GetFolderName(OPENFILENAME *ofn) { ofn->Flags|= OFN_EXPLORER|OFN_ENABLEHOOK; ofn->lpfnHook= OFNHookProc; ofn->lpstrCustomFilter= NULL; ofn->nFilterIndex= 0; ofn->lpstrFilter= " \0:\0\0"; //фильтр, который гарантирует показ только каталогов, но не файлов ofn->lpstrTitle= "Select Folder..."; int r= GetSaveFileName(ofn); strcpy(ofn->lpstrFile, getFolderNameResult); ofn->nFileOffset= (WORD)strlen(getFolderNameResult); return r; }
no subject
no subject
no subject