2 * COMMDLG - File Open Dialogs Win95 look and feel
13 #include "debugtools.h"
20 #include "filedlgbrowser.h"
21 #include "wine/undocshell.h"
22 #include "wine/obj_contextmenu.h"
24 DEFAULT_DEBUG_CHANNEL(commdlg
)
28 /***********************************************************************
29 * Data structure and global variables
31 typedef struct SFolder
33 int m_iImageIndex
; /* Index of picture in image list */
35 int m_iIndent
; /* Indentation index */
36 LPITEMIDLIST pidlItem
; /* absolute pidl of the item */
40 typedef struct tagLookInInfo
47 /***********************************************************************
48 * Defines and global variables
51 /* Draw item constant */
59 /* SearchItem methods */
62 #define ITEM_NOTFOUND -1
64 /* Undefined windows message sent by CreateViewObject*/
65 #define WM_GETISHELLBROWSER WM_USER+7
68 * Those macros exist in windowsx.h. However, you can't really use them since
69 * they rely on the UNICODE defines and can't be use inside Wine itself.
72 /* Combo box macros */
73 #define CBAddString(hwnd,str) \
74 SendMessageA(hwnd,CB_ADDSTRING,0,(LPARAM)str);
76 #define CBInsertString(hwnd,str,pos) \
77 SendMessageA(hwnd,CB_INSERTSTRING,(WPARAM)pos,(LPARAM)str);
79 #define CBDeleteString(hwnd,pos) \
80 SendMessageA(hwnd,CB_DELETESTRING,(WPARAM)pos,0);
82 #define CBSetItemDataPtr(hwnd,iItemId,dataPtr) \
83 SendMessageA(hwnd,CB_SETITEMDATA,(WPARAM)iItemId,(LPARAM)dataPtr);
85 #define CBGetItemDataPtr(hwnd,iItemId) \
86 SendMessageA(hwnd,CB_GETITEMDATA,(WPARAM)iItemId,0)
88 #define CBGetLBText(hwnd,iItemId,str) \
89 SendMessageA(hwnd,CB_GETLBTEXT,(WPARAM)iItemId,(LPARAM)str);
91 #define CBGetCurSel(hwnd) \
92 SendMessageA(hwnd,CB_GETCURSEL,0,0);
94 #define CBSetCurSel(hwnd,pos) \
95 SendMessageA(hwnd,CB_SETCURSEL,(WPARAM)pos,0);
97 #define CBGetCount(hwnd) \
98 SendMessageA(hwnd,CB_GETCOUNT,0,0);
99 #define CBShowDropDown(hwnd,show) \
100 SendMessageA(hwnd,CB_SHOWDROPDOWN,(WPARAM)show,0);
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 BOOL
FILEDLG95_SHELL_NewFolder(HWND hwnd
);
125 BOOL
FILEDLG95_SHELL_FillIncludedItemList(HWND hwnd
,
126 LPITEMIDLIST pidlCurrentFolder
,
128 static void FILEDLG95_SHELL_Clean(HWND hwnd
);
129 /* Functions used by the filetype combo box */
130 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
);
131 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
);
132 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPSTR lpstrExt
);
133 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
);
135 /* Functions used by the Look In combo box */
136 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
);
137 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
);
138 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
);
139 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
);
140 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
);
141 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
);
142 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
);
143 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
);
144 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
);
146 /* Miscellaneous tool functions */
147 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
);
148 HRESULT
GetFileName(HWND hwnd
, LPITEMIDLIST pidl
, LPSTR lpstrFileName
);
149 IShellFolder
* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
);
150 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
);
151 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPCSTR lpcstrFileName
);
153 /* Shell memory allocation */
154 void *MemAlloc(UINT size
);
155 void MemFree(void *mem
);
157 BOOL WINAPI
GetOpenFileName95(FileOpenDlgInfos
*fodInfos
);
158 BOOL WINAPI
GetSaveFileName95(FileOpenDlgInfos
*fodInfos
);
159 HRESULT WINAPI
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
161 /***********************************************************************
164 * Creates an Open common dialog box that lets the user select
165 * the drive, directory, and the name of a file or set of files to open.
167 * IN : The FileOpenDlgInfos structure associated with the dialog
168 * OUT : TRUE on success
169 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
171 BOOL WINAPI
GetOpenFileName95(FileOpenDlgInfos
*fodInfos
)
179 /* Create the dialog from a template */
181 if (fodInfos
->ofnInfos
.Flags
& OFN_ENABLETEMPLATEHANDLE
)
183 if (!(template = LockResource( MapHModuleSL(fodInfos
->ofnInfos
.hInstance
))))
185 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
189 else if (fodInfos
->ofnInfos
.Flags
& OFN_ENABLETEMPLATE
)
191 if (!(hRes
= FindResourceA(MapHModuleSL(fodInfos
->ofnInfos
.hInstance
),
192 (fodInfos
->ofnInfos
.lpTemplateName
), RT_DIALOGA
)))
194 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
197 if (!(hDlgTmpl
= LoadResource( MapHModuleSL(fodInfos
->ofnInfos
.hInstance
),
199 !(template = LockResource( hDlgTmpl
)))
201 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
207 if(!(hRes
= FindResourceA(COMMDLG_hInstance32
,MAKEINTRESOURCEA(IDD_OPENDIALOG
),RT_DIALOGA
)))
209 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
212 if (!(hDlgTmpl
= LoadResource(COMMDLG_hInstance32
, hRes
)) ||
213 !(template = LockResource( hDlgTmpl
)))
215 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
220 lRes
= DialogBoxIndirectParamA(COMMDLG_hInstance32
,
221 (LPDLGTEMPLATEA
) template,
222 fodInfos
->ofnInfos
.hwndOwner
,
223 (DLGPROC
) FileOpenDlgProc95
,
226 /* Unable to create the dialog*/
233 /***********************************************************************
236 * Creates an Save as common dialog box that lets the user select
237 * the drive, directory, and the name of a file or set of files to open.
239 * IN : The FileOpenDlgInfos structure associated with the dialog
240 * OUT : TRUE on success
241 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
243 BOOL WINAPI
GetSaveFileName95(FileOpenDlgInfos
*fodInfos
)
251 /* Create the dialog from a template */
253 if (fodInfos
->ofnInfos
.Flags
& OFN_ENABLETEMPLATEHANDLE
)
255 if (!(template = LockResource( MapHModuleSL(fodInfos
->ofnInfos
.hInstance
))))
257 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
261 else if (fodInfos
->ofnInfos
.Flags
& OFN_ENABLETEMPLATE
)
263 if (!(hRes
= FindResourceA(MapHModuleSL(fodInfos
->ofnInfos
.hInstance
),
264 (fodInfos
->ofnInfos
.lpTemplateName
), RT_DIALOGA
)))
266 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
269 if (!(hDlgTmpl
= LoadResource( MapHModuleSL(fodInfos
->ofnInfos
.hInstance
),
271 !(template = LockResource( hDlgTmpl
)))
273 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
279 if(!(hRes
= FindResourceA(COMMDLG_hInstance32
,MAKEINTRESOURCEA(IDD_SAVEDIALOG
),RT_DIALOGA
)))
281 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE
);
284 if (!(hDlgTmpl
= LoadResource(COMMDLG_hInstance32
, hRes
)) ||
285 !(template = LockResource( hDlgTmpl
)))
287 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE
);
291 lRes
= DialogBoxIndirectParamA(COMMDLG_hInstance32
,
292 (LPDLGTEMPLATEA
) template,
293 fodInfos
->ofnInfos
.hwndOwner
,
294 (DLGPROC
) FileOpenDlgProc95
,
296 /* Unable to create the dialog*/
303 /***********************************************************************
306 * Copy the OPENFILENAMEA structure in a FileOpenDlgInfos structure.
307 * Call GetOpenFileName95 with this structure and clean the memory.
309 * IN : The OPENFILENAMEA initialisation structure passed to
310 * GetOpenFileNameA win api function (see filedlg.c)
312 BOOL WINAPI
GetFileDialog95A(LPOPENFILENAMEA ofn
,UINT iDlgType
)
316 FileOpenDlgInfos
*fodInfos
;
318 /* Initialise FileOpenDlgInfos structure*/
319 fodInfos
= (FileOpenDlgInfos
*)MemAlloc(sizeof(FileOpenDlgInfos
));
320 memset(&fodInfos
->ofnInfos
,'\0',sizeof(*ofn
)); fodInfos
->ofnInfos
.lStructSize
= sizeof(*ofn
);
321 fodInfos
->ofnInfos
.hwndOwner
= ofn
->hwndOwner
;
322 fodInfos
->ofnInfos
.hInstance
= MapHModuleLS(ofn
->hInstance
);
323 if (ofn
->lpstrFilter
)
327 /* filter is a list... title\0ext\0......\0\0 */
328 s
= (LPSTR
)ofn
->lpstrFilter
;
332 x
= (LPSTR
)MemAlloc(s
-ofn
->lpstrFilter
);
333 memcpy(x
,ofn
->lpstrFilter
,s
-ofn
->lpstrFilter
);
334 fodInfos
->ofnInfos
.lpstrFilter
= (LPSTR
)x
;
336 if (ofn
->lpstrCustomFilter
)
340 /* filter is a list... title\0ext\0......\0\0 */
341 s
= (LPSTR
)ofn
->lpstrCustomFilter
;
345 x
= MemAlloc(s
-ofn
->lpstrCustomFilter
);
346 memcpy(x
,ofn
->lpstrCustomFilter
,s
-ofn
->lpstrCustomFilter
);
347 fodInfos
->ofnInfos
.lpstrCustomFilter
= (LPSTR
)x
;
349 fodInfos
->ofnInfos
.nMaxCustFilter
= ofn
->nMaxCustFilter
;
350 if(ofn
->nFilterIndex
)
351 fodInfos
->ofnInfos
.nFilterIndex
= --ofn
->nFilterIndex
;
354 fodInfos
->ofnInfos
.lpstrFile
= (LPSTR
)MemAlloc(ofn
->nMaxFile
);
355 strcpy((LPSTR
)fodInfos
->ofnInfos
.lpstrFile
,ofn
->lpstrFile
);
357 fodInfos
->ofnInfos
.nMaxFile
= ofn
->nMaxFile
;
358 fodInfos
->ofnInfos
.nMaxFileTitle
= ofn
->nMaxFileTitle
;
359 if (fodInfos
->ofnInfos
.nMaxFileTitle
)
360 fodInfos
->ofnInfos
.lpstrFileTitle
= (LPSTR
)MemAlloc(ofn
->nMaxFileTitle
);
361 if (ofn
->lpstrInitialDir
)
363 fodInfos
->ofnInfos
.lpstrInitialDir
= (LPSTR
)MemAlloc(strlen(ofn
->lpstrInitialDir
));
364 strcpy((LPSTR
)fodInfos
->ofnInfos
.lpstrInitialDir
,ofn
->lpstrInitialDir
);
369 fodInfos
->ofnInfos
.lpstrTitle
= (LPSTR
)MemAlloc(strlen(ofn
->lpstrTitle
));
370 strcpy((LPSTR
)fodInfos
->ofnInfos
.lpstrTitle
,ofn
->lpstrTitle
);
373 fodInfos
->ofnInfos
.Flags
= ofn
->Flags
|OFN_WINE
;
374 fodInfos
->ofnInfos
.nFileOffset
= ofn
->nFileOffset
;
375 fodInfos
->ofnInfos
.nFileExtension
= ofn
->nFileExtension
;
376 if (ofn
->lpstrDefExt
)
378 fodInfos
->ofnInfos
.lpstrDefExt
= MemAlloc(strlen(ofn
->lpstrDefExt
));
379 strcpy((LPSTR
)fodInfos
->ofnInfos
.lpstrDefExt
,ofn
->lpstrDefExt
);
381 fodInfos
->ofnInfos
.lCustData
= ofn
->lCustData
;
382 fodInfos
->ofnInfos
.lpfnHook
= (LPOFNHOOKPROC
)ofn
->lpfnHook
;
384 if (ofn
->lpTemplateName
)
386 /* template don't work - using normal dialog */
387 /* fodInfos->ofnInfos.lpTemplateName = MemAlloc(strlen(ofn->lpTemplateName));
388 strcpy((LPSTR)fodInfos->ofnInfos.lpTemplateName,ofn->lpTemplateName);*/
389 fodInfos
->ofnInfos
.Flags
&= ~OFN_ENABLETEMPLATEHANDLE
;
390 fodInfos
->ofnInfos
.Flags
&= ~OFN_ENABLETEMPLATE
;
391 FIXME("File dialog 95 template not implemented\n");
395 /* Replace the NULL lpstrInitialDir by the current folder */
396 if(!ofn
->lpstrInitialDir
)
398 fodInfos
->ofnInfos
.lpstrInitialDir
= MemAlloc(MAX_PATH
);
399 GetCurrentDirectoryA(MAX_PATH
,(LPSTR
)fodInfos
->ofnInfos
.lpstrInitialDir
);
405 ret
= GetOpenFileName95(fodInfos
);
408 ret
= GetSaveFileName95(fodInfos
);
414 ofn
->nFileOffset
= fodInfos
->ofnInfos
.nFileOffset
;
415 ofn
->nFileExtension
= fodInfos
->ofnInfos
.nFileExtension
;
416 if (fodInfos
->ofnInfos
.lpstrFilter
)
417 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrFilter
));
418 if (fodInfos
->ofnInfos
.lpTemplateName
)
419 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpTemplateName
));
420 if (fodInfos
->ofnInfos
.lpstrDefExt
)
421 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrDefExt
));
422 if (fodInfos
->ofnInfos
.lpstrTitle
)
423 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrTitle
));
424 if (fodInfos
->ofnInfos
.lpstrInitialDir
)
425 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrInitialDir
));
426 if (fodInfos
->ofnInfos
.lpstrCustomFilter
)
427 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrCustomFilter
));
429 if (fodInfos
->ofnInfos
.lpstrFile
)
431 strcpy(ofn
->lpstrFile
,fodInfos
->ofnInfos
.lpstrFile
);
432 MemFree((LPVOID
)fodInfos
->ofnInfos
.lpstrFile
);
434 if (fodInfos
->ofnInfos
.lpstrFileTitle
)
436 if (ofn
->lpstrFileTitle
)
437 strcpy(ofn
->lpstrFileTitle
,
438 fodInfos
->ofnInfos
.lpstrFileTitle
);
439 MemFree((LPVOID
)fodInfos
->ofnInfos
.lpstrFileTitle
);
442 MemFree((LPVOID
)(fodInfos
));
446 /***********************************************************************
449 * Copy the OPENFILENAMEW structure in a FileOpenDlgInfos structure.
450 * Call GetOpenFileName95 with this structure and clean the memory.
452 * IN : The OPENFILENAMEW initialisation structure passed to
453 * GetOpenFileNameW win api function (see filedlg.c)
455 BOOL WINAPI
GetFileDialog95W(LPOPENFILENAMEW ofn
,UINT iDlgType
)
458 FileOpenDlgInfos
*fodInfos
;
460 /* Initialise FileOpenDlgInfos structure*/
461 fodInfos
= (FileOpenDlgInfos
*)MemAlloc(sizeof(FileOpenDlgInfos
));
462 memset(&fodInfos
->ofnInfos
,'\0',sizeof(*ofn
));
463 fodInfos
->ofnInfos
.lStructSize
= sizeof(*ofn
);
464 fodInfos
->ofnInfos
.hwndOwner
= ofn
->hwndOwner
;
465 fodInfos
->ofnInfos
.hInstance
= MapHModuleLS(ofn
->hInstance
);
466 if (ofn
->lpstrFilter
)
472 /* filter is a list... title\0ext\0......\0\0 */
473 s
= (LPWSTR
)ofn
->lpstrFilter
;
478 n
= s
- ofn
->lpstrFilter
; /* already divides by 2. ptr magic */
479 x
= y
= (LPSTR
)MemAlloc(n
);
480 s
= (LPWSTR
)ofn
->lpstrFilter
;
487 fodInfos
->ofnInfos
.lpstrFilter
= (LPSTR
)y
;
489 if (ofn
->lpstrCustomFilter
) {
494 /* filter is a list... title\0ext\0......\0\0 */
495 s
= (LPWSTR
)ofn
->lpstrCustomFilter
;
499 n
= s
- ofn
->lpstrCustomFilter
;
500 x
= y
= (LPSTR
)MemAlloc(n
);
501 s
= (LPWSTR
)ofn
->lpstrCustomFilter
;
508 fodInfos
->ofnInfos
.lpstrCustomFilter
= (LPSTR
)y
;
510 fodInfos
->ofnInfos
.nMaxCustFilter
= ofn
->nMaxCustFilter
;
511 fodInfos
->ofnInfos
.nFilterIndex
= ofn
->nFilterIndex
;
513 fodInfos
->ofnInfos
.lpstrFile
= (LPSTR
)MemAlloc(ofn
->nMaxFile
);
514 fodInfos
->ofnInfos
.nMaxFile
= ofn
->nMaxFile
;
515 fodInfos
->ofnInfos
.nMaxFileTitle
= ofn
->nMaxFileTitle
;
516 if (ofn
->nMaxFileTitle
)
517 fodInfos
->ofnInfos
.lpstrFileTitle
= (LPSTR
)MemAlloc(ofn
->nMaxFileTitle
);
518 if (ofn
->lpstrInitialDir
)
519 fodInfos
->ofnInfos
.lpstrInitialDir
= (LPSTR
)MemAlloc(lstrlenW(ofn
->lpstrInitialDir
));
521 fodInfos
->ofnInfos
.lpstrTitle
= (LPSTR
)MemAlloc(lstrlenW(ofn
->lpstrTitle
));
522 fodInfos
->ofnInfos
.Flags
= ofn
->Flags
|OFN_WINE
|OFN_UNICODE
;
523 fodInfos
->ofnInfos
.nFileOffset
= ofn
->nFileOffset
;
524 fodInfos
->ofnInfos
.nFileExtension
= ofn
->nFileExtension
;
525 if (ofn
->lpstrDefExt
)
526 fodInfos
->ofnInfos
.lpstrDefExt
= (LPSTR
)MemAlloc(lstrlenW(ofn
->lpstrDefExt
));
527 fodInfos
->ofnInfos
.lCustData
= ofn
->lCustData
;
528 fodInfos
->ofnInfos
.lpfnHook
= (LPOFNHOOKPROC
)ofn
->lpfnHook
;
529 if (ofn
->lpTemplateName
)
530 fodInfos
->ofnInfos
.lpTemplateName
= (LPSTR
)MemAlloc(lstrlenW(ofn
->lpTemplateName
));
534 ret
= GetOpenFileName95(fodInfos
);
537 ret
= GetSaveFileName95(fodInfos
);
545 ofn
->nFileOffset
= fodInfos
->ofnInfos
.nFileOffset
;
546 ofn
->nFileExtension
= fodInfos
->ofnInfos
.nFileExtension
;
547 if (fodInfos
->ofnInfos
.lpstrFilter
)
548 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrFilter
));
549 if (fodInfos
->ofnInfos
.lpTemplateName
)
550 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpTemplateName
));
551 if (fodInfos
->ofnInfos
.lpstrDefExt
)
552 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrDefExt
));
553 if (fodInfos
->ofnInfos
.lpstrTitle
)
554 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrTitle
));
555 if (fodInfos
->ofnInfos
.lpstrInitialDir
)
556 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrInitialDir
));
557 if (fodInfos
->ofnInfos
.lpstrCustomFilter
)
558 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrCustomFilter
));
560 if (fodInfos
->ofnInfos
.lpstrFile
) {
561 lstrcpyAtoW(ofn
->lpstrFile
,(fodInfos
->ofnInfos
.lpstrFile
));
562 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrFile
));
565 if (fodInfos
->ofnInfos
.lpstrFileTitle
) {
566 if (ofn
->lpstrFileTitle
)
567 lstrcpyAtoW(ofn
->lpstrFileTitle
,
568 (fodInfos
->ofnInfos
.lpstrFileTitle
));
569 MemFree((LPVOID
)(fodInfos
->ofnInfos
.lpstrFileTitle
));
571 MemFree((LPVOID
)(fodInfos
));
577 /***********************************************************************
580 * File open dialog procedure
582 HRESULT WINAPI
FileOpenDlgProc95(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
588 return FILEDLG95_OnWMInitDialog(hwnd
, wParam
, lParam
);
590 return FILEDLG95_OnWMCommand(hwnd
, wParam
, lParam
);
593 switch(((LPDRAWITEMSTRUCT
)lParam
)->CtlID
)
596 FILEDLG95_LOOKIN_DrawItem((LPDRAWITEMSTRUCT
) lParam
);
602 case WM_GETISHELLBROWSER
:
603 return FILEDLG95_OnWMGetIShellBrowser(hwnd
);
606 RemovePropA(hwnd
, FileOpenDlgInfosStr
);
612 /***********************************************************************
613 * FILEDLG95_OnWMInitDialog
615 * WM_INITDIALOG message handler
617 static LRESULT
FILEDLG95_OnWMInitDialog(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
619 LPITEMIDLIST pidlItemId
;
620 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) lParam
;
624 /* Adds the FileOpenDlgInfos in the property list of the dialog
625 so it will be easily accessible through a GetPropA(...) */
626 SetPropA(hwnd
, FileOpenDlgInfosStr
, (HANDLE
) fodInfos
);
628 /* Make sure the common control DLL is loaded */
629 InitCommonControls();
631 /* Initialise shell objects */
632 FILEDLG95_SHELL_Init(hwnd
);
634 /* Initialise dialog UI */
635 FILEDLG95_InitUI(hwnd
);
637 /* Initialize the Look In combo box*/
638 FILEDLG95_LOOKIN_Init(fodInfos
->DlgInfos
.hwndLookInCB
);
640 /* Initialize the filter combo box */
641 FILEDLG95_FILETYPE_Init(hwnd
);
643 /* Get the initial directory pidl */
645 if(!(pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,fodInfos
->ofnInfos
.lpstrInitialDir
)))
649 GetCurrentDirectoryA(MAX_PATH
,path
);
650 pidlItemId
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,
655 /* Browse to the initial directory */
656 IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,pidlItemId
,SBSP_RELATIVE
);
658 /* Free pidlItem memory */
663 /***********************************************************************
666 * Regroups all the cleaning functions of the filedlg
668 void FILEDLG95_Clean(HWND hwnd
)
670 FILEDLG95_FILETYPE_Clean(hwnd
);
671 FILEDLG95_LOOKIN_Clean(hwnd
);
672 FILEDLG95_SHELL_Clean(hwnd
);
674 /***********************************************************************
675 * FILEDLG95_OnWMCommand
677 * WM_COMMAND message handler
679 static LRESULT
FILEDLG95_OnWMCommand(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
681 WORD wNotifyCode
= HIWORD(wParam
); // notification code
682 WORD wID
= LOWORD(wParam
); // item, control, or accelerator identifier
688 FILEDLG95_OnOpen(hwnd
);
692 FILEDLG95_Clean(hwnd
);
693 EndDialog(hwnd
, FALSE
);
695 /* Filetype combo box */
697 FILEDLG95_FILETYPE_OnCommand(hwnd
,wNotifyCode
);
699 /* LookIn combo box */
701 FILEDLG95_LOOKIN_OnCommand(hwnd
,wNotifyCode
);
703 /* Up folder button */
705 FILEDLG95_SHELL_UpFolder(hwnd
);
707 /* List option button */
709 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWLIST
);
711 /* Details option button */
713 FILEDLG95_SHELL_ExecuteCommand(hwnd
,CMDSTR_VIEWDETAILS
);
715 /* New folder button */
717 FILEDLG95_SHELL_NewFolder(hwnd
);
728 /***********************************************************************
729 * FILEDLG95_OnWMGetIShellBrowser
731 * WM_GETISHELLBROWSER message handler
733 static LRESULT
FILEDLG95_OnWMGetIShellBrowser(HWND hwnd
)
736 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
740 SetWindowLongA(hwnd
,DWL_MSGRESULT
,(LONG
)fodInfos
->Shell
.FOIShellBrowser
);
746 /***********************************************************************
750 static LRESULT
FILEDLG95_InitUI(HWND hwnd
)
752 HIMAGELIST himlToolbar
;
754 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
756 TRACE("%p\n", fodInfos
);
758 /* Get the hwnd of the controls */
759 fodInfos
->DlgInfos
.hwndFileName
= GetDlgItem(hwnd
,IDC_FILENAME
);
760 fodInfos
->DlgInfos
.hwndFileTypeCB
= GetDlgItem(hwnd
,IDC_FILETYPE
);
761 fodInfos
->DlgInfos
.hwndLookInCB
= GetDlgItem(hwnd
,IDC_LOOKIN
);
763 ShowWindow(GetDlgItem(hwnd
,IDC_SHELLSTATIC
),SW_HIDE
);
764 /* Load the icons bitmaps */
766 if((himlToolbar
= COMDLG32_ImageList_LoadImageA(COMMDLG_hInstance32
,
767 MAKEINTRESOURCEA(IDB_TOOLBAR
),
775 if((hicon
= COMDLG32_ImageList_GetIcon(himlToolbar
,0,ILD_NORMAL
)))
776 SendDlgItemMessageA(hwnd
,IDC_UPFOLDER
,BM_SETIMAGE
,(WPARAM
)IMAGE_ICON
,(LPARAM
)hicon
);
777 /* New folder icon */
778 if((hicon
= COMDLG32_ImageList_GetIcon(himlToolbar
,1,ILD_NORMAL
)))
779 SendDlgItemMessageA(hwnd
,IDC_NEWFOLDER
,BM_SETIMAGE
,(WPARAM
)IMAGE_ICON
,(LPARAM
)hicon
);
781 if((hicon
= COMDLG32_ImageList_GetIcon(himlToolbar
,2,ILD_NORMAL
)))
782 SendDlgItemMessageA(hwnd
,IDC_LIST
,BM_SETIMAGE
,(WPARAM
)IMAGE_ICON
,(LPARAM
)hicon
);
783 /* Detail view icon */
784 if((hicon
= COMDLG32_ImageList_GetIcon(himlToolbar
,3,ILD_NORMAL
)))
785 SendDlgItemMessageA(hwnd
,IDC_DETAILS
,BM_SETIMAGE
,(WPARAM
)IMAGE_ICON
,(LPARAM
)hicon
);
787 COMDLG32_ImageList_Destroy(himlToolbar
);
792 /* Set the window text with the text specified in the OPENFILENAME structure */
793 if(fodInfos
->ofnInfos
.lpstrTitle
)
794 SetWindowTextA(hwnd
,fodInfos
->ofnInfos
.lpstrTitle
);
796 /* Initialise the file name edit control */
797 if(strlen(fodInfos
->ofnInfos
.lpstrFile
))
799 SetDlgItemTextA(hwnd
,IDC_FILENAME
,fodInfos
->ofnInfos
.lpstrFile
);
801 /* Must the open as read only check box be checked ?*/
802 if(fodInfos
->ofnInfos
.Flags
& OFN_READONLY
)
804 SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_SETCHECK
,(WPARAM
)TRUE
,0);
806 /* Must the open as read only check box be hid ?*/
807 if(fodInfos
->ofnInfos
.Flags
& OFN_HIDEREADONLY
)
809 ShowWindow(GetDlgItem(hwnd
,IDC_OPENREADONLY
),SW_HIDE
);
815 /***********************************************************************
818 * Ok button WM_COMMAND message handler
820 * If the function succeeds, the return value is nonzero.
822 BOOL
FILEDLG95_OnOpen(HWND hwnd
)
824 char lpstrFileName
[MAX_PATH
];
825 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
829 if(GetDlgItemTextA(hwnd
,IDC_FILENAME
,lpstrFileName
,MAX_PATH
))
832 char lpstrFile
[MAX_PATH
];
834 /* Get the selected file name and path */
835 SHGetPathFromIDListA(fodInfos
->ShellInfos
.pidlAbsCurrent
,
837 if(strcmp(&lpstrFile
[strlen(lpstrFile
)-1],"\\"))
838 strcat(lpstrFile
,"\\");
839 strcat(lpstrFile
,lpstrFileName
);
841 /* Check if this is a search */
842 if(strchr(lpstrFileName
,'*') || strchr(lpstrFileName
,'?'))
846 /* Set the current filter with the current selection */
847 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
848 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
850 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFileName
)+1)*2);
851 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,(LPSTR
)strlwr((LPSTR
)lpstrFileName
));
854 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
856 if(-1 < (iPos
= FILEDLG95_FILETYPE_SearchExt(fodInfos
->DlgInfos
.hwndFileTypeCB
,lpstrFileName
)))
857 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
862 /* Check file extension */
864 if(!strrchr(lpstrFile
,'.'))
866 /* if the file has no extension, append the selected
867 extension of the filetype combo box */
871 iExt
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
872 lpstrTmp
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iExt
);
874 if((lpstrExt
= strchr(lpstrTmp
,';')))
876 int i
= lpstrExt
- lpstrTmp
;
877 lpstrExt
= MemAlloc(i
);
878 strncpy(lpstrExt
,&lpstrTmp
[1],i
-1);
882 lpstrExt
= MemAlloc(strlen(lpstrTmp
)-1);
883 strcpy(lpstrExt
,&lpstrTmp
[1]);
886 if(!strcmp(&lpstrExt
[1],"*") && fodInfos
->ofnInfos
.lpstrDefExt
)
888 lpstrExt
= MemAlloc(strlen(fodInfos
->ofnInfos
.lpstrDefExt
)+1);
889 strcat(lpstrExt
,".");
890 strcat(lpstrExt
,(LPSTR
) fodInfos
->ofnInfos
.lpstrDefExt
);
893 strcat(lpstrFile
,lpstrExt
);
895 /* Check if the selected file exist */
897 if(strlen(lpstrFile
) > fodInfos
->ofnInfos
.nMaxFile
)
899 /* set error FNERR_BUFFERTOSMALL */
900 FILEDLG95_Clean(hwnd
);
901 return EndDialog(hwnd
,FALSE
);
903 strcpy(fodInfos
->ofnInfos
.lpstrFile
,lpstrFile
);
905 /* Set the lpstrFileTitle of the OPENFILENAME structure */
906 if(fodInfos
->ofnInfos
.lpstrFileTitle
)
907 strncpy(fodInfos
->ofnInfos
.lpstrFileTitle
,
909 fodInfos
->ofnInfos
.nMaxFileTitle
);
911 /* Check if the file is to be opened as read only */
912 if(BST_CHECKED
== SendDlgItemMessageA(hwnd
,IDC_OPENREADONLY
,BM_GETSTATE
,0,0))
913 SetFileAttributesA(fodInfos
->ofnInfos
.lpstrFile
,FILE_ATTRIBUTE_READONLY
);
915 /* nFileExtension and nFileOffset of OPENFILENAME structure */
916 tmp
= strrchr(fodInfos
->ofnInfos
.lpstrFile
,'\\');
917 fodInfos
->ofnInfos
.nFileOffset
= tmp
- fodInfos
->ofnInfos
.lpstrFile
+ 1;
918 tmp
= strrchr(fodInfos
->ofnInfos
.lpstrFile
,'.');
919 fodInfos
->ofnInfos
.nFileExtension
= tmp
- fodInfos
->ofnInfos
.lpstrFile
+ 1;
921 /* Check if selected file exists */
922 if(!GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
, lpstrFileName
))
924 /* Tell the user the selected does not exist */
925 if(fodInfos
->ofnInfos
.Flags
& OFN_FILEMUSTEXIST
)
927 char lpstrNotFound
[100];
931 LoadStringA(COMMDLG_hInstance32
,IDS_FILENOTFOUND
,lpstrNotFound
,100);
932 LoadStringA(COMMDLG_hInstance32
,IDS_VERIFYFILE
,lpstrMsg
,100);
934 strcpy(tmp
,fodInfos
->ofnInfos
.lpstrFile
);
936 strcat(tmp
,lpstrNotFound
);
938 strcat(tmp
,lpstrMsg
);
940 MessageBoxA(hwnd
,tmp
,fodInfos
->ofnInfos
.lpstrTitle
,MB_OK
| MB_ICONEXCLAMATION
);
943 /* Ask the user if he wants to create the file*/
944 if(fodInfos
->ofnInfos
.Flags
& OFN_CREATEPROMPT
)
948 LoadStringA(COMMDLG_hInstance32
,IDS_CREATEFILE
,tmp
,100);
950 if(IDYES
== MessageBoxA(hwnd
,tmp
,fodInfos
->ofnInfos
.lpstrTitle
,MB_YESNO
| MB_ICONQUESTION
))
952 /* Create the file, clean and exit */
953 FILEDLG95_Clean(hwnd
);
954 return EndDialog(hwnd
,TRUE
);
960 FILEDLG95_Clean(hwnd
);
961 return EndDialog(hwnd
,TRUE
);
967 /***********************************************************************
968 * FILEDLG95_SHELL_Init
970 * Initialisation of the shell objects
972 static HRESULT
FILEDLG95_SHELL_Init(HWND hwnd
)
974 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
979 * Initialisation of the FileOpenDialogInfos structure
984 fodInfos
->Shell
.FOIShellView
= NULL
;
985 if(FAILED(SHGetDesktopFolder(&fodInfos
->Shell
.FOIShellFolder
)))
989 fodInfos
->ShellInfos
.hwndOwner
= hwnd
;
991 fodInfos
->ShellInfos
.folderSettings
.fFlags
= FWF_AUTOARRANGE
| FWF_ALIGNLEFT
;
992 fodInfos
->ShellInfos
.folderSettings
.ViewMode
= FVM_LIST
;
994 GetWindowRect(GetDlgItem(hwnd
,IDC_SHELLSTATIC
),&fodInfos
->ShellInfos
.rectView
);
995 ScreenToClient(hwnd
,(LPPOINT
)&fodInfos
->ShellInfos
.rectView
.left
);
996 ScreenToClient(hwnd
,(LPPOINT
)&fodInfos
->ShellInfos
.rectView
.right
);
998 /* Construct the IShellBrowser interface */
999 fodInfos
->Shell
.FOIShellBrowser
= IShellBrowserImpl_Construct(hwnd
);
1004 /***********************************************************************
1005 * FILEDLG95_SHELL_ExecuteCommand
1007 * Change the folder option and refresh the view
1008 * If the function succeeds, the return value is nonzero.
1010 static BOOL
FILEDLG95_SHELL_ExecuteCommand(HWND hwnd
, LPCSTR lpVerb
)
1012 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1015 CMINVOKECOMMANDINFO ci
;
1018 if(SUCCEEDED(IShellView_GetItemObject(fodInfos
->Shell
.FOIShellView
,
1023 ci
.cbSize
= sizeof(CMINVOKECOMMANDINFO
);
1027 IContextMenu_InvokeCommand(pcm
, &ci
);
1028 IContextMenu_Release(pcm
);
1034 /***********************************************************************
1035 * FILEDLG95_SHELL_UpFolder
1037 * Browse to the specified object
1038 * If the function succeeds, the return value is nonzero.
1040 static BOOL
FILEDLG95_SHELL_UpFolder(HWND hwnd
)
1042 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1046 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
1055 /***********************************************************************
1056 * FILEDLG95_SHELL_NewFolder
1058 * Creates a new directory with New folder as name
1059 * If the function succeeds, the return value is nonzero.
1060 * FIXME: let the contextmenu (CMDSTR_NEWFOLDER) do this thing
1062 static BOOL
FILEDLG95_SHELL_NewFolder(HWND hwnd
)
1064 char lpstrDirName
[MAX_PATH
] = "New folder";
1066 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1070 if((bRes
= CreateDirectoryA(lpstrDirName
,NULL
)))
1072 LPITEMIDLIST pidl
= GetPidlFromName(fodInfos
->Shell
.FOIShellFolder
,lpstrDirName
);
1073 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1074 IShellView_SelectItem(fodInfos
->Shell
.FOIShellView
,
1076 (SVSI_DESELECTOTHERS
| SVSI_EDIT
| SVSI_ENSUREVISIBLE
1077 |SVSI_FOCUSED
|SVSI_SELECT
));
1085 /***********************************************************************
1086 * FILEDLG95_SHELL_Clean
1088 * Cleans the memory used by shell objects
1090 static void FILEDLG95_SHELL_Clean(HWND hwnd
)
1092 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1096 /* clean Shell interfaces */
1097 IShellView_DestroyViewWindow(fodInfos
->Shell
.FOIShellView
);
1098 IShellView_Release(fodInfos
->Shell
.FOIShellView
);
1099 IShellFolder_Release(fodInfos
->Shell
.FOIShellFolder
);
1100 IShellBrowser_Release(fodInfos
->Shell
.FOIShellBrowser
);
1103 /***********************************************************************
1104 * FILEDLG95_FILETYPE_Init
1106 * Initialisation of the file type combo box
1108 static HRESULT
FILEDLG95_FILETYPE_Init(HWND hwnd
)
1110 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1114 if(fodInfos
->ofnInfos
.lpstrFilter
)
1123 /* filter is a list... title\0ext\0......\0\0 */
1124 /* Set the combo item text to the title and the item data
1126 char *lpstrExt
= NULL
;
1127 LPSTR lpstrExtTmp
= NULL
;
1129 lpstrTmp
= (&((LPBYTE
)fodInfos
->ofnInfos
.lpstrFilter
)[iStrIndex
]);
1130 if(!strlen(lpstrTmp
))
1132 iStrIndex
+= strlen(lpstrTmp
) +1;
1133 /* Get the extension */
1134 lpstrExtTmp
= (&((LPBYTE
)fodInfos
->ofnInfos
.lpstrFilter
)[iStrIndex
]);
1138 lpstrExt
= (LPSTR
) MemAlloc(strlen(lpstrExtTmp
));
1142 strcpy(lpstrExt
,lpstrExtTmp
);
1144 iStrIndex
+= strlen(lpstrExt
) +1;
1146 /* Add the item at the end of the combo */
1147 CBAddString(fodInfos
->DlgInfos
.hwndFileTypeCB
,lpstrTmp
);
1148 CBSetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
++,lpstrExt
);
1150 /* Set the current filter to the one specified
1151 in the initialisation structure */
1152 CBSetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1153 fodInfos
->ofnInfos
.nFilterIndex
);
1155 lpstrFilter
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1156 fodInfos
->ofnInfos
.nFilterIndex
);
1159 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFilter
)+1)*2);
1160 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,strlwr(lpstrFilter
));
1166 /***********************************************************************
1167 * FILEDLG95_FILETYPE_OnCommand
1169 * WM_COMMAND of the file type combo box
1170 * If the function succeeds, the return value is nonzero.
1172 static BOOL
FILEDLG95_FILETYPE_OnCommand(HWND hwnd
, WORD wNotifyCode
)
1174 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1182 /* Get the current item of the filetype combo box */
1183 int iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1185 /* Set the current filter with the current selection */
1186 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1187 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1189 lpstrFilter
= (LPSTR
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,
1193 fodInfos
->ShellInfos
.lpstrCurrentFilter
= MemAlloc((strlen(lpstrFilter
)+1)*2);
1194 lstrcpyAtoW(fodInfos
->ShellInfos
.lpstrCurrentFilter
,(LPSTR
)strlwr((LPSTR
)lpstrFilter
));
1197 /* Refresh the actual view to display the included items*/
1198 IShellView_Refresh(fodInfos
->Shell
.FOIShellView
);
1204 /***********************************************************************
1205 * FILEDLG95_FILETYPE_SearchExt
1207 * Search for pidl in the lookin combo box
1208 * returns the index of the found item
1210 static int FILEDLG95_FILETYPE_SearchExt(HWND hwnd
,LPSTR lpstrExt
)
1213 int iCount
= CBGetCount(hwnd
);
1219 LPSTR ext
= (LPSTR
) CBGetItemDataPtr(hwnd
,i
);
1221 if(!_stricmp(lpstrExt
,ext
))
1229 /***********************************************************************
1230 * FILEDLG95_FILETYPE_Clean
1232 * Clean the memory used by the filetype combo box
1234 static void FILEDLG95_FILETYPE_Clean(HWND hwnd
)
1236 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1238 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndFileTypeCB
);
1242 /* Delete each string of the combo and their associated data */
1243 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
1245 MemFree((LPVOID
)(CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
)));
1246 CBDeleteString(fodInfos
->DlgInfos
.hwndFileTypeCB
,iPos
);
1248 /* Current filter */
1249 if(fodInfos
->ShellInfos
.lpstrCurrentFilter
)
1250 MemFree((LPVOID
)fodInfos
->ShellInfos
.lpstrCurrentFilter
);
1254 /***********************************************************************
1255 * FILEDLG95_LOOKIN_Init
1257 * Initialisation of the look in combo box
1259 static HRESULT
FILEDLG95_LOOKIN_Init(HWND hwndCombo
)
1261 IShellFolder
*psfRoot
, *psfDrives
;
1262 IEnumIDList
*lpeRoot
, *lpeDrives
;
1263 LPITEMIDLIST pidlDrives
, pidlTmp
, pidlTmp1
, pidlAbsTmp
;
1265 LookInInfos
*liInfos
= MemAlloc(sizeof(LookInInfos
));
1269 liInfos
->iMaxIndentation
= 0;
1271 SetPropA(hwndCombo
, LookInInfosStr
, (HANDLE
) liInfos
);
1273 /* Initialise data of Desktop folder */
1274 SHGetSpecialFolderLocation(0,CSIDL_DESKTOP
,&pidlTmp
);
1275 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
1278 SHGetSpecialFolderLocation(0,CSIDL_DRIVES
,&pidlDrives
);
1280 SHGetDesktopFolder(&psfRoot
);
1284 /* enumerate the contents of the desktop */
1285 if(SUCCEEDED(IShellFolder_EnumObjects(psfRoot
, hwndCombo
, SHCONTF_FOLDERS
, &lpeRoot
)))
1287 while (S_OK
== IEnumIDList_Next(lpeRoot
, 1, &pidlTmp
, NULL
))
1289 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlTmp
,LISTEND
);
1291 /* special handling for CSIDL_DRIVES */
1292 if (ILIsEqual(pidlTmp
, pidlDrives
))
1294 if(SUCCEEDED(IShellFolder_BindToObject(psfRoot
, pidlTmp
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfDrives
)))
1296 /* enumerate the drives */
1297 if(SUCCEEDED(IShellFolder_EnumObjects(psfDrives
, hwndCombo
,SHCONTF_FOLDERS
, &lpeDrives
)))
1299 while (S_OK
== IEnumIDList_Next(lpeDrives
, 1, &pidlTmp1
, NULL
))
1301 pidlAbsTmp
= ILCombine(pidlTmp
, pidlTmp1
);
1302 FILEDLG95_LOOKIN_AddItem(hwndCombo
, pidlAbsTmp
,LISTEND
);
1306 IEnumIDList_Release(lpeDrives
);
1308 IShellFolder_Release(psfDrives
);
1313 IEnumIDList_Release(lpeRoot
);
1317 IShellFolder_Release(psfRoot
);
1323 /***********************************************************************
1324 * FILEDLG95_LOOKIN_DrawItem
1326 * WM_DRAWITEM message handler
1328 static LRESULT
FILEDLG95_LOOKIN_DrawItem(LPDRAWITEMSTRUCT pDIStruct
)
1330 COLORREF crWin
= GetSysColor(COLOR_WINDOW
);
1331 COLORREF crHighLight
= GetSysColor(COLOR_HIGHLIGHT
);
1332 COLORREF crText
= GetSysColor(COLOR_WINDOWTEXT
);
1336 HIMAGELIST ilItemImage
;
1338 LPSFOLDER tmpFolder
;
1341 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(pDIStruct
->hwndItem
,LookInInfosStr
);
1345 if(pDIStruct
->itemID
== -1)
1348 if(!(tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(pDIStruct
->hwndItem
,
1349 pDIStruct
->itemID
)))
1353 if(pDIStruct
->itemID
== liInfos
->uSelectedItem
)
1355 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
1358 sizeof (SHFILEINFOA
),
1359 SHGFI_PIDL
| SHGFI_SMALLICON
|
1360 SHGFI_OPENICON
| SHGFI_SYSICONINDEX
|
1361 SHGFI_DISPLAYNAME
);
1365 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
1368 sizeof (SHFILEINFOA
),
1369 SHGFI_PIDL
| SHGFI_SMALLICON
|
1370 SHGFI_SYSICONINDEX
|
1374 /* Is this item selected ?*/
1375 if(pDIStruct
->itemState
& ODS_SELECTED
)
1377 SetTextColor(pDIStruct
->hDC
,(0x00FFFFFF & ~(crText
)));
1378 SetBkColor(pDIStruct
->hDC
,crHighLight
);
1379 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,(HBRUSH
)crHighLight
);
1383 SetTextColor(pDIStruct
->hDC
,crText
);
1384 SetBkColor(pDIStruct
->hDC
,crWin
);
1385 FillRect(pDIStruct
->hDC
,&pDIStruct
->rcItem
,(HBRUSH
)crWin
);
1388 /* Do not indent item if drawing in the edit of the combo*/
1389 if(pDIStruct
->itemState
& ODS_COMBOBOXEDIT
)
1392 ilItemImage
= (HIMAGELIST
) SHGetFileInfoA ((LPCSTR
) tmpFolder
->pidlItem
,
1395 sizeof (SHFILEINFOA
),
1396 SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_OPENICON
1397 | SHGFI_SYSICONINDEX
| SHGFI_DISPLAYNAME
);
1402 iIndentation
= tmpFolder
->m_iIndent
;
1404 /* Draw text and icon */
1406 /* Initialise the icon display area */
1407 rectIcon
.left
= pDIStruct
->rcItem
.left
+ ICONWIDTH
/2 * iIndentation
;
1408 rectIcon
.top
= pDIStruct
->rcItem
.top
;
1409 rectIcon
.right
= rectIcon
.left
+ ICONWIDTH
;
1410 rectIcon
.bottom
= pDIStruct
->rcItem
.bottom
;
1412 /* Initialise the text display area */
1413 rectText
.left
= rectIcon
.right
;
1414 rectText
.top
= pDIStruct
->rcItem
.top
+ YTEXTOFFSET
;
1415 rectText
.right
= pDIStruct
->rcItem
.right
+ XTEXTOFFSET
;
1416 rectText
.bottom
= pDIStruct
->rcItem
.bottom
;
1419 /* Draw the icon from the image list */
1420 COMDLG32_ImageList_Draw(ilItemImage
,
1427 /* Draw the associated text */
1428 if(sfi
.szDisplayName
)
1429 TextOutA(pDIStruct
->hDC
,rectText
.left
,rectText
.top
,sfi
.szDisplayName
,strlen(sfi
.szDisplayName
));
1435 /***********************************************************************
1436 * FILEDLG95_LOOKIN_OnCommand
1438 * LookIn combo box WM_COMMAND message handler
1439 * If the function succeeds, the return value is nonzero.
1441 static BOOL
FILEDLG95_LOOKIN_OnCommand(HWND hwnd
, WORD wNotifyCode
)
1443 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1451 LPSFOLDER tmpFolder
;
1454 iItem
= CBGetCurSel(fodInfos
->DlgInfos
.hwndLookInCB
);
1456 tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,
1460 if(SUCCEEDED(IShellBrowser_BrowseObject(fodInfos
->Shell
.FOIShellBrowser
,
1461 tmpFolder
->pidlItem
,
1473 /***********************************************************************
1474 * FILEDLG95_LOOKIN_AddItem
1476 * Adds an absolute pidl item to the lookin combo box
1477 * returns the index of the inserted item
1479 static int FILEDLG95_LOOKIN_AddItem(HWND hwnd
,LPITEMIDLIST pidl
, int iInsertId
)
1481 LPITEMIDLIST pidlNext
;
1483 SFOLDER
*tmpFolder
= MemAlloc(sizeof(SFOLDER
));
1484 LookInInfos
*liInfos
;
1488 if(!(liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
)))
1491 tmpFolder
->m_iIndent
= 0;
1496 /* Calculate the indentation of the item in the lookin*/
1498 while( (pidlNext
=ILGetNext(pidlNext
)) )
1500 tmpFolder
->m_iIndent
++;
1503 tmpFolder
->pidlItem
= ILClone(pidl
);
1505 if(tmpFolder
->m_iIndent
> liInfos
->iMaxIndentation
)
1506 liInfos
->iMaxIndentation
= tmpFolder
->m_iIndent
;
1508 SHGetFileInfoA((LPSTR
)pidl
,
1512 SHGFI_DISPLAYNAME
| SHGFI_SYSICONINDEX
1513 | SHGFI_PIDL
| SHGFI_SMALLICON
| SHGFI_ATTRIBUTES
);
1516 if((sfi
.dwAttributes
& SFGAO_FILESYSANCESTOR
) || (sfi
.dwAttributes
& SFGAO_FILESYSTEM
))
1519 /* Add the item at the end of the list */
1522 iItemID
= CBAddString(hwnd
,sfi
.szDisplayName
);
1524 /* Insert the item at the iInsertId position*/
1527 iItemID
= CBInsertString(hwnd
,sfi
.szDisplayName
,iInsertId
);
1530 CBSetItemDataPtr(hwnd
,iItemID
,tmpFolder
);
1538 /***********************************************************************
1539 * FILEDLG95_LOOKIN_InsertItemAfterParent
1541 * Insert an item below its parent
1543 static int FILEDLG95_LOOKIN_InsertItemAfterParent(HWND hwnd
,LPITEMIDLIST pidl
)
1546 LPITEMIDLIST pidlParent
= GetParentPidl(pidl
);
1551 iParentPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidlParent
,SEARCH_PIDL
);
1555 iParentPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidlParent
);
1558 /* Free pidlParent memory */
1559 SHFree((LPVOID
)pidlParent
);
1561 return FILEDLG95_LOOKIN_AddItem(hwnd
,pidl
,iParentPos
+ 1);
1564 /***********************************************************************
1565 * FILEDLG95_LOOKIN_SelectItem
1567 * Adds an absolute pidl item to the lookin combo box
1568 * returns the index of the inserted item
1570 int FILEDLG95_LOOKIN_SelectItem(HWND hwnd
,LPITEMIDLIST pidl
)
1573 LookInInfos
*liInfos
;
1577 iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)pidl
,SEARCH_PIDL
);
1579 liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
1583 while(FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
) > -1);
1584 iItemPos
= FILEDLG95_LOOKIN_InsertItemAfterParent(hwnd
,pidl
);
1589 SFOLDER
*tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
1590 while(liInfos
->iMaxIndentation
> tmpFolder
->m_iIndent
)
1594 if(-1 == (iRemovedItem
= FILEDLG95_LOOKIN_RemoveMostExpandedItem(hwnd
)))
1596 if(iRemovedItem
< iItemPos
)
1601 CBSetCurSel(hwnd
,iItemPos
);
1602 liInfos
->uSelectedItem
= iItemPos
;
1608 /***********************************************************************
1609 * FILEDLG95_LOOKIN_RemoveMostExpandedItem
1611 * Remove the item with an expansion level over iExpansionLevel
1613 static int FILEDLG95_LOOKIN_RemoveMostExpandedItem(HWND hwnd
)
1617 LookInInfos
*liInfos
= (LookInInfos
*)GetPropA(hwnd
,LookInInfosStr
);
1621 if(liInfos
->iMaxIndentation
<= 2)
1624 if((iItemPos
= FILEDLG95_LOOKIN_SearchItem(hwnd
,(WPARAM
)liInfos
->iMaxIndentation
,SEARCH_EXP
)) >=0)
1627 tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,iItemPos
);
1628 CBDeleteString(hwnd
,iItemPos
);
1629 liInfos
->iMaxIndentation
--;
1637 /***********************************************************************
1638 * FILEDLG95_LOOKIN_SearchItem
1640 * Search for pidl in the lookin combo box
1641 * returns the index of the found item
1643 static int FILEDLG95_LOOKIN_SearchItem(HWND hwnd
,WPARAM searchArg
,int iSearchMethod
)
1646 int iCount
= CBGetCount(hwnd
);
1652 LPSFOLDER tmpFolder
= (LPSFOLDER
) CBGetItemDataPtr(hwnd
,i
);
1654 if(iSearchMethod
== SEARCH_PIDL
&& ILIsEqual((LPITEMIDLIST
)searchArg
,tmpFolder
->pidlItem
))
1656 if(iSearchMethod
== SEARCH_EXP
&& tmpFolder
->m_iIndent
== (int)searchArg
)
1664 /***********************************************************************
1665 * FILEDLG95_LOOKIN_Clean
1667 * Clean the memory used by the lookin combo box
1669 static void FILEDLG95_LOOKIN_Clean(HWND hwnd
)
1671 FileOpenDlgInfos
*fodInfos
= (FileOpenDlgInfos
*) GetPropA(hwnd
,FileOpenDlgInfosStr
);
1673 int iCount
= CBGetCount(fodInfos
->DlgInfos
.hwndLookInCB
);
1677 /* Delete each string of the combo and their associated data */
1678 for(iPos
= iCount
-1;iPos
>=0;iPos
--)
1680 MemFree((LPVOID
)(CBGetItemDataPtr(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
)));
1681 CBDeleteString(fodInfos
->DlgInfos
.hwndLookInCB
,iPos
);
1683 /* LookInInfos structure */
1684 RemovePropA(fodInfos
->DlgInfos
.hwndLookInCB
,LookInInfosStr
);
1691 /***********************************************************************
1694 * Get the pidl's display name (relative to folder) and
1695 * put it in lpstrFileName.
1697 * Return NOERROR on success,
1701 HRESULT
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST pidl
,DWORD dwFlags
,LPSTR lpstrFileName
)
1706 TRACE("%p %p\n", lpsf
, pidl
);
1711 SHGetDesktopFolder(&lpsf
);
1712 hRes
= GetName(lpsf
,pidl
,dwFlags
,lpstrFileName
);
1713 IShellFolder_Release(lpsf
);
1717 /* Get the display name of the pidl relative to the folder */
1718 if (SUCCEEDED(hRes
= IShellFolder_GetDisplayNameOf(lpsf
,
1723 return StrRetToStrNA(lpstrFileName
, MAX_PATH
, &str
, pidl
);
1728 /***********************************************************************
1729 * GetShellFolderFromPidl
1731 * pidlRel is the item pidl relative
1732 * Return the IShellFolder of the absolute pidl
1734 IShellFolder
*GetShellFolderFromPidl(LPITEMIDLIST pidlAbs
)
1736 IShellFolder
*psf
= NULL
,*psfParent
;
1738 TRACE("%p\n", pidlAbs
);
1740 if(SUCCEEDED(SHGetDesktopFolder(&psfParent
)))
1743 if(pidlAbs
&& pidlAbs
->mkid
.cb
)
1745 if(FAILED(IShellFolder_BindToObject(psfParent
, pidlAbs
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psf
)))
1750 IShellFolder_Release(psfParent
);
1757 /***********************************************************************
1760 * Return the LPITEMIDLIST to the parent of the pidl in the list
1762 LPITEMIDLIST
GetParentPidl(LPITEMIDLIST pidl
)
1764 LPITEMIDLIST pidlParent
;
1766 TRACE("%p\n", pidl
);
1768 pidlParent
= ILClone(pidl
);
1769 ILRemoveLastID(pidlParent
);
1775 /***********************************************************************
1778 * returns the pidl of the file name relative to folder
1779 * NULL if an error occured
1781 LPITEMIDLIST
GetPidlFromName(IShellFolder
*psf
,LPCSTR lpcstrFileName
)
1785 wchar_t lpwstrDirName
[MAX_PATH
];
1787 TRACE("sf=%p file=%s\n", psf
, lpcstrFileName
);
1792 MultiByteToWideChar(CP_ACP
,
1796 (LPWSTR
)lpwstrDirName
,
1801 if(SUCCEEDED(IShellFolder_ParseDisplayName(psf
,
1804 (LPWSTR
)lpwstrDirName
,
1814 /***********************************************************************
1818 BOOL
GetFileExtension(IShellFolder
*psf
,LPITEMIDLIST pidl
,LPSTR lpstrFileExtension
)
1820 char FileName
[MAX_PATH
];
1825 if(SUCCEEDED(GetName(psf
,pidl
,SHGDN_NORMAL
,FileName
)))
1827 if(!(pdest
= strrchr( FileName
, ch
)))
1830 result
= pdest
- FileName
+ 1;
1831 strcpy(lpstrFileExtension
,&FileName
[result
]);
1838 * Memory allocation methods */
1839 void *MemAlloc(UINT size
)
1841 return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
1844 void MemFree(void *mem
)
1848 HeapFree(GetProcessHeap(),0,mem
);