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