2 * COMMDLG - File Open Dialogs Win95 look and feel
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * FIXME: The whole concept of handling unicode is badly broken.
22 * many hook-messages expect a pointer to a
23 * OPENFILENAMEA or W structure. With the current architecture
24 * we would have to convert the beast at every call to a hook.
25 * we have to find a better solution but it would likely cause
26 * a complete rewrite after which we should handle the
27 * OPENFILENAME structure without any converting (jsch).
29 * FIXME: any hook gets a OPENFILENAMEA structure
31 * FIXME: CDN_FILEOK is wrong implemented, other CDN_ messages likely too
33 * FIXME: old style hook messages are not implemented (except FILEOKSTRING)
35 * FIXME: lpstrCustomFilter not handled
37 * FIXME: if the size of lpstrFile (nMaxFile) is too small the first
38 * two bytes of lpstrFile should contain the needed size
40 * FIXME: algorithm for selecting the initial directory is too simple
42 * FIXME: add to recent docs
44 * FIXME: flags not implemented: OFN_CREATEPROMPT, OFN_DONTADDTORECENT,
45 * OFN_ENABLEINCLUDENOTIFY, OFN_ENABLESIZING,
46 * OFN_NODEREFERENCELINKS, OFN_NOREADONLYRETURN,
47 * OFN_NOTESTFILECREATE, OFN_USEMONIKERS
49 * FIXME: lCustData for lpfnHook (WM_INITDIALOG)
55 #include "wine/port.h"
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
70 #include "wine/unicode.h"
76 #include "wine/debug.h"
81 #include "filedlgbrowser.h"
84 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
86 #define UNIMPLEMENTED_FLAGS \
87 (OFN_CREATEPROMPT | OFN_DONTADDTORECENT |\
88 OFN_ENABLEINCLUDENOTIFY | OFN_ENABLESIZING |\
89 OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
90 OFN_NOTESTFILECREATE /*| OFN_USEMONIKERS*/)
92 #define IsHooked(fodInfos) \
93 ((fodInfos->ofnInfos->Flags & OFN_ENABLEHOOK) && fodInfos->ofnInfos->lpfnHook)
94 /***********************************************************************
95 * Data structure and global variables
97 typedef struct SFolder
99 int m_iImageIndex
; /* Index of picture in image list */
101 int m_iIndent
; /* Indentation index */
102 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
104 } SFOLDER
,*LPSFOLDER
;
106 typedef struct tagLookInInfo
113 /***********************************************************************
114 * Defines and global variables
117 /* Draw item constant */
119 #define XTEXTOFFSET 3
124 /* SearchItem methods */
125 #define SEARCH_PIDL 1
127 #define ITEM_NOTFOUND -1
129 /* Undefined windows message sent by CreateViewObject*/
130 #define WM_GETISHELLBROWSER WM_USER+7
133 * Those macros exist in windowsx.h. However, you can't really use them since
134 * they rely on the UNICODE defines and can't be used inside Wine itself.
137 /* Combo box macros */
138 #define CBAddString(hwnd,str) \
139 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
140 #define CBAddStringW(hwnd,str) \
141 SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)str);
143 #define CBInsertString(hwnd,str,pos) \
144 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
146 #define CBDeleteString(hwnd,pos) \
147 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
149 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
150 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
152 #define CBGetItemDataPtr(hwnd,iItemId) \
153 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
155 #define CBGetLBText(hwnd,iItemId,str) \
156 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
158 #define CBGetCurSel(hwnd) \
159 SendMessageA(hwnd,CB_GETCURSEL,0,0);
161 #define CBSetCurSel(hwnd,pos) \
162 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
164 #define CBGetCount(hwnd) \
165 SendMessageA(hwnd,CB_GETCOUNT,0,0);
166 #define CBShowDropDown(hwnd,show) \
167 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
168 #define CBSetItemHeight(hwnd,index,height) \
169 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
171 #define CBSetExtendedUI(hwnd,flag) \
172 SendMessageA(hwnd,CB_SETEXTENDEDUI,(WPARAM)(flag),0)
174 const char *FileOpenDlgInfosStr
= "FileOpenDlgInfos"; /* windows property description string */
175 const char *LookInInfosStr
= "LookInInfos"; /* LOOKIN combo box property */
177 /***********************************************************************
181 /* Internal functions used by the dialog */
182 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
183 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
184 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
185 BOOL
FILEDLG95_OnOpen(HWND hwnd
);
186 static LRESULT
FILEDLG95_InitControls(HWND hwnd
);
187 static void FILEDLG95_Clean(HWND hwnd
);
189 /* Functions used by the shell navigation */
190 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
191 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
192 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
193 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
194 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
);
196 /* Functions used by the filetype combo box */
197 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
198 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
199 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
);
200 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
202 /* Functions used by the Look In combo box */
203 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
204 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
205 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
206 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
207 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
208 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
209 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
210 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
211 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
213 /* Miscellaneous tool functions */
214 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
215 HRESULT
GetFileName(HWND hwnd
, LPITEMIDLIST pidl
, LPSTR lpstrFileName
);
216 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
217 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
218 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPWSTR lpcstrFileName
);
220 /* Shell memory allocation */
221 static void *MemAlloc(UINT size
);
222 static void MemFree(void *mem
);
224 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
);
225 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
226 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
);
227 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
228 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
);
229 static BOOL
BrowseSelectedFolder(HWND hwnd
);
231 /***********************************************************************
234 * Creates an Open common dialog box that lets the user select
235 * the drive, directory, and the name of a file or set of files to open.
237 * IN : The FileOpenDlgInfos structure associated with the dialog
238 * OUT : TRUE on success
239 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
241 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
)
249 /* test for missing functionality */
250 if (fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
)
252 FIXME("Flags 0x%08lx not yet implemented\n",
253 fodInfos
->ofnInfos
->Flags
& UNIMPLEMENTED_FLAGS
);
256 /* Create the dialog from a template */
258 if(!(hRes
= FindResourceA(COMDLG32_hInstance
,MAKEINTRESOURCEA(NEWFILEOPENORD
),(LPSTR
)RT_DIALOG
)))
260 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
263 if (!(hDlgTmpl
= LoadResource(COMDLG32_hInstance
, hRes
)) ||
264 !(template = LockResource( hDlgTmpl
)))
266 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
270 /* old style hook messages */
271 if (IsHooked(fodInfos
))
273 fodInfos
->HookMsg
.fileokstring
= RegisterWindowMessageA(FILEOKSTRINGA
);
274 fodInfos
->HookMsg
.lbselchstring
= RegisterWindowMessageA(LBSELCHSTRINGA
);
275 fodInfos
->HookMsg
.helpmsgstring
= RegisterWindowMessageA(HELPMSGSTRINGA
);
276 fodInfos
->HookMsg
.sharevistring
= RegisterWindowMessageA(SHAREVISTRINGA
);
279 lRes
= DialogBoxIndirectParamA(COMDLG32_hInstance
,
280 (LPDLGTEMPLATEA
) template,
281 fodInfos
->ofnInfos
->hwndOwner
,
285 /* Unable to create the dialog */
292 /***********************************************************************
295 * Call GetFileName95 with this structure and clean the memory.
297 * IN : The OPENFILENAMEA initialisation structure passed to
298 * GetOpenFileNameA win api function (see filedlg.c)
300 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
303 FileOpenDlgInfos fodInfos
;
304 LPSTR lpstrSavDir
= NULL
;
306 LPWSTR defext
= NULL
;
307 LPWSTR filter
= NULL
;
308 LPWSTR customfilter
= NULL
;
310 /* Initialize FileOpenDlgInfos structure */
311 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
313 /* Pass in the original ofn */
314 fodInfos
.ofnInfos
= ofn
;
316 /* save current directory */
317 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
319 lpstrSavDir
= MemAlloc(MAX_PATH
);
320 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
323 fodInfos
.unicode
= FALSE
;
325 /* convert all the input strings to unicode */
326 if(ofn
->lpstrInitialDir
)
328 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, NULL
, 0 );
329 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
330 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrInitialDir
, -1, fodInfos
.initdir
, len
);
333 fodInfos
.initdir
= NULL
;
337 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
338 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFile
, -1, fodInfos
.filename
, ofn
->nMaxFile
);
341 fodInfos
.filename
= NULL
;
345 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, NULL
, 0 );
346 defext
= MemAlloc((len
+1)*sizeof(WCHAR
));
347 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrDefExt
, -1, defext
, len
);
349 fodInfos
.defext
= defext
;
353 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, NULL
, 0 );
354 title
= MemAlloc((len
+1)*sizeof(WCHAR
));
355 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrTitle
, -1, title
, len
);
357 fodInfos
.title
= title
;
359 if (ofn
->lpstrFilter
)
364 /* filter is a list... title\0ext\0......\0\0 */
365 s
= ofn
->lpstrFilter
;
366 while (*s
) s
= s
+strlen(s
)+1;
368 n
= s
- ofn
->lpstrFilter
;
369 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, NULL
, 0 );
370 filter
= MemAlloc(len
*sizeof(WCHAR
));
371 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrFilter
, n
, filter
, len
);
373 fodInfos
.filter
= filter
;
375 /* convert lpstrCustomFilter */
376 if (ofn
->lpstrCustomFilter
)
381 /* filter is a list... title\0ext\0......\0\0 */
382 s
= ofn
->lpstrCustomFilter
;
383 while (*s
) s
= s
+strlen(s
)+1;
385 n
= s
- ofn
->lpstrCustomFilter
;
386 len
= MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, NULL
, 0 );
387 customfilter
= MemAlloc(len
*sizeof(WCHAR
));
388 MultiByteToWideChar( CP_ACP
, 0, ofn
->lpstrCustomFilter
, n
, customfilter
, len
);
390 fodInfos
.customfilter
= customfilter
;
392 /* Initialize the dialog property */
393 fodInfos
.DlgInfos
.dwDlgProp
= 0;
394 fodInfos
.DlgInfos
.hwndCustomDlg
= NULL
;
399 ret
= GetFileName95(&fodInfos
);
402 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
403 ret
= GetFileName95(&fodInfos
);
411 SetCurrentDirectoryA(lpstrSavDir
);
412 MemFree(lpstrSavDir
);
422 MemFree(customfilter
);
424 MemFree(fodInfos
.initdir
);
426 if(fodInfos
.filename
)
427 MemFree(fodInfos
.filename
);
429 TRACE("selected file: %s\n",ofn
->lpstrFile
);
434 /***********************************************************************
437 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
438 * Call GetFileName95 with this structure and clean the memory.
440 * FIXME: lpstrCustomFilter has to be converted back
443 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
446 FileOpenDlgInfos fodInfos
;
447 LPSTR lpstrSavDir
= NULL
;
449 /* Initialize FileOpenDlgInfos structure */
450 ZeroMemory(&fodInfos
, sizeof(FileOpenDlgInfos
));
452 /* Pass in the original ofn */
453 fodInfos
.ofnInfos
= (LPOPENFILENAMEA
) ofn
;
455 fodInfos
.title
= ofn
->lpstrTitle
;
456 fodInfos
.defext
= ofn
->lpstrDefExt
;
457 fodInfos
.filter
= ofn
->lpstrFilter
;
458 fodInfos
.customfilter
= ofn
->lpstrCustomFilter
;
460 /* convert string arguments, save others */
463 fodInfos
.filename
= MemAlloc(ofn
->nMaxFile
*sizeof(WCHAR
));
464 strncpyW(fodInfos
.filename
,ofn
->lpstrFile
,ofn
->nMaxFile
);
467 fodInfos
.filename
= NULL
;
469 if(ofn
->lpstrInitialDir
)
471 DWORD len
= strlenW(ofn
->lpstrInitialDir
);
472 fodInfos
.initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
473 strcpyW(fodInfos
.initdir
,ofn
->lpstrInitialDir
);
476 fodInfos
.initdir
= NULL
;
478 /* save current directory */
479 if (ofn
->Flags
& OFN_NOCHANGEDIR
)
481 lpstrSavDir
= MemAlloc(MAX_PATH
);
482 GetCurrentDirectoryA(MAX_PATH
, lpstrSavDir
);
485 fodInfos
.unicode
= TRUE
;
490 ret
= GetFileName95(&fodInfos
);
493 fodInfos
.DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
494 ret
= GetFileName95(&fodInfos
);
502 SetCurrentDirectoryA(lpstrSavDir
);
503 MemFree(lpstrSavDir
);
506 /* restore saved IN arguments and convert OUT arguments back */
507 MemFree(fodInfos
.filename
);
508 MemFree(fodInfos
.initdir
);
512 /***********************************************************************
513 * ArrangeCtrlPositions [internal]
515 * NOTE: Do not change anything here without a lot of testing.
517 static void ArrangeCtrlPositions(HWND hwndChildDlg
, HWND hwndParentDlg
, BOOL hide_help
)
519 HWND hwndChild
, hwndStc32
;
520 RECT rectParent
, rectChild
, rectStc32
;
523 /* Take into account if open as read only checkbox and help button
528 RECT rectHelp
, rectCancel
;
529 GetWindowRect(GetDlgItem(hwndParentDlg
, pshHelp
), &rectHelp
);
530 GetWindowRect(GetDlgItem(hwndParentDlg
, IDCANCEL
), &rectCancel
);
531 /* subtract the height of the help button plus the space between
532 * the help button and the cancel button to the height of the dialog
534 help_fixup
= rectHelp
.bottom
- rectCancel
.bottom
;
538 There are two possibilities to add components to the default file dialog box.
540 By default, all the new components are added below the standard dialog box (the else case).
542 However, if there is a static text component with the stc32 id, a special case happens.
543 The x and y coordinates of stc32 indicate the top left corner where to place the standard file dialog box
544 in the window and the cx and cy indicate how to size the window.
545 Moreover, if the new component's coordinates are on the left of the stc32 , it is placed on the left
546 of the standard file dialog box. If they are above the stc32 component, it is placed above and so on....
550 GetClientRect(hwndParentDlg
, &rectParent
);
552 /* when arranging controls we have to use fixed parent size */
553 rectParent
.bottom
-= help_fixup
;
555 hwndStc32
= GetDlgItem(hwndChildDlg
, stc32
);
558 GetWindowRect(hwndStc32
, &rectStc32
);
559 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectStc32
, 2);
561 /* set the size of the stc32 control according to the size of
562 * client area of the parent dialog
564 SetWindowPos(hwndStc32
, 0,
566 rectParent
.right
, rectParent
.bottom
,
567 SWP_NOMOVE
| SWP_NOZORDER
);
570 SetRectEmpty(&rectStc32
);
572 /* this part moves controls of the child dialog */
573 hwndChild
= GetWindow(hwndChildDlg
, GW_CHILD
);
576 if (hwndChild
!= hwndStc32
)
578 GetWindowRect(hwndChild
, &rectChild
);
579 MapWindowPoints(0, hwndChildDlg
, (LPPOINT
)&rectChild
, 2);
581 /* move only if stc32 exist */
582 if (hwndStc32
&& rectChild
.left
> rectStc32
.right
)
584 /* move to the right of visible controls of the parent dialog */
585 rectChild
.left
+= rectParent
.right
;
586 rectChild
.left
-= rectStc32
.right
;
588 /* move even if stc32 doesn't exist */
589 if (rectChild
.top
> rectStc32
.bottom
)
591 /* move below visible controls of the parent dialog */
592 rectChild
.top
+= rectParent
.bottom
;
593 rectChild
.top
-= rectStc32
.bottom
- rectStc32
.top
;
596 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
597 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
599 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
602 /* this part moves controls of the parent dialog */
603 hwndChild
= GetWindow(hwndParentDlg
, GW_CHILD
);
606 if (hwndChild
!= hwndChildDlg
)
608 GetWindowRect(hwndChild
, &rectChild
);
609 MapWindowPoints(0, hwndParentDlg
, (LPPOINT
)&rectChild
, 2);
611 /* left,top of stc32 marks the position of controls
612 * from the parent dialog
614 rectChild
.left
+= rectStc32
.left
;
615 rectChild
.top
+= rectStc32
.top
;
617 SetWindowPos(hwndChild
, 0, rectChild
.left
, rectChild
.top
,
618 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
620 hwndChild
= GetWindow(hwndChild
, GW_HWNDNEXT
);
623 /* calculate the size of the resulting dialog */
625 /* here we have to use original parent size */
626 GetClientRect(hwndParentDlg
, &rectParent
);
627 GetClientRect(hwndChildDlg
, &rectChild
);
631 if (rectParent
.right
> rectChild
.right
)
633 rectParent
.right
+= rectChild
.right
;
634 rectParent
.right
-= rectStc32
.right
- rectStc32
.left
;
638 rectParent
.right
= rectChild
.right
;
641 if (rectParent
.bottom
> rectChild
.bottom
)
643 rectParent
.bottom
+= rectChild
.bottom
;
644 rectParent
.bottom
-= rectStc32
.bottom
- rectStc32
.top
;
648 rectParent
.bottom
= rectChild
.bottom
;
653 rectParent
.bottom
+= rectChild
.bottom
;
656 /* finally use fixed parent size */
657 rectParent
.bottom
-= help_fixup
;
659 /* save the size of the parent's client area */
660 rectChild
.right
= rectParent
.right
;
661 rectChild
.bottom
= rectParent
.bottom
;
663 /* set the size of the parent dialog */
664 AdjustWindowRectEx(&rectParent
, GetWindowLongW(hwndParentDlg
, GWL_STYLE
),
665 FALSE
, GetWindowLongW(hwndParentDlg
, GWL_EXSTYLE
));
666 SetWindowPos(hwndParentDlg
, 0,
668 rectParent
.right
- rectParent
.left
,
669 rectParent
.bottom
- rectParent
.top
,
670 SWP_NOMOVE
| SWP_NOZORDER
);
672 /* set the size of the child dialog */
673 SetWindowPos(hwndChildDlg
, HWND_BOTTOM
,
674 0, 0, rectChild
.right
, rectChild
.bottom
, SWP_NOACTIVATE
);
677 INT_PTR CALLBACK
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
679 FileOpenDlgInfos
*fodInfos
;
682 TRACE("0x%04x\n", uMsg
);
689 fodInfos
= (FileOpenDlgInfos
*)lParam
;
690 lParam
= (LPARAM
) fodInfos
->ofnInfos
;
692 if(fodInfos
&& IsHooked(fodInfos
))
693 return CallWindowProcA((WNDPROC
)fodInfos
->ofnInfos
->lpfnHook
,hwnd
,uMsg
,wParam
,lParam
);
698 fodInfos
= (FileOpenDlgInfos
*) GetPropA(GetParent(hwnd
),FileOpenDlgInfosStr
);
699 if(fodInfos
&& IsHooked(fodInfos
))
700 return CallWindowProcA((WNDPROC
)fodInfos
->ofnInfos
->lpfnHook
,hwnd
,uMsg
,wParam
,lParam
);
705 HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
, HWND hwnd
)
715 * If OFN_ENABLETEMPLATEHANDLE is specified, the OPENFILENAME
716 * structure's hInstance parameter is not a HINSTANCE, but
717 * instead a pointer to a template resource to use.
719 if (fodInfos
->ofnInfos
->Flags
& (OFN_ENABLETEMPLATE
| OFN_ENABLETEMPLATEHANDLE
))
722 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
725 if( !(template = LockResource( fodInfos
->ofnInfos
->hInstance
)))
727 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
733 hinst
= fodInfos
->ofnInfos
->hInstance
;
734 if(fodInfos
->unicode
)
736 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
737 hRes
= FindResourceW( hinst
, ofn
->lpTemplateName
, (LPWSTR
)RT_DIALOG
);
741 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
742 hRes
= FindResourceA( hinst
, ofn
->lpTemplateName
, (LPSTR
)RT_DIALOG
);
746 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
749 if (!(hDlgTmpl
= LoadResource( hinst
, hRes
)) ||
750 !(template = LockResource( hDlgTmpl
)))
752 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
756 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, template,
757 hwnd
, FileOpenDlgProcUserTemplate
, (LPARAM
)fodInfos
);
760 ShowWindow(hChildDlg
,SW_SHOW
);
764 else if( IsHooked(fodInfos
))
769 WORD menu
,class,title
;
771 GetClientRect(hwnd
,&rectHwnd
);
772 temp
.tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
| WS_VISIBLE
| DS_CONTROL
| DS_3DLOOK
;
773 temp
.tmplate
.dwExtendedStyle
= 0;
774 temp
.tmplate
.cdit
= 0;
779 temp
.menu
= temp
.class = temp
.title
= 0;
781 hChildDlg
= CreateDialogIndirectParamA(COMDLG32_hInstance
, &temp
.tmplate
,
782 hwnd
, FileOpenDlgProcUserTemplate
, (LPARAM
)fodInfos
);
789 /***********************************************************************
790 * SendCustomDlgNotificationMessage
792 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
795 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
797 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
799 TRACE("%p 0x%04x\n",hwndParentDlg
, uCode
);
801 if(!fodInfos
) return 0;
803 if(fodInfos
->unicode
)
804 FIXME("sending OPENFILENAMEA structure. Hook is expecting OPENFILENAMEW!\n");
806 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
810 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
811 ofnNotify
.hdr
.idFrom
=0;
812 ofnNotify
.hdr
.code
= uCode
;
813 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
814 ofnNotify
.pszFile
= NULL
;
815 TRACE("CALL NOTIFY for %x\n", uCode
);
816 ret
= SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
817 TRACE("RET NOTIFY\n");
823 HRESULT
FILEDLG95_Handle_GetFilePath(HWND hwnd
, DWORD size
, LPSTR buffer
)
825 UINT sizeUsed
= 0, n
, total
;
826 LPWSTR lpstrFileList
= NULL
;
827 WCHAR lpstrCurrentDir
[MAX_PATH
];
828 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
830 TRACE("CDM_GETFILEPATH:\n");
832 if ( ! (fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
835 /* get path and filenames */
836 SHGetPathFromIDListW(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrCurrentDir
);
837 n
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
839 TRACE("path >%s< filespec >%s< %d files\n",
840 debugstr_w(lpstrCurrentDir
),debugstr_w(lpstrFileList
),n
);
842 total
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
843 NULL
, 0, NULL
, NULL
);
844 total
+= WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
845 NULL
, 0, NULL
, NULL
);
847 /* Prepend the current path */
848 n
= WideCharToMultiByte(CP_ACP
, 0, lpstrCurrentDir
, -1,
849 buffer
, size
, NULL
, NULL
);
853 /* 'n' includes trailing \0 */
855 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
856 &buffer
[n
], size
-n
, NULL
, NULL
);
858 MemFree(lpstrFileList
);
860 TRACE("returned -> %s\n",debugstr_a(buffer
));
865 HRESULT
FILEDLG95_Handle_GetFileSpec(HWND hwnd
, DWORD size
, LPSTR buffer
)
868 LPWSTR lpstrFileList
= NULL
;
870 TRACE("CDM_GETSPEC:\n");
872 FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
873 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
, buffer
, size
, NULL
, NULL
);
874 MemFree(lpstrFileList
);
879 /***********************************************************************
880 * FILEDLG95_HandleCustomDialogMessages
882 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
884 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
886 char lpstrPath
[MAX_PATH
];
887 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
888 if(!fodInfos
) return -1;
892 case CDM_GETFILEPATH
:
893 return FILEDLG95_Handle_GetFilePath(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
895 case CDM_GETFOLDERPATH
:
896 TRACE("CDM_GETFOLDERPATH:\n");
897 SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrPath
);
898 if ((LPSTR
)lParam
!=NULL
)
899 lstrcpynA((LPSTR
)lParam
,lpstrPath
,(int)wParam
);
900 return strlen(lpstrPath
);
903 return FILEDLG95_Handle_GetFileSpec(hwnd
, (UINT
)wParam
, (LPSTR
)lParam
);
905 case CDM_SETCONTROLTEXT
:
906 TRACE("CDM_SETCONTROLTEXT:\n");
908 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
911 case CDM_HIDECONTROL
:
913 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
919 /***********************************************************************
922 * File open dialog procedure
924 INT_PTR CALLBACK
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
927 TRACE("0x%04x 0x%04x\n", hwnd
, uMsg
);
934 FileOpenDlgInfos
* fodInfos
= (FileOpenDlgInfos
*)lParam
;
936 /* Adds the FileOpenDlgInfos in the property list of the dialog
937 so it will be easily accessible through a GetPropA(...) */
938 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
940 fodInfos
->DlgInfos
.hwndCustomDlg
=
941 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
, hwnd
);
943 FILEDLG95_InitControls(hwnd
);
945 if (fodInfos
->DlgInfos
.hwndCustomDlg
)
946 ArrangeCtrlPositions(fodInfos
->DlgInfos
.hwndCustomDlg
, hwnd
,
947 (fodInfos
->ofnInfos
->Flags
& (OFN_HIDEREADONLY
| OFN_SHOWHELP
)) == OFN_HIDEREADONLY
);
949 FILEDLG95_FillControls(hwnd
, wParam
, lParam
);
951 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
952 SendCustomDlgNotificationMessage(hwnd
,CDN_FOLDERCHANGE
);
953 SendCustomDlgNotificationMessage(hwnd
,CDN_SELCHANGE
);
957 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
960 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
963 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
969 case WM_GETISHELLBROWSER
:
970 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
973 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
978 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
981 /* set up the button tooltips strings */
982 if(TTN_GETDISPINFOA
== lpnmh
->code
)
984 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
985 switch(lpnmh
->idFrom
)
987 /* Up folder button */
988 case FCIDM_TB_UPFOLDER
:
989 stringId
= IDS_UPFOLDER
;
991 /* New folder button */
992 case FCIDM_TB_NEWFOLDER
:
993 stringId
= IDS_NEWFOLDER
;
995 /* List option button */
996 case FCIDM_TB_SMALLICON
:
997 stringId
= IDS_LISTVIEW
;
999 /* Details option button */
1000 case FCIDM_TB_REPORTVIEW
:
1001 stringId
= IDS_REPORTVIEW
;
1003 /* Desktop button */
1004 case FCIDM_TB_DESKTOP
:
1005 stringId
= IDS_TODESKTOP
;
1010 lpdi
->hinst
= COMDLG32_hInstance
;
1011 lpdi
->lpszText
= (LPSTR
) stringId
;
1016 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
1017 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
1022 /***********************************************************************
1023 * FILEDLG95_InitControls
1025 * WM_INITDIALOG message handler (before hook notification)
1027 static LRESULT
FILEDLG95_InitControls(HWND hwnd
)
1029 int win2000plus
= 0;
1031 int handledPath
= FALSE
;
1032 OSVERSIONINFOA osVi
;
1033 const WCHAR szwSlash
[] = { '\\', 0 };
1034 const WCHAR szwStar
[] = { '*',0 };
1038 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
1039 {VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
1040 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
1041 {VIEW_NEWFOLDER
+1, FCIDM_TB_DESKTOP
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
1042 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
1043 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
1044 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
1045 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
1046 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
1051 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1053 tba
[0].hInst
= HINST_COMMCTRL
;
1054 tba
[0].nID
= IDB_VIEW_SMALL_COLOR
;
1055 tba
[1].hInst
= COMDLG32_hInstance
;
1058 TRACE("%p\n", fodInfos
);
1060 /* Get windows version emulating */
1061 osVi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
1062 GetVersionExA(&osVi
);
1063 if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) {
1064 win98plus
= ((osVi
.dwMajorVersion
> 4) || ((osVi
.dwMajorVersion
== 4) && (osVi
.dwMinorVersion
> 0)));
1065 } else if (osVi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1066 win2000plus
= (osVi
.dwMajorVersion
> 4);
1067 if (win2000plus
) win98plus
= TRUE
;
1069 TRACE("Running on 2000+ %d, 98+ %d\n", win2000plus
, win98plus
);
1071 /* Get the hwnd of the controls */
1072 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
1073 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
1074 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
1076 GetWindowRect( fodInfos
->DlgInfos
.hwndLookInCB
,&rectlook
);
1077 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectlook
,2);
1079 /* construct the toolbar */
1080 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
1081 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
1083 rectTB
.right
= rectlook
.right
+ rectTB
.right
- rectTB
.left
;
1084 rectTB
.bottom
= rectlook
.top
- 1 + rectTB
.bottom
- rectTB
.top
;
1085 rectTB
.left
= rectlook
.right
;
1086 rectTB
.top
= rectlook
.top
-1;
1088 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, NULL
,
1089 WS_CHILD
| WS_GROUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
1090 rectTB
.left
, rectTB
.top
,
1091 rectTB
.right
- rectTB
.left
, rectTB
.bottom
- rectTB
.top
,
1092 hwnd
, (HMENU
)IDC_TOOLBAR
, COMDLG32_hInstance
, NULL
);
1094 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
1096 /* FIXME: use TB_LOADIMAGES when implemented */
1097 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1098 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
[0]);
1099 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 1, (LPARAM
) &tba
[1]);
1101 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 9,(LPARAM
) &tbb
);
1102 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1104 /* Set the window text with the text specified in the OPENFILENAME structure */
1107 SetWindowTextW(hwnd
,fodInfos
->title
);
1109 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1111 SetWindowTextA(hwnd
,"Save");
1114 /* Initialise the file name edit control */
1115 handledPath
= FALSE
;
1116 TRACE("Before manipilation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1118 if(fodInfos
->filename
)
1120 /* 1. If win2000 or higher and filename contains a path, use it
1121 in preference over the lpstrInitialDir */
1122 if (win2000plus
&& *fodInfos
->filename
&& strpbrkW(fodInfos
->filename
, szwSlash
)) {
1123 WCHAR tmpBuf
[MAX_PATH
];
1127 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
, tmpBuf
, &nameBit
);
1130 /* nameBit is always shorter than the original filename */
1131 strcpyW(fodInfos
->filename
,nameBit
);
1134 if (fodInfos
->initdir
== NULL
)
1135 MemFree(fodInfos
->initdir
);
1136 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf
) + 1)*sizeof(WCHAR
));
1137 strcpyW(fodInfos
->initdir
, tmpBuf
);
1139 TRACE("Value in Filename includes path, overriding InitialDir: %s, %s\n",
1140 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1142 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1145 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1149 /* 2. (All platforms) If initdir is not null, then use it */
1150 if ((handledPath
== FALSE
) && (fodInfos
->initdir
!=NULL
) &&
1151 (*fodInfos
->initdir
!=0x00))
1153 /* Work out the proper path as supplied one might be relative */
1154 /* (Here because supplying '.' as dir browses to My Computer) */
1155 if (handledPath
==FALSE
) {
1156 WCHAR tmpBuf
[MAX_PATH
];
1157 WCHAR tmpBuf2
[MAX_PATH
];
1161 strcpyW(tmpBuf
, fodInfos
->initdir
);
1162 if( PathFileExistsW(tmpBuf
) ) {
1163 /* initdir does not have to be a directory. If a file is
1164 * specified, the dir part is taken */
1165 if( PathIsDirectoryW(tmpBuf
)) {
1166 if (tmpBuf
[strlenW(tmpBuf
)-1] != '\\') {
1167 strcatW(tmpBuf
, szwSlash
);
1169 strcatW(tmpBuf
, szwStar
);
1171 result
= GetFullPathNameW(tmpBuf
, MAX_PATH
, tmpBuf2
, &nameBit
);
1174 if (fodInfos
->initdir
)
1175 MemFree(fodInfos
->initdir
);
1176 fodInfos
->initdir
= MemAlloc((strlenW(tmpBuf2
) + 1)*sizeof(WCHAR
));
1177 strcpyW(fodInfos
->initdir
, tmpBuf2
);
1179 TRACE("Value in InitDir changed to %s\n", debugstr_w(fodInfos
->initdir
));
1182 else if (fodInfos
->initdir
)
1184 MemFree(fodInfos
->initdir
);
1185 fodInfos
->initdir
= NULL
;
1186 TRACE("Value in InitDir is not an existing path, changed to (nil)\n");
1191 if ((handledPath
== FALSE
) && ((fodInfos
->initdir
==NULL
) ||
1192 (*fodInfos
->initdir
==0x00)))
1194 /* 3. All except w2k+: if filename contains a path use it */
1195 if (!win2000plus
&& fodInfos
->filename
&&
1196 *fodInfos
->filename
&&
1197 strpbrkW(fodInfos
->filename
, szwSlash
)) {
1198 WCHAR tmpBuf
[MAX_PATH
];
1202 result
= GetFullPathNameW(fodInfos
->filename
, MAX_PATH
,
1207 /* nameBit is always shorter than the original filename */
1208 strcpyW(fodInfos
->filename
, nameBit
);
1211 len
= strlenW(tmpBuf
);
1212 if(fodInfos
->initdir
)
1213 MemFree(fodInfos
->initdir
);
1214 fodInfos
->initdir
= MemAlloc((len
+1)*sizeof(WCHAR
));
1215 strcpyW(fodInfos
->initdir
, tmpBuf
);
1218 TRACE("Value in Filename includes path, overriding initdir: %s, %s\n",
1219 debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1221 SetDlgItemTextW(hwnd
, IDC_FILENAME
, fodInfos
->filename
);
1224 /* 4. win98+ and win2000+ if any files of specified filter types in
1225 current directory, use it */
1226 if ( win98plus
&& handledPath
== FALSE
&&
1227 fodInfos
->filter
&& *fodInfos
->filter
) {
1229 BOOL searchMore
= TRUE
;
1230 LPCWSTR lpstrPos
= fodInfos
->filter
;
1231 WIN32_FIND_DATAW FindFileData
;
1236 /* filter is a list... title\0ext\0......\0\0 */
1238 /* Skip the title */
1239 if(! *lpstrPos
) break; /* end */
1240 lpstrPos
+= strlenW(lpstrPos
) + 1;
1242 /* See if any files exist in the current dir with this extension */
1243 if(! *lpstrPos
) break; /* end */
1245 hFind
= FindFirstFileW(lpstrPos
, &FindFileData
);
1247 if (hFind
== INVALID_HANDLE_VALUE
) {
1248 /* None found - continue search */
1249 lpstrPos
+= strlenW(lpstrPos
) + 1;
1254 if(fodInfos
->initdir
)
1255 MemFree(fodInfos
->initdir
);
1256 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1257 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1260 TRACE("No initial dir specified, but files of type %s found in current, so using it\n",
1261 debugstr_w(lpstrPos
));
1267 /* 5. Win2000+: FIXME: Next, Recently used? Not sure how windows does this */
1269 /* 6. Win98+ and 2000+: Use personal files dir, others use current dir */
1270 if (handledPath
== FALSE
&& (win2000plus
|| win98plus
)) {
1271 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1273 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_PERSONAL
, 0, 0, fodInfos
->initdir
)))
1275 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, fodInfos
->initdir
)))
1278 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1279 TRACE("No personal or desktop dir, using cwd as failsafe: %s\n", debugstr_w(fodInfos
->initdir
));
1281 TRACE("No personal dir, using desktop instead: %s\n", debugstr_w(fodInfos
->initdir
));
1284 TRACE("No initial dir specified, using personal files dir of %s\n", debugstr_w(fodInfos
->initdir
));
1287 } else if (handledPath
==FALSE
) {
1288 fodInfos
->initdir
= MemAlloc(MAX_PATH
*sizeof(WCHAR
));
1289 GetCurrentDirectoryW(MAX_PATH
, fodInfos
->initdir
);
1291 TRACE("No initial dir specified, using current dir of %s\n", debugstr_w(fodInfos
->initdir
));
1294 SetFocus(GetDlgItem(hwnd
, IDC_FILENAME
));
1295 TRACE("After manipulation, file = %s, dir = %s\n", debugstr_w(fodInfos
->filename
), debugstr_w(fodInfos
->initdir
));
1297 /* Must the open as read only check box be checked ?*/
1298 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1300 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1303 /* Must the open as read only check box be hidden? */
1304 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1306 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1307 EnableWindow(GetDlgItem(hwnd
, IDC_OPENREADONLY
), FALSE
);
1310 /* Must the help button be hidden? */
1311 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1313 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1314 EnableWindow(GetDlgItem(hwnd
, pshHelp
), FALSE
);
1317 /* Resize the height, if open as read only checkbox ad help button
1318 are hidden and we are not using a custom template nor a customDialog
1320 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1321 (!(fodInfos
->ofnInfos
->Flags
&
1322 (OFN_SHOWHELP
|OFN_ENABLETEMPLATE
|OFN_ENABLETEMPLATEHANDLE
))) &&
1323 (!fodInfos
->DlgInfos
.hwndCustomDlg
))
1325 RECT rectDlg
, rectHelp
, rectCancel
;
1326 GetWindowRect(hwnd
, &rectDlg
);
1327 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1328 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1329 /* subtract the height of the help button plus the space between
1330 the help button and the cancel button to the height of the dialog */
1331 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1332 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1333 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1335 /* change Open to Save FIXME: use resources */
1336 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1338 SetDlgItemTextA(hwnd
,IDOK
,"&Save");
1339 SetDlgItemTextA(hwnd
,IDC_LOOKINSTATIC
,"Save &in");
1344 /***********************************************************************
1345 * FILEDLG95_FillControls
1347 * WM_INITDIALOG message handler (after hook notification)
1349 static LRESULT
FILEDLG95_FillControls(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1351 LPITEMIDLIST pidlItemId
= NULL
;
1353 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
1355 TRACE("dir=%s file=%s\n",
1356 debugstr_w(fodInfos
->initdir
), debugstr_w(fodInfos
->filename
));
1358 /* Get the initial directory pidl */
1360 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->initdir
)))
1362 WCHAR path
[MAX_PATH
];
1364 GetCurrentDirectoryW(MAX_PATH
,path
);
1365 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, path
);
1368 /* Initialise shell objects */
1369 FILEDLG95_SHELL_Init(hwnd
);
1371 /* Initialize the Look In combo box */
1372 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
1374 /* Initialize the filter combo box */
1375 FILEDLG95_FILETYPE_Init(hwnd
);
1377 /* Browse to the initial directory */
1378 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
, SBSP_ABSOLUTE
);
1380 /* Free pidlItem memory */
1381 COMDLG32_SHFree(pidlItemId
);
1385 /***********************************************************************
1388 * Regroups all the cleaning functions of the filedlg
1390 void FILEDLG95_Clean(HWND hwnd
)
1392 FILEDLG95_FILETYPE_Clean(hwnd
);
1393 FILEDLG95_LOOKIN_Clean(hwnd
);
1394 FILEDLG95_SHELL_Clean(hwnd
);
1396 /***********************************************************************
1397 * FILEDLG95_OnWMCommand
1399 * WM_COMMAND message handler
1401 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1403 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
1404 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
1405 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1411 FILEDLG95_OnOpen(hwnd
);
1415 FILEDLG95_Clean(hwnd
);
1416 EndDialog(hwnd
, FALSE
);
1418 /* Filetype combo box */
1420 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
1422 /* LookIn combo box */
1424 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
1427 /* --- toolbar --- */
1428 /* Up folder button */
1429 case FCIDM_TB_UPFOLDER
:
1430 FILEDLG95_SHELL_UpFolder(hwnd
);
1432 /* New folder button */
1433 case FCIDM_TB_NEWFOLDER
:
1434 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDERA
);
1436 /* List option button */
1437 case FCIDM_TB_SMALLICON
:
1438 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLISTA
);
1440 /* Details option button */
1441 case FCIDM_TB_REPORTVIEW
:
1442 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILSA
);
1444 /* Details option button */
1445 case FCIDM_TB_DESKTOP
:
1446 FILEDLG95_SHELL_BrowseToDesktop(hwnd
);
1453 /* Do not use the listview selection anymore */
1454 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
1458 /***********************************************************************
1459 * FILEDLG95_OnWMGetIShellBrowser
1461 * WM_GETISHELLBROWSER message handler
1463 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
1466 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1470 SetWindowLongA(hwnd
,DWL_MSGRESULT
,(LONG
)fodInfos
->Shell
.FOIShellBrowser
);
1476 /***********************************************************************
1477 * FILEDLG95_SendFileOK
1479 * Sends the CDN_FILEOK notification if required
1482 * TRUE if the dialog should close
1483 * FALSE if the dialog should not be closed
1485 static BOOL
FILEDLG95_SendFileOK( HWND hwnd
, FileOpenDlgInfos
*fodInfos
)
1487 /* ask the hook if we can close */
1488 if(IsHooked(fodInfos
))
1491 /* First send CDN_FILEOK as MSDN doc says */
1492 SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
1494 /* fodInfos->ofnInfos points to an ASCII or UNICODE structure as appropriate */
1495 CallWindowProcA((WNDPROC
)fodInfos
->ofnInfos
->lpfnHook
,
1496 fodInfos
->DlgInfos
.hwndCustomDlg
,
1497 fodInfos
->HookMsg
.fileokstring
, 0, (LPARAM
)fodInfos
->ofnInfos
);
1498 if (GetWindowLongA(fodInfos
->DlgInfos
.hwndCustomDlg
, DWL_MSGRESULT
))
1500 TRACE("canceled\n");
1507 /***********************************************************************
1508 * FILEDLG95_OnOpenMultipleFiles
1510 * Handles the opening of multiple files.
1513 * check destination buffer size
1515 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPWSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1517 WCHAR lpstrPathSpec
[MAX_PATH
] = {0};
1518 UINT nCount
, nSizePath
;
1519 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1523 if(fodInfos
->unicode
)
1525 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1526 ofn
->lpstrFile
[0] = '\0';
1530 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1531 ofn
->lpstrFile
[0] = '\0';
1534 SHGetPathFromIDListW( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1536 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
) &&
1537 ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1538 ! ( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1540 LPWSTR lpstrTemp
= lpstrFileList
;
1542 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1546 pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrTemp
);
1549 WCHAR lpstrNotFound
[100];
1550 WCHAR lpstrMsg
[100];
1552 WCHAR nl
[] = {'\n',0};
1554 LoadStringW(COMDLG32_hInstance
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1555 LoadStringW(COMDLG32_hInstance
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1557 strcpyW(tmp
, lpstrTemp
);
1559 strcatW(tmp
, lpstrNotFound
);
1561 strcatW(tmp
, lpstrMsg
);
1563 MessageBoxW(hwnd
, tmp
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
1567 /* move to the next file in the list of files */
1568 lpstrTemp
+= strlenW(lpstrTemp
) + 1;
1569 COMDLG32_SHFree(pidl
);
1573 nSizePath
= strlenW(lpstrPathSpec
) + 1;
1574 if ( !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
) )
1576 /* For "oldstyle" dialog the components have to
1577 be spearated by blanks (not '\0'!) and short
1578 filenames have to be used! */
1579 FIXME("Components have to be separated by blanks");
1581 if(fodInfos
->unicode
)
1583 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1584 strcpyW( ofn
->lpstrFile
, lpstrPathSpec
);
1585 memcpy( ofn
->lpstrFile
+ nSizePath
, lpstrFileList
, sizeUsed
*sizeof(WCHAR
) );
1589 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1591 if (ofn
->lpstrFile
!= NULL
)
1593 WideCharToMultiByte(CP_ACP
, 0, lpstrPathSpec
, -1,
1594 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1595 if (ofn
->nMaxFile
> nSizePath
)
1597 WideCharToMultiByte(CP_ACP
, 0, lpstrFileList
, sizeUsed
,
1598 ofn
->lpstrFile
+ nSizePath
,
1599 ofn
->nMaxFile
- nSizePath
, NULL
, NULL
);
1604 fodInfos
->ofnInfos
->nFileOffset
= nSizePath
+ 1;
1605 fodInfos
->ofnInfos
->nFileExtension
= 0;
1607 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1610 /* clean and exit */
1611 FILEDLG95_Clean(hwnd
);
1612 return EndDialog(hwnd
,TRUE
);
1615 /***********************************************************************
1618 * Ok button WM_COMMAND message handler
1620 * If the function succeeds, the return value is nonzero.
1622 #define ONOPEN_BROWSE 1
1623 #define ONOPEN_OPEN 2
1624 #define ONOPEN_SEARCH 3
1625 static void FILEDLG95_OnOpenMessage(HWND hwnd
, int idCaption
, int idText
)
1627 char strMsgTitle
[MAX_PATH
];
1628 char strMsgText
[MAX_PATH
];
1630 LoadStringA(COMDLG32_hInstance
, idCaption
, strMsgTitle
, sizeof(strMsgTitle
));
1632 strMsgTitle
[0] = '\0';
1633 LoadStringA(COMDLG32_hInstance
, idText
, strMsgText
, sizeof(strMsgText
));
1634 MessageBoxA(hwnd
,strMsgText
, strMsgTitle
, MB_OK
| MB_ICONHAND
);
1637 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1639 LPWSTR lpstrFileList
;
1640 UINT nFileCount
= 0;
1643 WCHAR lpstrPathAndFile
[MAX_PATH
];
1644 WCHAR lpstrTemp
[MAX_PATH
];
1645 LPSHELLFOLDER lpsf
= NULL
;
1647 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1649 TRACE("hwnd=%p\n", hwnd
);
1651 /* get the files from the edit control */
1652 nFileCount
= FILEDLG95_FILENAME_GetFileNames(hwnd
, &lpstrFileList
, &sizeUsed
);
1654 /* try if the user selected a folder in the shellview */
1657 BrowseSelectedFolder(hwnd
);
1663 ret
= FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1667 TRACE("count=%u len=%u file=%s\n", nFileCount
, sizeUsed
, debugstr_w(lpstrFileList
));
1670 Step 1: Build a complete path name from the current folder and
1671 the filename or path in the edit box.
1673 - the path in the edit box is a root path
1674 (with or without drive letter)
1675 - the edit box contains ".." (or a path with ".." in it)
1678 /* Get the current directory name */
1679 if (!SHGetPathFromIDListW(fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathAndFile
))
1681 /* we are in a special folder, default to desktop */
1682 if(FAILED(COMDLG32_SHGetFolderPathW(hwnd
, CSIDL_DESKTOPDIRECTORY
|CSIDL_FLAG_CREATE
, 0, 0, lpstrPathAndFile
)))
1685 GetCurrentDirectoryW(MAX_PATH
, lpstrPathAndFile
);
1688 PathAddBackslashW(lpstrPathAndFile
);
1690 TRACE("current directory=%s\n", debugstr_w(lpstrPathAndFile
));
1692 /* if the user specifyed a fully qualified path use it */
1693 if(PathIsRelativeW(lpstrFileList
))
1695 strcatW(lpstrPathAndFile
, lpstrFileList
);
1699 /* does the path have a drive letter? */
1700 if (PathGetDriveNumberW(lpstrFileList
) == -1)
1701 strcpyW(lpstrPathAndFile
+2, lpstrFileList
);
1703 strcpyW(lpstrPathAndFile
, lpstrFileList
);
1706 /* resolve "." and ".." */
1707 PathCanonicalizeW(lpstrTemp
, lpstrPathAndFile
);
1708 strcpyW(lpstrPathAndFile
, lpstrTemp
);
1709 TRACE("canon=%s\n", debugstr_w(lpstrPathAndFile
));
1711 MemFree(lpstrFileList
);
1714 Step 2: here we have a cleaned up path
1716 We have to parse the path step by step to see if we have to browse
1717 to a folder if the path points to a directory or the last
1718 valid element is a directory.
1721 lpstrPathAndFile: cleaned up path
1724 nOpenAction
= ONOPEN_BROWSE
;
1726 /* don't apply any checks with OFN_NOVALIDATE */
1728 LPWSTR lpszTemp
, lpszTemp1
;
1729 LPITEMIDLIST pidl
= NULL
;
1730 WCHAR szwInvalid
[] = { '/',':','<','>','|', 0};
1732 /* check for invalid chars */
1733 if((strpbrkW(lpstrPathAndFile
+3, szwInvalid
) != NULL
) && !(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1735 FILEDLG95_OnOpenMessage(hwnd
, IDS_INVALID_FILENAME_TITLE
, IDS_INVALID_FILENAME
);
1740 if (FAILED (SHGetDesktopFolder(&lpsf
))) return FALSE
;
1742 lpszTemp1
= lpszTemp
= lpstrPathAndFile
;
1745 LPSHELLFOLDER lpsfChild
;
1746 WCHAR lpwstrTemp
[MAX_PATH
];
1747 DWORD dwEaten
, dwAttributes
;
1750 strcpyW(lpwstrTemp
, lpszTemp
);
1751 p
= PathFindNextComponentW(lpwstrTemp
);
1753 if (!p
) break; /* end of path */
1756 lpszTemp
= lpszTemp
+ strlenW(lpwstrTemp
);
1760 WCHAR wszWild
[] = { '*', '?', 0 };
1761 /* if the last element is a wildcard do a search */
1762 if(strpbrkW(lpszTemp1
, wszWild
) != NULL
)
1764 nOpenAction
= ONOPEN_SEARCH
;
1768 lpszTemp1
= lpszTemp
;
1770 TRACE("parse now=%s next=%s sf=%p\n",debugstr_w(lpwstrTemp
), debugstr_w(lpszTemp
), lpsf
);
1772 if(lstrlenW(lpwstrTemp
)==2) PathAddBackslashW(lpwstrTemp
);
1774 dwAttributes
= SFGAO_FOLDER
;
1775 if(SUCCEEDED(IShellFolder_ParseDisplayName(lpsf
, hwnd
, NULL
, lpwstrTemp
, &dwEaten
, &pidl
, &dwAttributes
)))
1777 /* the path component is valid, we have a pidl of the next path component */
1778 TRACE("parse OK attr=0x%08lx pidl=%p\n", dwAttributes
, pidl
);
1779 if(dwAttributes
& SFGAO_FOLDER
)
1781 if(FAILED(IShellFolder_BindToObject(lpsf
, pidl
, 0, &IID_IShellFolder
, (LPVOID
*)&lpsfChild
)))
1783 ERR("bind to failed\n"); /* should not fail */
1786 IShellFolder_Release(lpsf
);
1794 /* end dialog, return value */
1795 nOpenAction
= ONOPEN_OPEN
;
1798 COMDLG32_SHFree(pidl
);
1801 else if (!(fodInfos
->ofnInfos
->Flags
& OFN_NOVALIDATE
))
1803 if(*lpszTemp
) /* points to trailing null for last path element */
1805 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1807 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_PATHNOTEXISTING
);
1813 if( (fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
) &&
1814 !( fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) )
1816 FILEDLG95_OnOpenMessage(hwnd
, 0, IDS_FILENOTEXISTING
);
1820 /* change to the current folder */
1821 nOpenAction
= ONOPEN_OPEN
;
1826 nOpenAction
= ONOPEN_OPEN
;
1830 if(pidl
) COMDLG32_SHFree(pidl
);
1834 Step 3: here we have a cleaned up and validated path
1837 lpsf: ShellFolder bound to the rightmost valid path component
1838 lpstrPathAndFile: cleaned up path
1839 nOpenAction: action to do
1841 TRACE("end validate sf=%p\n", lpsf
);
1845 case ONOPEN_SEARCH
: /* set the current filter to the file mask and refresh */
1846 TRACE("ONOPEN_SEARCH %s\n", debugstr_w(lpstrPathAndFile
));
1849 LPWSTR lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1852 /* replace the current filter */
1853 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1854 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1855 len
= strlenW(lpszTemp
)+1;
1856 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc(len
* sizeof(WCHAR
));
1857 strcpyW( fodInfos
->ShellInfos
.lpstrCurrentFilter
, lpszTemp
);
1859 /* set the filter cb to the extension when possible */
1860 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpszTemp
)))
1861 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, iPos
);
1864 case ONOPEN_BROWSE
: /* browse to the highest folder we could bind to */
1865 TRACE("ONOPEN_BROWSE\n");
1867 IPersistFolder2
* ppf2
;
1868 if(SUCCEEDED(IShellFolder_QueryInterface( lpsf
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
)))
1870 LPITEMIDLIST pidlCurrent
;
1871 IPersistFolder2_GetCurFolder(ppf2
, &pidlCurrent
);
1872 IPersistFolder2_Release(ppf2
);
1873 if( ! COMDLG32_PIDL_ILIsEqual(pidlCurrent
, fodInfos
->ShellInfos
.pidlAbsCurrent
))
1875 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidlCurrent
, SBSP_ABSOLUTE
);
1877 else if( nOpenAction
== ONOPEN_SEARCH
)
1879 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1881 COMDLG32_SHFree(pidlCurrent
);
1886 case ONOPEN_OPEN
: /* fill in the return struct and close the dialog */
1887 TRACE("ONOPEN_OPEN %s\n", debugstr_w(lpstrPathAndFile
));
1889 /* add default extension */
1890 if (fodInfos
->defext
)
1892 WCHAR
*ext
= PathFindExtensionW(lpstrPathAndFile
);
1896 /* only add "." in case a default extension does exist */
1897 if (*fodInfos
->defext
!= '\0')
1899 const WCHAR szwDot
[] = {'.',0};
1900 int PathLength
= strlenW(lpstrPathAndFile
);
1902 strcatW(lpstrPathAndFile
, szwDot
);
1903 strcatW(lpstrPathAndFile
, fodInfos
->defext
);
1905 /* In Open dialog: if file does not exist try without extension */
1906 if (!(fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1907 && !PathFileExistsW(lpstrPathAndFile
))
1908 lpstrPathAndFile
[PathLength
] = '\0';
1912 /* Set/clear the output OFN_EXTENSIONDIFFERENT flag */
1915 if (!lstrcmpiW(fodInfos
->defext
, ext
))
1916 fodInfos
->ofnInfos
->Flags
&= ~OFN_EXTENSIONDIFFERENT
;
1918 fodInfos
->ofnInfos
->Flags
|= OFN_EXTENSIONDIFFERENT
;
1921 /* In Save dialog: check if the file already exists */
1922 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
1923 && fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
1924 && PathFileExistsW(lpstrPathAndFile
))
1926 WCHAR lpstrOverwrite
[100];
1929 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, lpstrOverwrite
, 100);
1930 answer
= MessageBoxW(hwnd
, lpstrOverwrite
, fodInfos
->title
,
1931 MB_YESNO
| MB_ICONEXCLAMATION
);
1939 /* Check that the size of the file does not exceed buffer size.
1940 (Allow for extra \0 if OFN_MULTISELECT is set.) */
1941 if(strlenW(lpstrPathAndFile
) < fodInfos
->ofnInfos
->nMaxFile
-
1942 ((fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
) ? 1 : 0))
1946 /* fill destination buffer */
1947 if (fodInfos
->ofnInfos
->lpstrFile
)
1949 if(fodInfos
->unicode
)
1951 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1953 strncpyW(ofn
->lpstrFile
, lpstrPathAndFile
, ofn
->nMaxFile
);
1954 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
1955 ofn
->lpstrFile
[lstrlenW(ofn
->lpstrFile
) + 1] = '\0';
1959 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1961 WideCharToMultiByte(CP_ACP
, 0, lpstrPathAndFile
, -1,
1962 ofn
->lpstrFile
, ofn
->nMaxFile
, NULL
, NULL
);
1963 if (ofn
->Flags
& OFN_ALLOWMULTISELECT
)
1964 ofn
->lpstrFile
[lstrlenA(ofn
->lpstrFile
) + 1] = '\0';
1968 /* set filename offset */
1969 lpszTemp
= PathFindFileNameW(lpstrPathAndFile
);
1970 fodInfos
->ofnInfos
->nFileOffset
= (lpszTemp
- lpstrPathAndFile
);
1972 /* set extension offset */
1973 lpszTemp
= PathFindExtensionW(lpstrPathAndFile
);
1974 fodInfos
->ofnInfos
->nFileExtension
= (*lpszTemp
) ? (lpszTemp
- lpstrPathAndFile
) + 1 : 0;
1976 /* set the lpstrFileTitle */
1977 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
1979 LPWSTR lpstrFileTitle
= PathFindFileNameW(lpstrPathAndFile
);
1980 if(fodInfos
->unicode
)
1982 LPOPENFILENAMEW ofn
= (LPOPENFILENAMEW
) fodInfos
->ofnInfos
;
1983 strncpyW(ofn
->lpstrFileTitle
, lpstrFileTitle
, ofn
->nMaxFileTitle
);
1987 LPOPENFILENAMEA ofn
= fodInfos
->ofnInfos
;
1988 WideCharToMultiByte(CP_ACP
, 0, lpstrFileTitle
, -1,
1989 ofn
->lpstrFileTitle
, ofn
->nMaxFileTitle
, NULL
, NULL
);
1993 if ( !FILEDLG95_SendFileOK(hwnd
, fodInfos
) )
1997 FILEDLG95_Clean(hwnd
);
1998 ret
= EndDialog(hwnd
, TRUE
);
2002 /* FIXME set error FNERR_BUFFERTOSMALL */
2003 FILEDLG95_Clean(hwnd
);
2004 ret
= EndDialog(hwnd
, FALSE
);
2012 if(lpsf
) IShellFolder_Release(lpsf
);
2016 /***********************************************************************
2017 * FILEDLG95_SHELL_Init
2019 * Initialisation of the shell objects
2021 static HRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
2023 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2028 * Initialisation of the FileOpenDialogInfos structure
2034 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
2036 /* Disable multi-select if flag not set */
2037 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
2039 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
2041 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
2042 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
2044 /* Construct the IShellBrowser interface */
2045 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
2050 /***********************************************************************
2051 * FILEDLG95_SHELL_ExecuteCommand
2053 * Change the folder option and refresh the view
2054 * If the function succeeds, the return value is nonzero.
2056 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
2058 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2061 TRACE("(%p,%p)\n", hwnd
, lpVerb
);
2063 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
2068 CMINVOKECOMMANDINFO ci
;
2069 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
2070 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
2074 IContextMenu_InvokeCommand(pcm
, &ci
);
2075 IContextMenu_Release(pcm
);
2081 /***********************************************************************
2082 * FILEDLG95_SHELL_UpFolder
2084 * Browse to the specified object
2085 * If the function succeeds, the return value is nonzero.
2087 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
2089 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2093 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2102 /***********************************************************************
2103 * FILEDLG95_SHELL_BrowseToDesktop
2105 * Browse to the Desktop
2106 * If the function succeeds, the return value is nonzero.
2108 static BOOL
FILEDLG95_SHELL_BrowseToDesktop(HWND hwnd
)
2110 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2116 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidl
);
2117 hres
= IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
, pidl
, SBSP_ABSOLUTE
);
2118 COMDLG32_SHFree(pidl
);
2119 return SUCCEEDED(hres
);
2121 /***********************************************************************
2122 * FILEDLG95_SHELL_Clean
2124 * Cleans the memory used by shell objects
2126 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
2128 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2132 COMDLG32_SHFree(fodInfos
->ShellInfos
.pidlAbsCurrent
);
2134 /* clean Shell interfaces */
2135 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
2136 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
2137 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
2138 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
2139 if (fodInfos
->Shell
.FOIDataObject
)
2140 IDataObject_Release(fodInfos
->Shell
.FOIDataObject
);
2143 /***********************************************************************
2144 * FILEDLG95_FILETYPE_Init
2146 * Initialisation of the file type combo box
2148 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
2150 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2154 if(fodInfos
->filter
)
2156 int nFilters
= 0; /* number of filters */
2158 LPCWSTR lpstrPos
= fodInfos
->filter
;
2162 /* filter is a list... title\0ext\0......\0\0
2163 * Set the combo item text to the title and the item data
2166 LPCWSTR lpstrDisplay
;
2170 if(! *lpstrPos
) break; /* end */
2171 lpstrDisplay
= lpstrPos
;
2172 lpstrPos
+= strlenW(lpstrPos
) + 1;
2174 /* Copy the extensions */
2175 if (! *lpstrPos
) return E_FAIL
; /* malformed filter */
2176 if (!(lpstrExt
= MemAlloc((strlenW(lpstrPos
)+1)*sizeof(WCHAR
)))) return E_FAIL
;
2177 strcpyW(lpstrExt
,lpstrPos
);
2178 lpstrPos
+= strlenW(lpstrPos
) + 1;
2180 /* Add the item at the end of the combo */
2181 CBAddStringW(fodInfos
->DlgInfos
.hwndFileTypeCB
, lpstrDisplay
);
2182 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, nFilters
, lpstrExt
);
2186 * Set the current filter to the one specified
2187 * in the initialisation structure
2188 * FIXME: lpstrCustomFilter not handled at all
2191 /* set default filter index */
2192 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->customfilter
== NULL
)
2193 fodInfos
->ofnInfos
->nFilterIndex
= 1;
2195 /* First, check to make sure our index isn't out of bounds. */
2196 if ( fodInfos
->ofnInfos
->nFilterIndex
> nFilters
)
2197 fodInfos
->ofnInfos
->nFilterIndex
= nFilters
;
2199 /* Set the current index selection. */
2200 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
, fodInfos
->ofnInfos
->nFilterIndex
-1);
2202 /* Get the corresponding text string from the combo box. */
2203 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2204 fodInfos
->ofnInfos
->nFilterIndex
-1);
2206 if ((INT
)lpstrFilter
== CB_ERR
) /* control is empty */
2212 CharLowerW(lpstrFilter
); /* lowercase */
2213 len
= strlenW(lpstrFilter
)+1;
2214 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2215 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2221 /***********************************************************************
2222 * FILEDLG95_FILETYPE_OnCommand
2224 * WM_COMMAND of the file type combo box
2225 * If the function succeeds, the return value is nonzero.
2227 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2229 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2237 /* Get the current item of the filetype combo box */
2238 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2240 /* set the current filter index - indexed from 1 */
2241 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+ 1;
2243 /* Set the current filter with the current selection */
2244 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2245 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2247 lpstrFilter
= (LPWSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
2249 if((int)lpstrFilter
!= CB_ERR
)
2252 CharLowerW(lpstrFilter
); /* lowercase */
2253 len
= strlenW(lpstrFilter
)+1;
2254 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc( len
* sizeof(WCHAR
) );
2255 strcpyW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,lpstrFilter
);
2256 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
2259 /* Refresh the actual view to display the included items*/
2260 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
2265 /***********************************************************************
2266 * FILEDLG95_FILETYPE_SearchExt
2268 * searches for a extension in the filetype box
2270 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPCWSTR lpstrExt
)
2272 int i
, iCount
= CBGetCount(hwnd
);
2274 TRACE("%s\n", debugstr_w(lpstrExt
));
2276 if(iCount
!= CB_ERR
)
2278 for(i
=0;i
<iCount
;i
++)
2280 if(!lstrcmpiW(lpstrExt
,(LPWSTR
)CBGetItemDataPtr(hwnd
,i
)))
2287 /***********************************************************************
2288 * FILEDLG95_FILETYPE_Clean
2290 * Clean the memory used by the filetype combo box
2292 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
2294 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2296 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
2300 /* Delete each string of the combo and their associated data */
2301 if(iCount
!= CB_ERR
)
2303 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2305 MemFree((LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
));
2306 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
2309 /* Current filter */
2310 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
2311 MemFree(fodInfos
->ShellInfos
.lpstrCurrentFilter
);
2315 /***********************************************************************
2316 * FILEDLG95_LOOKIN_Init
2318 * Initialisation of the look in combo box
2320 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
2322 IShellFolder
*psfRoot
, *psfDrives
;
2323 IEnumIDList
*lpeRoot
, *lpeDrives
;
2324 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
2326 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
2330 liInfos
->iMaxIndentation
= 0;
2332 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
2334 /* set item height for both text field and listbox */
2335 CBSetItemHeight(hwndCombo
,-1,GetSystemMetrics(SM_CYSMICON
));
2336 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
2338 /* Turn on the extended UI for the combo box like Windows does */
2339 CBSetExtendedUI(hwndCombo
, TRUE
);
2341 /* Initialise data of Desktop folder */
2342 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
2343 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2344 COMDLG32_SHFree(pidlTmp
);
2346 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
2348 SHGetDesktopFolder(&psfRoot
);
2352 /* enumerate the contents of the desktop */
2353 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
2355 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
2357 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
2359 /* special handling for CSIDL_DRIVES */
2360 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
2362 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
2364 /* enumerate the drives */
2365 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
2367 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
2369 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
2370 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
2371 COMDLG32_SHFree(pidlAbsTmp
);
2372 COMDLG32_SHFree(pidlTmp1
);
2374 IEnumIDList_Release(lpeDrives
);
2376 IShellFolder_Release(psfDrives
);
2379 COMDLG32_SHFree(pidlTmp
);
2381 IEnumIDList_Release(lpeRoot
);
2385 IShellFolder_Release(psfRoot
);
2386 COMDLG32_SHFree(pidlDrives
);
2390 /***********************************************************************
2391 * FILEDLG95_LOOKIN_DrawItem
2393 * WM_DRAWITEM message handler
2395 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
2397 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
2398 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
2399 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
2403 HIMAGELIST ilItemImage
;
2406 LPSFOLDER tmpFolder
;
2409 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
2413 if(pDIStruct
->itemID
== -1)
2416 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
2417 pDIStruct
->itemID
)))
2421 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
2423 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2426 sizeof (SHFILEINFOA
),
2427 SHGFI_PIDL
| SHGFI_SMALLICON
|
2428 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
2429 SHGFI_DISPLAYNAME
);
2433 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2436 sizeof (SHFILEINFOA
),
2437 SHGFI_PIDL
| SHGFI_SMALLICON
|
2438 SHGFI_SYSICONINDEX
|
2442 /* Is this item selected ? */
2443 if(pDIStruct
->itemState
& ODS_SELECTED
)
2445 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
2446 SetBkColor(pDIStruct
->hDC
,crHighLight
);
2447 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_HIGHLIGHT
));
2451 SetTextColor(pDIStruct
->hDC
,crText
);
2452 SetBkColor(pDIStruct
->hDC
,crWin
);
2453 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,GetSysColorBrush(COLOR_WINDOW
));
2456 /* Do not indent item if drawing in the edit of the combo */
2457 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2460 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2463 sizeof (SHFILEINFOA
),
2464 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2465 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2470 iIndentation
= tmpFolder
->m_iIndent
;
2472 /* Draw text and icon */
2474 /* Initialise the icon display area */
2475 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2476 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2477 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2478 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2480 /* Initialise the text display area */
2481 GetTextMetricsA(pDIStruct
->hDC
, &tm
);
2482 rectText
.left
= rectIcon
.right
;
2484 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
- tm
.tmHeight
) / 2;
2485 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2487 (pDIStruct
->rcItem
.top
+ pDIStruct
->rcItem
.bottom
+ tm
.tmHeight
) / 2;
2489 /* Draw the icon from the image list */
2490 ImageList_Draw(ilItemImage
,
2497 /* Draw the associated text */
2498 if(sfi
.szDisplayName
)
2499 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2505 /***********************************************************************
2506 * FILEDLG95_LOOKIN_OnCommand
2508 * LookIn combo box WM_COMMAND message handler
2509 * If the function succeeds, the return value is nonzero.
2511 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2513 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2515 TRACE("%p\n", fodInfos
);
2521 LPSFOLDER tmpFolder
;
2524 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2526 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2531 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2532 tmpFolder
->pidlItem
,
2544 /***********************************************************************
2545 * FILEDLG95_LOOKIN_AddItem
2547 * Adds an absolute pidl item to the lookin combo box
2548 * returns the index of the inserted item
2550 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2552 LPITEMIDLIST pidlNext
;
2555 LookInInfos
*liInfos
;
2557 TRACE("%08x\n", iInsertId
);
2562 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2565 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2566 tmpFolder
->m_iIndent
= 0;
2568 /* Calculate the indentation of the item in the lookin*/
2570 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2572 tmpFolder
->m_iIndent
++;
2575 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2577 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2578 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2580 sfi
.dwAttributes
= SFGAO_FILESYSANCESTOR
| SFGAO_FILESYSTEM
;
2581 SHGetFileInfoA((LPSTR
)pidl
,
2585 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2586 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
| SHGFI_ATTR_SPECIFIED
);
2588 TRACE("-- Add %s attr=%08lx\n", sfi
.szDisplayName
, sfi
.dwAttributes
);
2590 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2594 TRACE("-- Add %s at %u\n", sfi
.szDisplayName
, tmpFolder
->m_iIndent
);
2596 /* Add the item at the end of the list */
2599 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2601 /* Insert the item at the iInsertId position*/
2604 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2607 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2611 COMDLG32_SHFree( tmpFolder
->pidlItem
);
2612 MemFree( tmpFolder
);
2617 /***********************************************************************
2618 * FILEDLG95_LOOKIN_InsertItemAfterParent
2620 * Insert an item below its parent
2622 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2625 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2630 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2634 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2637 /* Free pidlParent memory */
2638 COMDLG32_SHFree((LPVOID
)pidlParent
);
2640 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2643 /***********************************************************************
2644 * FILEDLG95_LOOKIN_SelectItem
2646 * Adds an absolute pidl item to the lookin combo box
2647 * returns the index of the inserted item
2649 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2652 LookInInfos
*liInfos
;
2656 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2658 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2662 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2663 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2668 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2669 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2673 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2675 if(iRemovedItem
< iItemPos
)
2680 CBSetCurSel(hwnd
,iItemPos
);
2681 liInfos
->uSelectedItem
= iItemPos
;
2687 /***********************************************************************
2688 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2690 * Remove the item with an expansion level over iExpansionLevel
2692 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2696 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2700 if(liInfos
->iMaxIndentation
<= 2)
2703 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2705 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2706 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2708 CBDeleteString(hwnd
,iItemPos
);
2709 liInfos
->iMaxIndentation
--;
2717 /***********************************************************************
2718 * FILEDLG95_LOOKIN_SearchItem
2720 * Search for pidl in the lookin combo box
2721 * returns the index of the found item
2723 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2726 int iCount
= CBGetCount(hwnd
);
2728 TRACE("0x%08x 0x%x\n",searchArg
, iSearchMethod
);
2730 if (iCount
!= CB_ERR
)
2734 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2736 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
2738 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
2746 /***********************************************************************
2747 * FILEDLG95_LOOKIN_Clean
2749 * Clean the memory used by the lookin combo box
2751 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
2753 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2755 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
2759 /* Delete each string of the combo and their associated data */
2760 if (iCount
!= CB_ERR
)
2762 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2764 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2765 COMDLG32_SHFree(tmpFolder
->pidlItem
);
2767 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2771 /* LookInInfos structure */
2772 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
2775 /***********************************************************************
2776 * FILEDLG95_FILENAME_FillFromSelection
2778 * fills the edit box from the cached DataObject
2780 void FILEDLG95_FILENAME_FillFromSelection (HWND hwnd
)
2782 FileOpenDlgInfos
*fodInfos
;
2784 UINT nFiles
= 0, nFileToOpen
, nFileSelected
, nLength
= 0;
2785 char lpstrTemp
[MAX_PATH
];
2786 LPSTR lpstrAllFile
= NULL
, lpstrCurrFile
= NULL
;
2789 fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2791 /* Count how many files we have */
2792 nFileSelected
= GetNumSelected( fodInfos
->Shell
.FOIDataObject
);
2794 /* calculate the string length, count files */
2795 if (nFileSelected
>= 1)
2797 nLength
+= 3; /* first and last quotes, trailing \0 */
2798 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
2800 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
2804 /* get the total length of the selected file names */
2805 lpstrTemp
[0] = '\0';
2806 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
2808 if ( ! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
) ) /* Ignore folders */
2810 nLength
+= strlen( lpstrTemp
) + 3;
2813 COMDLG32_SHFree( pidl
);
2818 /* allocate the buffer */
2819 if (nFiles
<= 1) nLength
= MAX_PATH
;
2820 lpstrAllFile
= (LPSTR
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nLength
);
2821 lpstrAllFile
[0] = '\0';
2823 /* Generate the string for the edit control */
2826 lpstrCurrFile
= lpstrAllFile
;
2827 for ( nFileToOpen
= 0; nFileToOpen
< nFileSelected
; nFileToOpen
++ )
2829 pidl
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, nFileToOpen
+1 );
2833 /* get the file name */
2834 lpstrTemp
[0] = '\0';
2835 GetName( fodInfos
->Shell
.FOIShellFolder
, pidl
, SHGDN_INFOLDER
|SHGDN_FORPARSING
, lpstrTemp
);
2837 if (! IsPidlFolder(fodInfos
->Shell
.FOIShellFolder
, pidl
)) /* Ignore folders */
2841 *lpstrCurrFile
++ = '\"';
2842 strcpy( lpstrCurrFile
, lpstrTemp
);
2843 lpstrCurrFile
+= strlen( lpstrTemp
);
2844 strcpy( lpstrCurrFile
, "\" " );
2849 strcpy( lpstrAllFile
, lpstrTemp
);
2852 COMDLG32_SHFree( (LPVOID
) pidl
);
2855 SetWindowTextA( fodInfos
->DlgInfos
.hwndFileName
, lpstrAllFile
);
2857 /* Select the file name like Windows does */
2858 SendMessageA(fodInfos
->DlgInfos
.hwndFileName
, EM_SETSEL
, (WPARAM
)0, (LPARAM
)-1);
2860 HeapFree(GetProcessHeap(),0, lpstrAllFile
);
2864 /* copied from shell32 to avoid linking to it */
2865 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
2870 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
2871 COMDLG32_SHFree(src
->u
.pOleStr
);
2875 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
2879 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
2883 FIXME("unknown type!\n");
2886 *(LPSTR
)dest
= '\0';
2893 /***********************************************************************
2894 * FILEDLG95_FILENAME_GetFileNames
2896 * copies the filenames to a 0-delimited string list (A\0B\0C\0\0)
2898 int FILEDLG95_FILENAME_GetFileNames (HWND hwnd
, LPWSTR
* lpstrFileList
, UINT
* sizeUsed
)
2900 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2901 UINT nStrCharCount
= 0; /* index in src buffer */
2902 UINT nFileIndex
= 0; /* index in dest buffer */
2903 UINT nFileCount
= 0; /* number of files */
2904 UINT nStrLen
= 0; /* length of string in edit control */
2905 LPWSTR lpstrEdit
; /* buffer for string from edit control */
2909 /* get the filenames from the edit control */
2910 nStrLen
= SendMessageW(fodInfos
->DlgInfos
.hwndFileName
, WM_GETTEXTLENGTH
, 0, 0);
2911 lpstrEdit
= MemAlloc( (nStrLen
+1)*sizeof(WCHAR
) );
2912 GetDlgItemTextW(hwnd
, IDC_FILENAME
, lpstrEdit
, nStrLen
+1);
2914 TRACE("nStrLen=%u str=%s\n", nStrLen
, debugstr_w(lpstrEdit
));
2916 /* we might get single filename without any '"',
2917 * so we need nStrLen + terminating \0 + end-of-list \0 */
2918 *lpstrFileList
= MemAlloc( (nStrLen
+2)*sizeof(WCHAR
) );
2921 /* build 0-delimited file list from filenames */
2922 while ( nStrCharCount
<= nStrLen
)
2924 if ( lpstrEdit
[nStrCharCount
]=='"' )
2927 while ((lpstrEdit
[nStrCharCount
]!='"') && (nStrCharCount
<= nStrLen
))
2929 (*lpstrFileList
)[nFileIndex
++] = lpstrEdit
[nStrCharCount
];
2933 (*lpstrFileList
)[nFileIndex
++] = '\0';
2940 /* single, unquoted string */
2941 if ((nStrLen
> 0) && (*sizeUsed
== 0) )
2943 strcpyW(*lpstrFileList
, lpstrEdit
);
2944 nFileIndex
= strlenW(lpstrEdit
) + 1;
2945 (*sizeUsed
) = nFileIndex
;
2950 (*lpstrFileList
)[nFileIndex
] = '\0';
2957 #define SETDefFormatEtc(fe,cf,med) \
2959 (fe).cfFormat = cf;\
2960 (fe).dwAspect = DVASPECT_CONTENT; \
2967 * DATAOBJECT Helper functions
2970 /***********************************************************************
2971 * COMCTL32_ReleaseStgMedium
2973 * like ReleaseStgMedium from ole32
2975 static void COMCTL32_ReleaseStgMedium (STGMEDIUM medium
)
2977 if(medium
.pUnkForRelease
)
2979 IUnknown_Release(medium
.pUnkForRelease
);
2983 GlobalUnlock(medium
.u
.hGlobal
);
2984 GlobalFree(medium
.u
.hGlobal
);
2988 /***********************************************************************
2989 * GetPidlFromDataObject
2991 * Return pidl(s) by number from the cached DataObject
2993 * nPidlIndex=0 gets the fully qualified root path
2995 LPITEMIDLIST
GetPidlFromDataObject ( IDataObject
*doSelected
, UINT nPidlIndex
)
2999 FORMATETC formatetc
;
3000 LPITEMIDLIST pidl
= NULL
;
3002 TRACE("sv=%p index=%u\n", doSelected
, nPidlIndex
);
3004 /* Set the FORMATETC structure*/
3005 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3007 /* Get the pidls from IDataObject */
3008 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3010 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3011 if(nPidlIndex
<= cida
->cidl
)
3013 pidl
= COMDLG32_PIDL_ILClone((LPITEMIDLIST
)(&((LPBYTE
)cida
)[cida
->aoffset
[nPidlIndex
]]));
3015 COMCTL32_ReleaseStgMedium(medium
);
3020 /***********************************************************************
3023 * Return the number of selected items in the DataObject.
3026 UINT
GetNumSelected( IDataObject
*doSelected
)
3030 FORMATETC formatetc
;
3032 TRACE("sv=%p\n", doSelected
);
3034 if (!doSelected
) return 0;
3036 /* Set the FORMATETC structure*/
3037 SETDefFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
3039 /* Get the pidls from IDataObject */
3040 if(SUCCEEDED(IDataObject_GetData(doSelected
,&formatetc
,&medium
)))
3042 LPIDA cida
= GlobalLock(medium
.u
.hGlobal
);
3043 retVal
= cida
->cidl
;
3044 COMCTL32_ReleaseStgMedium(medium
);
3054 /***********************************************************************
3057 * Get the pidl's display name (relative to folder) and
3058 * put it in lpstrFileName.
3060 * Return NOERROR on success,
3064 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
3069 TRACE("sf=%p pidl=%p\n", lpsf
, pidl
);
3074 SHGetDesktopFolder(&lpsf
);
3075 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
3076 IShellFolder_Release(lpsf
);
3080 /* Get the display name of the pidl relative to the folder */
3081 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
, pidl
, dwFlags
, &str
)))
3083 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
3088 /***********************************************************************
3089 * GetShellFolderFromPidl
3091 * pidlRel is the item pidl relative
3092 * Return the IShellFolder of the absolute pidl
3094 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
3096 IShellFolder
*psf
= NULL
,*psfParent
;
3098 TRACE("%p\n", pidlAbs
);
3100 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
3103 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
3105 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
3107 IShellFolder_Release(psfParent
);
3111 /* return the desktop */
3117 /***********************************************************************
3120 * Return the LPITEMIDLIST to the parent of the pidl in the list
3122 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
3124 LPITEMIDLIST pidlParent
;
3126 TRACE("%p\n", pidl
);
3128 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
3129 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
3134 /***********************************************************************
3137 * returns the pidl of the file name relative to folder
3138 * NULL if an error occurred
3140 LPITEMIDLIST
GetPidlFromName(IShellFolder
*lpsf
,LPWSTR lpcstrFileName
)
3142 LPITEMIDLIST pidl
= NULL
;
3145 TRACE("sf=%p file=%s\n", lpsf
, debugstr_w(lpcstrFileName
));
3147 if(!lpcstrFileName
) return NULL
;
3148 if(!*lpcstrFileName
) return NULL
;
3152 if (SUCCEEDED(SHGetDesktopFolder(&lpsf
))) {
3153 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3154 IShellFolder_Release(lpsf
);
3159 IShellFolder_ParseDisplayName(lpsf
, 0, NULL
, lpcstrFileName
, &ulEaten
, &pidl
, NULL
);
3166 BOOL
IsPidlFolder (LPSHELLFOLDER psf
, LPCITEMIDLIST pidl
)
3168 ULONG uAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
3171 TRACE("%p, %p\n", psf
, pidl
);
3173 ret
= IShellFolder_GetAttributesOf( psf
, 1, &pidl
, &uAttr
);
3175 TRACE("-- 0x%08lx 0x%08lx\n", uAttr
, ret
);
3176 /* see documentation shell 4.1*/
3177 return uAttr
& (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
);
3180 /***********************************************************************
3181 * BrowseSelectedFolder
3183 static BOOL
BrowseSelectedFolder(HWND hwnd
)
3185 BOOL bBrowseSelFolder
= FALSE
;
3186 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
3190 if (GetNumSelected(fodInfos
->Shell
.FOIDataObject
) == 1)
3192 LPITEMIDLIST pidlSelection
;
3194 /* get the file selected */
3195 pidlSelection
= GetPidlFromDataObject( fodInfos
->Shell
.FOIDataObject
, 1);
3196 if (IsPidlFolder (fodInfos
->Shell
.FOIShellFolder
, pidlSelection
))
3198 if ( FAILED( IShellBrowser_BrowseObject( fodInfos
->Shell
.FOIShellBrowser
,
3199 pidlSelection
, SBSP_RELATIVE
) ) )
3201 WCHAR notexist
[] = {'P','a','t','h',' ','d','o','e','s',
3202 ' ','n','o','t',' ','e','x','i','s','t',0};
3203 MessageBoxW( hwnd
, notexist
, fodInfos
->title
, MB_OK
| MB_ICONEXCLAMATION
);
3206 bBrowseSelFolder
= TRUE
;
3208 COMDLG32_SHFree( pidlSelection
);
3211 return bBrowseSelFolder
;
3215 * Memory allocation methods */
3216 static void *MemAlloc(UINT size
)
3218 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
3221 static void MemFree(void *mem
)
3225 HeapFree(GetProcessHeap(),0,mem
);
3229 /* ------------------ APIs ---------------------- */
3231 /***********************************************************************
3232 * GetOpenFileNameA (COMDLG32.@)
3234 * Creates a dialog box for the user to select a file to open.
3237 * TRUE on success: user enters a valid file
3238 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3241 BOOL WINAPI
GetOpenFileNameA(
3242 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3244 return GetFileDialog95A(ofn
, OPEN_DIALOG
);
3247 /***********************************************************************
3248 * GetOpenFileNameW (COMDLG32.@)
3250 * Creates a dialog box for the user to select a file to open.
3253 * TRUE on success: user enters a valid file
3254 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3257 BOOL WINAPI
GetOpenFileNameW(
3258 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3260 return GetFileDialog95W(ofn
, OPEN_DIALOG
);
3263 /***********************************************************************
3264 * GetSaveFileNameA (COMDLG32.@)
3266 * Creates a dialog box for the user to select a file to save.
3269 * TRUE on success: user enters a valid file
3270 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3273 BOOL WINAPI
GetSaveFileNameA(
3274 LPOPENFILENAMEA ofn
) /* [in/out] address of init structure */
3276 return GetFileDialog95A(ofn
, SAVE_DIALOG
);
3279 /***********************************************************************
3280 * GetSaveFileNameW (COMDLG32.@)
3282 * Creates a dialog box for the user to select a file to save.
3285 * TRUE on success: user enters a valid file
3286 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
3289 BOOL WINAPI
GetSaveFileNameW(
3290 LPOPENFILENAMEW ofn
) /* [in/out] address of init structure */
3292 return GetFileDialog95W(ofn
, SAVE_DIALOG
);