1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_fpicker.hxx"
26
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30
31 #include "shared.hxx"
32 #include "WinFileOpenImpl.hxx"
33 #include <osl/diagnose.h>
34 #include <osl/file.hxx>
35 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
36 #include <com/sun/star/ui/dialogs/FilePickerEvent.hpp>
37 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
38 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
39 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
40 #include <com/sun/star/ui/dialogs/ListBoxControlActions.hpp>
41 #include "..\misc\WinImplHelper.hxx"
42
43 #ifndef _FILEPICKER_HXX_
44 #include "filepicker.hxx"
45 #endif
46 #include "controlaccess.hxx"
47 #include <rtl/ustrbuf.hxx>
48 #include <rtl/string.hxx>
49 #include <osl/thread.hxx>
50 #include "filepickerstate.hxx"
51
52 //------------------------------------------------------------------------
53 // namespace directives
54 //------------------------------------------------------------------------
55
56 using namespace com::sun::star;
57
58 using com::sun::star::ui::dialogs::FilePickerEvent;
59 using com::sun::star::lang::IllegalArgumentException;
60 using com::sun::star::ui::dialogs::XFilePicker2;
61
62 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
63 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
64 using namespace ::com::sun::star::ui::dialogs::ListboxControlActions;
65
66 //-------------------------------------------------------------------------
67 // to distinguish what to do in the enum child window callback function
68 //-------------------------------------------------------------------------
69
70 enum ECW_ACTION_T
71 {
72 INIT_CUSTOM_CONTROLS,
73 CACHE_CONTROL_VALUES
74 };
75
76 struct EnumParam
77 {
78 ECW_ACTION_T m_action;
79 CWinFileOpenImpl* m_instance;
80
EnumParamEnumParam81 EnumParam( ECW_ACTION_T action, CWinFileOpenImpl* instance ):
82 m_action( action ),
83 m_instance( instance )
84 {}
85 };
86
87 //-------------------------------------------------------------------------
88 // ctor
89 //-------------------------------------------------------------------------
90
CWinFileOpenImpl(CFilePicker * aFilePicker,sal_Bool bFileOpenDialog,sal_uInt32 dwFlags,sal_uInt32 dwTemplateId,HINSTANCE hInstance)91 CWinFileOpenImpl::CWinFileOpenImpl(
92 CFilePicker* aFilePicker,
93 sal_Bool bFileOpenDialog,
94 sal_uInt32 dwFlags,
95 sal_uInt32 dwTemplateId,
96 HINSTANCE hInstance) :
97 CFileOpenDialog(bFileOpenDialog, dwFlags, dwTemplateId, hInstance),
98 m_filterContainer(new CFilterContainer()),
99 m_Preview(new CPreviewAdapter(hInstance)),
100 m_CustomControlFactory(new CCustomControlFactory()),
101 m_CustomControls(m_CustomControlFactory->CreateCustomControlContainer()),
102 m_FilePicker(aFilePicker),
103 m_bInitialSelChanged(sal_True),
104 m_HelpPopupWindow(hInstance, m_hwndFileOpenDlg),
105 m_ExecuteFilePickerState(new CExecuteFilePickerState()),
106 m_NonExecuteFilePickerState(new CNonExecuteFilePickerState())
107 {
108 m_FilePickerState = m_NonExecuteFilePickerState;
109 }
110
111 //------------------------------------------------------------------------
112 // dtor
113 //------------------------------------------------------------------------
114
~CWinFileOpenImpl()115 CWinFileOpenImpl::~CWinFileOpenImpl()
116 {
117 delete m_ExecuteFilePickerState;
118 delete m_NonExecuteFilePickerState;
119 }
120
121 //------------------------------------------------------------------------
122 // we expect the directory in URL format
123 //------------------------------------------------------------------------
124
setDisplayDirectory(const rtl::OUString & aDirectory)125 void CWinFileOpenImpl::setDisplayDirectory(const rtl::OUString& aDirectory)
126 {
127 rtl::OUString aSysDirectory;
128 if( aDirectory.getLength() > 0)
129 {
130 if ( ::osl::FileBase::E_None !=
131 ::osl::FileBase::getSystemPathFromFileURL(aDirectory,aSysDirectory))
132 throw IllegalArgumentException(
133 rtl::OUString::createFromAscii("Invalid directory"),
134 static_cast<XFilePicker2*>(m_FilePicker), 1);
135
136 // we ensure that there is a trailing '/' at the end of
137 // he given file url, because the windows functions only
138 // works correctly when providing "c:\" or an environment
139 // variable like "=c:=c:\.." etc. is set, else the
140 // FolderPicker would stand in the root of the shell
141 // hierarchie which is the desktop folder
142 if ( aSysDirectory.lastIndexOf(BACKSLASH) != (aSysDirectory.getLength() - 1))
143 aSysDirectory += BACKSLASH;
144 }
145
146 // call base class method
147 CFileOpenDialog::setDisplayDirectory(aSysDirectory);
148 }
149
150 //------------------------------------------------------------------------
151 // we return the directory in URL format
152 //------------------------------------------------------------------------
153
getDisplayDirectory()154 rtl::OUString CWinFileOpenImpl::getDisplayDirectory()
155 {
156 return m_FilePickerState->getDisplayDirectory(this);
157 }
158
159 //-----------------------------------------------------------------------------------------
160 //
161 //-----------------------------------------------------------------------------------------
162
setDefaultName(const rtl::OUString & aName)163 void SAL_CALL CWinFileOpenImpl::setDefaultName(const rtl::OUString& aName)
164 {
165 // we don't set the default name directly
166 // because this influences how the file open
167 // dialog sets the initial path when it is about
168 // to open (see MSDN: OPENFILENAME)
169 // so we save the default name which should
170 // appear in the file-name-box and set
171 // this name when processing onInitDone
172 m_defaultName = aName;
173 }
174
175 //-----------------------------------------------------------------------------------------
176 // return format: URL
177 // if multiselection is allowed there are two different cases
178 // 1. one file selected: the sequence contains one entry path\filename.ext
179 // 2. multiple files selected: the sequence contains multiple entries
180 // the first entry is the path url, all other entries are file names
181 //-----------------------------------------------------------------------------------------
182
getFiles()183 uno::Sequence<rtl::OUString> SAL_CALL CWinFileOpenImpl::getFiles()
184 {
185 return m_FilePickerState->getFiles(this);
186 }
187
188 //-----------------------------------------------------------------------------------------
189 // shows the FileOpen/FileSave dialog
190 //-----------------------------------------------------------------------------------------
191
execute()192 sal_Int16 SAL_CALL CWinFileOpenImpl::execute( )
193 {
194 sal_Int16 rc = CFileOpenDialog::doModal();
195
196 if (1 == rc)
197 rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::OK;
198 else if (0 == rc)
199 rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
200 else
201 throw uno::RuntimeException(
202 rtl::OUString::createFromAscii("Error executing dialog"),
203 static_cast<XFilePicker2*>(m_FilePicker));
204
205 return rc;
206 }
207
208 //-----------------------------------------------------------------------------------------
209 // appends a new filter
210 // returns false if the title (aTitle) was already added or the title or the filter are
211 // empty
212 //-----------------------------------------------------------------------------------------
213
appendFilter(const rtl::OUString & aTitle,const rtl::OUString & aFilter)214 void SAL_CALL CWinFileOpenImpl::appendFilter(const rtl::OUString& aTitle, const rtl::OUString& aFilter)
215 {
216 sal_Bool bRet = m_filterContainer->addFilter(aTitle, aFilter);
217
218 if (!bRet)
219 throw IllegalArgumentException(
220 rtl::OUString::createFromAscii("filter already exists"),
221 static_cast<XFilePicker2*>(m_FilePicker), 1);
222
223 // #95345# see MSDN OPENFILENAME
224 // If nFilterIndex is zero and lpstrCustomFilter is NULL,
225 // the system uses the first filter in the lpstrFilter buffer.
226 // to reflect this we must set the filter index so that calls
227 // to getSelectedFilterIndex without explicitly calling
228 // setFilterIndex before does not return 0 which leads to a
229 // false state
230 if (0 == getSelectedFilterIndex())
231 CFileOpenDialog::setFilterIndex(1);
232 }
233
234 //-----------------------------------------------------------------------------------------
235 // sets a current filter
236 //-----------------------------------------------------------------------------------------
237
setCurrentFilter(const rtl::OUString & aTitle)238 void SAL_CALL CWinFileOpenImpl::setCurrentFilter(const rtl::OUString& aTitle)
239 {
240 sal_Int32 filterPos = m_filterContainer->getFilterPos(aTitle);
241
242 if (filterPos < 0)
243 throw IllegalArgumentException(
244 rtl::OUString::createFromAscii("filter doesn't exist"),
245 static_cast<XFilePicker2*>(m_FilePicker), 1);
246
247 // filter index of the base class starts with 1
248 CFileOpenDialog::setFilterIndex(filterPos + 1);
249 }
250
251 //-----------------------------------------------------------------------------------------
252 // returns the currently selected filter
253 //-----------------------------------------------------------------------------------------
254
getCurrentFilter()255 rtl::OUString SAL_CALL CWinFileOpenImpl::getCurrentFilter()
256 {
257 sal_uInt32 nIndex = getSelectedFilterIndex();
258
259 rtl::OUString currentFilter;
260 if (nIndex > 0)
261 {
262 // filter index of the base class starts with 1
263 if (!m_filterContainer->getFilter(nIndex - 1, currentFilter)) {
264 OSL_ASSERT(false);
265 }
266 }
267
268 return currentFilter;
269 }
270
271 //-----------------------------------------------------------------------------------------
272 //
273 //-----------------------------------------------------------------------------------------
274
appendFilterGroupSeparator()275 inline void SAL_CALL CWinFileOpenImpl::appendFilterGroupSeparator()
276 {
277 m_filterContainer->addFilter(FILTER_SEPARATOR, ALL_FILES_WILDCARD, ALLOW_DUPLICATES);
278 }
279
280 //-----------------------------------------------------------------------------------------
281 // XFilterGroupManager
282 //-----------------------------------------------------------------------------------------
283
appendFilterGroup(const rtl::OUString & sGroupTitle,const uno::Sequence<beans::StringPair> & aFilters)284 void SAL_CALL CWinFileOpenImpl::appendFilterGroup(const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters)
285 {
286 (void) sGroupTitle; // avoid warning
287 OSL_ENSURE(0 == sGroupTitle.getLength(), "appendFilterGroup: Parameter 'GroupTitle' currently ignored");
288
289 sal_Int32 nFilters = aFilters.getLength();
290
291 OSL_PRECOND(nFilters > 0, "Empty filter list");
292
293 if (nFilters > 0)
294 {
295 // append a separator before the next group if
296 // there is already a group of filters
297 if (m_filterContainer->numFilter() > 0)
298 appendFilterGroupSeparator();
299
300 for (int i = 0; i < nFilters; i++)
301 appendFilter(aFilters[i].First, aFilters[i].Second);
302 }
303 }
304
305 //=================================================================================================================
306 // XExtendedFilePicker
307 //=================================================================================================================
308
309 // #i90917: Due to a different feature set for the system-dependent file pickers
310 // it's possible that generic code (e.g. sfx2) provides control ids
311 // (see ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR) which are NOT
312 // available on all platforms. This filter function should filter out control ids
313 // which are only available on KDE/GTK file pickers.
filterControlCommand(sal_Int16 nControlId)314 static bool filterControlCommand( sal_Int16 nControlId )
315 {
316 if ( nControlId == LISTBOX_FILTER_SELECTOR )
317 return true;
318 return false;
319 }
320
setValue(sal_Int16 aControlId,sal_Int16 aControlAction,const uno::Any & aValue)321 void SAL_CALL CWinFileOpenImpl::setValue(sal_Int16 aControlId, sal_Int16 aControlAction, const uno::Any& aValue)
322 {
323 OSL_ASSERT(m_FilePickerState);
324 if ( !filterControlCommand( aControlId ))
325 m_FilePickerState->setValue(aControlId, aControlAction, aValue);
326 }
327
328 //-----------------------------------------------------------------------------------------
329 // returns the value of an custom template element
330 // we assume that there are only checkboxes or comboboxes
331 //-----------------------------------------------------------------------------------------
332
getValue(sal_Int16 aControlId,sal_Int16 aControlAction)333 uno::Any SAL_CALL CWinFileOpenImpl::getValue(sal_Int16 aControlId, sal_Int16 aControlAction)
334 {
335 OSL_ASSERT(m_FilePickerState);
336 if ( !filterControlCommand( aControlId ))
337 return m_FilePickerState->getValue(aControlId, aControlAction);
338 else
339 return uno::Any();
340 }
341
342 //-----------------------------------------------------------------------------------------
343 // enables a custom template element
344 //-----------------------------------------------------------------------------------------
345
enableControl(sal_Int16 ControlID,sal_Bool bEnable)346 void SAL_CALL CWinFileOpenImpl::enableControl(sal_Int16 ControlID, sal_Bool bEnable)
347 {
348 OSL_ASSERT(m_FilePickerState);
349 if ( !filterControlCommand( ControlID ))
350 m_FilePickerState->enableControl(ControlID, bEnable);
351 }
352
353 //-----------------------------------------------------------------------------------------
354 //
355 //-----------------------------------------------------------------------------------------
356
setLabel(sal_Int16 aControlId,const rtl::OUString & aLabel)357 void SAL_CALL CWinFileOpenImpl::setLabel( sal_Int16 aControlId, const rtl::OUString& aLabel )
358 {
359 OSL_ASSERT(m_FilePickerState);
360 if ( !filterControlCommand( aControlId ))
361 m_FilePickerState->setLabel(aControlId, aLabel);
362 }
363
364 //-----------------------------------------------------------------------------------------
365 //
366 //-----------------------------------------------------------------------------------------
367
getLabel(sal_Int16 aControlId)368 rtl::OUString SAL_CALL CWinFileOpenImpl::getLabel( sal_Int16 aControlId )
369 {
370 OSL_ASSERT(m_FilePickerState);
371 if ( !filterControlCommand( aControlId ))
372 return m_FilePickerState->getLabel(aControlId);
373 else
374 return rtl::OUString();
375 }
376
377 //-----------------------------------------------------------------------------------------
378 //
379 //-----------------------------------------------------------------------------------------
380
getSupportedImageFormats()381 uno::Sequence<sal_Int16> SAL_CALL CWinFileOpenImpl::getSupportedImageFormats()
382 {
383 return m_Preview->getSupportedImageFormats();
384 }
385
386 //-----------------------------------------------------------------------------------------
387 //
388 //-----------------------------------------------------------------------------------------
389
getTargetColorDepth()390 sal_Int32 SAL_CALL CWinFileOpenImpl::getTargetColorDepth()
391 {
392 return m_Preview->getTargetColorDepth();
393 }
394
395 //-----------------------------------------------------------------------------------------
396 //
397 //-----------------------------------------------------------------------------------------
398
getAvailableWidth()399 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableWidth()
400 {
401 return m_Preview->getAvailableWidth();
402 }
403
404 //-----------------------------------------------------------------------------------------
405 //
406 //-----------------------------------------------------------------------------------------
407
getAvailableHeight()408 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableHeight()
409 {
410 return m_Preview->getAvailableHeight();
411 }
412
413 //-----------------------------------------------------------------------------------------
414 //
415 //-----------------------------------------------------------------------------------------
416
setImage(sal_Int16 aImageFormat,const uno::Any & aImage)417 void SAL_CALL CWinFileOpenImpl::setImage(sal_Int16 aImageFormat, const uno::Any& aImage)
418 {
419 m_Preview->setImage(aImageFormat,aImage);
420 }
421
422 //-----------------------------------------------------------------------------------------
423 //
424 //-----------------------------------------------------------------------------------------
425
setShowState(sal_Bool bShowState)426 sal_Bool SAL_CALL CWinFileOpenImpl::setShowState(sal_Bool bShowState)
427 {
428 return m_Preview->setShowState(bShowState);
429 }
430
431 //-----------------------------------------------------------------------------------------
432 //
433 //-----------------------------------------------------------------------------------------
434
getShowState()435 sal_Bool SAL_CALL CWinFileOpenImpl::getShowState()
436 {
437 return m_Preview->getShowState();
438 }
439
440 //-----------------------------------------------------------------------------------------
441 //
442 //-----------------------------------------------------------------------------------------
443
cancel()444 void SAL_CALL CWinFileOpenImpl::cancel()
445 {
446 if (IsWindow(m_hwndFileOpenDlg))
447 {
448 // simulate a mouse click to the
449 // cancel button
450 PostMessage(
451 m_hwndFileOpenDlg,
452 WM_COMMAND,
453 MAKEWPARAM(IDCANCEL,BN_CLICKED),
454 (LPARAM)GetDlgItem(m_hwndFileOpenDlg, IDCANCEL));
455 }
456 }
457
458 //-----------------------------------------------------------------------------------------
459 // returns the id of a custom template element
460 //-----------------------------------------------------------------------------------------
461
getFocused()462 sal_Int16 SAL_CALL CWinFileOpenImpl::getFocused()
463 {
464 int nID = GetDlgCtrlID(GetFocus());
465
466 // we don't forward id's of standard file open
467 // dialog elements (ctlFirst is defined in dlgs.h
468 // in MS Platform SDK)
469 if (nID >= ctlFirst)
470 nID = 0;
471
472 return sal::static_int_cast< sal_Int16 >(nID);
473 }
474
475 //-----------------------------------------------------------------------------------------
476 //
477 //-----------------------------------------------------------------------------------------
478
IsCustomControlHelpRequested(LPHELPINFO lphi) const479 inline sal_Bool SAL_CALL CWinFileOpenImpl::IsCustomControlHelpRequested(LPHELPINFO lphi) const
480 {
481 return ((lphi->iCtrlId != IDOK) && (lphi->iCtrlId != IDCANCEL) && (lphi->iCtrlId < ctlFirst));
482 }
483
484 //-----------------------------------------------------------------------------------------
485 // our own DlgProc because we do subclass the dialog
486 // we catch the WM_NCDESTROY message in order to erase an entry in our static map
487 // if one instance dies
488 //-----------------------------------------------------------------------------------------
489
SubClassFunc(HWND hWnd,UINT wMessage,WPARAM wParam,LPARAM lParam)490 LRESULT CALLBACK CWinFileOpenImpl::SubClassFunc(
491 HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
492 {
493 LRESULT lResult = 0;
494
495 CWinFileOpenImpl* pImpl = dynamic_cast<CWinFileOpenImpl*>(getCurrentInstance(hWnd));
496
497 switch(wMessage)
498 {
499 case WM_HELP:
500 {
501 LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
502
503 if (pImpl->IsCustomControlHelpRequested(lphi))
504 pImpl->onCustomControlHelpRequest(lphi);
505 else
506 lResult = CallWindowProc(
507 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
508 hWnd,wMessage,wParam,lParam);
509 }
510 break;
511
512 case WM_SIZE:
513 lResult = CallWindowProc(
514 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
515 hWnd,wMessage,wParam,lParam);
516
517 pImpl->onWMSize();
518 break;
519
520 case WM_WINDOWPOSCHANGED:
521 lResult = CallWindowProc(
522 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
523 hWnd,wMessage,wParam,lParam);
524
525 pImpl->onWMWindowPosChanged();
526 break;
527
528 case WM_SHOWWINDOW:
529 lResult = CallWindowProc(
530 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
531 hWnd,wMessage,wParam,lParam);
532
533 pImpl->onWMShow((sal_Bool)wParam);
534 break;
535
536 case WM_NCDESTROY:
537 // restore the old window proc
538 SetWindowLongPtr(hWnd, GWLP_WNDPROC,
539 reinterpret_cast<LONG_PTR>(pImpl->m_pfnOldDlgProc));
540
541 lResult = CallWindowProc(
542 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
543 hWnd,wMessage,wParam,lParam);
544 break;
545
546 default:
547 lResult = CallWindowProc(
548 reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
549 hWnd,wMessage,wParam,lParam);
550 break;
551
552 } // switch
553
554 return lResult;
555 }
556
557 //-----------------------------------------------------------------
558 //
559 //-----------------------------------------------------------------
560
InitControlLabel(HWND hWnd)561 void SAL_CALL CWinFileOpenImpl::InitControlLabel(HWND hWnd)
562 {
563 //-----------------------------------------
564 // set the labels for all extendet controls
565 //-----------------------------------------
566
567 sal_Int16 aCtrlId = sal::static_int_cast< sal_Int16 >(GetDlgCtrlID(hWnd));
568 rtl::OUString aLabel = m_ResProvider.getResString(aCtrlId);
569 if (aLabel.getLength())
570 setLabel(aCtrlId, aLabel);
571 }
572
573 //-----------------------------------------------------------------
574 // There may be problems with the layout of our custom controls,
575 // so that they are not aligned with the standard controls of the
576 // FileOpen dialog.
577 // We use a simple algorithm to move the custom controls to their
578 // proper position and resize them.
579 // Our approach is to align all static text controls with the
580 // static text control "File name" of the FileOpen dialog,
581 // all checkboxes and all list/comboboxes will be left aligned with
582 // the standard combobox edt1 (defined in MS platform sdk dlgs.h)
583 // and all push buttons will be left aligned with the standard
584 // "OK" button
585 //-----------------------------------------------------------------
586
InitCustomControlContainer(HWND hCustomControl)587 void SAL_CALL CWinFileOpenImpl::InitCustomControlContainer(HWND hCustomControl)
588 {
589 m_CustomControls->AddControl(
590 m_CustomControlFactory->CreateCustomControl(hCustomControl,m_hwndFileOpenDlg));
591 }
592
593 //-----------------------------------------------------------------
594 //
595 //-----------------------------------------------------------------
596
CacheControlState(HWND hWnd)597 void SAL_CALL CWinFileOpenImpl::CacheControlState(HWND hWnd)
598 {
599 OSL_ASSERT(m_FilePickerState && m_NonExecuteFilePickerState);
600 m_ExecuteFilePickerState->cacheControlState(hWnd, m_NonExecuteFilePickerState);
601 }
602
603 //-----------------------------------------------------------------
604 //
605 //-----------------------------------------------------------------
606
EnumChildWndProc(HWND hWnd,LPARAM lParam)607 BOOL CALLBACK CWinFileOpenImpl::EnumChildWndProc(HWND hWnd, LPARAM lParam)
608 {
609 EnumParam* enumParam = (EnumParam*)lParam;
610 CWinFileOpenImpl* pImpl = enumParam->m_instance;
611
612 OSL_ASSERT(pImpl);
613
614 sal_Bool bRet = sal_True;
615
616 switch(enumParam->m_action)
617 {
618 case INIT_CUSTOM_CONTROLS:
619 pImpl->InitControlLabel(hWnd);
620 pImpl->InitCustomControlContainer(hWnd);
621 break;
622
623 case CACHE_CONTROL_VALUES:
624 pImpl->CacheControlState(hWnd);
625 break;
626
627 default:
628 // should not end here
629 OSL_ASSERT(sal_False);
630 }
631
632 return bRet;
633 }
634
635 //-----------------------------------------------------------------
636 //
637 //-----------------------------------------------------------------
638
onFileOk()639 UINT_PTR SAL_CALL CWinFileOpenImpl::onFileOk()
640 {
641 m_NonExecuteFilePickerState->reset();
642
643 EnumParam enumParam(CACHE_CONTROL_VALUES,this);
644
645 EnumChildWindows(
646 m_hwndFileOpenDlgChild,
647 CWinFileOpenImpl::EnumChildWndProc,
648 (LPARAM)&enumParam);
649
650 return 0;
651 }
652
653 //-----------------------------------------------------------------
654 //
655 //-----------------------------------------------------------------
656
onSelChanged(HWND)657 void SAL_CALL CWinFileOpenImpl::onSelChanged(HWND)
658 {
659 // the windows file open dialog sends an initial
660 // SelChanged message after the InitDone message
661 // when the dialog is about to be opened
662 // if the lpstrFile buffer of the OPENFILENAME is
663 // empty (zero length string) the windows file open
664 // dialog sends a WM_SETTEXT message with an empty
665 // string to the file name edit line
666 // this would overwritte our text when we would set
667 // the default name in onInitDone, so we have to
668 // remember that this is the first SelChanged message
669 // and set the default name here to overwrite the
670 // windows setting
671 InitialSetDefaultName();
672
673 FilePickerEvent evt;
674 m_FilePicker->fileSelectionChanged(evt);
675 }
676
677 // #i40865# The size of the standard labels 'File name'
678 // and 'File type' is to short in some cases when the
679 // label will be changed (e.g. in the Brazil version).
680 // We just make sure that the labels are using the maximum
681 // available space.
EnlargeStdControlLabels() const682 void CWinFileOpenImpl::EnlargeStdControlLabels() const
683 {
684 HWND hFilterBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc2);
685 HWND hFileNameBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc3);
686 HWND hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, cmb13);
687 if (!hFileNameBox)
688 hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, edt1); // under Win98 it is edt1 instead of cmb13
689
690 HWND hFilterBox = GetDlgItem(m_hwndFileOpenDlg, cmb1);
691 HWND hOkButton = GetDlgItem(m_hwndFileOpenDlg, IDOK);
692
693 // Move filter and file name box nearer to OK and Cancel button
694 RECT rcOkButton;
695 GetWindowRect(hOkButton, &rcOkButton);
696
697 const int MAX_GAP = IsWindows98() ? 5 : 10;
698 const int OFFSET = IsWindows98() ? 10 : 0;
699
700 RECT rcFileNameBox;
701 GetWindowRect(hFileNameBox, &rcFileNameBox);
702 int w = rcFileNameBox.right - rcFileNameBox.left;
703 int h = rcFileNameBox.bottom - rcFileNameBox.top;
704
705 int gap = rcOkButton.left - rcFileNameBox.right;
706 gap = (gap > MAX_GAP) ? gap - MAX_GAP : gap;
707
708 ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBox);
709 MoveWindow(hFileNameBox, rcFileNameBox.left + gap + OFFSET, rcFileNameBox.top, w - OFFSET, h, true);
710
711 RECT rcFilterBox;
712 GetWindowRect(hFilterBox, &rcFilterBox);
713 w = rcFilterBox.right - rcFilterBox.left;
714 h = rcFilterBox.bottom - rcFilterBox.top;
715 ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBox);
716 MoveWindow(hFilterBox, rcFilterBox.left + gap + OFFSET, rcFilterBox.top, w - OFFSET, h, true);
717
718 // get the new window rect
719 GetWindowRect(hFileNameBox, &rcFileNameBox);
720
721 RECT rcFilterBoxLabel;
722 GetWindowRect(hFilterBoxLabel, &rcFilterBoxLabel);
723 int offset = rcFileNameBox.left - rcFilterBoxLabel.right - 1;
724
725 w = rcFilterBoxLabel.right - rcFilterBoxLabel.left + offset;
726 h = rcFilterBoxLabel.bottom - rcFilterBoxLabel.top;
727 ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBoxLabel);
728 MoveWindow(hFilterBoxLabel, rcFilterBoxLabel.left, rcFilterBoxLabel.top, w, h, true);
729
730 RECT rcFileNameBoxLabel;
731 GetWindowRect(hFileNameBoxLabel, &rcFileNameBoxLabel);
732 w = rcFileNameBoxLabel.right - rcFileNameBoxLabel.left + offset;
733 h = rcFileNameBoxLabel.bottom - rcFileNameBoxLabel.top;
734 ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBoxLabel);
735 MoveWindow(hFileNameBoxLabel, rcFileNameBoxLabel.left, rcFileNameBoxLabel.top, w, h, true);
736 }
737
onInitDone()738 void SAL_CALL CWinFileOpenImpl::onInitDone()
739 {
740 m_Preview->setParent(m_hwndFileOpenDlg);
741
742 // but now we have a valid parent handle
743 m_HelpPopupWindow.setParent(m_hwndFileOpenDlg);
744
745 EnlargeStdControlLabels();
746
747 // #99826
748 // Set the online filepicker state before initializing
749 // the control labels from the resource else we are
750 // overriding the offline settings
751 m_ExecuteFilePickerState->setHwnd(m_hwndFileOpenDlgChild);
752
753 m_FilePickerState = m_ExecuteFilePickerState;
754
755 // initialize controls from cache
756
757 EnumParam enumParam(INIT_CUSTOM_CONTROLS,this);
758
759 EnumChildWindows(
760 m_hwndFileOpenDlgChild,
761 CWinFileOpenImpl::EnumChildWndProc,
762 (LPARAM)&enumParam);
763
764 m_ExecuteFilePickerState->initFilePickerControls(
765 m_NonExecuteFilePickerState->getControlCommand());
766
767 SetDefaultExtension();
768
769 m_CustomControls->Align();
770
771 m_CustomControls->SetFont(
772 reinterpret_cast<HFONT>(SendMessage(m_hwndFileOpenDlg, WM_GETFONT, 0, 0)));
773
774 // resume event notification that was
775 // defered in onInitDialog
776 m_FilePicker->resumeEventNotification();
777
778 //#105996 let vcl know that now a system window is active
779 PostMessage(
780 HWND_BROADCAST,
781 RegisterWindowMessage(TEXT("SYSTEM_WINDOW_ACTIVATED")),
782 0,
783 0);
784
785 // call the parent function to center the
786 // dialog to it's parent
787 CFileOpenDialog::onInitDone();
788 }
789
790 //-----------------------------------------------------------------
791 //
792 //-----------------------------------------------------------------
793
onFolderChanged()794 void SAL_CALL CWinFileOpenImpl::onFolderChanged()
795 {
796 FilePickerEvent evt;
797 m_FilePicker->directoryChanged(evt);
798 }
799
800 //-----------------------------------------------------------------
801 //
802 //-----------------------------------------------------------------
803
onTypeChanged(sal_uInt32)804 void SAL_CALL CWinFileOpenImpl::onTypeChanged(sal_uInt32)
805 {
806 SetDefaultExtension();
807
808 FilePickerEvent evt;
809 evt.ElementId = LISTBOX_FILTER;
810 m_FilePicker->controlStateChanged(evt);
811 }
812
813 //-----------------------------------------------------------------------------------------
814 // onMessageCommand handler
815 //-----------------------------------------------------------------------------------------
816
onCtrlCommand(HWND,sal_uInt16 ctrlId,sal_uInt16)817 UINT_PTR SAL_CALL CWinFileOpenImpl::onCtrlCommand(
818 HWND, sal_uInt16 ctrlId, sal_uInt16)
819 {
820 SetDefaultExtension();
821
822 if (ctrlId < ctlFirst)
823 {
824 FilePickerEvent evt;
825 evt.ElementId = ctrlId;
826 m_FilePicker->controlStateChanged(evt);
827 }
828
829 return 0;
830 }
831
832 //-----------------------------------------------------------------------------------------
833 //
834 //-----------------------------------------------------------------------------------------
835
onWMSize()836 void CWinFileOpenImpl::onWMSize()
837 {
838 m_Preview->notifyParentSizeChanged();
839 m_CustomControls->Align();
840 m_FilePicker->dialogSizeChanged();
841 }
842
843 //-----------------------------------------------------------------------------------------
844 //
845 //-----------------------------------------------------------------------------------------
846
onWMShow(sal_Bool bShow)847 void CWinFileOpenImpl::onWMShow(sal_Bool bShow)
848 {
849 m_Preview->notifyParentShow(bShow);
850 }
851
852 //-----------------------------------------------------------------------------------------
853 //
854 //-----------------------------------------------------------------------------------------
855
onWMWindowPosChanged()856 void CWinFileOpenImpl::onWMWindowPosChanged()
857 {
858 m_Preview->notifyParentWindowPosChanged();
859 }
860
861 //-----------------------------------------------------------------------------------------
862 //
863 //-----------------------------------------------------------------------------------------
864
onCustomControlHelpRequest(LPHELPINFO lphi)865 void CWinFileOpenImpl::onCustomControlHelpRequest(LPHELPINFO lphi)
866 {
867 FilePickerEvent evt;
868 evt.ElementId = sal::static_int_cast< sal_Int16 >(lphi->iCtrlId);
869
870 rtl::OUString aPopupHelpText = m_FilePicker->helpRequested(evt);
871
872 if (aPopupHelpText.getLength())
873 {
874 m_HelpPopupWindow.setText(aPopupHelpText);
875
876 DWORD dwMsgPos = GetMessagePos();
877 m_HelpPopupWindow.show(LOWORD(dwMsgPos),HIWORD(dwMsgPos));
878 }
879 }
880
881 //-----------------------------------------------------------------------------------------
882 //
883 //-----------------------------------------------------------------------------------------
884
onInitDialog(HWND hwndDlg)885 void SAL_CALL CWinFileOpenImpl::onInitDialog(HWND hwndDlg)
886 {
887 // subclass the dialog window
888 m_pfnOldDlgProc =
889 reinterpret_cast<WNDPROC>(
890 SetWindowLongPtr( hwndDlg, GWLP_WNDPROC,
891 reinterpret_cast<LONG_PTR>(SubClassFunc)));
892 }
893
894 //-----------------------------------------------------------------------------------------
895 // processing before showing the dialog
896 //-----------------------------------------------------------------------------------------
897
preModal()898 bool SAL_CALL CWinFileOpenImpl::preModal()
899 {
900 CFileOpenDialog::setFilter(
901 makeWinFilterBuffer(*m_filterContainer.get()));
902
903 return true;
904 }
905
906 //-----------------------------------------------------------------------------------------
907 // processing after showing the dialog
908 //-----------------------------------------------------------------------------------------
909
postModal(sal_Int16 nDialogResult)910 void CWinFileOpenImpl::postModal(sal_Int16 nDialogResult)
911 {
912 CFileOpenDialog::postModal(nDialogResult);
913
914 // empty the container in order to get rid off
915 // invalid controls in case someone calls execute
916 // twice in sequence with the same instance
917 m_CustomControls->RemoveAllControls();
918
919 m_FilePickerState = m_NonExecuteFilePickerState;
920 }
921
922 //-----------------------------------------------------------------------------------------
923 //
924 //-----------------------------------------------------------------------------------------
925
SetDefaultExtension()926 void SAL_CALL CWinFileOpenImpl::SetDefaultExtension()
927 {
928 HWND hwndChkSaveWithExt = GetDlgItem(m_hwndFileOpenDlgChild, 100);
929
930 if (hwndChkSaveWithExt)
931 {
932 uno::Any aAny = CheckboxGetState(hwndChkSaveWithExt);
933 sal_Bool bChecked = *reinterpret_cast<const sal_Bool*>(aAny.getValue());
934
935 if (bChecked)
936 {
937 sal_uInt32 nIndex = getSelectedFilterIndex();
938
939 rtl::OUString currentFilter;
940 if (nIndex > 0)
941 {
942 // filter index of the base class starts with 1
943 m_filterContainer->getFilter(nIndex - 1, currentFilter);
944
945 if (currentFilter.getLength())
946 {
947 rtl::OUString FilterExt;
948 m_filterContainer->getFilter(currentFilter, FilterExt);
949
950 sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
951 const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
952
953 sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
954 if (posOfSemiColon < 0)
955 posOfSemiColon = FilterExt.getLength() - 1;
956
957 FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
958
959 SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(FilterExt.getStr()));
960 }
961 }
962 }
963 else
964 {
965 SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(TEXT("")));
966 }
967 }
968
969 // !!! HACK !!!
970 }
971
972 //-----------------------------------------------------------------------------------------
973 //
974 //-----------------------------------------------------------------------------------------
975
InitialSetDefaultName()976 void SAL_CALL CWinFileOpenImpl::InitialSetDefaultName()
977 {
978 // manually setting the file name that appears
979 // initially in the file-name-box of the file
980 // open dialog (reason: see above setDefaultName)
981 if (m_bInitialSelChanged && m_defaultName.getLength())
982 {
983 sal_Int32 edt1Id = edt1;
984
985 // under W2k the there is a combobox instead
986 // of an edit field for the file name edit field
987 // the control id of this box is cmb13 and not
988 // edt1 as before so we must use this id
989 if (IsWindows2000Platform())
990 edt1Id = cmb13;
991
992 HWND hwndEdt1 = GetDlgItem(m_hwndFileOpenDlg, edt1Id);
993 SetWindowText(hwndEdt1, reinterpret_cast<LPCTSTR>(m_defaultName.getStr()));
994 }
995
996 m_bInitialSelChanged = sal_False;
997 }
998