427fe74c70
2008/04/01 15:17:05 thb 1.11.154.3: #i85898# Stripping all external header guards 2008/04/01 12:30:51 thb 1.11.154.2: #i85898# Stripping all external header guards 2008/03/31 13:13:18 rt 1.11.154.1: #i87441# Change license header to LPGL v3.
475 lines
13 KiB
C++
475 lines
13 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: dibpreview.cxx,v $
|
|
* $Revision: 1.12 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_fpicker.hxx"
|
|
|
|
//------------------------------------------------------------------------
|
|
// includes
|
|
//------------------------------------------------------------------------
|
|
|
|
#include <tchar.h>
|
|
#include "dibpreview.hxx"
|
|
#include <osl/diagnose.h>
|
|
|
|
#ifndef _COM_SUN_STAR_UI_DIALOG_FILEPREVIEWIMAGEFORMATS_HPP_
|
|
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
|
|
#endif
|
|
|
|
#ifndef _USTRING_HXX_
|
|
#include <rtl/ustring.hxx>
|
|
#endif
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
//------------------------------------------------------------------------
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
using ::com::sun::star::uno::Sequence;
|
|
using ::com::sun::star::uno::RuntimeException;
|
|
using ::com::sun::star::uno::Any;
|
|
using ::com::sun::star::lang::IllegalArgumentException;
|
|
using rtl::OUString;
|
|
|
|
//------------------------------------------------------------------------
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
namespace /* private */
|
|
{
|
|
const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst");
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
// defines
|
|
//------------------------------------------------------------------------
|
|
|
|
#define PREVIEWWND_CLASS_NAME TEXT("DIBPreviewWnd###")
|
|
|
|
// means 3 pixel left and 3 pixel right
|
|
#define HORZ_BODER_SPACE 6
|
|
|
|
// means 3 pixel top and 3 pixel bottom
|
|
#define VERT_BORDER_SPACE 6
|
|
|
|
//---------------------------------------------------
|
|
// static member initialization
|
|
//---------------------------------------------------
|
|
|
|
osl::Mutex CDIBPreview::s_Mutex;
|
|
ATOM CDIBPreview::s_ClassAtom = 0;
|
|
sal_Int32 CDIBPreview::s_RegisterDibPreviewWndCount = 0;
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
CDIBPreview::CDIBPreview(HINSTANCE instance,HWND parent,sal_Bool bShowWindow) :
|
|
m_Instance(instance)
|
|
{
|
|
RegisterDibPreviewWindowClass();
|
|
|
|
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
|
|
|
if (bShowWindow)
|
|
dwStyle |= WS_VISIBLE;
|
|
|
|
m_Hwnd = CreateWindowEx(
|
|
WS_EX_CLIENTEDGE,
|
|
PREVIEWWND_CLASS_NAME,
|
|
TEXT(""),
|
|
dwStyle,
|
|
0, 0, 0, 0,
|
|
parent,
|
|
(HMENU)0x0, // for child windows this will
|
|
// be used as child window identifier
|
|
m_Instance,
|
|
(LPVOID)this // pass a pointer to the current
|
|
// instance of this class
|
|
);
|
|
|
|
bool bSuccess = IsWindow(m_Hwnd);
|
|
|
|
OSL_POSTCOND(bSuccess,"Coud not create preview window");
|
|
|
|
if (!bSuccess)
|
|
{
|
|
UnregisterDibPreviewWindowClass();
|
|
throw std::runtime_error("Could not create preview window");
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
CDIBPreview::~CDIBPreview( )
|
|
{
|
|
// remember: we don't have to destroy the
|
|
// preview window because it will be destroyed
|
|
// by it's parent window (the FileOpen dialog)
|
|
// but we have to unregister the window class
|
|
//if ( m_bWndClassRegistered )
|
|
UnregisterDibPreviewWindowClass();
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
sal_Int32 SAL_CALL CDIBPreview::getTargetColorDepth() throw (RuntimeException)
|
|
{
|
|
HDC hdc = GetDC(m_Hwnd);
|
|
int clrRes = 0;
|
|
|
|
if (hdc)
|
|
clrRes = GetDeviceCaps(hdc, COLORRES);
|
|
|
|
return clrRes;
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
sal_Int32 SAL_CALL CDIBPreview::getAvailableWidth() throw (RuntimeException)
|
|
{
|
|
RECT rect;
|
|
bool bRet = GetClientRect(m_Hwnd,&rect);
|
|
|
|
sal_Int32 cx = 0;
|
|
|
|
if ( bRet )
|
|
cx = rect.right;
|
|
|
|
return cx;
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
sal_Int32 SAL_CALL CDIBPreview::getAvailableHeight() throw (RuntimeException)
|
|
{
|
|
RECT rect;
|
|
bool bRet = GetClientRect(m_Hwnd,&rect);
|
|
|
|
sal_Int32 cy = 0;
|
|
|
|
if ( bRet )
|
|
cy = rect.bottom;
|
|
|
|
return cy;
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
void SAL_CALL CDIBPreview::setImage(sal_Int16 aImageFormat, const Any& aImage)
|
|
throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
PreviewBase::setImage(aImageFormat,aImage);
|
|
|
|
// if the any has no value we have an
|
|
// empty Sequence which clears the
|
|
// preview window
|
|
osl::ClearableMutexGuard aGuard(m_PaintLock);
|
|
|
|
m_Image.realloc(0);
|
|
m_ImageData >>= m_Image;
|
|
|
|
aGuard.clear();
|
|
|
|
InvalidateRect(m_Hwnd,NULL,FALSE);
|
|
UpdateWindow(m_Hwnd);
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
sal_Bool SAL_CALL CDIBPreview::setShowState(sal_Bool bShowState) throw (RuntimeException)
|
|
{
|
|
PreviewBase::setShowState(bShowState);
|
|
ShowWindow(m_Hwnd, m_bShowState ? SW_SHOW : SW_HIDE);
|
|
return sal_True;
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
sal_Bool SAL_CALL CDIBPreview::getShowState() throw (RuntimeException)
|
|
{
|
|
return (sal_Bool)IsWindowVisible(m_Hwnd);
|
|
}
|
|
|
|
//-------------------------------
|
|
//
|
|
//-------------------------------
|
|
|
|
HWND SAL_CALL CDIBPreview::getWindowHandle() const
|
|
{
|
|
return m_Hwnd;
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
void SAL_CALL CDIBPreview::onPaint(HWND hWnd, HDC hDC)
|
|
{
|
|
BITMAPFILEHEADER* pbmfh;
|
|
BITMAPINFO * pbmi;
|
|
BYTE * pBits;
|
|
int cxDib;
|
|
int cyDib;
|
|
|
|
osl::MutexGuard aGuard(m_PaintLock);
|
|
|
|
try
|
|
{
|
|
pbmfh = reinterpret_cast<BITMAPFILEHEADER*>(m_Image.getArray());
|
|
|
|
if ( !IsBadReadPtr( pbmfh, sizeof(BITMAPFILEHEADER)) &&
|
|
(pbmfh->bfType == ('B' | ('M' << 8))) )
|
|
{
|
|
pbmi = reinterpret_cast<BITMAPINFO*>((pbmfh + 1));
|
|
pBits = reinterpret_cast<BYTE*>(((DWORD)pbmfh) + pbmfh->bfOffBits);
|
|
|
|
cxDib = pbmi->bmiHeader.biWidth;
|
|
cyDib = abs (pbmi->bmiHeader.biHeight);
|
|
|
|
SetStretchBltMode(hDC, COLORONCOLOR);
|
|
|
|
int nWidth = getAvailableWidth();
|
|
int nHeight = getAvailableHeight();
|
|
|
|
int nX = abs(nWidth - cxDib) / 2;
|
|
int nY = abs(nHeight - cyDib) / 2;
|
|
|
|
int GDIError = GDI_ERROR;
|
|
GDIError = StretchDIBits(
|
|
hDC, nX, nY, cxDib, cyDib,
|
|
0, 0, cxDib, cyDib, pBits, pbmi,
|
|
DIB_RGB_COLORS, SRCCOPY);
|
|
|
|
OSL_ASSERT(GDI_ERROR != GDIError);
|
|
|
|
// paint the border
|
|
RECT rc;
|
|
|
|
if (nY > 0)
|
|
{
|
|
// top
|
|
rc.left = 0;
|
|
rc.top = 0;
|
|
rc.right = nWidth;
|
|
rc.bottom = nY;
|
|
FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1));
|
|
|
|
// bottom
|
|
rc.left = 0;
|
|
rc.top = nHeight - nY - 1;
|
|
rc.right = nWidth;
|
|
rc.bottom = nHeight;
|
|
FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1));
|
|
}
|
|
|
|
if (nX > 0)
|
|
{
|
|
// left
|
|
rc.left = 0;
|
|
rc.top = nY;
|
|
rc.right = nX;
|
|
rc.bottom = nHeight - nY;
|
|
FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1));
|
|
|
|
// right
|
|
rc.left = nWidth - nX - 1;
|
|
rc.top = nY;
|
|
rc.right = nWidth;
|
|
rc.bottom = nHeight - nY;
|
|
FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1));
|
|
}
|
|
}
|
|
else // clear background
|
|
{
|
|
RECT rc;
|
|
GetClientRect(hWnd,&rc);
|
|
FillRect(hDC,&rc,(HBRUSH)(COLOR_INACTIVEBORDER + 1));
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
OSL_ASSERT(sal_False);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
LRESULT CALLBACK CDIBPreview::WndProc(
|
|
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lResult = 0;
|
|
|
|
switch(uMsg)
|
|
{
|
|
|
|
// we connect a pointer to the current instance
|
|
// with a window instance via SetProp
|
|
case WM_CREATE:
|
|
{
|
|
LPCREATESTRUCT lpcs =
|
|
reinterpret_cast< LPCREATESTRUCT >(lParam);
|
|
|
|
OSL_ASSERT(lpcs->lpCreateParams);
|
|
|
|
// connect the instance handle to the window
|
|
SetProp(hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams);
|
|
}
|
|
break;
|
|
|
|
// we remove the window property which connects
|
|
// a class instance with a window class
|
|
case WM_NCDESTROY:
|
|
{
|
|
// RemoveProp returns the saved value on success
|
|
if (reinterpret_cast<CDIBPreview*>(
|
|
RemoveProp(hWnd, CURRENT_INSTANCE)) == NULL)
|
|
{
|
|
OSL_ASSERT(false);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
CDIBPreview* pImpl = reinterpret_cast<CDIBPreview*>(
|
|
GetProp(hWnd, CURRENT_INSTANCE));
|
|
|
|
OSL_ASSERT(pImpl);
|
|
|
|
HDC hDC;
|
|
PAINTSTRUCT ps;
|
|
|
|
hDC = BeginPaint(hWnd,&ps);
|
|
pImpl->onPaint(hWnd,hDC);
|
|
EndPaint(hWnd,&ps);
|
|
}
|
|
break;
|
|
|
|
// ignore this message in order to
|
|
// avoid flickering during paint
|
|
case WM_ERASEBKGND:
|
|
lResult = 1;
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
ATOM SAL_CALL CDIBPreview::RegisterDibPreviewWindowClass()
|
|
{
|
|
osl::MutexGuard aGuard( s_Mutex );
|
|
|
|
if (0 == s_ClassAtom)
|
|
{
|
|
// register the preview window class
|
|
WNDCLASSEX wndClsEx;
|
|
ZeroMemory(&wndClsEx, sizeof(wndClsEx));
|
|
|
|
wndClsEx.cbSize = sizeof(wndClsEx);
|
|
wndClsEx.style = CS_HREDRAW | CS_VREDRAW;
|
|
wndClsEx.lpfnWndProc = CDIBPreview::WndProc;
|
|
wndClsEx.hInstance = m_Instance;
|
|
wndClsEx.hbrBackground = (HBRUSH)(COLOR_INACTIVEBORDER + 1);
|
|
wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME;
|
|
|
|
// register the preview window class
|
|
// !!! Win95 - the window class will be unregistered automaticly
|
|
// if the dll is unloaded
|
|
// Win2000 - the window class must be unregistered manually
|
|
// if the dll is unloaded
|
|
s_ClassAtom = RegisterClassEx(&wndClsEx);
|
|
|
|
OSL_POSTCOND(s_ClassAtom,"Could not register preview window class");
|
|
|
|
if (0 == s_ClassAtom)
|
|
throw std::runtime_error("Preview window class could not be registered");
|
|
}
|
|
|
|
// increment the register class counter
|
|
// so that we keep track of the number
|
|
// of class registrations
|
|
//if ( 0 != s_ClassAtom )
|
|
s_RegisterDibPreviewWndCount++;
|
|
|
|
return s_ClassAtom;
|
|
}
|
|
|
|
//---------------------------------------------------
|
|
//
|
|
//---------------------------------------------------
|
|
|
|
void SAL_CALL CDIBPreview::UnregisterDibPreviewWindowClass()
|
|
{
|
|
osl::MutexGuard aGuard( s_Mutex );
|
|
|
|
OSL_ASSERT( ( (0 != s_ClassAtom) && (s_RegisterDibPreviewWndCount > 0)) ||
|
|
( (0 == s_ClassAtom) && (0 == s_RegisterDibPreviewWndCount) ) );
|
|
|
|
// update the register class counter
|
|
// and unregister the window class if
|
|
// counter drops to zero
|
|
if (0 != s_ClassAtom)
|
|
{
|
|
s_RegisterDibPreviewWndCount--;
|
|
OSL_ASSERT(s_RegisterDibPreviewWndCount >= 0);
|
|
}
|
|
|
|
if (0 == s_RegisterDibPreviewWndCount)
|
|
{
|
|
UnregisterClass((LPCTSTR)MAKELONG(s_ClassAtom,0),m_Instance);
|
|
s_ClassAtom = 0;
|
|
}
|
|
}
|