druid_win_shell/
dialog.rs1#![allow(non_upper_case_globals)]
18
19use winapi::Interface;
20use winapi::shared::minwindef::*;
21use winapi::shared::ntdef::LPWSTR;
22use winapi::shared::windef::*;
23use winapi::shared::wtypesbase::*;
24use winapi::um::combaseapi::*;
25use winapi::um::shobjidl::*;
26use winapi::um::shobjidl_core::*;
27use wio::com::ComPtr;
28
29use std::ptr::null_mut;
30use std::ffi::OsString;
31use util::{as_result, Error, FromWide};
32
33pub enum FileDialogType {
35 Open,
37 Save,
39}
40
41#[derive(Default)]
47pub struct FileDialogOptions(DWORD);
48
49impl FileDialogOptions {
50 pub fn set_show_hidden(&mut self) {
54 self.0 |= FOS_FORCESHOWHIDDEN;
55 }
56
57 }
59
60DEFINE_GUID!{CLSID_FileOpenDialog,
62 0xDC1C5A9C, 0xE88A, 0x4DDE, 0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}
63DEFINE_GUID!{CLSID_FileSaveDialog,
64 0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}
65
66pub(crate) unsafe fn get_file_dialog_path(hwnd_owner: HWND, ty: FileDialogType,
67 options: FileDialogOptions) -> Result<OsString, Error>
68{
69 let mut pfd: *mut IFileDialog = null_mut();
70 let (class, id) = match ty {
71 FileDialogType::Open => (&CLSID_FileOpenDialog, IFileOpenDialog::uuidof()),
72 FileDialogType::Save => (&CLSID_FileSaveDialog, IFileSaveDialog::uuidof()),
73 };
74 as_result(CoCreateInstance(class,
75 null_mut(),
76 CLSCTX_INPROC_SERVER,
77 &id,
78 &mut pfd as *mut *mut IFileDialog as *mut LPVOID
79 ))?;
80 let file_dialog = ComPtr::from_raw(pfd);
81 as_result(file_dialog.SetOptions(options.0))?;
82 as_result(file_dialog.Show(hwnd_owner))?;
83 let mut result_ptr: *mut IShellItem = null_mut();
84 as_result(file_dialog.GetResult(&mut result_ptr))?;
85 let shell_item = ComPtr::from_raw(result_ptr);
86 let mut display_name: LPWSTR = null_mut();
87 as_result(shell_item.GetDisplayName(SIGDN_FILESYSPATH, &mut display_name))?;
88 let filename = display_name.to_os_string();
89 CoTaskMemFree(display_name as LPVOID);
90
91 Ok(filename)
92}