1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
31 //------------------------------------------------------------------------
33 //------------------------------------------------------------------------
36 #include <osl/diagnose.h>
37 #include "../misc/WinImplHelper.hxx"
38 #include "FileOpenDlg.hxx"
40 //------------------------------------------------------------------------
42 //------------------------------------------------------------------------
44 namespace /* private */
46 // we choose such large buffers because the size of
47 // an single line edit field can be up to 32k; if
48 // a user has a multi selection FilePicker and selects
49 // a lot of files in a large directory we may reach this
50 // limit and don't want to get out of memory;
51 // another much more elegant way would be to subclass the
52 // FileOpen dialog and overload the BM_CLICK event of the
53 // OK button so that we determine the size of the text
54 // currently in the edit field and resize our buffer
55 // appropriately - in the future we will do this
56 const size_t MAX_FILENAME_BUFF_SIZE
= 32000;
57 const size_t MAX_FILETITLE_BUFF_SIZE
= 32000;
58 const size_t MAX_FILTER_BUFF_SIZE
= 4096;
60 const LPTSTR CURRENT_INSTANCE
= TEXT("CurrInst");
62 //------------------------------------------
63 // find an appropriate parent window
64 //------------------------------------------
66 inline bool is_current_process_window(HWND hwnd
)
69 GetWindowThreadProcessId(hwnd
, &pid
);
70 return (pid
== GetCurrentProcessId());
73 HWND
choose_parent_window()
75 HWND hwnd_parent
= GetForegroundWindow();
76 if (!is_current_process_window(hwnd_parent
))
77 hwnd_parent
= GetDesktopWindow();
83 //------------------------------------------------------------------------
85 //------------------------------------------------------------------------
87 CFileOpenDialog::CFileOpenDialog(
90 sal_uInt32 dwTemplateId
,
91 HINSTANCE hInstance
) :
93 m_hwndFileOpenDlgChild(0),
94 m_bFileOpenDialog(bFileOpenDialog
),
95 m_filterBuffer(MAX_FILTER_BUFF_SIZE
),
96 m_fileTitleBuffer(MAX_FILETITLE_BUFF_SIZE
),
97 m_helperBuffer(MAX_FILENAME_BUFF_SIZE
),
98 m_fileNameBuffer(MAX_FILENAME_BUFF_SIZE
),
101 // initialize the OPENFILENAME struct
102 if (IsWindows2000Platform() || IsWindowsME())
104 ZeroMemory(&m_ofn
, sizeof(m_ofn
));
105 m_ofn
.lStructSize
= sizeof(m_ofn
);
107 else // OSVER < Win2000
109 // the size of the OPENFILENAME structure is different
110 // under windows < win2000
111 ZeroMemory(&m_ofn
, _OPENFILENAME_SIZE_VERSION_400
);
112 m_ofn
.lStructSize
= _OPENFILENAME_SIZE_VERSION_400
;
115 // 0x02000000 for #97681, sfx will make the entry into
116 // the recent document list
117 m_ofn
.Flags
|= dwFlags
|
123 OFN_OVERWRITEPROMPT
|
125 OFN_DONTADDTORECENT
; // 0x02000000 -> OFN_DONTADDTORECENT only available with new platform sdk
127 // it is a little hack but how else could
128 // we get a parent window (using a vcl window?)
129 m_ofn
.hwndOwner
= choose_parent_window();
131 m_ofn
.lpstrFile
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileNameBuffer
.getStr()));
132 m_ofn
.nMaxFile
= m_fileNameBuffer
.getCapacity();
134 m_ofn
.lpstrFileTitle
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileTitleBuffer
.getStr()));
135 m_ofn
.nMaxFileTitle
= m_fileTitleBuffer
.getCapacity();
137 m_ofn
.lpfnHook
= CFileOpenDialog::ofnHookProc
;
139 // set a custom template
143 OSL_ASSERT(hInstance
);
145 m_ofn
.Flags
|= OFN_ENABLETEMPLATE
;
146 m_ofn
.lpTemplateName
= MAKEINTRESOURCE(dwTemplateId
);
147 m_ofn
.hInstance
= hInstance
;
150 // set a pointer to myself as ofn parameter
151 m_ofn
.lCustData
= reinterpret_cast<long>(this);
154 //------------------------------------------------------------------------
156 //------------------------------------------------------------------------
158 CFileOpenDialog::~CFileOpenDialog()
162 //------------------------------------------------------------------------
164 //------------------------------------------------------------------------
166 void SAL_CALL
CFileOpenDialog::setTitle(const rtl::OUString
& aTitle
)
168 m_dialogTitle
= aTitle
;
169 m_ofn
.lpstrTitle
= reinterpret_cast<LPCTSTR
>(m_dialogTitle
.getStr());
172 //------------------------------------------------------------------------
174 //------------------------------------------------------------------------
176 void CFileOpenDialog::setFilter(const rtl::OUString
& aFilter
)
179 // "*.TXT" or multiple separate by ';' like "*.TXT;*.DOC;*.SXW"
180 // Do not include spaces in the pattern string
181 m_filterBuffer
.ensureCapacity(aFilter
.getLength());
182 m_filterBuffer
.setLength(0);
183 m_filterBuffer
.append(aFilter
);
184 m_ofn
.lpstrFilter
= reinterpret_cast<LPCTSTR
>(m_filterBuffer
.getStr());
187 //------------------------------------------------------------------------
189 //------------------------------------------------------------------------
191 bool CFileOpenDialog::setFilterIndex(sal_uInt32 aIndex
)
193 OSL_ASSERT(aIndex
> 0);
194 m_ofn
.nFilterIndex
= aIndex
;
198 //------------------------------------------------------------------------
200 //------------------------------------------------------------------------
202 sal_uInt32
CFileOpenDialog::getSelectedFilterIndex() const
204 return m_ofn
.nFilterIndex
;
207 //------------------------------------------------------------------------
209 //------------------------------------------------------------------------
211 void SAL_CALL
CFileOpenDialog::setDefaultName(const rtl::OUString
& aName
)
213 m_fileNameBuffer
.setLength(0);
214 m_fileNameBuffer
.append(aName
);
215 m_ofn
.lpstrFile
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileNameBuffer
.getStr()));
218 //------------------------------------------------------------------------
220 //------------------------------------------------------------------------
222 void SAL_CALL
CFileOpenDialog::setDisplayDirectory(const rtl::OUString
& aDirectory
)
224 m_displayDirectory
= aDirectory
;
225 m_ofn
.lpstrInitialDir
= reinterpret_cast<LPCTSTR
>(m_displayDirectory
.getStr());
228 //------------------------------------------------------------------------
230 //------------------------------------------------------------------------
232 rtl::OUString SAL_CALL
CFileOpenDialog::getLastDisplayDirectory() const
234 return m_displayDirectory
;
237 //------------------------------------------------------------------------
239 //------------------------------------------------------------------------
241 rtl::OUString SAL_CALL
CFileOpenDialog::getFullFileName() const
243 return rtl::OUString(m_fileNameBuffer
.getStr(),
244 _wcslenex(m_fileNameBuffer
.getStr()));
247 //------------------------------------------------------------------------
249 //------------------------------------------------------------------------
251 rtl::OUString SAL_CALL
CFileOpenDialog::getFileName() const
253 return rtl::OUString(m_fileTitleBuffer
);
256 //------------------------------------------------------------------------
258 //------------------------------------------------------------------------
260 rtl::OUString
CFileOpenDialog::getFileExtension()
262 if (m_ofn
.nFileExtension
)
263 return rtl::OUString(m_fileNameBuffer
.getStr() + m_ofn
.nFileExtension
,
264 rtl_ustr_getLength(m_fileNameBuffer
.getStr() + m_ofn
.nFileExtension
));
266 return rtl::OUString();
269 //------------------------------------------------------------------------
271 //------------------------------------------------------------------------
273 void CFileOpenDialog::setDefaultFileExtension(const rtl::OUString
& aExtension
)
275 m_defaultExtension
= aExtension
;
276 m_ofn
.lpstrDefExt
= reinterpret_cast<LPCTSTR
>(m_defaultExtension
.getStr());
279 //------------------------------------------------------------------------
281 //------------------------------------------------------------------------
283 void SAL_CALL
CFileOpenDialog::setMultiSelectionMode(bool bMode
)
286 m_ofn
.Flags
|= OFN_ALLOWMULTISELECT
;
288 m_ofn
.Flags
&= ~OFN_ALLOWMULTISELECT
;
291 //------------------------------------------------------------------------
293 //------------------------------------------------------------------------
295 bool SAL_CALL
CFileOpenDialog::getMultiSelectionMode() const
297 return ((m_ofn
.Flags
& OFN_ALLOWMULTISELECT
) > 0);
300 //------------------------------------------------------------------------
302 //------------------------------------------------------------------------
304 sal_Int16 SAL_CALL
CFileOpenDialog::doModal()
313 if (m_bFileOpenDialog
)
314 bRet
= m_GetFileNameWrapper
.getOpenFileName(
315 reinterpret_cast<LPOPENFILENAME
>(&m_ofn
));
317 bRet
= m_GetFileNameWrapper
.getSaveFileName(
318 reinterpret_cast<LPOPENFILENAME
>(&m_ofn
));
323 nRC
= (0 == m_GetFileNameWrapper
.commDlgExtendedError()) ? 0 : -1;
332 //------------------------------------------------------------------------
334 //------------------------------------------------------------------------
336 sal_uInt32 SAL_CALL
CFileOpenDialog::getLastDialogError() const
338 return CommDlgExtendedError();
341 //------------------------------------------------------------------------
343 //------------------------------------------------------------------------
345 bool SAL_CALL
CFileOpenDialog::preModal()
350 //------------------------------------------------------------------------
352 //------------------------------------------------------------------------
354 void SAL_CALL
CFileOpenDialog::postModal(sal_Int16 nDialogResult
)
356 OSL_ASSERT((-1 <= nDialogResult
) && (nDialogResult
<= 1));
358 if (1 == nDialogResult
)
360 // Attention: assuming that nFileOffset is always greater 0 because under
361 // Windows there is always a drive letter or a server in a complete path
362 // the OPENFILENAME docu never says that nFileOffset can be 0
363 m_displayDirectory
= rtl::OUString(reinterpret_cast<const sal_Unicode
*>(m_ofn
.lpstrFile
),m_ofn
.nFileOffset
);
367 //------------------------------------------------------------------------
369 //------------------------------------------------------------------------
371 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFilePath() const
373 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
375 LPARAM nLen
= SendMessage(
378 m_helperBuffer
.getCapacity(),
379 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
383 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
384 return rtl::OUString(m_helperBuffer
);
386 return rtl::OUString();
389 //------------------------------------------------------------------------
391 //------------------------------------------------------------------------
393 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFolderPath() const
395 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
397 LPARAM nLen
= SendMessage(
400 m_helperBuffer
.getCapacity(),
401 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
405 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
406 return rtl::OUString(m_helperBuffer
);
408 return rtl::OUString();
411 //------------------------------------------------------------------------
413 //------------------------------------------------------------------------
415 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFileName() const
417 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
419 LPARAM nLen
= SendMessage(
422 m_helperBuffer
.getCapacity(),
423 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
427 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
428 return rtl::OUString(m_helperBuffer
);
430 return rtl::OUString();
433 //------------------------------------------------------------------------
435 //------------------------------------------------------------------------
437 sal_uInt32 SAL_CALL
CFileOpenDialog::onShareViolation(const rtl::OUString
&)
442 //------------------------------------------------------------------------
444 //------------------------------------------------------------------------
446 sal_uInt32 SAL_CALL
CFileOpenDialog::onFileOk()
451 //------------------------------------------------------------------------
453 //------------------------------------------------------------------------
455 void SAL_CALL
CFileOpenDialog::onSelChanged(HWND
)
459 //------------------------------------------------------------------------
461 //------------------------------------------------------------------------
463 void SAL_CALL
CFileOpenDialog::onHelp()
467 //------------------------------------------------------------------------
469 //------------------------------------------------------------------------
471 void SAL_CALL
CFileOpenDialog::onInitDone()
473 centerPositionToParent();
476 //------------------------------------------------------------------------
478 //------------------------------------------------------------------------
480 void SAL_CALL
CFileOpenDialog::onFolderChanged()
484 //------------------------------------------------------------------------
486 //------------------------------------------------------------------------
488 void SAL_CALL
CFileOpenDialog::onTypeChanged(sal_uInt32
)
492 //------------------------------------------------------------------------
494 //------------------------------------------------------------------------
496 sal_uInt32 SAL_CALL
CFileOpenDialog::onCtrlCommand(HWND
, sal_uInt16
, sal_uInt16
)
501 //------------------------------------------------------------------------
503 //------------------------------------------------------------------------
505 sal_uInt32 SAL_CALL
CFileOpenDialog::onWMNotify( HWND
, LPOFNOTIFY lpOfNotify
)
507 switch(lpOfNotify
->hdr
.code
)
509 case CDN_SHAREVIOLATION
:
510 return onShareViolation(reinterpret_cast<const sal_Unicode
*>(lpOfNotify
->pszFile
));
516 onSelChanged(lpOfNotify
->hdr
.hwndFrom
);
527 case CDN_FOLDERCHANGE
:
532 m_ofn
.nFilterIndex
= lpOfNotify
->lpOFN
->nFilterIndex
;
533 onTypeChanged(lpOfNotify
->lpOFN
->nFilterIndex
);
540 //------------------------------------------------------------------------
542 //------------------------------------------------------------------------
544 void SAL_CALL
CFileOpenDialog::handleInitDialog(HWND hwndDlg
, HWND hwndChild
)
546 m_hwndFileOpenDlg
= hwndDlg
;
547 m_hwndFileOpenDlgChild
= hwndChild
;
549 OSL_ASSERT(GetParent(hwndChild
) == hwndDlg
);
551 // calling virtual function which the
552 // client can overload
553 onInitDialog(hwndDlg
);
556 //------------------------------------------------------------------------
558 //------------------------------------------------------------------------
560 unsigned int CALLBACK
CFileOpenDialog::ofnHookProc(
561 HWND hChildDlg
, unsigned int uiMsg
, WPARAM wParam
, LPARAM lParam
)
563 HWND hwndDlg
= GetParent(hChildDlg
);
564 CFileOpenDialog
* pImpl
= NULL
;
570 _LPOPENFILENAME lpofn
= reinterpret_cast<_LPOPENFILENAME
>(lParam
);
571 pImpl
= reinterpret_cast<CFileOpenDialog
*>(lpofn
->lCustData
);
574 // subclass the base dialog for WM_NCDESTROY processing
575 pImpl
->m_pfnBaseDlgProc
=
576 reinterpret_cast<WNDPROC
>(
580 reinterpret_cast<LONG
>(CFileOpenDialog::BaseDlgProc
)));
581 // connect the instance handle to the window
582 SetProp(hwndDlg
, CURRENT_INSTANCE
, pImpl
);
583 pImpl
->handleInitDialog(hwndDlg
, hChildDlg
);
589 pImpl
= getCurrentInstance(hwndDlg
);
590 return pImpl
->onWMNotify(
591 hChildDlg
, reinterpret_cast<LPOFNOTIFY
>(lParam
));
596 pImpl
= getCurrentInstance(hwndDlg
);
599 return pImpl
->onCtrlCommand(
600 hChildDlg
, LOWORD(wParam
), HIWORD(lParam
));
607 //------------------------------------------------------------------------
609 //------------------------------------------------------------------------
611 LRESULT CALLBACK
CFileOpenDialog::BaseDlgProc(
612 HWND hWnd
, UINT wMessage
, WPARAM wParam
, LPARAM lParam
)
614 CFileOpenDialog
* pImpl
= 0;
616 if (WM_NCDESTROY
== wMessage
)
618 pImpl
= reinterpret_cast<CFileOpenDialog
*>(
619 RemoveProp(hWnd
,CURRENT_INSTANCE
));
621 SetWindowLong(hWnd
, GWL_WNDPROC
,
622 reinterpret_cast<LONG
>(pImpl
->m_pfnBaseDlgProc
));
626 pImpl
= getCurrentInstance(hWnd
);
631 return CallWindowProc(
632 reinterpret_cast<WNDPROC
>(pImpl
->m_pfnBaseDlgProc
),
633 hWnd
,wMessage
,wParam
,lParam
);
636 //------------------------------------------------------------------------
638 //------------------------------------------------------------------------
640 CFileOpenDialog
* SAL_CALL
CFileOpenDialog::getCurrentInstance(HWND hwnd
)
642 OSL_ASSERT(IsWindow( hwnd
));
643 return reinterpret_cast<CFileOpenDialog
*>(
644 GetProp(hwnd
, CURRENT_INSTANCE
));
647 //------------------------------------------------------------------------
649 //------------------------------------------------------------------------
651 void SAL_CALL
CFileOpenDialog::centerPositionToParent() const
653 OSL_PRECOND(IsWindow(m_hwndFileOpenDlg
), "no dialog window, call method only after or in onInitDone");
655 HWND hwndParent
= m_ofn
.hwndOwner
;
657 if (!IsWindow(hwndParent
))
658 hwndParent
= GetDesktopWindow();
660 OSL_ASSERT(IsWindow(hwndParent
));
663 GetWindowRect(hwndParent
, &rcPar
);
666 GetWindowRect(m_hwndFileOpenDlg
, &rcDlg
);
668 int lDlgW
= rcDlg
.right
- rcDlg
.left
;
669 int lDlgH
= rcDlg
.bottom
- rcDlg
.top
;
671 int x
= (rcPar
.left
+ rcPar
.right
- lDlgW
) / 2;
672 int y
= (rcPar
.top
+ rcPar
.bottom
- lDlgH
) / 2;
674 HDC hdc
= GetDC(m_hwndFileOpenDlg
);
676 int hResol
= GetDeviceCaps(hdc
, HORZRES
);
677 int vResol
= GetDeviceCaps(hdc
, VERTRES
);
679 ReleaseDC(m_hwndFileOpenDlg
, hdc
);
683 else if ((x
+ lDlgW
) > hResol
)
688 else if ((y
+ lDlgH
) > vResol
)
694 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
);