代码片段,在windows下用C语言调用文件选择对话框,以备忘
#define DEFAULT_DIR "" char extraction_path[MAX_PATH] = DEFAULT_DIR; /* * Browse for a folder and update the folder edit box * Will use the newer IFileOpenDialog if *compiled* for Vista or later */ void browse_for_folder(void) { BROWSEINFOW bi; LPITEMIDLIST pidl; #if (_WIN32_WINNT >= 0x0600) // Vista and later WCHAR *wpath; size_t i; HRESULT hr; IShellItem *psi = NULL; IShellItem *si_path = NULL; // Automatically freed IFileOpenDialog *pfod = NULL; WCHAR *fname; char* tmp_path = NULL; // Even if we have Vista support with the compiler, // it does not mean we have the Vista API available INIT_VISTA_SHELL32; if (IS_VISTA_SHELL32_AVAILABLE) { hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, &IID_IFileOpenDialog, (LPVOID)&pfod); if (FAILED(hr)) { dprintf("CoCreateInstance for FileOpenDialog failed: error %X", hr); pfod = NULL; // Just in case goto fallback; } hr = pfod->lpVtbl->SetOptions(pfod, FOS_PICKFOLDERS); if (FAILED(hr)) { dprintf("Failed to set folder option for FileOpenDialog: error %X", hr); goto fallback; } // Set the initial folder (if the path is invalid, will simply use last) wpath = utf8_to_wchar(extraction_path); // The new IFileOpenDialog makes us split the path fname = NULL; if ((wpath != NULL) && (wcslen(wpath) >= 1)) { for (i=wcslen(wpath)-1; i!=0; i--) { if (wpath[i] == L'\') { wpath[i] = 0; fname = &wpath[i+1]; break; } } } hr = (*pSHCreateItemFromParsingName)(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path); if (SUCCEEDED(hr)) { if (wpath != NULL) { hr = pfod->lpVtbl->SetFolder(pfod, si_path); } if (fname != NULL) { hr = pfod->lpVtbl->SetFileName(pfod, fname); } } safe_free(wpath); hr = pfod->lpVtbl->Show(pfod, hMain); if (SUCCEEDED(hr)) { hr = pfod->lpVtbl->GetResult(pfod, &psi); if (SUCCEEDED(hr)) { psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &wpath); tmp_path = wchar_to_utf8(wpath); CoTaskMemFree(wpath); if (tmp_path == NULL) { dprintf("Could not convert path"); } else { safe_strcpy(extraction_path, MAX_PATH, tmp_path); safe_free(tmp_path); } } else { dprintf("Failed to set folder option for FileOpenDialog: error %X", hr); } } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { // If it's not a user cancel, assume the dialog didn't show and fallback dprintf("could not show FileOpenDialog: error %X", hr); goto fallback; } pfod->lpVtbl->Release(pfod); return; } fallback: if (pfod != NULL) { pfod->lpVtbl->Release(pfod); } #endif INIT_XP_SHELL32; memset(&bi, 0, sizeof(BROWSEINFOW)); bi.hwndOwner = hMain; bi.lpszTitle = L"Please select the installation folder:"; bi.lpfn = browseinfo_callback; // BIF_NONEWFOLDERBUTTON = 0x00000200 is unknown on MinGW bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN | BIF_EDITBOX | 0x00000200; pidl = SHBrowseForFolderW(&bi); if (pidl != NULL) { CoTaskMemFree(pidl); } }