2 * COMMDLG - File Open Dialogs Win95 look and feel
15 #include "debugtools.h"
21 #include "filedlgbrowser.h"
22 #include "wine/obj_contextmenu.h"
24 DEFAULT_DEBUG_CHANNEL(commdlg
);
26 /***********************************************************************
27 * Data structure and global variables
29 typedef struct SFolder
31 int m_iImageIndex
; /* Index of picture in image list */
33 int m_iIndent
; /* Indentation index */
34 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
38 typedef struct tagLookInInfo
45 /***********************************************************************
46 * Defines and global variables
49 /* Draw item constant */
57 /* SearchItem methods */
60 #define ITEM_NOTFOUND -1
62 /* Undefined windows message sent by CreateViewObject*/
63 #define WM_GETISHELLBROWSER WM_USER+7
66 * Those macros exist in windowsx.h. However, you can't really use them since
67 * they rely on the UNICODE defines and can't be use inside Wine itself.
70 /* Combo box macros */
71 #define CBAddString(hwnd,str) \
72 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
74 #define CBInsertString(hwnd,str,pos) \
75 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
77 #define CBDeleteString(hwnd,pos) \
78 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
80 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
81 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
83 #define CBGetItemDataPtr(hwnd,iItemId) \
84 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
86 #define CBGetLBText(hwnd,iItemId,str) \
87 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
89 #define CBGetCurSel(hwnd) \
90 SendMessageA(hwnd,CB_GETCURSEL,0,0);
92 #define CBSetCurSel(hwnd,pos) \
93 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
95 #define CBGetCount(hwnd) \
96 SendMessageA(hwnd,CB_GETCOUNT,0,0);
97 #define CBShowDropDown(hwnd,show) \
98 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
99 #define CBSetItemHeight(hwnd,index,height) \
100 SendMessageA(hwnd,CB_SETITEMHEIGHT,(WPARAM)index,(LPARAM)height);
103 const char *FileOpenDlgInfosStr
= "FileOpenDlgInfos"; /* windows property description string */
104 const char *LookInInfosStr
= "LookInInfos"; /* LOOKIN combo box property */
106 static const char defaultFilter
[] = "*.*";
108 /***********************************************************************
112 /* Internal functions used by the dialog */
113 static LRESULT
FILEDLG95_OnWMInitDialog(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
114 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
);
115 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
);
116 BOOL
FILEDLG95_OnOpen(HWND hwnd
);
117 static LRESULT
FILEDLG95_InitUI(HWND hwnd
);
118 static void FILEDLG95_Clean(HWND hwnd
);
120 /* Functions used by the shell object */
121 static LRESULT
FILEDLG95_SHELL_Init(HWND hwnd
);
122 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
);
123 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
);
124 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
126 /* Functions used by the filetype combo box */
127 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
128 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
129 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPSTR lpstrExt
);
130 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
132 /* Functions used by the Look In combo box */
133 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
134 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
135 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
136 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
137 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
138 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
139 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
140 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
141 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
143 /* Miscellaneous tool functions */
144 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
145 HRESULT
GetFileName(HWND hwnd
, LPITEMIDLIST pidl
, LPSTR lpstrFileName
);
146 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
147 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
148 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPCSTR lpcstrFileName
);
150 /* Shell memory allocation */
151 static void *MemAlloc(UINT size
);
152 static void MemFree(void *mem
);
154 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
);
155 HRESULT WINAPI
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
156 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
);
157 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
158 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
);
160 /***********************************************************************
163 * Creates an Open common dialog box that lets the user select
164 * the drive, directory, and the name of a file or set of files to open.
166 * IN : The FileOpenDlgInfos structure associated with the dialog
167 * OUT : TRUE on success
168 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
170 BOOL WINAPI
GetFileName95(FileOpenDlgInfos
*fodInfos
)
178 /* Create the dialog from a template */
180 if(!(hRes
= FindResourceA(COMMDLG_hInstance32
,MAKEINTRESOURCEA(NEWFILEOPENORD
),RT_DIALOGA
)))
182 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
185 if (!(hDlgTmpl
= LoadResource(COMMDLG_hInstance32
, hRes
)) ||
186 !(template = LockResource( hDlgTmpl
)))
188 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
191 lRes
= DialogBoxIndirectParamA(COMMDLG_hInstance32
,
192 (LPDLGTEMPLATEA
) template,
193 fodInfos
->ofnInfos
->hwndOwner
,
194 (DLGPROC
) FileOpenDlgProc95
,
197 /* Unable to create the dialog*/
204 /***********************************************************************
207 * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
208 * Call GetFileName95 with this structure and clean the memory.
210 * IN : The OPENFILENAMEA initialisation structure passed to
211 * GetOpenFileNameA win api function (see filedlg.c)
213 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
217 FileOpenDlgInfos
*fodInfos
;
219 LPCSTR lpstrFilter
= NULL
;
220 LPSTR lpstrCustomFilter
= NULL
;
221 LPCSTR lpstrInitialDir
= NULL
;
224 /* Initialise FileOpenDlgInfos structure*/
225 fodInfos
= (FileOpenDlgInfos
*)MemAlloc(sizeof(FileOpenDlgInfos
));
227 /* Pass in the original ofn */
228 fodInfos
->ofnInfos
= ofn
;
230 /* Save original hInstance value */
231 hInstance
= ofn
->hInstance
;
232 fodInfos
->ofnInfos
->hInstance
= MapHModuleLS(ofn
->hInstance
);
234 if (ofn
->lpstrFilter
)
237 lpstrFilter
= ofn
->lpstrFilter
;
239 /* filter is a list... title\0ext\0......\0\0 */
240 s
= (LPSTR
)ofn
->lpstrFilter
;
244 x
= (LPSTR
)MemAlloc(s
-ofn
->lpstrFilter
);
245 memcpy(x
,ofn
->lpstrFilter
,s
-ofn
->lpstrFilter
);
246 fodInfos
->ofnInfos
->lpstrFilter
= (LPSTR
)x
;
248 if (ofn
->lpstrCustomFilter
)
251 lpstrCustomFilter
= ofn
->lpstrCustomFilter
;
253 /* filter is a list... title\0ext\0......\0\0 */
254 s
= (LPSTR
)ofn
->lpstrCustomFilter
;
258 x
= MemAlloc(s
-ofn
->lpstrCustomFilter
);
259 memcpy(x
,ofn
->lpstrCustomFilter
,s
-ofn
->lpstrCustomFilter
);
260 fodInfos
->ofnInfos
->lpstrCustomFilter
= (LPSTR
)x
;
263 dwFlags
= ofn
->Flags
;
264 fodInfos
->ofnInfos
->Flags
= ofn
->Flags
|OFN_WINE
;
266 /* Replace the NULL lpstrInitialDir by the current folder */
267 lpstrInitialDir
= ofn
->lpstrInitialDir
;
270 fodInfos
->ofnInfos
->lpstrInitialDir
= MemAlloc(MAX_PATH
);
271 GetCurrentDirectoryA(MAX_PATH
,(LPSTR
)fodInfos
->ofnInfos
->lpstrInitialDir
);
274 /* Initialise the dialog property */
275 fodInfos
->DlgInfos
.dwDlgProp
= 0;
276 fodInfos
->DlgInfos
.hwndCustomDlg
= (HWND
)NULL
;
281 ret
= GetFileName95(fodInfos
);
284 fodInfos
->DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
285 ret
= GetFileName95(fodInfos
);
293 MemFree((LPVOID
)(fodInfos
->ofnInfos
->lpstrInitialDir
));
294 fodInfos
->ofnInfos
->lpstrInitialDir
= lpstrInitialDir
;
298 MemFree((LPVOID
)(fodInfos
->ofnInfos
->lpstrFilter
));
299 fodInfos
->ofnInfos
->lpstrFilter
= lpstrFilter
;
301 if (lpstrCustomFilter
)
303 MemFree((LPVOID
)(fodInfos
->ofnInfos
->lpstrCustomFilter
));
304 fodInfos
->ofnInfos
->lpstrCustomFilter
= lpstrCustomFilter
;
307 ofn
->Flags
= dwFlags
;
308 ofn
->hInstance
= hInstance
;
309 MemFree((LPVOID
)(fodInfos
));
313 /***********************************************************************
316 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
317 * Call GetFileName95 with this structure and clean the memory.
319 * IN : The OPENFILENAMEW initialisation structure passed to
320 * GetOpenFileNameW win api function (see filedlg.c)
323 * some more strings are needing to be convertet AtoW
325 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
328 FileOpenDlgInfos
*fodInfos
;
330 LPCSTR lpstrFilter
= NULL
;
331 LPSTR lpstrCustomFilter
= NULL
;
332 LPWSTR lpstrFile
= NULL
;
335 /* Initialise FileOpenDlgInfos structure*/
336 fodInfos
= (FileOpenDlgInfos
*)MemAlloc(sizeof(FileOpenDlgInfos
));
338 /* Pass in the original ofn */
339 fodInfos
->ofnInfos
= (LPOPENFILENAMEA
) ofn
;
342 hInstance
= fodInfos
->ofnInfos
->hInstance
;
343 fodInfos
->ofnInfos
->hInstance
= MapHModuleLS(ofn
->hInstance
);
345 /* Save lpstrFilter */
346 if (ofn
->lpstrFilter
)
352 lpstrFilter
= fodInfos
->ofnInfos
->lpstrFilter
;
354 /* filter is a list... title\0ext\0......\0\0 */
355 s
= (LPWSTR
)ofn
->lpstrFilter
;
360 n
= s
- ofn
->lpstrFilter
; /* already divides by 2. ptr magic */
361 x
= y
= (LPSTR
)MemAlloc(n
);
362 s
= (LPWSTR
)ofn
->lpstrFilter
;
369 fodInfos
->ofnInfos
->lpstrFilter
= (LPSTR
)y
;
371 /* Save lpstrCustomFilter */
372 if (ofn
->lpstrCustomFilter
)
378 lpstrCustomFilter
= fodInfos
->ofnInfos
->lpstrCustomFilter
;
379 /* filter is a list... title\0ext\0......\0\0 */
380 s
= (LPWSTR
)ofn
->lpstrCustomFilter
;
384 n
= s
- ofn
->lpstrCustomFilter
;
385 x
= y
= (LPSTR
)MemAlloc(n
);
386 s
= (LPWSTR
)ofn
->lpstrCustomFilter
;
393 fodInfos
->ofnInfos
->lpstrCustomFilter
= (LPSTR
)y
;
397 dwFlags
= fodInfos
->ofnInfos
->Flags
;
398 fodInfos
->ofnInfos
->Flags
= ofn
->Flags
|OFN_WINE
|OFN_UNICODE
;
400 /* Initialise the dialog property */
401 fodInfos
->DlgInfos
.dwDlgProp
= 0;
403 /* allocate ansi filename buffer */
404 lpstrFile
= ofn
->lpstrFile
;
405 ofn
->lpstrFile
= MemAlloc(ofn
->nMaxFile
);
410 ret
= GetFileName95(fodInfos
);
413 fodInfos
->DlgInfos
.dwDlgProp
|= FODPROP_SAVEDLG
;
414 ret
= GetFileName95(fodInfos
);
422 fodInfos
->ofnInfos
->Flags
= dwFlags
;
424 /* Restore lpstrFilter */
425 if (fodInfos
->ofnInfos
->lpstrFilter
)
427 MemFree((LPVOID
)(fodInfos
->ofnInfos
->lpstrFilter
));
428 fodInfos
->ofnInfos
->lpstrFilter
= lpstrFilter
;
430 if (fodInfos
->ofnInfos
->lpstrCustomFilter
)
432 MemFree((LPVOID
)(fodInfos
->ofnInfos
->lpstrCustomFilter
));
433 fodInfos
->ofnInfos
->lpstrCustomFilter
= lpstrCustomFilter
;
436 /* Restore hInstance */
437 fodInfos
->ofnInfos
->hInstance
= hInstance
;
438 MemFree((LPVOID
)(fodInfos
));
441 lstrcpynAtoW(lpstrFile
, (LPCSTR
)ofn
->lpstrFile
, ofn
->nMaxFile
);
442 MemFree(ofn
->lpstrFile
);
443 ofn
->lpstrFile
= lpstrFile
;
448 void ArrangeCtrlPositions( HWND hwndChildDlg
, HWND hwndParentDlg
)
451 HWND hwndChild
,hwndStc32
;
452 RECT rectParent
, rectChild
, rectCtrl
, rectStc32
, rectTemp
;
454 POINT ptParentClient
;
456 ptMoveCtl
.x
= ptMoveCtl
.y
= 0;
457 hwndStc32
=GetDlgItem(hwndChildDlg
,stc32
);
458 GetClientRect(hwndParentDlg
,&rectParent
);
459 GetClientRect(hwndChildDlg
,&rectChild
);
462 GetWindowRect(hwndStc32
,&rectStc32
);
463 MapWindowPoints(0, hwndChildDlg
,(LPPOINT
)&rectStc32
,2);
464 CopyRect(&rectTemp
,&rectStc32
);
466 SetRect(&rectStc32
,rectStc32
.left
,rectStc32
.top
,rectStc32
.left
+ (rectParent
.right
-rectParent
.left
),rectStc32
.top
+(rectParent
.bottom
-rectParent
.top
));
467 SetWindowPos(hwndStc32
,0,rectStc32
.left
,rectStc32
.top
,rectStc32
.right
-rectStc32
.left
,rectStc32
.bottom
-rectStc32
.top
,SWP_NOMOVE
|SWP_NOZORDER
| SWP_NOACTIVATE
);
469 if(rectStc32
.right
< rectTemp
.right
)
471 ptParentClient
.x
= max((rectParent
.right
-rectParent
.left
),(rectChild
.right
-rectChild
.left
));
476 ptMoveCtl
.x
= (rectStc32
.right
- rectTemp
.right
);
477 ptParentClient
.x
= max((rectParent
.right
-rectParent
.left
),((rectChild
.right
-rectChild
.left
)+rectStc32
.right
-rectTemp
.right
));
479 if(rectStc32
.bottom
< rectTemp
.bottom
)
481 ptParentClient
.y
= max((rectParent
.bottom
-rectParent
.top
),(rectChild
.bottom
-rectChild
.top
));
486 ptMoveCtl
.y
= (rectStc32
.bottom
- rectTemp
.bottom
);
487 ptParentClient
.y
= max((rectParent
.bottom
-rectParent
.top
),((rectChild
.bottom
-rectChild
.top
)+rectStc32
.bottom
-rectTemp
.bottom
));
492 if( (GetWindow(hwndChildDlg
,GW_CHILD
)) == (HWND
) NULL
)
494 SetRectEmpty(&rectTemp
);
495 ptParentClient
.x
= max((rectParent
.right
-rectParent
.left
),(rectChild
.right
-rectChild
.left
));
496 ptParentClient
.y
= (rectParent
.bottom
-rectParent
.top
) + (rectChild
.bottom
-rectChild
.top
);
497 ptMoveCtl
.y
= rectParent
.bottom
-rectParent
.top
;
500 SetRect(&rectParent
,rectParent
.left
,rectParent
.top
,rectParent
.left
+ptParentClient
.x
,rectParent
.top
+ptParentClient
.y
);
501 AdjustWindowRectEx( &rectParent
,GetWindowLongA(hwndParentDlg
,GWL_STYLE
),FALSE
,GetWindowLongA(hwndParentDlg
,GWL_EXSTYLE
));
503 SetWindowPos(hwndChildDlg
, 0, 0,0, ptParentClient
.x
,ptParentClient
.y
,
505 SetWindowPos(hwndParentDlg
, 0, rectParent
.left
,rectParent
.top
, (rectParent
.right
- rectParent
.left
),
506 (rectParent
.bottom
-rectParent
.top
),SWP_NOMOVE
| SWP_NOZORDER
);
508 hwndChild
= GetWindow(hwndChildDlg
,GW_CHILD
);
511 GetWindowRect(hwndStc32
,&rectStc32
);
512 MapWindowPoints( 0, hwndChildDlg
,(LPPOINT
)&rectStc32
,2);
515 SetRect(&rectStc32
,0,0,0,0);
521 if(hwndChild
!= hwndStc32
)
523 if (GetWindowLongA( hwndChild
, GWL_STYLE
) & WS_MAXIMIZE
)
525 GetWindowRect(hwndChild
,&rectCtrl
);
526 MapWindowPoints( 0, hwndParentDlg
,(LPPOINT
)&rectCtrl
,2);
529 Check the initial position of the controls relative to the initial
530 position and size of stc32 (before it is expanded).
532 if (rectCtrl
.left
>= rectTemp
.right
&& rectCtrl
.top
>= rectTemp
.bottom
)
534 rectCtrl
.left
+= ptMoveCtl
.x
;
535 rectCtrl
.top
+= ptMoveCtl
.y
;
537 else if (rectCtrl
.left
>= rectTemp
.right
)
538 rectCtrl
.left
+= ptMoveCtl
.x
;
539 else if (rectCtrl
.top
>= rectTemp
.bottom
)
540 rectCtrl
.top
+= ptMoveCtl
.y
;
542 SetWindowPos( hwndChild
, 0, rectCtrl
.left
, rectCtrl
.top
,
543 rectCtrl
.right
-rectCtrl
.left
,rectCtrl
.bottom
-rectCtrl
.top
,
544 SWP_NOSIZE
| SWP_NOZORDER
);
547 while ((hwndChild
=GetWindow( hwndChild
, GW_HWNDNEXT
)) != (HWND
)NULL
);
549 hwndChild
= GetWindow(hwndParentDlg
,GW_CHILD
);
553 GetWindowRect(hwndStc32
,&rectStc32
);
554 MapWindowPoints( 0, hwndChildDlg
,(LPPOINT
)&rectStc32
,2);
555 ptMoveCtl
.x
= rectStc32
.left
- 0;
556 ptMoveCtl
.y
= rectStc32
.top
- 0;
561 if(hwndChild
!= hwndChildDlg
)
564 if (GetWindowLongA( hwndChild
, GWL_STYLE
) & WS_MAXIMIZE
)
566 GetWindowRect(hwndChild
,&rectCtrl
);
567 MapWindowPoints( 0, hwndParentDlg
,(LPPOINT
)&rectCtrl
,2);
569 rectCtrl
.left
+= ptMoveCtl
.x
;
570 rectCtrl
.top
+= ptMoveCtl
.y
;
572 SetWindowPos( hwndChild
, 0, rectCtrl
.left
, rectCtrl
.top
,
573 rectCtrl
.right
-rectCtrl
.left
,rectCtrl
.bottom
-rectCtrl
.top
,
574 SWP_NOSIZE
|SWP_NOZORDER
);
577 while ((hwndChild
=GetWindow( hwndChild
, GW_HWNDNEXT
)) != (HWND
)NULL
);
584 HRESULT WINAPI
FileOpenDlgProcUserTemplate(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
586 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(GetParent(hwnd
),FileOpenDlgInfosStr
);
591 fodInfos
= (FileOpenDlgInfos
*)lParam
;
592 lParam
= (LPARAM
) fodInfos
->ofnInfos
;
593 ArrangeCtrlPositions(hwnd
,GetParent(hwnd
));
594 if(fodInfos
&& (fodInfos
->ofnInfos
->Flags
& OFN_ENABLEHOOK
) && fodInfos
->ofnInfos
->lpfnHook
)
595 return CallWindowProcA((WNDPROC
)fodInfos
->ofnInfos
->lpfnHook
,hwnd
,uMsg
,wParam
,lParam
);
599 if(fodInfos
&& (fodInfos
->ofnInfos
->Flags
& OFN_ENABLEHOOK
) && fodInfos
->ofnInfos
->lpfnHook
)
600 return CallWindowProcA((WNDPROC
)fodInfos
->ofnInfos
->lpfnHook
,hwnd
,uMsg
,wParam
,lParam
);
601 return DefWindowProcA(hwnd
,uMsg
,wParam
,lParam
);
604 HWND
CreateTemplateDialog(FileOpenDlgInfos
*fodInfos
,HWND hwnd
)
610 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATE
|| fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
612 if (fodInfos
->ofnInfos
->Flags
& OFN_ENABLETEMPLATEHANDLE
)
614 if( !(template = LockResource( fodInfos
->ofnInfos
->hInstance
)))
616 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
623 if (!(hRes
= FindResourceA(MapHModuleSL(fodInfos
->ofnInfos
->hInstance
),
624 (fodInfos
->ofnInfos
->lpTemplateName
), RT_DIALOGA
)))
626 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
629 if (!(hDlgTmpl
= LoadResource( MapHModuleSL(fodInfos
->ofnInfos
->hInstance
),
631 !(template = LockResource( hDlgTmpl
)))
633 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
638 hChildDlg
= CreateDialogIndirectParamA(fodInfos
->ofnInfos
->hInstance
,template,hwnd
,(DLGPROC
)FileOpenDlgProcUserTemplate
,(LPARAM
)fodInfos
);
641 ShowWindow(hChildDlg
,SW_SHOW
);
645 else if(fodInfos
->ofnInfos
->Flags
& OFN_ENABLEHOOK
&& fodInfos
->ofnInfos
->lpfnHook
)
649 GetClientRect(hwnd
,&rectHwnd
);
650 tmplate
.style
= WS_CHILD
| WS_CLIPSIBLINGS
;
651 tmplate
.dwExtendedStyle
= 0;
655 tmplate
.cx
= rectHwnd
.right
-rectHwnd
.left
;
656 tmplate
.cy
= rectHwnd
.bottom
-rectHwnd
.top
;
658 return CreateDialogIndirectParamA(fodInfos
->ofnInfos
->hInstance
,&tmplate
,hwnd
,(DLGPROC
)FileOpenDlgProcUserTemplate
,(LPARAM
)fodInfos
);
663 /***********************************************************************
664 * SendCustomDlgNotificationMessage
666 * Send CustomDialogNotification (CDN_FIRST -- CDN_LAST) message to the custom template dialog
669 HRESULT
SendCustomDlgNotificationMessage(HWND hwndParentDlg
, UINT uCode
)
671 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwndParentDlg
,FileOpenDlgInfosStr
);
674 if(fodInfos
->DlgInfos
.hwndCustomDlg
)
677 ofnNotify
.hdr
.hwndFrom
=hwndParentDlg
;
678 ofnNotify
.hdr
.idFrom
=0;
679 ofnNotify
.hdr
.code
= uCode
;
680 ofnNotify
.lpOFN
= fodInfos
->ofnInfos
;
681 return SendMessageA(fodInfos
->DlgInfos
.hwndCustomDlg
,WM_NOTIFY
,0,(LPARAM
)&ofnNotify
);
686 /***********************************************************************
687 * FILEDLG95_HandleCustomDialogMessages
689 * Handle Custom Dialog Messages (CDM_FIRST -- CDM_LAST) messages
691 HRESULT
FILEDLG95_HandleCustomDialogMessages(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
695 char lpstrPath
[MAX_PATH
];
696 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
697 if(!fodInfos
) return -1;
701 case CDM_GETFILEPATH
:
702 GetDlgItemTextA(hwnd
,IDC_FILENAME
,lpstrPath
, sizeof(lpstrPath
));
703 lpstrFileSpec
= (LPSTR
)COMDLG32_PathFindFilenameA(lpstrPath
);
704 if (lpstrFileSpec
==lpstrPath
)
706 char lpstrCurrentDir
[MAX_PATH
];
707 /* Prepend the current path */
708 COMDLG32_SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrCurrentDir
);
709 if ((LPSTR
)lParam
!=NULL
)
710 wsnprintfA((LPSTR
)lParam
,(int)wParam
,"%s\\%s",lpstrCurrentDir
,lpstrPath
);
711 reqSize
=strlen(lpstrCurrentDir
)+1+strlen(lpstrPath
)+1;
715 lstrcpynA((LPSTR
)lParam
,(LPSTR
)lpstrPath
,(int)wParam
);
716 reqSize
=strlen(lpstrPath
);
718 /* return the required buffer size */
721 case CDM_GETFOLDERPATH
:
722 COMDLG32_SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,lpstrPath
);
723 if ((LPSTR
)lParam
!=NULL
)
724 lstrcpynA((LPSTR
)lParam
,lpstrPath
,(int)wParam
);
725 return strlen(lpstrPath
);
728 reqSize
=GetDlgItemTextA(hwnd
,IDC_FILENAME
,lpstrPath
, sizeof(lpstrPath
));
729 lpstrFileSpec
= (LPSTR
)COMDLG32_PathFindFilenameA(lpstrPath
);
730 if ((LPSTR
)lParam
!=NULL
)
731 lstrcpynA((LPSTR
)lParam
, lpstrFileSpec
, (int)wParam
);
732 return strlen(lpstrFileSpec
);
734 case CDM_SETCONTROLTEXT
:
736 SetDlgItemTextA( hwnd
, (UINT
) wParam
, (LPSTR
) lParam
);
739 case CDM_HIDECONTROL
:
741 FIXME("CDM_HIDECONTROL,CDM_SETCONTROLTEXT,CDM_SETDEFEXT not implemented\n");
747 /***********************************************************************
750 * File open dialog procedure
752 HRESULT WINAPI
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
757 /* Adds the FileOpenDlgInfos in the property list of the dialog
758 so it will be easily accessible through a GetPropA(...) */
759 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) lParam
);
761 FILEDLG95_OnWMInitDialog(hwnd
, wParam
, lParam
);
762 ((FileOpenDlgInfos
*)lParam
)->DlgInfos
.hwndCustomDlg
=
763 CreateTemplateDialog((FileOpenDlgInfos
*)lParam
,hwnd
);
764 SendCustomDlgNotificationMessage(hwnd
,CDN_INITDONE
);
767 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
770 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
773 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
779 case WM_GETISHELLBROWSER
:
780 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
783 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
788 LPNMHDR lpnmh
= (LPNMHDR
)lParam
;
791 /* set up the button tooltips strings */
792 if(TTN_GETDISPINFOA
== lpnmh
->code
)
794 LPNMTTDISPINFOA lpdi
= (LPNMTTDISPINFOA
)lParam
;
795 switch(lpnmh
->idFrom
)
797 /* Up folder button */
798 case FCIDM_TB_UPFOLDER
:
799 stringId
= IDS_UPFOLDER
;
801 /* New folder button */
802 case FCIDM_TB_NEWFOLDER
:
803 stringId
= IDS_NEWFOLDER
;
805 /* List option button */
806 case FCIDM_TB_SMALLICON
:
807 stringId
= IDS_LISTVIEW
;
809 /* Details option button */
810 case FCIDM_TB_REPORTVIEW
:
811 stringId
= IDS_REPORTVIEW
;
814 lpdi
->hinst
= COMMDLG_hInstance32
;
815 lpdi
->lpszText
= (LPSTR
) stringId
;
820 if(uMsg
>= CDM_FIRST
&& uMsg
<= CDM_LAST
)
821 return FILEDLG95_HandleCustomDialogMessages(hwnd
, uMsg
, wParam
, lParam
);
826 /***********************************************************************
827 * FILEDLG95_OnWMInitDialog
829 * WM_INITDIALOG message handler
831 static LRESULT
FILEDLG95_OnWMInitDialog(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
833 LPITEMIDLIST pidlItemId
;
834 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
838 /* Initialise shell objects */
839 FILEDLG95_SHELL_Init(hwnd
);
841 /* Initialise dialog UI */
842 FILEDLG95_InitUI(hwnd
);
844 /* Initialize the Look In combo box*/
845 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
847 /* Initialize the filter combo box */
848 FILEDLG95_FILETYPE_Init(hwnd
);
850 /* Get the initial directory pidl */
852 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->ofnInfos
->lpstrInitialDir
)))
856 GetCurrentDirectoryA(MAX_PATH
,path
);
857 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,
862 /* Browse to the initial directory */
863 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
,SBSP_RELATIVE
);
865 /* Free pidlItem memory */
866 COMDLG32_SHFree(pidlItemId
);
870 /***********************************************************************
873 * Regroups all the cleaning functions of the filedlg
875 void FILEDLG95_Clean(HWND hwnd
)
877 FILEDLG95_FILETYPE_Clean(hwnd
);
878 FILEDLG95_LOOKIN_Clean(hwnd
);
879 FILEDLG95_SHELL_Clean(hwnd
);
881 /***********************************************************************
882 * FILEDLG95_OnWMCommand
884 * WM_COMMAND message handler
886 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
888 WORD wNotifyCode
= HIWORD(wParam
); /* notification code */
889 WORD wID
= LOWORD(wParam
); /* item, control, or accelerator identifier */
890 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
896 if(FILEDLG95_OnOpen(hwnd
))
897 SendCustomDlgNotificationMessage(hwnd
,CDN_FILEOK
);
901 FILEDLG95_Clean(hwnd
);
902 EndDialog(hwnd
, FALSE
);
904 /* Filetype combo box */
906 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
908 /* LookIn combo box */
910 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
913 /* --- toolbar --- */
914 /* Up folder button */
915 case FCIDM_TB_UPFOLDER
:
916 FILEDLG95_SHELL_UpFolder(hwnd
);
918 /* New folder button */
919 case FCIDM_TB_NEWFOLDER
:
920 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_NEWFOLDER
);
922 /* List option button */
923 case FCIDM_TB_SMALLICON
:
924 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLIST
);
926 /* Details option button */
927 case FCIDM_TB_REPORTVIEW
:
928 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILS
);
935 /* Do not use the listview selection anymore */
936 fodInfos
->DlgInfos
.dwDlgProp
&= ~FODPROP_USEVIEW
;
940 /***********************************************************************
941 * FILEDLG95_OnWMGetIShellBrowser
943 * WM_GETISHELLBROWSER message handler
945 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
948 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
952 SetWindowLongA(hwnd
,DWL_MSGRESULT
,(LONG
)fodInfos
->Shell
.FOIShellBrowser
);
958 /***********************************************************************
962 static LRESULT
FILEDLG95_InitUI(HWND hwnd
)
965 {{VIEW_PARENTFOLDER
, FCIDM_TB_UPFOLDER
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
966 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
967 {VIEW_NEWFOLDER
, FCIDM_TB_NEWFOLDER
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
968 {0, 0, TBSTATE_ENABLED
, TBSTYLE_SEP
, {0, 0}, 0, 0 },
969 {VIEW_LIST
, FCIDM_TB_SMALLICON
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
970 {VIEW_DETAILS
, FCIDM_TB_REPORTVIEW
, TBSTATE_ENABLED
, TBSTYLE_BUTTON
, {0, 0}, 0, 0 },
972 TBADDBITMAP tba
= { HINST_COMMCTRL
, IDB_VIEW_SMALL_COLOR
};
975 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
977 TRACE("%p\n", fodInfos
);
979 /* Get the hwnd of the controls */
980 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
981 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
982 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
984 /* construct the toolbar */
985 GetWindowRect(GetDlgItem(hwnd
,IDC_TOOLBARSTATIC
),&rectTB
);
986 MapWindowPoints( 0, hwnd
,(LPPOINT
)&rectTB
,2);
988 fodInfos
->DlgInfos
.hwndTB
= CreateWindowExA(0, TOOLBARCLASSNAMEA
, (LPSTR
) NULL
,
989 WS_CHILD
| WS_GROUP
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
| CCS_NORESIZE
,
991 hwnd
, (HMENU
) IDC_TOOLBAR
, COMMDLG_hInstance32
, NULL
);
993 SetWindowPos(fodInfos
->DlgInfos
.hwndTB
, 0,
994 rectTB
.left
,rectTB
.top
, rectTB
.right
-rectTB
.left
, rectTB
.bottom
-rectTB
.top
,
995 SWP_SHOWWINDOW
| SWP_NOACTIVATE
| SWP_NOZORDER
);
997 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
) sizeof(TBBUTTON
), 0);
999 /* fixme: use TB_LOADIMAGES when implemented */
1000 /* SendMessageA(fodInfos->DlgInfos.hwndTB, TB_LOADIMAGES, (WPARAM) IDB_VIEW_SMALL_COLOR, HINST_COMMCTRL);*/
1001 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBITMAP
, (WPARAM
) 12, (LPARAM
) &tba
);
1003 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_ADDBUTTONSA
, (WPARAM
) 6,(LPARAM
) &tbb
);
1004 SendMessageA(fodInfos
->DlgInfos
.hwndTB
, TB_AUTOSIZE
, 0, 0);
1006 /* Set the window text with the text specified in the OPENFILENAME structure */
1007 if(fodInfos
->ofnInfos
->lpstrTitle
)
1009 SetWindowTextA(hwnd
,fodInfos
->ofnInfos
->lpstrTitle
);
1011 else if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1013 SetWindowTextA(hwnd
,"Save");
1016 /* Initialise the file name edit control */
1017 if(fodInfos
->ofnInfos
->lpstrFile
)
1019 SetDlgItemTextA(hwnd
,IDC_FILENAME
,fodInfos
->ofnInfos
->lpstrFile
);
1021 /* Must the open as read only check box be checked ?*/
1022 if(fodInfos
->ofnInfos
->Flags
& OFN_READONLY
)
1024 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
1026 /* Must the open as read only check box be hid ?*/
1027 if(fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
)
1029 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
1031 /* Must the help button be hid ?*/
1032 if (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
))
1034 ShowWindow(GetDlgItem(hwnd
, pshHelp
), SW_HIDE
);
1036 /* Resize the height, if open as read only checkbox ad help button
1038 if ( (fodInfos
->ofnInfos
->Flags
& OFN_HIDEREADONLY
) &&
1039 (!(fodInfos
->ofnInfos
->Flags
& OFN_SHOWHELP
)) )
1041 RECT rectDlg
, rectHelp
, rectCancel
;
1042 GetWindowRect(hwnd
, &rectDlg
);
1043 GetWindowRect(GetDlgItem(hwnd
, pshHelp
), &rectHelp
);
1044 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rectCancel
);
1045 /* subtract the height of the help button plus the space between
1046 the help button and the cancel button to the height of the dialog */
1047 SetWindowPos(hwnd
, 0, 0, 0, rectDlg
.right
-rectDlg
.left
,
1048 (rectDlg
.bottom
-rectDlg
.top
) - (rectHelp
.bottom
- rectCancel
.bottom
),
1049 SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOZORDER
);
1051 /* change Open to Save */
1052 if (fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
)
1054 SetDlgItemTextA(hwnd
,IDOK
,"Save");
1059 /***********************************************************************
1060 * FILEDLG95_OnOpenMultipleFiles
1062 * Handles the opening of multiple files.
1065 BOOL
FILEDLG95_OnOpenMultipleFiles(HWND hwnd
, LPSTR lpstrFileList
, UINT nFileCount
, UINT sizeUsed
)
1067 CHAR lpstrPathSpec
[MAX_PATH
] = "";
1068 CHAR lpstrTempFileList
[MAX_PATH
] = "";
1072 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1076 lpstrFile
= fodInfos
->ofnInfos
->lpstrFile
;
1078 COMDLG32_SHGetPathFromIDListA( fodInfos
->ShellInfos
.pidlAbsCurrent
, lpstrPathSpec
);
1079 sizePath
= lstrlenA( lpstrPathSpec
);
1081 memset( lpstrFile
, 0x0, fodInfos
->ofnInfos
->nMaxFile
* sizeof(CHAR
) );
1083 if ( fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
||
1084 !(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
))
1086 LPSTR lpstrTemp
= lpstrFileList
;
1088 for ( nCount
= 0; nCount
< nFileCount
; nCount
++ )
1090 WIN32_FIND_DATAA findData
;
1091 CHAR lpstrFindFile
[MAX_PATH
];
1093 memset( lpstrFindFile
, 0x0, MAX_PATH
* sizeof(CHAR
) );
1095 lstrcpyA( lpstrFindFile
, lpstrPathSpec
);
1096 lstrcatA( lpstrFindFile
, "\\" );
1097 lstrcatA( lpstrFindFile
, lpstrTemp
);
1099 if ( FindFirstFileA( lpstrFindFile
, &findData
) == INVALID_HANDLE_VALUE
)
1101 CHAR lpstrNotFound
[100];
1105 LoadStringA(COMMDLG_hInstance32
, IDS_FILENOTFOUND
, lpstrNotFound
, 100);
1106 LoadStringA(COMMDLG_hInstance32
, IDS_VERIFYFILE
, lpstrMsg
, 100);
1108 strcpy(tmp
, lpstrFindFile
);
1110 strcat(tmp
, lpstrNotFound
);
1112 strcat(tmp
, lpstrMsg
);
1116 fodInfos
->ofnInfos
->lpstrTitle
,
1117 MB_OK
| MB_ICONEXCLAMATION
);
1121 if (!(fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
))
1123 lstrcatA( lpstrTempFileList
, findData
.cAlternateFileName
);
1124 if ( nCount
+ 1 < nFileCount
)
1125 lstrcatA( lpstrTempFileList
, " ");
1127 lpstrTemp
+= strlen(lpstrFileList
) + 1;
1131 if ( fodInfos
->ofnInfos
->Flags
& OFN_EXPLORER
)
1133 lstrcpyA( lpstrFile
, lpstrPathSpec
);
1134 memcpy( lpstrFile
+ sizePath
+ 1, lpstrFileList
, sizeof(CHAR
) * sizeUsed
);
1138 memcpy( lpstrFile
, lpstrTempFileList
, sizeof(CHAR
) * strlen(lpstrTempFileList
));
1141 fodInfos
->ofnInfos
->nFileOffset
= sizePath
+ 1;
1142 fodInfos
->ofnInfos
->nFileExtension
= 0;
1144 /* clean and exit */
1145 FILEDLG95_Clean(hwnd
);
1146 return EndDialog(hwnd
,TRUE
);
1149 /***********************************************************************
1152 * Ok button WM_COMMAND message handler
1154 * If the function succeeds, the return value is nonzero.
1156 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
1158 CHAR lpstrSpecifiedByUser
[MAX_PATH
];
1159 CHAR lpstrFileList
[MAX_PATH
];
1161 UINT nStrCharCount
= 0;
1162 UINT nFileCount
= 0;
1163 UINT nFileIndex
= 0;
1166 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1168 lpstrSpecifiedByUser
[0]=0;
1173 lpstrFile
= fodInfos
->ofnInfos
->lpstrFile
;
1175 GetDlgItemTextA(hwnd
, IDC_FILENAME
, lpstrSpecifiedByUser
, MAX_PATH
);
1176 nStrLen
= strlen(lpstrSpecifiedByUser
);
1178 while ( nStrCharCount
<= nStrLen
)
1180 if ( lpstrSpecifiedByUser
[nStrCharCount
]=='"' )
1183 while ((lpstrSpecifiedByUser
[nStrCharCount
]!='"') &&
1184 (nStrCharCount
<= nStrLen
))
1186 lpstrFileList
[nFileIndex
++] = lpstrSpecifiedByUser
[nStrCharCount
];
1190 lpstrFileList
[nFileIndex
++] = '\0';
1198 return FILEDLG95_OnOpenMultipleFiles(hwnd
, lpstrFileList
, nFileCount
, sizeUsed
);
1202 LPSHELLFOLDER psfDesktop
;
1203 LPITEMIDLIST browsePidl
;
1204 LPSTR lpstrFileSpec
;
1206 char lpstrPathSpec
[MAX_PATH
];
1207 char lpstrCurrentDir
[MAX_PATH
];
1208 char lpstrPathAndFile
[MAX_PATH
];
1210 lpstrPathSpec
[0] = '\0';
1211 lpstrCurrentDir
[0] = '\0';
1212 lpstrPathAndFile
[0] = '\0';
1214 /* Separate the file spec from the path spec
1216 lpstrSpecifiedByUser lpstrPathSpec lpstrFileSpec
1217 C:\TEXT1\TEXT2 C:\TEXT1 TEXT2
1219 if (nFileCount
== 0)
1221 lpstrFileSpec
= (LPSTR
)COMDLG32_PathFindFilenameA(lpstrSpecifiedByUser
);
1222 strcpy(lpstrPathSpec
,lpstrSpecifiedByUser
);
1223 COMDLG32_PathRemoveFileSpecA(lpstrPathSpec
);
1226 /* Get the index of the selected item in the filetype combo box */
1227 fodInfos
->ofnInfos
->nFilterIndex
= (DWORD
) CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1228 /* nFilterIndex is 1 based while combo GetCurSel return zero based index */
1229 fodInfos
->ofnInfos
->nFilterIndex
++;
1231 /* Get the current directory name */
1232 COMDLG32_SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,
1235 /* Create an absolute path name */
1236 if(lpstrSpecifiedByUser
[1] != ':')
1238 switch(lpstrSpecifiedByUser
[0])
1240 /* Add drive spec \TEXT => C:\TEXT */
1243 int lenPathSpec
=strlen(lpstrPathSpec
);
1244 int iCopy
= (lenPathSpec
!=0?2:3);
1245 memmove(lpstrPathSpec
+iCopy
,lpstrPathSpec
,lenPathSpec
);
1246 strncpy(lpstrPathSpec
,lpstrCurrentDir
,iCopy
);
1249 /* Go to parent ..\TEXT */
1253 char lpstrTmp2
[MAX_PATH
];
1254 LPSTR lpstrTmp
= strrchr(lpstrCurrentDir
,'\\');
1256 iSize
= lpstrTmp
- lpstrCurrentDir
;
1257 strncpy(lpstrTmp2
,lpstrCurrentDir
,iSize
+ 1);
1258 if(strlen(lpstrSpecifiedByUser
) <= 3)
1259 *lpstrFileSpec
='\0';
1260 if(strcmp(lpstrPathSpec
,".."))
1261 strcat(lpstrTmp2
,&lpstrPathSpec
[3]);
1262 strcpy(lpstrPathSpec
,lpstrTmp2
);
1267 char lpstrTmp
[MAX_PATH
];
1269 if(strcmp(&lpstrCurrentDir
[strlen(lpstrCurrentDir
)-1],"\\"))
1270 strcat(lpstrCurrentDir
,"\\");
1271 strcpy(lpstrTmp
,lpstrCurrentDir
);
1272 strcat(lpstrTmp
,lpstrPathSpec
);
1273 strcpy(lpstrPathSpec
,lpstrTmp
);
1278 if(strlen(lpstrPathSpec
))
1280 /* Browse to the right directory */
1281 COMDLG32_SHGetDesktopFolder(&psfDesktop
);
1282 if((browsePidl
= GetPidlFromName(psfDesktop
,lpstrPathSpec
)))
1284 /* Browse to directory */
1285 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
1288 COMDLG32_SHFree(browsePidl
);
1292 /* Path does not exist */
1293 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1296 "Path does not exist",
1297 fodInfos
->ofnInfos
->lpstrTitle
,
1298 MB_OK
| MB_ICONEXCLAMATION
);
1303 strcat(lpstrPathAndFile
,lpstrPathSpec
);
1304 IShellFolder_Release(psfDesktop
);
1308 strcat(lpstrPathAndFile
,lpstrCurrentDir
);
1311 /* Create the path and file string */
1312 COMDLG32_PathAddBackslashA(lpstrPathAndFile
);
1313 strcat(lpstrPathAndFile
,lpstrFileSpec
);
1315 /* Update the edit field */
1316 SetDlgItemTextA(hwnd
,IDC_FILENAME
,lpstrFileSpec
);
1317 SendDlgItemMessageA(hwnd
,IDC_FILENAME
,EM_SETSEL
,0,-1);
1319 /* Don't go further if we dont have a file spec */
1320 if(!strlen(lpstrFileSpec
) || !strcmp(lpstrFileSpec
,lpstrPathSpec
))
1323 /* Time to check lpstrFileSpec */
1324 /* search => contains * or ? */
1325 /* browse => contains a directory name */
1326 /* file => contains a file name */
1328 /* Check if this is a search */
1329 if(strchr(lpstrFileSpec
,'*') || strchr(lpstrFileSpec
,'?'))
1333 /* Set the current filter with the current selection */
1334 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1335 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1337 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFileSpec
)+1)*2);
1338 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,
1339 (LPSTR
)strlwr((LPSTR
)lpstrFileSpec
));
1341 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1343 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1345 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
1350 /* browse if the user specified a directory */
1351 browsePidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,
1353 if (!browsePidl
) /* not a directory check the specified file exists */
1356 char lpstrFileSpecTemp
[MAX_PATH
];
1360 iExt
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1361 lpOrg
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
, iExt
);
1362 if ((int)lpOrg
== -1)
1363 lpOrg
= NULL
; /* we get -1 if the filetype LB is empty */
1368 add user specified extentions to the file one by one and
1369 check if the file exists
1374 if ((lpstrExt
= strchr(lpOrg
, ';')))
1376 i
= lpstrExt
- lpOrg
;
1380 lpBuf
= MemAlloc(i
+1);
1381 strncpy(lpBuf
, lpOrg
, i
);
1383 strcpy(lpstrFileSpecTemp
, lpstrFileSpec
);
1384 if (lpstrFileSpecTemp
[strlen(lpstrFileSpecTemp
)-1] == '.')
1386 if (strchr(lpBuf
, '.'))
1387 strcat(lpstrFileSpecTemp
, (strchr(lpBuf
, '.')) + 1);
1390 strcat(lpstrFileSpecTemp
, strchr(lpBuf
, '.'));
1391 browsePidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,
1393 MemFree((void *)lpBuf
);
1396 strcpy(lpstrFileSpec
,lpstrFileSpecTemp
);
1408 ULONG ulAttr
= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
;
1410 char lpstrFileExist
[MAX_PATH
+ 50];
1412 IShellFolder_GetAttributesOf(fodInfos
->Shell
.FOIShellFolder
,
1417 /* Browse to directory if it is a folder */
1418 if (ulAttr
& SFGAO_FOLDER
)
1420 if(FAILED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
1424 if(fodInfos
->ofnInfos
->Flags
& OFN_PATHMUSTEXIST
)
1427 "Path does not exist",
1428 fodInfos
->ofnInfos
->lpstrTitle
,
1429 MB_OK
| MB_ICONEXCLAMATION
);
1430 COMDLG32_SHFree(browsePidl
);
1434 COMDLG32_SHFree(browsePidl
);
1438 /* The file does exist, so ask the user if we should overwrite it */
1439 if((fodInfos
->DlgInfos
.dwDlgProp
& FODPROP_SAVEDLG
) &&
1440 (fodInfos
->ofnInfos
->Flags
& OFN_OVERWRITEPROMPT
))
1442 strcpy(lpstrFileExist
, lpstrFileSpec
);
1443 strcat(lpstrFileExist
, " already exists.\nDo you want to replace it?");
1445 nMsgBoxRet
= MessageBoxA(hwnd
,
1447 fodInfos
->ofnInfos
->lpstrTitle
,
1448 MB_YESNO
| MB_ICONEXCLAMATION
);
1449 if (nMsgBoxRet
== IDNO
)
1451 COMDLG32_SHFree(browsePidl
);
1455 COMDLG32_SHFree(browsePidl
);
1459 /* File does not exist in current directory */
1461 /* The selected file does not exist */
1462 /* Tell the user the selected does not exist */
1463 if(fodInfos
->ofnInfos
->Flags
& OFN_FILEMUSTEXIST
)
1465 char lpstrNotFound
[100];
1469 LoadStringA(COMMDLG_hInstance32
,
1473 LoadStringA(COMMDLG_hInstance32
,
1478 strcpy(tmp
,fodInfos
->ofnInfos
->lpstrFile
);
1480 strcat(tmp
,lpstrNotFound
);
1482 strcat(tmp
,lpstrMsg
);
1486 fodInfos
->ofnInfos
->lpstrTitle
,
1487 MB_OK
| MB_ICONEXCLAMATION
);
1490 /* Ask the user if he wants to create the file*/
1491 if(fodInfos
->ofnInfos
->Flags
& OFN_CREATEPROMPT
)
1495 LoadStringA(COMMDLG_hInstance32
,IDS_CREATEFILE
,tmp
,100);
1497 if(IDYES
== MessageBoxA(hwnd
,tmp
,fodInfos
->ofnInfos
->lpstrTitle
,
1498 MB_YESNO
| MB_ICONQUESTION
))
1500 /* Create the file, clean and exit */
1501 FILEDLG95_Clean(hwnd
);
1502 return EndDialog(hwnd
,TRUE
);
1508 /* Open the selected file */
1510 /* Check file extension */
1511 if(!strrchr(lpstrPathAndFile
,'.'))
1513 /* if the file has no extension, append the selected
1514 extension of the filetype combo box */
1517 iExt
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1518 lpstrTemp
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iExt
);
1520 if((LPSTR
)-1 != lpstrTemp
)
1522 if((lpstrExt
= strchr(lpstrTemp
,';')))
1524 int i
= lpstrExt
- lpstrTemp
;
1525 lpstrExt
= MemAlloc(i
);
1526 strncpy(lpstrExt
,&lpstrTemp
[1],i
-1);
1530 lpstrExt
= MemAlloc(strlen(lpstrTemp
));
1531 strcpy(lpstrExt
,&lpstrTemp
[1]);
1534 if(!strcmp(&lpstrExt
[1],"*") && fodInfos
->ofnInfos
->lpstrDefExt
)
1537 lpstrExt
= MemAlloc(strlen(fodInfos
->ofnInfos
->lpstrDefExt
)+2);
1538 strcat(lpstrExt
,".");
1539 strcat(lpstrExt
,(LPSTR
) fodInfos
->ofnInfos
->lpstrDefExt
);
1541 strcat(lpstrPathAndFile
,lpstrExt
);
1542 MemFree( lpstrExt
);
1545 /* Check that size size of the file does not exceed buffer size */
1546 if(strlen(lpstrPathAndFile
) > fodInfos
->ofnInfos
->nMaxFile
)
1548 /* set error FNERR_BUFFERTOSMALL */
1549 FILEDLG95_Clean(hwnd
);
1550 return EndDialog(hwnd
,FALSE
);
1552 strcpy(fodInfos
->ofnInfos
->lpstrFile
,lpstrPathAndFile
);
1554 /* Set the lpstrFileTitle of the OPENFILENAME structure */
1555 if(fodInfos
->ofnInfos
->lpstrFileTitle
)
1556 strncpy(fodInfos
->ofnInfos
->lpstrFileTitle
,
1558 fodInfos
->ofnInfos
->nMaxFileTitle
);
1560 /* Check if the file is to be opened as read only */
1561 if(BST_CHECKED
== SendDlgItemMessageA(hwnd
,
1564 SetFileAttributesA(fodInfos
->ofnInfos
->lpstrFile
,
1565 FILE_ATTRIBUTE_READONLY
);
1567 /* nFileExtension and nFileOffset of OPENFILENAME structure */
1568 lpstrTemp
= strrchr(fodInfos
->ofnInfos
->lpstrFile
,'\\');
1569 fodInfos
->ofnInfos
->nFileOffset
= lpstrTemp
- fodInfos
->ofnInfos
->lpstrFile
+ 1;
1570 lpstrTemp
= strrchr(fodInfos
->ofnInfos
->lpstrFile
,'.');
1571 fodInfos
->ofnInfos
->nFileExtension
= lpstrTemp
- fodInfos
->ofnInfos
->lpstrFile
+ 1;
1574 /* clean and exit */
1575 FILEDLG95_Clean(hwnd
);
1576 return EndDialog(hwnd
,TRUE
);
1582 /***********************************************************************
1583 * FILEDLG95_SHELL_Init
1585 * Initialisation of the shell objects
1587 static HRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
1589 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1594 * Initialisation of the FileOpenDialogInfos structure
1599 fodInfos
->Shell
.FOIShellView
= NULL
;
1600 if(FAILED(COMDLG32_SHGetDesktopFolder(&fodInfos
->Shell
.FOIShellFolder
)))
1604 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
1606 fodInfos
->ShellInfos
.folderSettings
.fFlags
= 0;
1607 /* Disable multi-select if flag not set */
1608 if (!(fodInfos
->ofnInfos
->Flags
& OFN_ALLOWMULTISELECT
))
1610 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_SINGLESEL
;
1612 fodInfos
->ShellInfos
.folderSettings
.fFlags
|= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
1613 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
1615 GetWindowRect(GetDlgItem(hwnd
,IDC_SHELLSTATIC
),&fodInfos
->ShellInfos
.rectView
);
1616 ScreenToClient(hwnd
,(LPPOINT
)&fodInfos
->ShellInfos
.rectView
.left
);
1617 ScreenToClient(hwnd
,(LPPOINT
)&fodInfos
->ShellInfos
.rectView
.right
);
1619 /* Construct the IShellBrowser interface */
1620 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
1625 /***********************************************************************
1626 * FILEDLG95_SHELL_ExecuteCommand
1628 * Change the folder option and refresh the view
1629 * If the function succeeds, the return value is nonzero.
1631 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
1633 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1636 TRACE("(0x%08x,%p)\n", hwnd
, lpVerb
);
1638 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
1643 CMINVOKECOMMANDINFO ci
;
1644 ZeroMemory(&ci
, sizeof(CMINVOKECOMMANDINFO
));
1645 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
1649 IContextMenu_InvokeCommand(pcm
, &ci
);
1650 IContextMenu_Release(pcm
);
1656 /***********************************************************************
1657 * FILEDLG95_SHELL_UpFolder
1659 * Browse to the specified object
1660 * If the function succeeds, the return value is nonzero.
1662 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
1664 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1668 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
1677 /***********************************************************************
1678 * FILEDLG95_SHELL_Clean
1680 * Cleans the memory used by shell objects
1682 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
1684 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1688 /* clean Shell interfaces */
1689 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
1690 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
1691 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
1692 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
1695 /***********************************************************************
1696 * FILEDLG95_FILETYPE_Init
1698 * Initialisation of the file type combo box
1700 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
1702 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1706 if(fodInfos
->ofnInfos
->lpstrFilter
)
1715 /* filter is a list... title\0ext\0......\0\0
1716 * Set the combo item text to the title and the item data
1719 char *lpstrExt
= NULL
;
1720 LPSTR lpstrExtTmp
= NULL
;
1723 lpstrTmp
= (&((LPBYTE
)fodInfos
->ofnInfos
->lpstrFilter
)[iStrIndex
]);
1724 if(!strlen(lpstrTmp
))
1726 iStrIndex
+= strlen(lpstrTmp
) +1;
1727 /* Get the extension */
1728 lpstrExtTmp
= (&((LPBYTE
)fodInfos
->ofnInfos
->lpstrFilter
)[iStrIndex
]);
1732 lpstrExt
= (LPSTR
) MemAlloc(strlen(lpstrExtTmp
)+1);
1736 strcpy(lpstrExt
,lpstrExtTmp
);
1738 iStrIndex
+= strlen(lpstrExt
) +1;
1740 /* Add the item at the end of the combo */
1741 CBAddString(fodInfos
->DlgInfos
.hwndFileTypeCB
,lpstrTmp
);
1742 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
++,lpstrExt
);
1744 /* Set the current filter to the one specified
1745 * in the initialisation structure
1748 /* set default filter index */
1749 if(fodInfos
->ofnInfos
->nFilterIndex
== 0 && fodInfos
->ofnInfos
->lpstrCustomFilter
== NULL
)
1750 fodInfos
->ofnInfos
->nFilterIndex
= 1;
1751 /* First, check to make sure our index isn't out of bounds. */
1752 if ( fodInfos
->ofnInfos
->nFilterIndex
> iPos
)
1753 fodInfos
->ofnInfos
->nFilterIndex
= iPos
;
1756 /* Get the current index selection. */
1757 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1758 fodInfos
->ofnInfos
->nFilterIndex
-1);
1760 /* Get the corresponding text string from the combo box. */
1761 lpstrFilter
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1762 fodInfos
->ofnInfos
->nFilterIndex
-1);
1766 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFilter
)+1)*2);
1767 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,strlwr(lpstrFilter
));
1773 /***********************************************************************
1774 * FILEDLG95_FILETYPE_OnCommand
1776 * WM_COMMAND of the file type combo box
1777 * If the function succeeds, the return value is nonzero.
1779 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
1781 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1789 /* Get the current item of the filetype combo box */
1790 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1792 /* set the current filter index - indexed from 1 */
1793 fodInfos
->ofnInfos
->nFilterIndex
= iItem
+ 1;
1795 /* Set the current filter with the current selection */
1796 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1797 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1799 lpstrFilter
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1801 if((int)lpstrFilter
!= CB_ERR
)
1803 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFilter
)+1)*2);
1804 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,(LPSTR
)strlwr((LPSTR
)lpstrFilter
));
1805 SendCustomDlgNotificationMessage(hwnd
,CDN_TYPECHANGE
);
1808 /* Refresh the actual view to display the included items*/
1809 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1815 /***********************************************************************
1816 * FILEDLG95_FILETYPE_SearchExt
1818 * Search for pidl in the lookin combo box
1819 * returns the index of the found item
1821 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPSTR lpstrExt
)
1824 int iCount
= CBGetCount(hwnd
);
1830 LPSTR ext
= (LPSTR
) CBGetItemDataPtr(hwnd
,i
);
1831 if(!strcasecmp(lpstrExt
,ext
))
1838 /***********************************************************************
1839 * FILEDLG95_FILETYPE_Clean
1841 * Clean the memory used by the filetype combo box
1843 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
1845 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1847 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1851 /* Delete each string of the combo and their associated data */
1852 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
1854 MemFree((LPVOID
)(CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
)));
1855 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
1857 /* Current filter */
1858 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1859 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1863 /***********************************************************************
1864 * FILEDLG95_LOOKIN_Init
1866 * Initialisation of the look in combo box
1868 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
1870 IShellFolder
*psfRoot
, *psfDrives
;
1871 IEnumIDList
*lpeRoot
, *lpeDrives
;
1872 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
1874 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
1878 liInfos
->iMaxIndentation
= 0;
1880 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
1881 CBSetItemHeight(hwndCombo
,0,GetSystemMetrics(SM_CYSMICON
));
1883 /* Initialise data of Desktop folder */
1884 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
1885 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
1886 COMDLG32_SHFree(pidlTmp
);
1888 COMDLG32_SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
1890 COMDLG32_SHGetDesktopFolder(&psfRoot
);
1894 /* enumerate the contents of the desktop */
1895 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
1897 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
1899 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
1901 /* special handling for CSIDL_DRIVES */
1902 if (COMDLG32_PIDL_ILIsEqual(pidlTmp
, pidlDrives
))
1904 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
1906 /* enumerate the drives */
1907 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
1909 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
1911 pidlAbsTmp
= COMDLG32_PIDL_ILCombine(pidlTmp
, pidlTmp1
);
1912 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
1913 COMDLG32_SHFree(pidlAbsTmp
);
1914 COMDLG32_SHFree(pidlTmp1
);
1916 IEnumIDList_Release(lpeDrives
);
1918 IShellFolder_Release(psfDrives
);
1921 COMDLG32_SHFree(pidlTmp
);
1923 IEnumIDList_Release(lpeRoot
);
1927 IShellFolder_Release(psfRoot
);
1928 COMDLG32_SHFree(pidlDrives
);
1932 /***********************************************************************
1933 * FILEDLG95_LOOKIN_DrawItem
1935 * WM_DRAWITEM message handler
1937 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
1939 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
1940 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
1941 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
1945 HIMAGELIST ilItemImage
;
1947 LPSFOLDER tmpFolder
;
1950 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
1954 if(pDIStruct
->itemID
== -1)
1957 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
1958 pDIStruct
->itemID
)))
1962 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
1964 ilItemImage
= (HIMAGELIST
) COMDLG32_SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
1967 sizeof (SHFILEINFOA
),
1968 SHGFI_PIDL
| SHGFI_SMALLICON
|
1969 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
1970 SHGFI_DISPLAYNAME
);
1974 ilItemImage
= (HIMAGELIST
) COMDLG32_SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
1977 sizeof (SHFILEINFOA
),
1978 SHGFI_PIDL
| SHGFI_SMALLICON
|
1979 SHGFI_SYSICONINDEX
|
1983 /* Is this item selected ?*/
1984 if(pDIStruct
->itemState
& ODS_SELECTED
)
1986 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
1987 SetBkColor(pDIStruct
->hDC
,crHighLight
);
1988 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,(HBRUSH
)crHighLight
);
1992 SetTextColor(pDIStruct
->hDC
,crText
);
1993 SetBkColor(pDIStruct
->hDC
,crWin
);
1994 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,(HBRUSH
)crWin
);
1997 /* Do not indent item if drawing in the edit of the combo*/
1998 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
2001 ilItemImage
= (HIMAGELIST
) COMDLG32_SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
2004 sizeof (SHFILEINFOA
),
2005 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
2006 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
2011 iIndentation
= tmpFolder
->m_iIndent
;
2013 /* Draw text and icon */
2015 /* Initialise the icon display area */
2016 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
2017 rectIcon
.top
= pDIStruct
->rcItem
.top
;
2018 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
2019 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
2021 /* Initialise the text display area */
2022 rectText
.left
= rectIcon
.right
;
2023 rectText
.top
= pDIStruct
->rcItem
.top
+ YTEXTOFFSET
;
2024 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
2025 rectText
.bottom
= pDIStruct
->rcItem
.bottom
;
2028 /* Draw the icon from the image list */
2029 COMDLG32_ImageList_Draw(ilItemImage
,
2036 /* Draw the associated text */
2037 if(sfi
.szDisplayName
)
2038 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
2044 /***********************************************************************
2045 * FILEDLG95_LOOKIN_OnCommand
2047 * LookIn combo box WM_COMMAND message handler
2048 * If the function succeeds, the return value is nonzero.
2050 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
2052 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2054 TRACE("%p\n", fodInfos
);
2060 LPSFOLDER tmpFolder
;
2063 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
2065 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
2070 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
2071 tmpFolder
->pidlItem
,
2083 /***********************************************************************
2084 * FILEDLG95_LOOKIN_AddItem
2086 * Adds an absolute pidl item to the lookin combo box
2087 * returns the index of the inserted item
2089 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
2091 LPITEMIDLIST pidlNext
;
2094 LookInInfos
*liInfos
;
2101 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
2104 tmpFolder
= MemAlloc(sizeof(SFOLDER
));
2105 tmpFolder
->m_iIndent
= 0;
2107 /* Calculate the indentation of the item in the lookin*/
2109 while( (pidlNext
=COMDLG32_PIDL_ILGetNext(pidlNext
)) )
2111 tmpFolder
->m_iIndent
++;
2114 tmpFolder
->pidlItem
= COMDLG32_PIDL_ILClone(pidl
);
2116 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
2117 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
2119 COMDLG32_SHGetFileInfoA((LPSTR
)pidl
,
2123 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
2124 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
);
2127 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
2130 /* Add the item at the end of the list */
2133 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
2135 /* Insert the item at the iInsertId position*/
2138 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
2141 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
2145 MemFree( tmpFolder
);
2150 /***********************************************************************
2151 * FILEDLG95_LOOKIN_InsertItemAfterParent
2153 * Insert an item below its parent
2155 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
2158 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
2163 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
2167 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
2170 /* Free pidlParent memory */
2171 COMDLG32_SHFree((LPVOID
)pidlParent
);
2173 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
2176 /***********************************************************************
2177 * FILEDLG95_LOOKIN_SelectItem
2179 * Adds an absolute pidl item to the lookin combo box
2180 * returns the index of the inserted item
2182 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
2185 LookInInfos
*liInfos
;
2189 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
2191 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2195 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
2196 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
2201 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2202 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
2206 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
2208 if(iRemovedItem
< iItemPos
)
2213 CBSetCurSel(hwnd
,iItemPos
);
2214 liInfos
->uSelectedItem
= iItemPos
;
2220 /***********************************************************************
2221 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
2223 * Remove the item with an expansion level over iExpansionLevel
2225 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
2229 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
2233 if(liInfos
->iMaxIndentation
<= 2)
2236 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
2239 tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
2240 CBDeleteString(hwnd
,iItemPos
);
2241 liInfos
->iMaxIndentation
--;
2249 /***********************************************************************
2250 * FILEDLG95_LOOKIN_SearchItem
2252 * Search for pidl in the lookin combo box
2253 * returns the index of the found item
2255 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
2258 int iCount
= CBGetCount(hwnd
);
2264 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
2266 if(iSearchMethod
== SEARCH_PIDL
&& COMDLG32_PIDL_ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
2268 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
2276 /***********************************************************************
2277 * FILEDLG95_LOOKIN_Clean
2279 * Clean the memory used by the lookin combo box
2281 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
2283 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
2285 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
2289 /* Delete each string of the combo and their associated data */
2290 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
2292 MemFree((LPVOID
)(CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
)));
2293 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
2295 /* LookInInfos structure */
2296 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
2303 /* copied from shell32 to avoid linking to it */
2304 static HRESULT
COMDLG32_StrRetToStrNA (LPVOID dest
, DWORD len
, LPSTRRET src
, LPITEMIDLIST pidl
)
2309 WideCharToMultiByte(CP_ACP
, 0, src
->u
.pOleStr
, -1, (LPSTR
)dest
, len
, NULL
, NULL
);
2310 COMDLG32_SHFree(src
->u
.pOleStr
);
2314 lstrcpynA((LPSTR
)dest
, src
->u
.cStr
, len
);
2317 case STRRET_OFFSETA
:
2318 lstrcpynA((LPSTR
)dest
, ((LPCSTR
)&pidl
->mkid
)+src
->u
.uOffset
, len
);
2322 FIXME("unknown type!\n");
2325 *(LPSTR
)dest
= '\0';
2332 /***********************************************************************
2335 * Get the pidl's display name (relative to folder) and
2336 * put it in lpstrFileName.
2338 * Return NOERROR on success,
2342 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
2347 TRACE("%p %p\n", lpsf
, pidl
);
2352 COMDLG32_SHGetDesktopFolder(&lpsf
);
2353 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
2354 IShellFolder_Release(lpsf
);
2358 /* Get the display name of the pidl relative to the folder */
2359 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
,
2364 return COMDLG32_StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
2369 /***********************************************************************
2370 * GetShellFolderFromPidl
2372 * pidlRel is the item pidl relative
2373 * Return the IShellFolder of the absolute pidl
2375 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
2377 IShellFolder
*psf
= NULL
,*psfParent
;
2379 TRACE("%p\n", pidlAbs
);
2381 if(SUCCEEDED(COMDLG32_SHGetDesktopFolder(&psfParent
)))
2384 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
2386 if(SUCCEEDED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
2388 IShellFolder_Release(psfParent
);
2392 /* return the desktop */
2398 /***********************************************************************
2401 * Return the LPITEMIDLIST to the parent of the pidl in the list
2403 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
2405 LPITEMIDLIST pidlParent
;
2407 TRACE("%p\n", pidl
);
2409 pidlParent
= COMDLG32_PIDL_ILClone(pidl
);
2410 COMDLG32_PIDL_ILRemoveLastID(pidlParent
);
2415 /***********************************************************************
2418 * returns the pidl of the file name relative to folder
2419 * NULL if an error occured
2421 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPCSTR lpcstrFileName
)
2425 wchar_t lpwstrDirName
[MAX_PATH
];
2428 TRACE("sf=%p file=%s\n", psf
, lpcstrFileName
);
2433 MultiByteToWideChar(CP_ACP
,
2437 (LPWSTR
)lpwstrDirName
,
2440 IShellFolder_ParseDisplayName(psf
, 0,
2442 (LPWSTR
)lpwstrDirName
,
2450 /***********************************************************************
2454 BOOL
GetFileExtension(IShellFolder
*psf
,LPITEMIDLIST pidl
,LPSTR lpstrFileExtension
)
2456 char FileName
[MAX_PATH
];
2461 if(SUCCEEDED(GetName(psf
,pidl
,SHGDN_NORMAL
,FileName
)))
2463 if(!(pdest
= strrchr( FileName
, ch
)))
2466 result
= pdest
- FileName
+ 1;
2467 strcpy(lpstrFileExtension
,&FileName
[result
]);
2474 * Memory allocation methods */
2475 static void *MemAlloc(UINT size
)
2477 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
2480 static void MemFree(void *mem
)
2484 HeapFree(GetProcessHeap(),0,mem
);