bump product version to 4.1.6.2
[LibreOffice.git] / fpicker / source / win32 / filepicker / PreviewCtrl.cxx
blobbc37fbad9666d6d443069213efe22cbc702ca75e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tchar.h>
21 #include "PreviewCtrl.hxx"
22 #include <osl/diagnose.h>
24 #if defined _MSC_VER
25 #pragma warning(push, 1)
26 #endif
27 #include <windows.h>
28 #if defined _MSC_VER
29 #pragma warning(pop)
30 #endif
31 #include <ocidl.h>
32 #include <olectl.h>
34 #define PREVIEWWND_CLASS_NAME TEXT("PreviewWnd###")
36 #define HIMETRIC_INCH 2540
38 // means 3 pixel left and 3 pixel right
39 #define HORZ_BODER_SPACE 6
41 // means 3 pixel top and 3 pixel bottom
42 #define VERT_BORDER_SPACE 6
44 //---------------------------------------------------
45 // static member initialization
46 //---------------------------------------------------
48 CFilePreview* CFilePreview::s_FilePreviewInst = NULL;
49 CFilePreview::FILEPREVIEW_SINGLETON_DESTROYER_T CFilePreview::s_SingletonDestroyer;
51 //---------------------------------------------------
52 // some useful helper functions
53 //---------------------------------------------------
55 namespace // private
57 class CPreviewException
59 // used when registering or creation
60 // of the preview window failed
63 //------------------------------------------------------------
65 //------------------------------------------------------------
67 inline
68 sal_Int32 SubDiv( sal_Int32 nNumber, sal_Int32 nMinuend, sal_Int32 nDenominator )
70 return ( static_cast<sal_Int32>( ( nNumber - nMinuend ) / nDenominator ) );
73 //------------------------------------------------------------
74 // convert himetric to pixel
75 //------------------------------------------------------------
77 inline
78 sal_Int32 Himetric2Pixel( HDC hDC, sal_Int32 hmSize, sal_Int32 nIndex )
80 return MulDiv( hmSize, GetDeviceCaps( hDC, nIndex), HIMETRIC_INCH );
83 //------------------------------------------------------------
85 //------------------------------------------------------------
87 inline
88 sal_uInt32 _getWidthRect( const RECT& aRect )
90 return ( aRect.right - aRect.left );
93 //------------------------------------------------------------
95 //------------------------------------------------------------
97 inline
98 sal_uInt32 _getHeightRect( const RECT& aRect )
100 return ( aRect.bottom - aRect.top );
103 //------------------------------------------------------------
104 // calc the upper left corner so that a given window will be
105 // displayed centered within the given window
106 //------------------------------------------------------------
108 inline
109 POINT _calcULCorner( HWND hwnd, const CDimension& aPicSize )
111 RECT rect;
112 GetClientRect( hwnd, &rect );
114 sal_Int32 nWidthWnd = _getWidthRect( rect );
115 sal_Int32 nHeightWnd = _getHeightRect( rect );
117 POINT ulCorner;
118 ulCorner.x = SubDiv( nWidthWnd, aPicSize.m_cx, 2 );
119 ulCorner.y = SubDiv( nHeightWnd, aPicSize.m_cy, 2 );
121 return ulCorner;
124 //------------------------------------------------------------
125 // test if a picture with the given dimensions fits into an
126 // arbitrary window
127 // we expect the width and height to be in pixel
128 //------------------------------------------------------------
130 inline
131 sal_Bool _pictureSizeFitsWindowSize( HWND hwnd, const CDimension& aPicSize )
133 RECT rect;
134 GetClientRect( hwnd, &rect );
136 sal_Int32 nWidthWnd = _getWidthRect( rect );
137 sal_Int32 nHeightWnd = _getHeightRect( rect );
139 return ( ( ( nWidthWnd - HORZ_BODER_SPACE ) >= aPicSize.m_cx ) &&
140 ( ( nHeightWnd - VERT_BORDER_SPACE ) >= aPicSize.m_cy ) );
143 //------------------------------------------------------------
144 // calc the dimemsions so that a given picture fits into a
145 // given window, if the picture fits into the given window
146 // the original CDimension will be returned
147 //------------------------------------------------------------
149 inline
150 CDimension _scalePictureSize( HWND hwnd, const CDimension& aPicSize )
152 CDimension scaledPicSize = aPicSize;
154 if ( !_pictureSizeFitsWindowSize( hwnd, aPicSize ) )
156 RECT rect;
157 GetClientRect( hwnd, &rect );
159 // the dimensions of the preview wnd are not equal
160 // that's why we equalize it
161 sal_Int32 nHeightWnd = _getHeightRect( rect ) - VERT_BORDER_SPACE;
162 sal_Int32 nWidthWnd = nHeightWnd;
164 if ( aPicSize.m_cx >= aPicSize.m_cy )
166 scaledPicSize.m_cx = nWidthWnd;
167 scaledPicSize.m_cy =
168 static_cast< sal_Int32 >(
169 aPicSize.m_cy * nWidthWnd / aPicSize.m_cx );
171 else
173 scaledPicSize.m_cx =
174 static_cast< sal_Int32 >(
175 aPicSize.m_cx * nHeightWnd / aPicSize.m_cy );
176 scaledPicSize.m_cy = nHeightWnd;
180 return scaledPicSize;
183 } // end namespace
186 //---------------------------------------------------
187 // to ensure only one instance (singleton)
188 //---------------------------------------------------
190 CFilePreview* CFilePreview::createInstance(
191 HWND aParent,
192 POINT ulCorner,
193 const CDimension& aSize,
194 HINSTANCE hInstance,
195 sal_Bool bShow,
196 sal_Bool bEnabled )
198 if ( !s_FilePreviewInst )
202 s_FilePreviewInst = new CFilePreview(
203 aParent, ulCorner, aSize, hInstance, bShow, bEnabled );
204 s_SingletonDestroyer.reset( s_FilePreviewInst );
206 catch( CPreviewException& )
208 OSL_ASSERT( !s_FilePreviewInst );
209 OSL_FAIL( "Creation of the preview window failed" );
211 catch( CAutoOleInit::COleInitException& )
213 OSL_ASSERT( !s_FilePreviewInst );
214 OSL_FAIL( "OleInitalize failed" );
218 return s_FilePreviewInst;
221 //---------------------------------------------------
223 //---------------------------------------------------
225 CFilePreview::CFilePreview(
226 HWND aParent,
227 POINT ulCorner,
228 const CDimension& aSize,
229 HINSTANCE hInstance,
230 sal_Bool bShow,
231 sal_Bool bEnabled ) :
232 m_hInstance( hInstance ),
233 m_bEnabled( bEnabled )
235 // register the preview window class
236 WNDCLASSEX wndClsEx;
237 ZeroMemory(&wndClsEx, sizeof(wndClsEx));
239 wndClsEx.cbSize = sizeof(wndClsEx);
240 wndClsEx.style = CS_HREDRAW | CS_VREDRAW;
241 wndClsEx.lpfnWndProc = CFilePreview::WndProc;
242 wndClsEx.hInstance = m_hInstance;
243 wndClsEx.hbrBackground = (HBRUSH)( COLOR_INACTIVEBORDER + 1 );
244 wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME;
246 // register the preview window class
247 // !!! Win95 - the window class will be unregistered automaticly
248 // if the dll is unloaded
249 // Win2000 - the window class must be unregistered manually
250 // if the dll is unloaded
251 m_atomPrevWndClass = RegisterClassEx(&wndClsEx);
252 if ( !m_atomPrevWndClass )
253 throw CPreviewException( );
255 // create the preview window in invisible state
256 sal_uInt32 dwStyle = bShow ? (WS_CHILD | WS_VISIBLE) : WS_CHILD;
257 m_hwnd = CreateWindowEx(
258 WS_EX_CLIENTEDGE,
259 PREVIEWWND_CLASS_NAME,
260 TEXT(""),
261 dwStyle,
262 ulCorner.x,
263 ulCorner.y,
264 aSize.m_cx,
265 aSize.m_cy,
266 aParent,
267 (HMENU)100, // for child windows this will
268 // be used as child window identifier
269 m_hInstance,
270 0 );
271 if (!IsWindow(m_hwnd))
272 throw CPreviewException( );
275 //---------------------------------------------------
277 //---------------------------------------------------
279 CFilePreview::~CFilePreview( )
281 // unregister preview window class
282 sal_Bool bRet = UnregisterClass(
283 (LPCTSTR)MAKELONG( m_atomPrevWndClass, 0 ),
284 m_hInstance );
285 OSL_POSTCOND( bRet, "Unregister preview window class failed" );
288 //---------------------------------------------------
289 // sets the size of the preview window
290 //---------------------------------------------------
292 sal_Bool SAL_CALL CFilePreview::setSize( const CDimension& aSize )
294 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
296 // resize the fileopen file listbox
297 return SetWindowPos(
298 m_hwnd,
299 NULL,
302 aSize.m_cx,
303 aSize.m_cy,
304 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
307 //---------------------------------------------------
308 // returns the dimension of the preview
309 //---------------------------------------------------
311 sal_Bool SAL_CALL CFilePreview::getSize( CDimension& theSize ) const
313 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
315 RECT rect;
316 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
318 theSize.m_cx = _getWidthRect( rect );
319 theSize.m_cy = _getHeightRect( rect );
321 return bRet;
324 //---------------------------------------------------
325 // sets the position of the upper left corner
326 // of the preview window relative to the
327 // upper left corner of the parent window
328 //---------------------------------------------------
330 sal_Bool SAL_CALL CFilePreview::setPos( POINT ulCorner )
332 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
334 // resize the fileopen file listbox
335 return SetWindowPos(
336 m_hwnd,
337 NULL,
338 ulCorner.x,
339 ulCorner.y,
342 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
345 //---------------------------------------------------
346 // returns the current position of the preview
347 // relative to the upper left corner of the
348 // parent window
349 //---------------------------------------------------
351 sal_Bool SAL_CALL CFilePreview::getPos( POINT& ulCorner ) const
353 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
355 POINT pt = { 0, 0 };
356 RECT rect;
358 sal_Bool bRet = GetWindowRect( m_hwnd, &rect );
360 ulCorner.x = rect.left;
361 ulCorner.y = rect.top;
363 ScreenToClient( m_hwnd, &ulCorner );
365 return bRet;
368 //---------------------------------------------------
370 //---------------------------------------------------
372 void SAL_CALL CFilePreview::enable( sal_Bool bEnable )
374 m_bEnabled = bEnable;
376 // force a redraw
377 InvalidateRect( m_hwnd, NULL, sal_True );
378 UpdateWindow( m_hwnd );
381 //---------------------------------------------------
382 // shows the preview window
383 // possible values see SHOW_STATE
384 // SS_SHOW - make the window visible
385 // SS_HIDE - hide the window
386 // SS_ENABLED - enable the window
387 // SS_DISABLED - disable the window
388 //---------------------------------------------------
390 sal_Bool SAL_CALL CFilePreview::show( sal_Bool bShow )
392 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
394 sal_Int32 showState = bShow ? SW_SHOW : SW_HIDE;
395 return ShowWindow( m_hwnd, showState );
398 //---------------------------------------------------
399 // if the preview is shown and enabled
400 // preview of the given file will be shown
401 // returns true on success or false if an error
402 // occurred (the file in not there or not accessible etc.)
403 //---------------------------------------------------
405 sal_Bool SAL_CALL CFilePreview::update( const OUString& aFileName )
407 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
411 if ( m_bEnabled )
413 if ( m_IPicture )
414 m_IPicture.Release( );
416 loadFile( aFileName );
418 // force a complete window redraw
419 InvalidateRect( m_hwnd, NULL, sal_True );
420 UpdateWindow( m_hwnd );
423 catch( _com_error& )
427 return sal_True;
430 //---------------------------------------------------
432 //---------------------------------------------------
434 void SAL_CALL CFilePreview::onPaint( HWND hWnd, HDC hDC )
436 OSL_PRECOND( IsWindow( m_hwnd ), "Preview window not initialized" );
440 if ( m_bEnabled )
442 // get width and height of picture
443 long cxPicHIMETRIC;
444 long cyPicHIMETRIC;
446 m_IPicture->get_Width( &cxPicHIMETRIC );
447 m_IPicture->get_Height( &cyPicHIMETRIC );
449 // convert himetric to pixels
450 int cxPicPIXEL = Himetric2Pixel( hDC, cxPicHIMETRIC, LOGPIXELSX );
451 int cyPicPIXEL = Himetric2Pixel( hDC, cyPicHIMETRIC, LOGPIXELSY );
453 // scale the picture based on the size of the preview window
454 RECT rcPrevWnd;
455 GetClientRect(hWnd, &rcPrevWnd);
457 CDimension scaledPicSize = _scalePictureSize(
458 hWnd, CDimension( cxPicPIXEL, cyPicPIXEL ) );
460 // calc the upper left corner so that the picture
461 // is centered within the window
462 POINT ulCorner = _calcULCorner( hWnd, scaledPicSize );
464 // render the picture
465 HRESULT hr = m_IPicture->Render(
466 hDC,
467 ulCorner.x,
468 ulCorner.y,
469 scaledPicSize.m_cx,
470 scaledPicSize.m_cy,
472 cyPicHIMETRIC,
473 cxPicHIMETRIC,
474 -cyPicHIMETRIC,
475 &rcPrevWnd );
476 } // end if ( m_bEnabled )
478 catch( _com_error& )
483 //---------------------------------------------------
485 //---------------------------------------------------
487 sal_Bool CFilePreview::loadFile( const OUString& aFileName )
489 HANDLE hFile = 0;
490 HGLOBAL hGlobal = 0;
491 LPVOID pData = NULL;
492 IStreamPtr pIStream;
493 HRESULT hr = E_FAIL;
494 sal_Bool bRet;
495 sal_uInt32 nBytesRead;
496 sal_uInt32 fszExtra;
497 sal_uInt32 fsize;
499 hFile = CreateFile(
500 aFileName.getStr( ),
501 GENERIC_READ,
503 NULL,
504 OPEN_EXISTING,
506 NULL );
507 if ( INVALID_HANDLE_VALUE == hFile )
508 goto CLEANUP_AND_EXIT;
510 fszExtra = 0;
511 fsize = GetFileSize( hFile, &fszExtra );
513 // empty file, error or file to big
514 if ( -1 == fsize || 0 == fsize || fszExtra )
515 goto CLEANUP_AND_EXIT;
517 hGlobal = GlobalAlloc( GMEM_MOVEABLE, fsize );
518 if ( !hGlobal )
519 goto CLEANUP_AND_EXIT;
521 pData = GlobalLock( hGlobal );
522 if ( !pData )
523 goto CLEANUP_AND_EXIT;
525 bRet = ReadFile(
526 hFile, pData, fsize, &nBytesRead, NULL );
528 if ( !bRet )
529 goto CLEANUP_AND_EXIT;
531 hr = CreateStreamOnHGlobal(
532 hGlobal, sal_False, &pIStream );
534 if ( SUCCEEDED( hr ) )
536 hr = OleLoadPicture(
537 pIStream, fsize, sal_False,
538 __uuidof( IPicture ), (LPVOID*)&m_IPicture );
541 CLEANUP_AND_EXIT:
542 if ( hFile )
543 CloseHandle( hFile );
545 if ( pData )
546 GlobalUnlock( hGlobal );
548 if ( hGlobal )
549 GlobalFree( hGlobal );
551 return ( SUCCEEDED( hr ) );
554 //---------------------------------------------------
556 //---------------------------------------------------
558 LRESULT CALLBACK CFilePreview::WndProc(
559 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
561 LRESULT lResult = 0;
563 switch( uMsg )
565 case WM_PAINT:
567 OSL_PRECOND( s_FilePreviewInst, "Static member not initialized" );
569 HDC hDC;
570 PAINTSTRUCT ps;
572 hDC = BeginPaint( hWnd, &ps );
573 s_FilePreviewInst->onPaint( hWnd, hDC );
574 EndPaint( hWnd, &ps );
576 break;
578 // under windows 95/98 the creation of the
579 // hidden target request window fails if
580 // we don't handle this message ourself
581 // because the DefWindowProc returns 0 as
582 // a result of handling WM_NCCREATE what
583 // leads to a failure of CreateWindow[Ex]!!!
584 case WM_NCCREATE:
585 lResult = sal_True;
586 break;
588 default:
589 return DefWindowProc( hWnd, uMsg, wParam, lParam );
592 return lResult;
597 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */