Files
libreoffice/fpicker/source/win32/filepicker/dibpreview.cxx
Stephan Bergmann 432e3162e6 clang-cl loplugin: fpicker
Change-Id: Ib19175affd48610fc164a996d609b369256d4f72
Reviewed-on: https://gerrit.libreoffice.org/29865
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Tested-by: Stephan Bergmann <sbergman@redhat.com>
2016-10-16 14:19:12 +00:00

389 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "dibpreview.hxx"
#include <osl/diagnose.h>
#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
#include <rtl/ustring.hxx>
#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;
namespace /* private */
{
const PCWSTR CURRENT_INSTANCE = L"CurrInst";
};
#define PREVIEWWND_CLASS_NAME L"DIBPreviewWnd###"
// 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,bool bShowWindow) :
m_Instance(instance)
{
RegisterDibPreviewWindowClass();
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (bShowWindow)
dwStyle |= WS_VISIBLE;
m_Hwnd = CreateWindowExW(
WS_EX_CLIENTEDGE,
PREVIEWWND_CLASS_NAME,
L"",
dwStyle,
0, 0, 0, 0,
parent,
nullptr, // for child windows this will
// be used as child window identifier
m_Instance,
this // pass a pointer to the current
// instance of this class
);
if (!IsWindow(m_Hwnd))
{
SAL_WARN("fpicker","Could not create preview window");
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 its 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,nullptr,false);
UpdateWindow(m_Hwnd);
}
bool SAL_CALL CDIBPreview::setShowState(bool bShowState) throw (RuntimeException)
{
PreviewBase::setShowState(bShowState);
ShowWindow(m_Hwnd, m_bShowState ? SW_SHOW : SW_HIDE);
return true;
}
bool SAL_CALL CDIBPreview::getShowState() throw (RuntimeException)
{
return bool(IsWindowVisible(m_Hwnd));
}
HWND SAL_CALL CDIBPreview::getWindowHandle() const
{
return m_Hwnd;
}
void SAL_CALL CDIBPreview::onPaint(HWND hWnd, HDC hDC)
{
osl::MutexGuard aGuard(m_PaintLock);
try
{
BITMAPFILEHEADER* pbmfh = reinterpret_cast<BITMAPFILEHEADER*>(m_Image.getArray());
if ( !IsBadReadPtr( pbmfh, sizeof(BITMAPFILEHEADER)) &&
(pbmfh->bfType == ('B' | ('M' << 8))) )
{
BITMAPINFO * pbmi = reinterpret_cast<BITMAPINFO*>((pbmfh + 1));
sal_uInt8 * pBits = reinterpret_cast<sal_uInt8*>(pbmfh) + pbmfh->bfOffBits;
int cxDib = pbmi->bmiHeader.biWidth;
int 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 = StretchDIBits(
hDC, nX, nY, cxDib, cyDib,
0, 0, cxDib, cyDib, pBits, pbmi,
DIB_RGB_COLORS, SRCCOPY);
OSL_ASSERT(0 != 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,reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1));
// bottom
rc.left = 0;
rc.top = nHeight - nY - 1;
rc.right = nWidth;
rc.bottom = nHeight;
FillRect(hDC,&rc,reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1));
}
if (nX > 0)
{
// left
rc.left = 0;
rc.top = nY;
rc.right = nX;
rc.bottom = nHeight - nY;
FillRect(hDC,&rc,reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1));
// right
rc.left = nWidth - nX - 1;
rc.top = nY;
rc.right = nWidth;
rc.bottom = nHeight - nY;
FillRect(hDC,&rc,reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1));
}
}
else // clear background
{
RECT rc;
GetClientRect(hWnd,&rc);
FillRect(hDC,&rc,reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1));
}
}
catch(...)
{
OSL_ASSERT(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
SetPropW(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 (static_cast<CDIBPreview*>(
RemovePropW(hWnd, CURRENT_INSTANCE)) == nullptr)
{
OSL_ASSERT(false);
}
}
break;
case WM_PAINT:
{
CDIBPreview* pImpl = static_cast<CDIBPreview*>(
GetPropW(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 = reinterpret_cast<HBRUSH>(COLOR_INACTIVEBORDER + 1);
wndClsEx.lpszClassName = PREVIEWWND_CLASS_NAME;
// register the preview window class
// !!! Win95 - the window class will be unregistered automatically
// if the dll is unloaded
// Win2000 - the window class must be unregistered manually
// if the dll is unloaded
s_ClassAtom = RegisterClassExW(&wndClsEx);
if (0 == s_ClassAtom)
{
SAL_WARN("fpicker", "Could not register preview window class");
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)
{
UnregisterClassW(reinterpret_cast<PCWSTR>((DWORD_PTR)MAKELONG(s_ClassAtom,0)),m_Instance);
s_ClassAtom = 0;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */