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