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