1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FileOpenDlg.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_fpicker.hxx"
34 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
39 #include <osl/diagnose.h>
40 #include "../misc/WinImplHelper.hxx"
41 #include "FileOpenDlg.hxx"
43 //------------------------------------------------------------------------
45 //------------------------------------------------------------------------
47 namespace /* private */
49 // we choose such large buffers because the size of
50 // an single line edit field can be up to 32k; if
51 // a user has a multi selection FilePicker and selects
52 // a lot of files in a large directory we may reach this
53 // limit and don't want to get out of memory;
54 // another much more elegant way would be to subclass the
55 // FileOpen dialog and overload the BM_CLICK event of the
56 // OK button so that we determine the size of the text
57 // currently in the edit field and resize our buffer
58 // appropriately - in the future we will do this
59 const size_t MAX_FILENAME_BUFF_SIZE
= 32000;
60 const size_t MAX_FILETITLE_BUFF_SIZE
= 32000;
61 const size_t MAX_FILTER_BUFF_SIZE
= 4096;
63 const LPTSTR CURRENT_INSTANCE
= TEXT("CurrInst");
65 //------------------------------------------
66 // find an appropriate parent window
67 //------------------------------------------
69 inline bool is_current_process_window(HWND hwnd
)
72 GetWindowThreadProcessId(hwnd
, &pid
);
73 return (pid
== GetCurrentProcessId());
76 HWND
choose_parent_window()
78 HWND hwnd_parent
= GetForegroundWindow();
79 if (!is_current_process_window(hwnd_parent
))
80 hwnd_parent
= GetDesktopWindow();
86 //------------------------------------------------------------------------
88 //------------------------------------------------------------------------
90 CFileOpenDialog::CFileOpenDialog(
93 sal_uInt32 dwTemplateId
,
94 HINSTANCE hInstance
) :
96 m_hwndFileOpenDlgChild(0),
97 m_bFileOpenDialog(bFileOpenDialog
),
98 m_filterBuffer(MAX_FILTER_BUFF_SIZE
),
99 m_fileTitleBuffer(MAX_FILETITLE_BUFF_SIZE
),
100 m_helperBuffer(MAX_FILENAME_BUFF_SIZE
),
101 m_fileNameBuffer(MAX_FILENAME_BUFF_SIZE
),
104 // initialize the OPENFILENAME struct
105 if (IsWindows2000Platform() || IsWindowsME())
107 ZeroMemory(&m_ofn
, sizeof(m_ofn
));
108 m_ofn
.lStructSize
= sizeof(m_ofn
);
110 else // OSVER < Win2000
112 // the size of the OPENFILENAME structure is different
113 // under windows < win2000
114 ZeroMemory(&m_ofn
, _OPENFILENAME_SIZE_VERSION_400
);
115 m_ofn
.lStructSize
= _OPENFILENAME_SIZE_VERSION_400
;
118 // 0x02000000 for #97681, sfx will make the entry into
119 // the recent document list
120 m_ofn
.Flags
|= dwFlags
|
126 OFN_OVERWRITEPROMPT
|
128 OFN_DONTADDTORECENT
; // 0x02000000 -> OFN_DONTADDTORECENT only available with new platform sdk
130 // it is a little hack but how else could
131 // we get a parent window (using a vcl window?)
132 m_ofn
.hwndOwner
= choose_parent_window();
134 m_ofn
.lpstrFile
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileNameBuffer
.getStr()));
135 m_ofn
.nMaxFile
= m_fileNameBuffer
.getCapacity();
137 m_ofn
.lpstrFileTitle
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileTitleBuffer
.getStr()));
138 m_ofn
.nMaxFileTitle
= m_fileTitleBuffer
.getCapacity();
140 m_ofn
.lpfnHook
= CFileOpenDialog::ofnHookProc
;
142 // set a custom template
146 OSL_ASSERT(hInstance
);
148 m_ofn
.Flags
|= OFN_ENABLETEMPLATE
;
149 m_ofn
.lpTemplateName
= MAKEINTRESOURCE(dwTemplateId
);
150 m_ofn
.hInstance
= hInstance
;
153 // set a pointer to myself as ofn parameter
154 m_ofn
.lCustData
= reinterpret_cast<long>(this);
157 //------------------------------------------------------------------------
159 //------------------------------------------------------------------------
161 CFileOpenDialog::~CFileOpenDialog()
165 //------------------------------------------------------------------------
167 //------------------------------------------------------------------------
169 void SAL_CALL
CFileOpenDialog::setTitle(const rtl::OUString
& aTitle
)
171 m_dialogTitle
= aTitle
;
172 m_ofn
.lpstrTitle
= reinterpret_cast<LPCTSTR
>(m_dialogTitle
.getStr());
175 //------------------------------------------------------------------------
177 //------------------------------------------------------------------------
179 void CFileOpenDialog::setFilter(const rtl::OUString
& aFilter
)
182 // "*.TXT" or multiple separate by ';' like "*.TXT;*.DOC;*.SXW"
183 // Do not include spaces in the pattern string
184 m_filterBuffer
.ensureCapacity(aFilter
.getLength());
185 m_filterBuffer
.setLength(0);
186 m_filterBuffer
.append(aFilter
);
187 m_ofn
.lpstrFilter
= reinterpret_cast<LPCTSTR
>(m_filterBuffer
.getStr());
190 //------------------------------------------------------------------------
192 //------------------------------------------------------------------------
194 bool CFileOpenDialog::setFilterIndex(sal_uInt32 aIndex
)
196 OSL_ASSERT(aIndex
> 0);
197 m_ofn
.nFilterIndex
= aIndex
;
201 //------------------------------------------------------------------------
203 //------------------------------------------------------------------------
205 sal_uInt32
CFileOpenDialog::getSelectedFilterIndex() const
207 return m_ofn
.nFilterIndex
;
210 //------------------------------------------------------------------------
212 //------------------------------------------------------------------------
214 void SAL_CALL
CFileOpenDialog::setDefaultName(const rtl::OUString
& aName
)
216 m_fileNameBuffer
.setLength(0);
217 m_fileNameBuffer
.append(aName
);
218 m_ofn
.lpstrFile
= reinterpret_cast<LPTSTR
>(const_cast<sal_Unicode
*>(m_fileNameBuffer
.getStr()));
221 //------------------------------------------------------------------------
223 //------------------------------------------------------------------------
225 void SAL_CALL
CFileOpenDialog::setDisplayDirectory(const rtl::OUString
& aDirectory
)
227 m_displayDirectory
= aDirectory
;
228 m_ofn
.lpstrInitialDir
= reinterpret_cast<LPCTSTR
>(m_displayDirectory
.getStr());
231 //------------------------------------------------------------------------
233 //------------------------------------------------------------------------
235 rtl::OUString SAL_CALL
CFileOpenDialog::getLastDisplayDirectory() const
237 return m_displayDirectory
;
240 //------------------------------------------------------------------------
242 //------------------------------------------------------------------------
244 rtl::OUString SAL_CALL
CFileOpenDialog::getFullFileName() const
246 return rtl::OUString(m_fileNameBuffer
.getStr(),
247 _wcslenex(m_fileNameBuffer
.getStr()));
250 //------------------------------------------------------------------------
252 //------------------------------------------------------------------------
254 rtl::OUString SAL_CALL
CFileOpenDialog::getFileName() const
256 return rtl::OUString(m_fileTitleBuffer
);
259 //------------------------------------------------------------------------
261 //------------------------------------------------------------------------
263 rtl::OUString
CFileOpenDialog::getFileExtension()
265 if (m_ofn
.nFileExtension
)
266 return rtl::OUString(m_fileNameBuffer
.getStr() + m_ofn
.nFileExtension
,
267 rtl_ustr_getLength(m_fileNameBuffer
.getStr() + m_ofn
.nFileExtension
));
269 return rtl::OUString();
272 //------------------------------------------------------------------------
274 //------------------------------------------------------------------------
276 void CFileOpenDialog::setDefaultFileExtension(const rtl::OUString
& aExtension
)
278 m_defaultExtension
= aExtension
;
279 m_ofn
.lpstrDefExt
= reinterpret_cast<LPCTSTR
>(m_defaultExtension
.getStr());
282 //------------------------------------------------------------------------
284 //------------------------------------------------------------------------
286 void SAL_CALL
CFileOpenDialog::setMultiSelectionMode(bool bMode
)
289 m_ofn
.Flags
|= OFN_ALLOWMULTISELECT
;
291 m_ofn
.Flags
&= ~OFN_ALLOWMULTISELECT
;
294 //------------------------------------------------------------------------
296 //------------------------------------------------------------------------
298 bool SAL_CALL
CFileOpenDialog::getMultiSelectionMode() const
300 return ((m_ofn
.Flags
& OFN_ALLOWMULTISELECT
) > 0);
303 //------------------------------------------------------------------------
305 //------------------------------------------------------------------------
307 sal_Int16 SAL_CALL
CFileOpenDialog::doModal()
316 if (m_bFileOpenDialog
)
317 bRet
= m_GetFileNameWrapper
.getOpenFileName(
318 reinterpret_cast<LPOPENFILENAME
>(&m_ofn
));
320 bRet
= m_GetFileNameWrapper
.getSaveFileName(
321 reinterpret_cast<LPOPENFILENAME
>(&m_ofn
));
326 nRC
= (0 == m_GetFileNameWrapper
.commDlgExtendedError()) ? 0 : -1;
335 //------------------------------------------------------------------------
337 //------------------------------------------------------------------------
339 sal_uInt32 SAL_CALL
CFileOpenDialog::getLastDialogError() const
341 return CommDlgExtendedError();
344 //------------------------------------------------------------------------
346 //------------------------------------------------------------------------
348 bool SAL_CALL
CFileOpenDialog::preModal()
353 //------------------------------------------------------------------------
355 //------------------------------------------------------------------------
357 void SAL_CALL
CFileOpenDialog::postModal(sal_Int16 nDialogResult
)
359 OSL_ASSERT((-1 <= nDialogResult
) && (nDialogResult
<= 1));
361 if (1 == nDialogResult
)
363 // Attention: assuming that nFileOffset is always greater 0 because under
364 // Windows there is always a drive letter or a server in a complete path
365 // the OPENFILENAME docu never says that nFileOffset can be 0
366 m_displayDirectory
= rtl::OUString(reinterpret_cast<const sal_Unicode
*>(m_ofn
.lpstrFile
),m_ofn
.nFileOffset
);
370 //------------------------------------------------------------------------
372 //------------------------------------------------------------------------
374 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFilePath() const
376 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
378 LPARAM nLen
= SendMessage(
381 m_helperBuffer
.getCapacity(),
382 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
386 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
387 return rtl::OUString(m_helperBuffer
);
389 return rtl::OUString();
392 //------------------------------------------------------------------------
394 //------------------------------------------------------------------------
396 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFolderPath() const
398 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
400 LPARAM nLen
= SendMessage(
403 m_helperBuffer
.getCapacity(),
404 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
408 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
409 return rtl::OUString(m_helperBuffer
);
411 return rtl::OUString();
414 //------------------------------------------------------------------------
416 //------------------------------------------------------------------------
418 rtl::OUString SAL_CALL
CFileOpenDialog::getCurrentFileName() const
420 OSL_ASSERT(IsWindow(m_hwndFileOpenDlg
));
422 LPARAM nLen
= SendMessage(
425 m_helperBuffer
.getCapacity(),
426 reinterpret_cast<LPARAM
>(m_helperBuffer
.getStr()));
430 m_helperBuffer
.setLength((nLen
* sizeof(sal_Unicode
)) - 1);
431 return rtl::OUString(m_helperBuffer
);
433 return rtl::OUString();
436 //------------------------------------------------------------------------
438 //------------------------------------------------------------------------
440 sal_uInt32 SAL_CALL
CFileOpenDialog::onShareViolation(const rtl::OUString
&)
445 //------------------------------------------------------------------------
447 //------------------------------------------------------------------------
449 sal_uInt32 SAL_CALL
CFileOpenDialog::onFileOk()
454 //------------------------------------------------------------------------
456 //------------------------------------------------------------------------
458 void SAL_CALL
CFileOpenDialog::onSelChanged(HWND
)
462 //------------------------------------------------------------------------
464 //------------------------------------------------------------------------
466 void SAL_CALL
CFileOpenDialog::onHelp()
470 //------------------------------------------------------------------------
472 //------------------------------------------------------------------------
474 void SAL_CALL
CFileOpenDialog::onInitDone()
476 centerPositionToParent();
479 //------------------------------------------------------------------------
481 //------------------------------------------------------------------------
483 void SAL_CALL
CFileOpenDialog::onFolderChanged()
487 //------------------------------------------------------------------------
489 //------------------------------------------------------------------------
491 void SAL_CALL
CFileOpenDialog::onTypeChanged(sal_uInt32
)
495 //------------------------------------------------------------------------
497 //------------------------------------------------------------------------
499 sal_uInt32 SAL_CALL
CFileOpenDialog::onCtrlCommand(HWND
, sal_uInt16
, sal_uInt16
)
504 //------------------------------------------------------------------------
506 //------------------------------------------------------------------------
508 sal_uInt32 SAL_CALL
CFileOpenDialog::onWMNotify( HWND
, LPOFNOTIFY lpOfNotify
)
510 switch(lpOfNotify
->hdr
.code
)
512 case CDN_SHAREVIOLATION
:
513 return onShareViolation(reinterpret_cast<const sal_Unicode
*>(lpOfNotify
->pszFile
));
519 onSelChanged(lpOfNotify
->hdr
.hwndFrom
);
530 case CDN_FOLDERCHANGE
:
535 m_ofn
.nFilterIndex
= lpOfNotify
->lpOFN
->nFilterIndex
;
536 onTypeChanged(lpOfNotify
->lpOFN
->nFilterIndex
);
543 //------------------------------------------------------------------------
545 //------------------------------------------------------------------------
547 void SAL_CALL
CFileOpenDialog::handleInitDialog(HWND hwndDlg
, HWND hwndChild
)
549 m_hwndFileOpenDlg
= hwndDlg
;
550 m_hwndFileOpenDlgChild
= hwndChild
;
552 OSL_ASSERT(GetParent(hwndChild
) == hwndDlg
);
554 // calling virtual function which the
555 // client can overload
556 onInitDialog(hwndDlg
);
559 //------------------------------------------------------------------------
561 //------------------------------------------------------------------------
563 unsigned int CALLBACK
CFileOpenDialog::ofnHookProc(
564 HWND hChildDlg
, unsigned int uiMsg
, WPARAM wParam
, LPARAM lParam
)
566 HWND hwndDlg
= GetParent(hChildDlg
);
567 CFileOpenDialog
* pImpl
= NULL
;
573 _LPOPENFILENAME lpofn
= reinterpret_cast<_LPOPENFILENAME
>(lParam
);
574 pImpl
= reinterpret_cast<CFileOpenDialog
*>(lpofn
->lCustData
);
577 // subclass the base dialog for WM_NCDESTROY processing
578 pImpl
->m_pfnBaseDlgProc
=
579 reinterpret_cast<WNDPROC
>(
583 reinterpret_cast<LONG
>(CFileOpenDialog::BaseDlgProc
)));
584 // connect the instance handle to the window
585 SetProp(hwndDlg
, CURRENT_INSTANCE
, pImpl
);
586 pImpl
->handleInitDialog(hwndDlg
, hChildDlg
);
592 pImpl
= getCurrentInstance(hwndDlg
);
593 return pImpl
->onWMNotify(
594 hChildDlg
, reinterpret_cast<LPOFNOTIFY
>(lParam
));
599 pImpl
= getCurrentInstance(hwndDlg
);
602 return pImpl
->onCtrlCommand(
603 hChildDlg
, LOWORD(wParam
), HIWORD(lParam
));
610 //------------------------------------------------------------------------
612 //------------------------------------------------------------------------
614 LRESULT CALLBACK
CFileOpenDialog::BaseDlgProc(
615 HWND hWnd
, UINT wMessage
, WPARAM wParam
, LPARAM lParam
)
617 CFileOpenDialog
* pImpl
= 0;
619 if (WM_NCDESTROY
== wMessage
)
621 pImpl
= reinterpret_cast<CFileOpenDialog
*>(
622 RemoveProp(hWnd
,CURRENT_INSTANCE
));
624 SetWindowLong(hWnd
, GWL_WNDPROC
,
625 reinterpret_cast<LONG
>(pImpl
->m_pfnBaseDlgProc
));
629 pImpl
= getCurrentInstance(hWnd
);
634 return CallWindowProc(
635 reinterpret_cast<WNDPROC
>(pImpl
->m_pfnBaseDlgProc
),
636 hWnd
,wMessage
,wParam
,lParam
);
639 //------------------------------------------------------------------------
641 //------------------------------------------------------------------------
643 CFileOpenDialog
* SAL_CALL
CFileOpenDialog::getCurrentInstance(HWND hwnd
)
645 OSL_ASSERT(IsWindow( hwnd
));
646 return reinterpret_cast<CFileOpenDialog
*>(
647 GetProp(hwnd
, CURRENT_INSTANCE
));
650 //------------------------------------------------------------------------
652 //------------------------------------------------------------------------
654 void SAL_CALL
CFileOpenDialog::centerPositionToParent() const
656 OSL_PRECOND(IsWindow(m_hwndFileOpenDlg
), "no dialog window, call method only after or in onInitDone");
658 HWND hwndParent
= m_ofn
.hwndOwner
;
660 if (!IsWindow(hwndParent
))
661 hwndParent
= GetDesktopWindow();
663 OSL_ASSERT(IsWindow(hwndParent
));
666 GetWindowRect(hwndParent
, &rcPar
);
669 GetWindowRect(m_hwndFileOpenDlg
, &rcDlg
);
671 int lDlgW
= rcDlg
.right
- rcDlg
.left
;
672 int lDlgH
= rcDlg
.bottom
- rcDlg
.top
;
674 int x
= (rcPar
.left
+ rcPar
.right
- lDlgW
) / 2;
675 int y
= (rcPar
.top
+ rcPar
.bottom
- lDlgH
) / 2;
677 HDC hdc
= GetDC(m_hwndFileOpenDlg
);
679 int hResol
= GetDeviceCaps(hdc
, HORZRES
);
680 int vResol
= GetDeviceCaps(hdc
, VERTRES
);
682 ReleaseDC(m_hwndFileOpenDlg
, hdc
);
686 else if ((x
+ lDlgW
) > hResol
)
691 else if ((y
+ lDlgH
) > vResol
)
697 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
);