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