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 { 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 154 rtl::OUString CWinFileOpenImpl::getDisplayDirectory() 155 { 156 return m_FilePickerState->getDisplayDirectory(this); 157 } 158 159 //----------------------------------------------------------------------------------------- 160 // 161 //----------------------------------------------------------------------------------------- 162 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 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 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 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 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 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 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 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. 314 static bool filterControlCommand( sal_Int16 nControlId ) 315 { 316 if ( nControlId == LISTBOX_FILTER_SELECTOR ) 317 return true; 318 return false; 319 } 320 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 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 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 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 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 381 uno::Sequence<sal_Int16> SAL_CALL CWinFileOpenImpl::getSupportedImageFormats() 382 { 383 return m_Preview->getSupportedImageFormats(); 384 } 385 386 //----------------------------------------------------------------------------------------- 387 // 388 //----------------------------------------------------------------------------------------- 389 390 sal_Int32 SAL_CALL CWinFileOpenImpl::getTargetColorDepth() 391 { 392 return m_Preview->getTargetColorDepth(); 393 } 394 395 //----------------------------------------------------------------------------------------- 396 // 397 //----------------------------------------------------------------------------------------- 398 399 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableWidth() 400 { 401 return m_Preview->getAvailableWidth(); 402 } 403 404 //----------------------------------------------------------------------------------------- 405 // 406 //----------------------------------------------------------------------------------------- 407 408 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableHeight() 409 { 410 return m_Preview->getAvailableHeight(); 411 } 412 413 //----------------------------------------------------------------------------------------- 414 // 415 //----------------------------------------------------------------------------------------- 416 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 426 sal_Bool SAL_CALL CWinFileOpenImpl::setShowState(sal_Bool bShowState) 427 { 428 return m_Preview->setShowState(bShowState); 429 } 430 431 //----------------------------------------------------------------------------------------- 432 // 433 //----------------------------------------------------------------------------------------- 434 435 sal_Bool SAL_CALL CWinFileOpenImpl::getShowState() 436 { 437 return m_Preview->getShowState(); 438 } 439 440 //----------------------------------------------------------------------------------------- 441 // 442 //----------------------------------------------------------------------------------------- 443 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 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 479 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 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 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 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 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 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 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 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. 682 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 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 794 void SAL_CALL CWinFileOpenImpl::onFolderChanged() 795 { 796 FilePickerEvent evt; 797 m_FilePicker->directoryChanged(evt); 798 } 799 800 //----------------------------------------------------------------- 801 // 802 //----------------------------------------------------------------- 803 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 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 836 void CWinFileOpenImpl::onWMSize() 837 { 838 m_Preview->notifyParentSizeChanged(); 839 m_CustomControls->Align(); 840 m_FilePicker->dialogSizeChanged(); 841 } 842 843 //----------------------------------------------------------------------------------------- 844 // 845 //----------------------------------------------------------------------------------------- 846 847 void CWinFileOpenImpl::onWMShow(sal_Bool bShow) 848 { 849 m_Preview->notifyParentShow(bShow); 850 } 851 852 //----------------------------------------------------------------------------------------- 853 // 854 //----------------------------------------------------------------------------------------- 855 856 void CWinFileOpenImpl::onWMWindowPosChanged() 857 { 858 m_Preview->notifyParentWindowPosChanged(); 859 } 860 861 //----------------------------------------------------------------------------------------- 862 // 863 //----------------------------------------------------------------------------------------- 864 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 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 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 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 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 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