diff options
Diffstat (limited to 'CPP/Windows/Shell.cpp')
-rw-r--r-- | CPP/Windows/Shell.cpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp new file mode 100644 index 0000000..d0f9032 --- /dev/null +++ b/CPP/Windows/Shell.cpp | |||
@@ -0,0 +1,358 @@ | |||
1 | // Windows/Shell.cpp | ||
2 | |||
3 | #include "StdAfx.h" | ||
4 | |||
5 | /* | ||
6 | #include <stdio.h> | ||
7 | #include <string.h> | ||
8 | */ | ||
9 | |||
10 | #include "../Common/MyCom.h" | ||
11 | #ifndef _UNICODE | ||
12 | #include "../Common/StringConvert.h" | ||
13 | #endif | ||
14 | |||
15 | #include "COM.h" | ||
16 | #include "Shell.h" | ||
17 | |||
18 | #ifndef _UNICODE | ||
19 | extern bool g_IsNT; | ||
20 | #endif | ||
21 | |||
22 | namespace NWindows { | ||
23 | namespace NShell { | ||
24 | |||
25 | #ifndef UNDER_CE | ||
26 | |||
27 | // SHGetMalloc is unsupported in Windows Mobile? | ||
28 | |||
29 | void CItemIDList::Free() | ||
30 | { | ||
31 | if (m_Object == NULL) | ||
32 | return; | ||
33 | CMyComPtr<IMalloc> shellMalloc; | ||
34 | if (::SHGetMalloc(&shellMalloc) != NOERROR) | ||
35 | throw 41099; | ||
36 | shellMalloc->Free(m_Object); | ||
37 | m_Object = NULL; | ||
38 | } | ||
39 | |||
40 | /* | ||
41 | CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) | ||
42 | { *this = itemIDList; } | ||
43 | CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) | ||
44 | { *this = itemIDList; } | ||
45 | |||
46 | CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) | ||
47 | { | ||
48 | Free(); | ||
49 | if (object != 0) | ||
50 | { | ||
51 | UINT32 size = GetSize(object); | ||
52 | m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); | ||
53 | if (m_Object != NULL) | ||
54 | MoveMemory(m_Object, object, size); | ||
55 | } | ||
56 | return *this; | ||
57 | } | ||
58 | |||
59 | CItemIDList& CItemIDList::operator=(const CItemIDList &object) | ||
60 | { | ||
61 | Free(); | ||
62 | if (object.m_Object != NULL) | ||
63 | { | ||
64 | UINT32 size = GetSize(object.m_Object); | ||
65 | m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); | ||
66 | if (m_Object != NULL) | ||
67 | MoveMemory(m_Object, object.m_Object, size); | ||
68 | } | ||
69 | return *this; | ||
70 | } | ||
71 | */ | ||
72 | |||
73 | ///////////////////////////// | ||
74 | // CDrop | ||
75 | |||
76 | void CDrop::Attach(HDROP object) | ||
77 | { | ||
78 | Free(); | ||
79 | m_Object = object; | ||
80 | m_Assigned = true; | ||
81 | } | ||
82 | |||
83 | void CDrop::Free() | ||
84 | { | ||
85 | if (m_MustBeFinished && m_Assigned) | ||
86 | Finish(); | ||
87 | m_Assigned = false; | ||
88 | } | ||
89 | |||
90 | UINT CDrop::QueryCountOfFiles() | ||
91 | { | ||
92 | return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); | ||
93 | } | ||
94 | |||
95 | UString CDrop::QueryFileName(UINT fileIndex) | ||
96 | { | ||
97 | UString fileName; | ||
98 | #ifndef _UNICODE | ||
99 | if (!g_IsNT) | ||
100 | { | ||
101 | AString fileNameA; | ||
102 | UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0); | ||
103 | const unsigned len = bufferSize + 2; | ||
104 | QueryFile(fileIndex, fileNameA.GetBuf(len), bufferSize + 1); | ||
105 | fileNameA.ReleaseBuf_CalcLen(len); | ||
106 | fileName = GetUnicodeString(fileNameA); | ||
107 | } | ||
108 | else | ||
109 | #endif | ||
110 | { | ||
111 | UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); | ||
112 | const unsigned len = bufferSize + 2; | ||
113 | QueryFile(fileIndex, fileName.GetBuf(len), bufferSize + 1); | ||
114 | fileName.ReleaseBuf_CalcLen(len); | ||
115 | } | ||
116 | return fileName; | ||
117 | } | ||
118 | |||
119 | void CDrop::QueryFileNames(UStringVector &fileNames) | ||
120 | { | ||
121 | UINT numFiles = QueryCountOfFiles(); | ||
122 | /* | ||
123 | char s[100]; | ||
124 | sprintf(s, "QueryFileNames: %d files", numFiles); | ||
125 | OutputDebugStringA(s); | ||
126 | */ | ||
127 | fileNames.ClearAndReserve(numFiles); | ||
128 | for (UINT i = 0; i < numFiles; i++) | ||
129 | { | ||
130 | const UString s2 = QueryFileName(i); | ||
131 | if (!s2.IsEmpty()) | ||
132 | fileNames.AddInReserved(s2); | ||
133 | /* | ||
134 | OutputDebugStringW(L"file ---"); | ||
135 | OutputDebugStringW(s2); | ||
136 | */ | ||
137 | } | ||
138 | } | ||
139 | |||
140 | |||
141 | bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) | ||
142 | { | ||
143 | const unsigned len = MAX_PATH * 2; | ||
144 | bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); | ||
145 | path.ReleaseBuf_CalcLen(len); | ||
146 | return result; | ||
147 | } | ||
148 | |||
149 | #endif | ||
150 | |||
151 | #ifdef UNDER_CE | ||
152 | |||
153 | bool BrowseForFolder(LPBROWSEINFO, CSysString) | ||
154 | { | ||
155 | return false; | ||
156 | } | ||
157 | |||
158 | bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) | ||
159 | { | ||
160 | return false; | ||
161 | } | ||
162 | |||
163 | bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, | ||
164 | LPCTSTR /* initialFolder */, CSysString & /* resultPath */) | ||
165 | { | ||
166 | /* | ||
167 | // SHBrowseForFolder doesn't work before CE 6.0 ? | ||
168 | if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) | ||
169 | MessageBoxW(0, L"no", L"", 0); | ||
170 | else | ||
171 | MessageBoxW(0, L"yes", L"", 0); | ||
172 | */ | ||
173 | /* | ||
174 | UString s = "all files"; | ||
175 | s += " (*.*)"; | ||
176 | return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); | ||
177 | */ | ||
178 | return false; | ||
179 | } | ||
180 | |||
181 | #else | ||
182 | |||
183 | bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) | ||
184 | { | ||
185 | NWindows::NCOM::CComInitializer comInitializer; | ||
186 | LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); | ||
187 | if (itemIDList == NULL) | ||
188 | return false; | ||
189 | CItemIDList itemIDListHolder; | ||
190 | itemIDListHolder.Attach(itemIDList); | ||
191 | return GetPathFromIDList(itemIDList, resultPath); | ||
192 | } | ||
193 | |||
194 | |||
195 | static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) | ||
196 | { | ||
197 | #ifndef UNDER_CE | ||
198 | switch (uMsg) | ||
199 | { | ||
200 | case BFFM_INITIALIZED: | ||
201 | { | ||
202 | SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); | ||
203 | break; | ||
204 | } | ||
205 | /* | ||
206 | case BFFM_SELCHANGED: | ||
207 | { | ||
208 | TCHAR dir[MAX_PATH]; | ||
209 | if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) | ||
210 | SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); | ||
211 | else | ||
212 | SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); | ||
213 | break; | ||
214 | } | ||
215 | */ | ||
216 | default: | ||
217 | break; | ||
218 | } | ||
219 | #endif | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | |||
224 | static bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, | ||
225 | LPCTSTR initialFolder, CSysString &resultPath) | ||
226 | { | ||
227 | CSysString displayName; | ||
228 | BROWSEINFO browseInfo; | ||
229 | browseInfo.hwndOwner = owner; | ||
230 | browseInfo.pidlRoot = NULL; | ||
231 | |||
232 | // there are Unicode/Astring problems in some WinCE SDK ? | ||
233 | /* | ||
234 | #ifdef UNDER_CE | ||
235 | browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); | ||
236 | browseInfo.lpszTitle = (LPCSTR)title; | ||
237 | #else | ||
238 | */ | ||
239 | browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); | ||
240 | browseInfo.lpszTitle = title; | ||
241 | // #endif | ||
242 | browseInfo.ulFlags = ulFlags; | ||
243 | browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL; | ||
244 | browseInfo.lParam = (LPARAM)initialFolder; | ||
245 | return BrowseForFolder(&browseInfo, resultPath); | ||
246 | } | ||
247 | |||
248 | bool BrowseForFolder(HWND owner, LPCTSTR title, | ||
249 | LPCTSTR initialFolder, CSysString &resultPath) | ||
250 | { | ||
251 | return BrowseForFolder(owner, title, | ||
252 | #ifndef UNDER_CE | ||
253 | BIF_NEWDIALOGSTYLE | | ||
254 | #endif | ||
255 | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); | ||
256 | // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) | ||
257 | } | ||
258 | |||
259 | #ifndef _UNICODE | ||
260 | |||
261 | typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); | ||
262 | |||
263 | bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) | ||
264 | { | ||
265 | path.Empty(); | ||
266 | SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) | ||
267 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); | ||
268 | if (shGetPathFromIDListW == 0) | ||
269 | return false; | ||
270 | const unsigned len = MAX_PATH * 2; | ||
271 | bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); | ||
272 | path.ReleaseBuf_CalcLen(len); | ||
273 | return result; | ||
274 | } | ||
275 | |||
276 | typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); | ||
277 | |||
278 | static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) | ||
279 | { | ||
280 | NWindows::NCOM::CComInitializer comInitializer; | ||
281 | SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) | ||
282 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); | ||
283 | if (shBrowseForFolderW == 0) | ||
284 | return false; | ||
285 | LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); | ||
286 | if (itemIDList == NULL) | ||
287 | return false; | ||
288 | CItemIDList itemIDListHolder; | ||
289 | itemIDListHolder.Attach(itemIDList); | ||
290 | return GetPathFromIDList(itemIDList, resultPath); | ||
291 | } | ||
292 | |||
293 | static | ||
294 | int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) | ||
295 | { | ||
296 | switch (uMsg) | ||
297 | { | ||
298 | case BFFM_INITIALIZED: | ||
299 | { | ||
300 | SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); | ||
301 | break; | ||
302 | } | ||
303 | /* | ||
304 | case BFFM_SELCHANGED: | ||
305 | { | ||
306 | wchar_t dir[MAX_PATH * 2]; | ||
307 | |||
308 | if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) | ||
309 | SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); | ||
310 | else | ||
311 | SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); | ||
312 | break; | ||
313 | } | ||
314 | */ | ||
315 | default: | ||
316 | break; | ||
317 | } | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | |||
322 | static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, | ||
323 | LPCWSTR initialFolder, UString &resultPath) | ||
324 | { | ||
325 | UString displayName; | ||
326 | BROWSEINFOW browseInfo; | ||
327 | browseInfo.hwndOwner = owner; | ||
328 | browseInfo.pidlRoot = NULL; | ||
329 | browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); | ||
330 | browseInfo.lpszTitle = title; | ||
331 | browseInfo.ulFlags = ulFlags; | ||
332 | browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL; | ||
333 | browseInfo.lParam = (LPARAM)initialFolder; | ||
334 | return BrowseForFolder(&browseInfo, resultPath); | ||
335 | } | ||
336 | |||
337 | bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) | ||
338 | { | ||
339 | if (g_IsNT) | ||
340 | return BrowseForFolder(owner, title, | ||
341 | BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | ||
342 | // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. | ||
343 | , initialFolder, resultPath); | ||
344 | // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) | ||
345 | CSysString s; | ||
346 | bool res = BrowseForFolder(owner, GetSystemString(title), | ||
347 | BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | ||
348 | // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. | ||
349 | , GetSystemString(initialFolder), s); | ||
350 | resultPath = GetUnicodeString(s); | ||
351 | return res; | ||
352 | } | ||
353 | |||
354 | #endif | ||
355 | |||
356 | #endif | ||
357 | |||
358 | }} | ||