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 <tchar.h> 36 #include "PreviewCtrl.hxx" 37 #include <osl/diagnose.h> 38 39 #if defined _MSC_VER 40 #pragma warning(push, 1) 41 #endif 42 #include <windows.h> 43 #if defined _MSC_VER 44 #pragma warning(pop) 45 #endif 46 #include <ocidl.h> 47 #include <olectl.h> 48 49 //------------------------------------------------------------------------ 50 // defines 51 //------------------------------------------------------------------------ 52 53 #define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###") 54 55 #define HIMETRIC_INCH 2540 56 57 // means 3 pixel left and 3 pixel right 58 #define HORZ_BODER_SPACE 6 59 60 // means 3 pixel top and 3 pixel bottom 61 #define VERT_BORDER_SPACE 6 62 63 //--------------------------------------------------- 64 // static member initialization 65 //--------------------------------------------------- 66 67 CFilePreview* CFilePreview::s_FilePreviewInst = NULL; 68 CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer; 69 70 //--------------------------------------------------- 71 // some useful helper functions 72 //--------------------------------------------------- 73 74 namespace // private 75 { 76 class CPreviewException 77 { 78 // used when registering or creation 79 // of the preview window failed 80 }; 81 82 //------------------------------------------------------------ 83 // 84 //------------------------------------------------------------ 85 86 inline 87 sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator ) 88 { 89 return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) ); 90 } 91 92 //------------------------------------------------------------ 93 // convert himetric to pixel 94 //------------------------------------------------------------ 95 96 inline 97 sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex ) 98 { 99 return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH ); 100 } 101 102 //------------------------------------------------------------ 103 // 104 //------------------------------------------------------------ 105 106 inline 107 sal_uInt32 _getWidthRect( const RECT& aRect ) 108 { 109 return ( aRect.right - aRect.left ); 110 } 111 112 //------------------------------------------------------------ 113 // 114 //------------------------------------------------------------ 115 116 inline 117 sal_uInt32 _getHeightRect( const RECT& aRect ) 118 { 119 return ( aRect.bottom - aRect.top ); 120 } 121 122 //------------------------------------------------------------ 123 // calc the upper left corner so that a given window will be 124 // displayed centered within the given window 125 //------------------------------------------------------------ 126 127 inline 128 POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize ) 129 { 130 RECT rect; 131 GetClientRect( hwnd, &rect ); 132 133 sal_Int32 nWidthWnd = _getWidthRect( rect ); 134 sal_Int32 nHeightWnd = _getHeightRect( rect ); 135 136 POINT ulCorner; 137 ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 ); 138 ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 ); 139 140 return ulCorner; 141 } 142 143 //------------------------------------------------------------ 144 // test if a picture with the given dimensions fits into an 145 // arbitrary window 146 // we expect the width and height to be in pixel 147 //------------------------------------------------------------ 148 149 inline 150 sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize ) 151 { 152 RECT rect; 153 GetClientRect( hwnd, &rect ); 154 155 sal_Int32 nWidthWnd = _getWidthRect( rect ); 156 sal_Int32 nHeightWnd = _getHeightRect( rect ); 157 158 return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) && 159 ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) ); 160 } 161 162 //------------------------------------------------------------ 163 // calc the dimemsions so that a given picture fits into a 164 // given window, if the picture fits into the given window 165 // the original CDimension will be returned 166 //------------------------------------------------------------ 167 168 inline 169 CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize ) 170 { 171 CDimension scaledPicSize = aPicSize; 172 173 if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) ) 174 { 175 RECT rect; 176 GetClientRect( hwnd, &rect ); 177 178 // the dimensions of the preview wnd are not equal 179 // that's why we equalize it 180 sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE; 181 sal_Int32 nWidthWnd = nHeightWnd; 182 183 if ( aPicSize.m_cx >= aPicSize.m_cy ) 184 { 185 scaledPicSize.m_cx = nWidthWnd; 186 scaledPicSize.m_cy = 187 static_cast< sal_Int32 >( 188 aPicSize.m_cy * nWidthWnd / aPicSize.m_cx ); 189 } 190 else 191 { 192 scaledPicSize.m_cx = 193 static_cast< sal_Int32 >( 194 aPicSize.m_cx * nHeightWnd / aPicSize.m_cy ); 195 scaledPicSize.m_cy = nHeightWnd; 196 } 197 } 198 199 return scaledPicSize; 200 } 201 202 } // end namespace 203 204 205 //--------------------------------------------------- 206 // to ensure only one instance (singleton) 207 //--------------------------------------------------- 208 209 CFilePreview* CFilePreview::createInstance( 210 HWND aParent, 211 POINT ulCorner, 212 const CDimension& aSize, 213 HINSTANCE hInstance, 214 sal_Bool bShow, 215 sal_Bool bEnabled ) 216 { 217 if ( !s_FilePreviewInst ) 218 { 219 try 220 { 221 s_FilePreviewInst = new CFilePreview( 222 aParent, ulCorner, aSize, hInstance, bShow, bEnabled ); 223 s_SingletonDestroyer.reset( s_FilePreviewInst ); 224 } 225 catch( CPreviewException& ) 226 { 227 OSL_ASSERT( !s_FilePreviewInst ); 228 OSL_ENSURE( sal_False, "Creation of the preview window failed" ); 229 } 230 catch( CAutoOleInit::COleInitException& ) 231 { 232 OSL_ASSERT( !s_FilePreviewInst ); 233 OSL_ENSURE( sal_False, "OleInitalize failed" ); 234 } 235 } 236 237 return s_FilePreviewInst; 238 } 239 240 //--------------------------------------------------- 241 // 242 //--------------------------------------------------- 243 244 CFilePreview::CFilePreview( 245 HWND aParent, 246 POINT ulCorner, 247 const CDimension& aSize, 248 HINSTANCE hInstance, 249 sal_Bool bShow, 250 sal_Bool bEnabled ) : 251 m_hInstance( hInstance ), 252 m_bEnabled( bEnabled ) 253 { 254 // register the preview window class 255 WNDCLASSEX wndClsEx; 256 ZeroMemory(&wndClsEx, sizeof(wndClsEx)); 257 258 wndClsEx.cbSize = sizeof(wndClsEx); 259 wndClsEx.style = CS_HREDRAW | CS_VREDRAW; 260 wndClsEx.lpfnWndProc = CFilePreview::WndProc; 261 wndClsEx.hInstance = m_hInstance; 262 wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 ); 263 wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME; 264 265 // register the preview window class 266 // !!! Win95 - the window class will be unregistered automaticly 267 // if the dll is unloaded 268 // Win2000 - the window class must be unregistered manually 269 // if the dll is unloaded 270 m_atomPrevWndClass = RegisterClassEx(&wndClsEx); 271 if ( !m_atomPrevWndClass ) 272 throw CPreviewException( ); 273 274 // create the preview window in invisible state 275 sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD; 276 m_hwnd = CreateWindowEx( 277 WS_EX_CLIENTEDGE, 278 PREVIEWWND_CLASS_NAME, 279 TEXT(""), 280 dwStyle, 281 ulCorner.x, 282 ulCorner.y, 283 aSize.m_cx, 284 aSize.m_cy, 285 aParent, 286 (HMENU)100, // for child windows this will 287 // be used as child window identifier 288 m_hInstance, 289 0 ); 290 if (!IsWindow(m_hwnd)) 291 throw CPreviewException( ); 292 } 293 294 //--------------------------------------------------- 295 // 296 //--------------------------------------------------- 297 298 CFilePreview::~CFilePreview( ) 299 { 300 // unregister preview window class 301 sal_Bool bRet = UnregisterClass( 302 (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ), 303 m_hInstance ); 304 OSL_POSTCOND( bRet, "Unregister preview window class failed" ); 305 } 306 307 //--------------------------------------------------- 308 // sets the size of the preview window 309 //--------------------------------------------------- 310 311 sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize ) 312 { 313 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 314 315 // resize the fileopen file listbox 316 return SetWindowPos( 317 m_hwnd, 318 NULL, 319 0, 320 0, 321 aSize.m_cx, 322 aSize.m_cy, 323 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 324 } 325 326 //--------------------------------------------------- 327 // returns the dimension of the preview 328 //--------------------------------------------------- 329 330 sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const 331 { 332 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 333 334 RECT rect; 335 sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); 336 337 theSize.m_cx = _getWidthRect( rect ); 338 theSize.m_cy = _getHeightRect( rect ); 339 340 return bRet; 341 } 342 343 //--------------------------------------------------- 344 // sets the position of the upper left corner 345 // of the preview window relative to the 346 // upper left corner of the parent window 347 //--------------------------------------------------- 348 349 sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner ) 350 { 351 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 352 353 // resize the fileopen file listbox 354 return SetWindowPos( 355 m_hwnd, 356 NULL, 357 ulCorner.x, 358 ulCorner.y, 359 0, 360 0, 361 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); 362 } 363 364 //--------------------------------------------------- 365 // returns the current position of the preview 366 // relative to the upper left corner of the 367 // parent window 368 //--------------------------------------------------- 369 370 sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const 371 { 372 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 373 374 POINT pt = { 0, 0 }; 375 RECT rect; 376 377 sal_Bool bRet = GetWindowRect( m_hwnd, &rect ); 378 379 ulCorner.x = rect.left; 380 ulCorner.y = rect.top; 381 382 ScreenToClient( m_hwnd, &ulCorner ); 383 384 return bRet; 385 } 386 387 //--------------------------------------------------- 388 // 389 //--------------------------------------------------- 390 391 void SAL_CALL CFilePreview::enable( sal_Bool bEnable ) 392 { 393 m_bEnabled = bEnable; 394 395 // force a redraw 396 InvalidateRect( m_hwnd, NULL, sal_True ); 397 UpdateWindow( m_hwnd ); 398 } 399 400 //--------------------------------------------------- 401 // shows the preview window 402 // possible values see SHOW_STATE 403 // SS_SHOW - make the window visible 404 // SS_HIDE - hide the window 405 // SS_ENABLED - enable the window 406 // SS_DISABLED - disable the window 407 //--------------------------------------------------- 408 409 sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow ) 410 { 411 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 412 413 sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE; 414 return ShowWindow( m_hwnd, showState ); 415 } 416 417 //--------------------------------------------------- 418 // if the preview is shown and enabled 419 // preview of the given file will be shown 420 // returns true on success or false if an error 421 // occured (the file in not there or not accessible etc.) 422 //--------------------------------------------------- 423 424 sal_Bool SAL_CALL CFilePreview::update( const rtl::OUString& aFileName ) 425 { 426 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 427 428 try 429 { 430 if ( m_bEnabled ) 431 { 432 if ( m_IPicture ) 433 m_IPicture.Release( ); 434 435 loadFile( aFileName ); 436 437 // force a complete window redraw 438 InvalidateRect( m_hwnd, NULL, sal_True ); 439 UpdateWindow( m_hwnd ); 440 } 441 } 442 catch( _com_error& ) 443 { 444 } 445 446 return sal_True; 447 } 448 449 //--------------------------------------------------- 450 // 451 //--------------------------------------------------- 452 453 void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC ) 454 { 455 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" ); 456 457 try 458 { 459 if ( m_bEnabled ) 460 { 461 // get width and height of picture 462 long cxPicHIMETRIC; 463 long cyPicHIMETRIC; 464 465 m_IPicture->get_Width( &cxPicHIMETRIC ); 466 m_IPicture->get_Height( &cyPicHIMETRIC ); 467 468 // convert himetric to pixels 469 int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX ); 470 int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY ); 471 472 // scale the picture based on the size of the preview window 473 RECT rcPrevWnd; 474 GetClientRect(hWnd, &rcPrevWnd); 475 476 CDimension scaledPicSize = _scalePictureSize( 477 hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) ); 478 479 // calc the upper left corner so that the picture 480 // is centered within the window 481 POINT ulCorner = _calcULCorner( hWnd, scaledPicSize ); 482 483 // render the picture 484 HRESULT hr = m_IPicture->Render( 485 hDC, 486 ulCorner.x, 487 ulCorner.y, 488 scaledPicSize.m_cx, 489 scaledPicSize.m_cy, 490 0, 491 cyPicHIMETRIC, 492 cxPicHIMETRIC, 493 -cyPicHIMETRIC, 494 &rcPrevWnd ); 495 } // end if ( m_bEnabled ) 496 } 497 catch( _com_error& ) 498 { 499 } 500 } 501 502 //--------------------------------------------------- 503 // 504 //--------------------------------------------------- 505 506 sal_Bool CFilePreview::loadFile( const rtl::OUString& aFileName ) 507 { 508 HANDLE hFile = 0; 509 HGLOBAL hGlobal = 0; 510 LPVOID pData = NULL; 511 IStreamPtr pIStream; 512 HRESULT hr = E_FAIL; 513 sal_Bool bRet; 514 sal_uInt32 nBytesRead; 515 sal_uInt32 fszExtra; 516 sal_uInt32 fsize; 517 518 hFile = CreateFile( 519 aFileName.getStr( ), 520 GENERIC_READ, 521 0, 522 NULL, 523 OPEN_EXISTING, 524 0, 525 NULL ); 526 if ( INVALID_HANDLE_VALUE == hFile ) 527 goto CLEANUP_AND_EXIT; 528 529 fszExtra = 0; 530 fsize = GetFileSize( hFile, &fszExtra ); 531 532 // empty file, error or file to big 533 if ( -1 == fsize || 0 == fsize || fszExtra ) 534 goto CLEANUP_AND_EXIT; 535 536 hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize ); 537 if ( !hGlobal ) 538 goto CLEANUP_AND_EXIT; 539 540 pData = GlobalLock( hGlobal ); 541 if ( !pData ) 542 goto CLEANUP_AND_EXIT; 543 544 bRet = ReadFile( 545 hFile, pData, fsize, &nBytesRead, NULL ); 546 547 if ( !bRet ) 548 goto CLEANUP_AND_EXIT; 549 550 hr = CreateStreamOnHGlobal( 551 hGlobal, sal_False, &pIStream ); 552 553 if ( SUCCEEDED( hr ) ) 554 { 555 hr = OleLoadPicture( 556 pIStream, fsize, sal_False, 557 __uuidof( IPicture ), (LPVOID*)&m_IPicture ); 558 } 559 560 CLEANUP_AND_EXIT: 561 if ( hFile ) 562 CloseHandle( hFile ); 563 564 if ( pData ) 565 GlobalUnlock( hGlobal ); 566 567 if ( hGlobal ) 568 GlobalFree( hGlobal ); 569 570 return ( SUCCEEDED( hr ) ); 571 } 572 573 //--------------------------------------------------- 574 // 575 //--------------------------------------------------- 576 577 LRESULT CALLBACK CFilePreview::WndProc( 578 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 579 { 580 LRESULT lResult = 0; 581 582 switch( uMsg ) 583 { 584 case WM_PAINT: 585 { 586 OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" ); 587 588 HDC hDC; 589 PAINTSTRUCT ps; 590 591 hDC = BeginPaint( hWnd, &ps ); 592 s_FilePreviewInst->onPaint( hWnd, hDC ); 593 EndPaint( hWnd, &ps ); 594 } 595 break; 596 597 // under windows 95/98 the creation of the 598 // hidden target request window fails if 599 // we don't handle this message ourself 600 // because the DefWindowProc returns 0 as 601 // a result of handling WM_NCCREATE what 602 // leads to a failure of CreateWindow[Ex]!!! 603 case WM_NCCREATE: 604 lResult = sal_True; 605 break; 606 607 default: 608 return DefWindowProc( hWnd, uMsg, wParam, lParam ); 609 } 610 611 return lResult; 612 } 613 614 615 616