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 #include <tchar.h> 28 #include "previewadapter.hxx" 29 30 #ifndef _COM_SUN_STAR_UI_DIALOG_FILEPREVIEWIMAGEFORMATS_HPP_ 31 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> 32 #endif 33 #include "dibpreview.hxx" 34 #include "../misc/WinImplHelper.hxx" 35 36 #include <memory> 37 #include <stdexcept> 38 39 //--------------------------------------------- 40 // 41 //--------------------------------------------- 42 43 using namespace ::com::sun::star::uno; 44 using namespace ::com::sun::star::lang; 45 46 //--------------------------------------------- 47 // An impl class to hide implementation details 48 // from clients 49 //--------------------------------------------- 50 51 class CPreviewAdapterImpl 52 { 53 public: 54 CPreviewAdapterImpl(HINSTANCE instance); 55 56 virtual ~CPreviewAdapterImpl(); 57 58 virtual sal_Int32 SAL_CALL getTargetColorDepth(); 59 60 virtual sal_Int32 SAL_CALL getAvailableWidth(); 61 62 virtual sal_Int32 SAL_CALL getAvailableHeight(); 63 64 virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const Any& aImage ) 65 throw (IllegalArgumentException,RuntimeException); 66 67 virtual sal_Bool SAL_CALL setShowState(sal_Bool bShowState); 68 69 virtual sal_Bool SAL_CALL getShowState(); 70 71 virtual void SAL_CALL setParent(HWND parent); 72 73 virtual HWND SAL_CALL getParent(); 74 75 //------------------------------------- 76 // parent notification handler 77 //------------------------------------- 78 79 virtual void SAL_CALL notifyParentShow(sal_Bool bShow); 80 81 virtual void SAL_CALL notifyParentSizeChanged(); 82 83 virtual void SAL_CALL notifyParentWindowPosChanged(); 84 85 protected: 86 virtual void SAL_CALL calcRightMargin(); 87 88 virtual void SAL_CALL rearrangeLayout(); 89 90 void SAL_CALL initializeActivePreview() throw(std::runtime_error); 91 92 HWND SAL_CALL findFileListbox() const; 93 94 // member 95 protected: 96 HINSTANCE m_Instance; 97 std::auto_ptr<PreviewBase> m_Preview; 98 HWND m_FileDialog; 99 int m_RightMargin; 100 101 //prevent copy/assignment 102 private: 103 CPreviewAdapterImpl(const CPreviewAdapterImpl&); 104 CPreviewAdapterImpl& operator=(const CPreviewAdapterImpl&); 105 }; 106 107 //----------------------------------------- 108 // 109 //----------------------------------------- 110 111 CPreviewAdapterImpl::CPreviewAdapterImpl(HINSTANCE instance) : 112 m_Instance(instance), 113 m_Preview(new PreviewBase()), // create dummy preview (NULL-Object pattern) 114 m_FileDialog(0), 115 m_RightMargin(0) 116 { 117 } 118 119 //----------------------------------------- 120 // 121 //----------------------------------------- 122 123 CPreviewAdapterImpl::~CPreviewAdapterImpl() 124 { 125 } 126 127 //----------------------------------------- 128 // 129 //----------------------------------------- 130 131 sal_Int32 SAL_CALL CPreviewAdapterImpl::getTargetColorDepth() 132 { 133 return m_Preview->getTargetColorDepth(); 134 } 135 136 //----------------------------------------- 137 // 138 //----------------------------------------- 139 140 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableWidth() 141 { 142 return m_Preview->getAvailableWidth(); 143 } 144 145 //----------------------------------------- 146 // 147 //----------------------------------------- 148 149 sal_Int32 SAL_CALL CPreviewAdapterImpl::getAvailableHeight() 150 { 151 return m_Preview->getAvailableHeight(); 152 } 153 154 //----------------------------------------- 155 // 156 //----------------------------------------- 157 158 void SAL_CALL CPreviewAdapterImpl::setImage( sal_Int16 aImageFormat, const Any& aImage ) 159 throw (IllegalArgumentException,RuntimeException) 160 { 161 m_Preview->setImage(aImageFormat,aImage); 162 } 163 164 //----------------------------------------- 165 // 166 //----------------------------------------- 167 168 sal_Bool SAL_CALL CPreviewAdapterImpl::setShowState( sal_Bool bShowState ) 169 { 170 sal_Bool bRet = m_Preview->setShowState(bShowState); 171 rearrangeLayout(); 172 return bRet; 173 } 174 175 //----------------------------------------- 176 // 177 //----------------------------------------- 178 179 sal_Bool SAL_CALL CPreviewAdapterImpl::getShowState() 180 { 181 return m_Preview->getShowState(); 182 } 183 184 //----------------------------------------- 185 // 186 //----------------------------------------- 187 188 void SAL_CALL CPreviewAdapterImpl::setParent(HWND parent) 189 { 190 OSL_PRECOND(IsWindow(parent),"Invalid FileDialog handle"); 191 192 m_FileDialog = parent; 193 calcRightMargin(); 194 } 195 196 //----------------------------------------- 197 // 198 //----------------------------------------- 199 200 HWND SAL_CALL CPreviewAdapterImpl::getParent() 201 { 202 return m_FileDialog; 203 } 204 205 //----------------------------------------- 206 // 207 //----------------------------------------- 208 209 void SAL_CALL CPreviewAdapterImpl::calcRightMargin() 210 { 211 // Calculate the right reference margin 212 // 213 // Assumtions: 214 // 1. This method will be called before the dialog becomes 215 // visible 216 // 2. There exist a FileListbox with the id lst1 even 217 // if it is not visible like under Win2000/XP 218 // 3. Initially this FileListbox has the appropriate size 219 // to fit within the FileListbox 220 // 4. The margin between the right edge of the FileListbox 221 // and the right edge of the FileDialog will be constant 222 // even if the size of the dialog changes 223 224 HWND flb = GetDlgItem(m_FileDialog,lst1); 225 226 OSL_ENSURE(IsWindow(flb),"Filelistbox not found"); 227 228 RECT rcFlb; 229 GetWindowRect(flb,&rcFlb); 230 231 RECT rcFileDlg; 232 GetWindowRect(m_FileDialog,&rcFileDlg); 233 234 m_RightMargin = rcFileDlg.right - rcFlb.right; 235 } 236 237 //----------------------------------------- 238 // 239 //----------------------------------------- 240 241 void SAL_CALL CPreviewAdapterImpl::notifyParentShow(sal_Bool) 242 { 243 } 244 245 //----------------------------------------- 246 // 247 //----------------------------------------- 248 249 void SAL_CALL CPreviewAdapterImpl::notifyParentSizeChanged() 250 { 251 rearrangeLayout(); 252 } 253 254 //----------------------------------------- 255 // 256 //----------------------------------------- 257 258 void SAL_CALL CPreviewAdapterImpl::notifyParentWindowPosChanged() 259 { 260 } 261 262 //----------------------------------------- 263 // 264 //----------------------------------------- 265 266 void SAL_CALL CPreviewAdapterImpl::rearrangeLayout() 267 { 268 // try to get a handle to the filelistbox 269 // if there is no new-style filelistbox like 270 // in Win2000/XP there should be at least the 271 // old listbox, so we take this one 272 // lst1 - identifies the old-style filelistbox 273 // lst2 - identifies the new-style filelistbox 274 // see dlgs.h 275 HWND flb_new = findFileListbox(); 276 277 // under Windows NT 4.0 the size of the old 278 // filelistbox will be used as reference for 279 // sizing the new filelistbox, so we have 280 // to change the size of it too 281 HWND flb_old = GetDlgItem(m_FileDialog,lst1); 282 283 RECT rcFlbNew; 284 GetWindowRect(flb_new,&rcFlbNew); 285 286 RECT rcFileDlg; 287 GetWindowRect(m_FileDialog,&rcFileDlg); 288 rcFileDlg.right -= m_RightMargin; 289 290 // the available area for the filelistbox should be 291 // the left edge of the filelistbox and the right 292 // edge of the OK button, we take this as reference 293 int height = rcFlbNew.bottom - rcFlbNew.top; 294 int width = rcFileDlg.right - rcFlbNew.left; 295 296 HWND prvwnd = m_Preview->getWindowHandle(); 297 298 // we use GetWindowLong to ask for the visibility 299 // of the preview window because IsWindowVisible 300 // only returns true the specified window including 301 // its parent windows are visible 302 // this is not the case when we are called in response 303 // to the WM_SHOWWINDOW message, somehow the WS_VISIBLE 304 // style bit of the FileOpen dialog must be set after that 305 // message 306 LONG lStyle = GetWindowLong(prvwnd,GWL_STYLE); 307 bool bIsVisible = ((lStyle & WS_VISIBLE) != 0); 308 309 int cx = 0; 310 311 if (IsWindow(prvwnd) && bIsVisible) 312 { 313 cx = width/2; 314 315 // resize the filelistbox to the half of the 316 // available space 317 bool bRet = SetWindowPos(flb_new, 318 NULL, 0, 0, cx, height, 319 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 320 321 bRet = SetWindowPos(flb_old, 322 NULL, 0, 0, cx, height, 323 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 324 325 // get the new dimensions of the filelistbox after 326 // resizing and take the right,top corner as starting 327 // point for the preview window 328 GetWindowRect(flb_new,&rcFlbNew); 329 POINT pt = { rcFlbNew.right, rcFlbNew.top }; 330 ScreenToClient(m_FileDialog,&pt); 331 332 // resize the preview window to fit within 333 // the available space and set the window 334 // to the top of the z-order else it will 335 // be invisible 336 SetWindowPos(prvwnd, 337 HWND_TOP, pt.x, pt.y, cx, height, SWP_NOACTIVATE); 338 } 339 else 340 { 341 // resize the filelistbox to the maximum available 342 // space 343 cx = rcFileDlg.right - rcFlbNew.left; 344 345 // resize the old filelistbox 346 SetWindowPos(flb_old, 347 NULL, 0, 0, cx, height, 348 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 349 350 // resize the new filelistbox 351 SetWindowPos(flb_new, 352 NULL, 0, 0, cx, height, 353 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 354 } 355 } 356 357 //----------------------------------------- 358 // 359 //----------------------------------------- 360 361 void SAL_CALL CPreviewAdapterImpl::initializeActivePreview() throw(std::runtime_error) 362 { 363 sal_Bool bShowState = m_Preview->getImaginaryShowState(); 364 365 sal_Int16 aImgFrmt; 366 Any aImg; 367 m_Preview->getImage(aImgFrmt,aImg); 368 369 HWND flb = findFileListbox(); 370 371 PreviewBase* prv = new CDIBPreview( 372 m_Instance, GetParent(flb), bShowState); 373 374 m_Preview.reset(prv); 375 376 m_Preview->setImage(aImgFrmt,aImg); 377 } 378 379 //----------------------------------------- 380 // 381 //----------------------------------------- 382 383 HWND SAL_CALL CPreviewAdapterImpl::findFileListbox() const 384 { 385 // try to get a handle to the filelistbox 386 // if there is no new-style filelistbox like 387 // in Win2000/XP there should be at least the 388 // old listbox, so we take this one 389 // lst1 - identifies the old-style filelistbox 390 // lst2 - identifies the new-style filelistbox 391 // see dlgs.h 392 HWND flb = GetDlgItem(m_FileDialog,lst2); 393 if (!IsWindow(flb)) 394 flb = GetDlgItem(m_FileDialog,lst1); 395 396 return flb; 397 } 398 399 400 //############################################################## 401 402 403 //----------------------------------------- 404 // Special implementation for Win98 405 // because: 406 // 407 //----------------------------------------- 408 409 class CWin98PreviewAdapterImpl : public CPreviewAdapterImpl 410 { 411 public: 412 CWin98PreviewAdapterImpl(HINSTANCE instance); 413 414 virtual void SAL_CALL notifyParentWindowPosChanged(); 415 416 protected: 417 virtual void SAL_CALL rearrangeLayout(); 418 419 bool isValidToolbarDimension() const; 420 421 private: 422 sal_Bool m_PreviewActive; 423 int m_ToolbarPosX; 424 int m_ToolbarPosY; 425 int m_ToolbarWidth; 426 int m_ToolbarHeight; 427 }; 428 429 //-------------------------------------------- 430 // 431 //-------------------------------------------- 432 433 CWin98PreviewAdapterImpl::CWin98PreviewAdapterImpl(HINSTANCE instance) : 434 CPreviewAdapterImpl(instance), 435 m_PreviewActive(sal_False), 436 m_ToolbarPosX(0), 437 m_ToolbarPosY(0), 438 m_ToolbarWidth(0), 439 m_ToolbarHeight(0) 440 { 441 } 442 443 //-------------------------------------------- 444 // 445 //-------------------------------------------- 446 447 void SAL_CALL CWin98PreviewAdapterImpl::notifyParentWindowPosChanged() 448 { 449 try 450 { 451 // the reason for this condition is 452 // Windows 98 453 // Under Windows 98 the message WM_SHOWWINDOW 454 // will be sent only the first time the 455 // GetOpenFileName function is called within 456 // the same process 457 // so we must use another message to initialize 458 // the preview window 459 if (IsWindow(m_FileDialog) && !m_PreviewActive) 460 { 461 initializeActivePreview(); 462 m_PreviewActive = sal_True; 463 rearrangeLayout(); 464 } 465 466 if (IsWindow(m_FileDialog) && !isValidToolbarDimension()) 467 { 468 RECT rcStc1; 469 GetWindowRect(GetDlgItem(m_FileDialog,stc1),&rcStc1); 470 471 RECT rcCmb2; 472 GetWindowRect(GetDlgItem(m_FileDialog,cmb2),&rcCmb2); 473 474 // Assumption: 475 // the toolbar position is only valid 476 // if the left edge is greater or equal 477 // than the right edge of the drives listbox 478 // the stc1 static text is invisible at runtime 479 // but will be used as reference for the position 480 // and dimension of the toolbar 481 if (rcStc1.left >= rcCmb2.right) 482 { 483 // important: save the upper left corner in 484 // client coordinates 485 POINT pt = {rcStc1.left,rcStc1.top}; 486 ScreenToClient(m_FileDialog,&pt); 487 488 m_ToolbarPosX = pt.x; 489 m_ToolbarPosY = pt.y; 490 m_ToolbarWidth = rcStc1.right - rcStc1.left; 491 m_ToolbarHeight = rcStc1.bottom - rcStc1.top; 492 } 493 } 494 } 495 catch(std::runtime_error&) 496 { 497 } 498 } 499 500 //-------------------------------------------- 501 // 502 //-------------------------------------------- 503 504 void SAL_CALL CWin98PreviewAdapterImpl::rearrangeLayout() 505 { 506 CPreviewAdapterImpl::rearrangeLayout(); 507 508 // fix the position of the upper toolbar 509 // because the FileDialog moves all windows 510 // that are to the right of the FileListbox 511 // so if we have changed the size of the 512 // FileListbox we would run into trouble else 513 if (isValidToolbarDimension()) 514 { 515 HWND hwndTlb = FindWindowEx( 516 m_FileDialog,NULL,TEXT("ToolbarWindow32"),NULL); 517 518 SetWindowPos(hwndTlb, 519 HWND_TOP, 520 m_ToolbarPosX, 521 m_ToolbarPosY, 522 m_ToolbarWidth, 523 m_ToolbarHeight, 524 SWP_NOACTIVATE); 525 } 526 } 527 528 //-------------------------------------------- 529 // 530 //-------------------------------------------- 531 532 bool CWin98PreviewAdapterImpl::isValidToolbarDimension() const 533 { 534 return (m_ToolbarPosX > 0 && 535 m_ToolbarPosY > 0 && 536 m_ToolbarWidth > 0 && 537 m_ToolbarHeight > 0); 538 } 539 540 //############################################################## 541 542 543 //-------------------------------------------- 544 // Implementation for Windows 95/NT/ME/2000/XP 545 // because: 546 // 547 //-------------------------------------------- 548 549 class CWin95NTPreviewAdapterImpl : public CPreviewAdapterImpl 550 { 551 public: 552 CWin95NTPreviewAdapterImpl(HINSTANCE instance); 553 554 virtual void SAL_CALL notifyParentShow(sal_Bool bShow); 555 }; 556 557 //-------------------------------------------- 558 // 559 //-------------------------------------------- 560 561 CWin95NTPreviewAdapterImpl::CWin95NTPreviewAdapterImpl(HINSTANCE instance) : 562 CPreviewAdapterImpl(instance) 563 { 564 } 565 566 //-------------------------------------------- 567 // 568 //-------------------------------------------- 569 570 void SAL_CALL CWin95NTPreviewAdapterImpl::notifyParentShow(sal_Bool bShow) 571 { 572 try 573 { 574 if (bShow) 575 { 576 initializeActivePreview(); 577 rearrangeLayout(); 578 } 579 } 580 catch(std::runtime_error&) 581 { 582 } 583 } 584 585 586 //############################################################## 587 588 589 //------------------------------- 590 // ctor 591 //------------------------------- 592 593 CPreviewAdapter::CPreviewAdapter(HINSTANCE instance) 594 { 595 if (!IsWindows98()) 596 m_pImpl.reset(new CWin95NTPreviewAdapterImpl(instance)); 597 else 598 m_pImpl.reset(new CWin98PreviewAdapterImpl(instance)); 599 } 600 601 //------------------------------- 602 // 603 //------------------------------- 604 605 CPreviewAdapter::~CPreviewAdapter() 606 { 607 } 608 609 //------------------------------- 610 // 611 //------------------------------- 612 613 Sequence<sal_Int16> SAL_CALL CPreviewAdapter::getSupportedImageFormats() 614 { 615 com::sun::star::uno::Sequence<sal_Int16> imgFormats(1); 616 imgFormats[0] = ::com::sun::star::ui::dialogs::FilePreviewImageFormats::BITMAP; 617 return imgFormats; 618 } 619 620 //------------------------------- 621 // 622 //------------------------------- 623 624 sal_Int32 SAL_CALL CPreviewAdapter::getTargetColorDepth() 625 { 626 return m_pImpl->getTargetColorDepth(); 627 } 628 629 //------------------------------- 630 // 631 //------------------------------- 632 633 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableWidth() 634 { 635 return m_pImpl->getAvailableWidth(); 636 } 637 638 //------------------------------- 639 // 640 //------------------------------- 641 642 sal_Int32 SAL_CALL CPreviewAdapter::getAvailableHeight() 643 { 644 return m_pImpl->getAvailableHeight(); 645 } 646 647 //------------------------------- 648 // 649 //------------------------------- 650 651 void SAL_CALL CPreviewAdapter::setImage( sal_Int16 aImageFormat, const Any& aImage ) 652 throw (IllegalArgumentException, RuntimeException) 653 { 654 m_pImpl->setImage(aImageFormat,aImage); 655 } 656 657 //------------------------------- 658 // 659 //------------------------------- 660 661 sal_Bool SAL_CALL CPreviewAdapter::setShowState( sal_Bool bShowState ) 662 { 663 return m_pImpl->setShowState(bShowState); 664 } 665 666 //------------------------------- 667 // 668 //------------------------------- 669 670 sal_Bool SAL_CALL CPreviewAdapter::getShowState() 671 { 672 return m_pImpl->getShowState(); 673 } 674 675 //------------------------------- 676 // 677 //------------------------------- 678 679 void SAL_CALL CPreviewAdapter::setParent(HWND parent) 680 { 681 m_pImpl->setParent(parent); 682 } 683 684 //------------------------------- 685 // 686 //------------------------------- 687 688 void SAL_CALL CPreviewAdapter::notifyParentShow(bool bShow) 689 { 690 m_pImpl->notifyParentShow(bShow); 691 } 692 693 //------------------------------- 694 // 695 //------------------------------- 696 697 void SAL_CALL CPreviewAdapter::notifyParentSizeChanged() 698 { 699 m_pImpl->notifyParentSizeChanged(); 700 } 701 702 //------------------------------- 703 // 704 //------------------------------- 705 706 void SAL_CALL CPreviewAdapter::notifyParentWindowPosChanged() 707 { 708 m_pImpl->notifyParentWindowPosChanged(); 709 } 710