2267 lines
73 KiB
C++
2267 lines
73 KiB
C++
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 1998
|
|
*
|
|
* TITLE: PREVWND.CPP
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: ShaunIv
|
|
*
|
|
* DATE: 10/9/1998
|
|
*
|
|
* DESCRIPTION: Scanner Preview Control
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "prevwnd.h"
|
|
#include "pviewids.h"
|
|
#include "simcrack.h"
|
|
#include "miscutil.h"
|
|
#include "simrect.h"
|
|
#include "waitcurs.h"
|
|
#include "comctrlp.h"
|
|
#include "dlgunits.h"
|
|
#include "simrect.h"
|
|
|
|
#define IDC_PROGRESSCONTROL 100
|
|
|
|
#undef DITHER_DISABLED_CONTROL
|
|
|
|
//
|
|
// The range of image sizes for which we will detect regions.
|
|
//
|
|
#define MIN_REGION_DETECTION_X 100
|
|
#define MIN_REGION_DETECTION_Y 100
|
|
#define MAX_REGION_DETECTION_X 1275
|
|
#define MAX_REGION_DETECTION_Y 2100
|
|
|
|
#if defined(OLD_CRAPPY_HOME_SETUP)
|
|
static HINSTANCE g_hMsImgInst=LoadLibrary( TEXT("msimg32.dll") );
|
|
static AlphaBlendFn AlphaBlend=(AlphaBlendFn)GetProcAddress( g_hMsImgInst, "AlphaBlend" );
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Mouse hit test codes
|
|
*/
|
|
#define HIT_NONE 0x0000
|
|
#define HIT_BORDER 0x0001
|
|
#define HIT_TOP 0x0002
|
|
#define HIT_BOTTOM 0x0004
|
|
#define HIT_LEFT 0x0008
|
|
#define HIT_RIGHT 0x0010
|
|
#define HIT_SELECTED 0x0020
|
|
#define HIT_TOPLEFT (HIT_TOP|HIT_LEFT)
|
|
#define HIT_TOPRIGHT (HIT_TOP|HIT_RIGHT)
|
|
#define HIT_BOTTOMLEFT (HIT_BOTTOM|HIT_LEFT)
|
|
#define HIT_BOTTOMRIGHT (HIT_BOTTOM|HIT_RIGHT)
|
|
|
|
|
|
/*
|
|
* Defaults
|
|
*/
|
|
#define DEFAULT_ACCEL_FACTOR 8
|
|
#define DEFAULT_HANDLE_SIZE 6
|
|
#define DEFAULT_BORDER 6
|
|
#define DEFAULT_BG_ALPHA 96
|
|
|
|
#define DEFAULT_SELECTED_HANDLE_FILL_COLOR RGB(0,128,0)
|
|
#define DEFAULT_UNSELECTED_HANDLE_FILL_COLOR RGB(128,0,0)
|
|
#define DEFAULT_DISABLED_HANDLE_FILL_COLOR GetSysColor(COLOR_3DSHADOW)
|
|
|
|
#define DEFAULT_SELECTED_BORDER_COLOR RGB(0,0,0)
|
|
#define DEFAULT_UNSELECTED_BORDER_COLOR RGB(0,0,0)
|
|
#define DEFAULT_DISABLED_BORDER_COLOR GetSysColor(COLOR_3DSHADOW)
|
|
|
|
#define DEFAULT_SELECTION_HANDLE_SHADOW RGB(128,128,128)
|
|
#define DEFAULT_SELECTION_HANDLE_HIGHLIGHT RGB(255,255,255)
|
|
|
|
#define DEFAULT_HANDLE_TYPE (PREVIEW_WINDOW_SQUAREHANDLES|PREVIEW_WINDOW_FILLEDHANDLES)
|
|
|
|
#define DEFAULT_BORDER_STYLE PS_DOT
|
|
|
|
#define BORDER_SELECTION_PEN_THICKNESS 0
|
|
|
|
#define REGION_DETECTION_BORDER 1
|
|
|
|
static inline RECT CreateRect( int left, int top, int right, int bottom )
|
|
{
|
|
RECT r;
|
|
r.left = left;
|
|
r.top = top;
|
|
r.right = right;
|
|
r.bottom = bottom;
|
|
return(r);
|
|
}
|
|
|
|
static HBRUSH CreateDitheredPatternBrush(void)
|
|
{
|
|
const BYTE s_GrayBitmapBits[] = {
|
|
0xAA, 0x00,
|
|
0x55, 0x00,
|
|
0xAA, 0x00,
|
|
0x55, 0x00,
|
|
0xAA, 0x00,
|
|
0x55, 0x00,
|
|
0xAA, 0x00,
|
|
0x55, 0x00
|
|
};
|
|
HBITMAP hBmp = CreateBitmap( 8, 8, 1, 1, s_GrayBitmapBits );
|
|
if (hBmp)
|
|
{
|
|
HBRUSH hbrPatBrush = CreatePatternBrush(hBmp);
|
|
DeleteObject(hBmp);
|
|
return(hbrPatBrush);
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
static void DitherRect( HDC hDC, RECT &rc )
|
|
{
|
|
const DWORD ROP_DPNA = 0x000A0329;
|
|
HBRUSH hbr = CreateDitheredPatternBrush();
|
|
if (hbr)
|
|
{
|
|
HBRUSH hbrOld = (HBRUSH)SelectObject(hDC, hbr);
|
|
PatBlt( hDC, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ROP_DPNA );
|
|
SelectObject( hDC, hbrOld );
|
|
DeleteObject( hbr );
|
|
}
|
|
}
|
|
|
|
static inline int PointInRect( const RECT &rc, const POINT &pt )
|
|
{
|
|
return(PtInRect(&rc,pt));
|
|
}
|
|
|
|
static inline int Boundary( int val, int min, int max )
|
|
{
|
|
if (val < min)
|
|
return(min);
|
|
if (val > max)
|
|
return(max);
|
|
return(val);
|
|
}
|
|
|
|
template <class T>
|
|
static inline T Minimum( const T &a, const T &b )
|
|
{
|
|
return(a < b) ? a : b;
|
|
}
|
|
|
|
template <class T>
|
|
static inline T Maximum( const T &a, const T &b )
|
|
{
|
|
return(a > b) ? a : b;
|
|
}
|
|
|
|
// Just like API UnionRect, but handles empty rects
|
|
static void TrueUnionRect( RECT *prcDest, const RECT *prcSrc1, const RECT *prcSrc2 )
|
|
{
|
|
prcDest->left = Minimum( prcSrc1->left, prcSrc2->left );
|
|
prcDest->right = Maximum( prcSrc1->right, prcSrc2->right );
|
|
prcDest->top = Minimum( prcSrc1->top, prcSrc2->top );
|
|
prcDest->bottom = Maximum( prcSrc1->bottom, prcSrc2->bottom );
|
|
}
|
|
|
|
// Constructor
|
|
CWiaPreviewWindow::CWiaPreviewWindow( HWND hWnd )
|
|
: m_hWnd(hWnd),
|
|
m_bDeleteBitmap(TRUE),
|
|
m_bSizing(FALSE),
|
|
m_bAllowNullSelection(FALSE),
|
|
m_hBufferBitmap(NULL),
|
|
m_hPaintBitmap(NULL),
|
|
m_hAlphaBitmap(NULL),
|
|
m_hPreviewBitmap(NULL),
|
|
m_hCursorArrow(LoadCursor(NULL,IDC_ARROW)),
|
|
m_hCursorCrossHairs(LoadCursor(NULL,IDC_CROSS)),
|
|
m_hCursorMove(LoadCursor(NULL,IDC_SIZEALL)),
|
|
m_hCursorSizeNS(LoadCursor(NULL,IDC_SIZENS)),
|
|
m_hCursorSizeNeSw(LoadCursor(NULL,IDC_SIZENESW)),
|
|
m_hCursorSizeNwSe(LoadCursor(NULL,IDC_SIZENWSE)),
|
|
m_hCursorSizeWE(LoadCursor(NULL,IDC_SIZEWE)),
|
|
m_MovingSel(HIT_NONE),
|
|
m_nBorderSize(DEFAULT_BORDER),
|
|
m_nHandleType(DEFAULT_HANDLE_TYPE),
|
|
m_nHandleSize(DEFAULT_HANDLE_SIZE),
|
|
m_hHalftonePalette(NULL),
|
|
m_nCurrentRect(0),
|
|
m_hBackgroundBrush(CreateSolidBrush(GetSysColor(COLOR_WINDOW))),
|
|
m_bPreviewMode(false),
|
|
m_bSuccessfulRegionDetection(false),
|
|
m_bUserChangedSelection(false)
|
|
{
|
|
ZeroMemory(&m_rcCurrSel,sizeof(m_rcCurrSel));
|
|
ZeroMemory(&m_rcSavedImageRect,sizeof(m_rcSavedImageRect));
|
|
ZeroMemory(&m_Resolution,sizeof(m_Resolution));
|
|
ZeroMemory(&m_Delta,sizeof(m_Delta));
|
|
ZeroMemory(&m_bfBlendFunction,sizeof(m_bfBlendFunction));
|
|
ZeroMemory(&m_rcSavedImageRect,sizeof(m_rcSavedImageRect));
|
|
|
|
m_bfBlendFunction.BlendOp = AC_SRC_OVER;
|
|
m_bfBlendFunction.SourceConstantAlpha = DEFAULT_BG_ALPHA;
|
|
|
|
m_aHandlePens[Selected] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTED_BORDER_COLOR );
|
|
m_aHandlePens[Unselected] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_UNSELECTED_BORDER_COLOR );
|
|
m_aHandlePens[Disabled] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_DISABLED_BORDER_COLOR );
|
|
|
|
m_aBorderPens[Selected] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTED_BORDER_COLOR );
|
|
m_aBorderPens[Unselected] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_UNSELECTED_BORDER_COLOR );
|
|
m_aBorderPens[Disabled] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_DISABLED_BORDER_COLOR );
|
|
|
|
m_aHandleBrushes[Selected] = CreateSolidBrush( DEFAULT_SELECTED_HANDLE_FILL_COLOR );
|
|
m_aHandleBrushes[Unselected] = CreateSolidBrush( DEFAULT_UNSELECTED_HANDLE_FILL_COLOR );
|
|
m_aHandleBrushes[Disabled] = CreateSolidBrush( DEFAULT_DISABLED_HANDLE_FILL_COLOR );
|
|
|
|
m_hHandleShadow = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTION_HANDLE_SHADOW);
|
|
m_hHandleHighlight = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTION_HANDLE_HIGHLIGHT);
|
|
|
|
}
|
|
|
|
void CWiaPreviewWindow::DestroyBitmaps(void)
|
|
{
|
|
if (m_hPaintBitmap)
|
|
{
|
|
DeleteObject(m_hPaintBitmap);
|
|
m_hPaintBitmap = NULL;
|
|
}
|
|
if (m_hBufferBitmap)
|
|
{
|
|
DeleteObject(m_hBufferBitmap);
|
|
m_hBufferBitmap = NULL;
|
|
}
|
|
if (m_hAlphaBitmap)
|
|
{
|
|
DeleteObject(m_hAlphaBitmap);
|
|
m_hAlphaBitmap = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
CWiaPreviewWindow::~CWiaPreviewWindow()
|
|
{
|
|
DestroyBitmaps();
|
|
|
|
if (m_bDeleteBitmap && m_hPreviewBitmap)
|
|
{
|
|
DeleteObject(m_hPreviewBitmap);
|
|
m_hPreviewBitmap = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_hPreviewBitmap = NULL;
|
|
}
|
|
|
|
if (m_hHalftonePalette)
|
|
{
|
|
DeleteObject(m_hHalftonePalette);
|
|
m_hHalftonePalette = NULL;
|
|
}
|
|
|
|
// Destroy all of the handle pens
|
|
for (int i=0;i<ARRAYSIZE(m_aHandlePens);i++)
|
|
{
|
|
if (m_aHandlePens[i])
|
|
{
|
|
DeleteObject(m_aHandlePens[i]);
|
|
m_aHandlePens[i] = NULL;
|
|
}
|
|
}
|
|
|
|
// Destroy all of the selection rectangle pens
|
|
for (i=0;i<ARRAYSIZE(m_aBorderPens);i++)
|
|
{
|
|
if (m_aBorderPens[i])
|
|
{
|
|
DeleteObject(m_aBorderPens[i]);
|
|
m_aBorderPens[i] = NULL;
|
|
}
|
|
}
|
|
|
|
// Destroy all of the brushes
|
|
for (i=0;i<ARRAYSIZE(m_aHandleBrushes);i++)
|
|
{
|
|
if (m_aHandleBrushes[i])
|
|
{
|
|
DeleteObject(m_aHandleBrushes[i]);
|
|
m_aHandleBrushes[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if (m_hHandleHighlight)
|
|
{
|
|
DeleteObject(m_hHandleHighlight);
|
|
m_hHandleHighlight = NULL;
|
|
}
|
|
|
|
if (m_hHandleShadow)
|
|
{
|
|
DeleteObject(m_hHandleShadow);
|
|
m_hHandleShadow = NULL;
|
|
}
|
|
|
|
if (m_hBackgroundBrush)
|
|
{
|
|
DeleteObject(m_hBackgroundBrush);
|
|
m_hBackgroundBrush = NULL;
|
|
}
|
|
|
|
m_hWnd = NULL;
|
|
|
|
// Zero out all of the cursors. No need to free them
|
|
m_hCursorSizeNeSw = NULL;
|
|
m_hCursorSizeNwSe = NULL;
|
|
m_hCursorCrossHairs = NULL;
|
|
m_hCursorMove = NULL;
|
|
m_hCursorSizeNS = NULL;
|
|
m_hCursorSizeWE = NULL;
|
|
m_hCursorArrow = NULL;
|
|
}
|
|
|
|
void CWiaPreviewWindow::Repaint( PRECT pRect, bool bErase )
|
|
{
|
|
InvalidateRect( m_hWnd, pRect, (bErase != false) );
|
|
UpdateWindow( m_hWnd );
|
|
}
|
|
|
|
void CWiaPreviewWindow::DrawHandle( HDC dc, const RECT &r, int nState )
|
|
{
|
|
HPEN hOldPen = (HPEN)SelectObject( dc, m_aHandlePens[nState] );
|
|
HBRUSH hOldBrush = (HBRUSH)SelectObject( dc, m_aHandleBrushes[nState] );
|
|
|
|
if (PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType)
|
|
{
|
|
SelectObject( dc, GetStockObject(NULL_BRUSH) );
|
|
}
|
|
|
|
if (PREVIEW_WINDOW_ROUNDHANDLES&m_nHandleType)
|
|
{
|
|
Ellipse(dc,r.left,r.top,r.right,r.bottom);
|
|
if (!(PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType))
|
|
{
|
|
RECT rcHighlight = r;
|
|
InflateRect(&rcHighlight,-1,-1);
|
|
SelectObject(dc,GetStockObject(NULL_BRUSH));
|
|
SelectObject(dc,m_hHandleShadow);
|
|
Arc(dc,rcHighlight.left,rcHighlight.top,rcHighlight.right,rcHighlight.bottom,rcHighlight.left,rcHighlight.bottom,rcHighlight.right,rcHighlight.top);
|
|
SelectObject(dc,m_hHandleHighlight);
|
|
Arc(dc,rcHighlight.left,rcHighlight.top,rcHighlight.right,rcHighlight.bottom,rcHighlight.right,rcHighlight.top,rcHighlight.left,rcHighlight.bottom);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Rectangle(dc,r.left,r.top,r.right,r.bottom);
|
|
if (!(PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType))
|
|
{
|
|
RECT rcHighlight = r;
|
|
InflateRect(&rcHighlight,-1,-1);
|
|
rcHighlight.right--;
|
|
rcHighlight.bottom--;
|
|
if (!IsRectEmpty(&rcHighlight))
|
|
{
|
|
SelectObject(dc,m_hHandleHighlight);
|
|
MoveToEx(dc,rcHighlight.left,rcHighlight.bottom,NULL);
|
|
LineTo(dc,rcHighlight.left,rcHighlight.top);
|
|
LineTo(dc,rcHighlight.right,rcHighlight.top);
|
|
SelectObject(dc,m_hHandleShadow);
|
|
LineTo(dc,rcHighlight.right,rcHighlight.bottom);
|
|
LineTo(dc,rcHighlight.left,rcHighlight.bottom);
|
|
}
|
|
}
|
|
}
|
|
|
|
SelectObject( dc, hOldPen );
|
|
SelectObject( dc, hOldBrush );
|
|
}
|
|
|
|
RECT CWiaPreviewWindow::GetSizingHandleRect( const RECT &rcSelection, int iWhich )
|
|
{
|
|
RECT rcSel;
|
|
CopyRect(&rcSel,&rcSelection);
|
|
NormalizeRect(rcSel);
|
|
int sizeWidth = Minimum<int>(m_nHandleSize,WiaUiUtil::RectWidth(rcSel)/2);
|
|
int sizeHeight = Minimum<int>(m_nHandleSize,WiaUiUtil::RectHeight(rcSel)/2);
|
|
switch (iWhich)
|
|
{
|
|
case HIT_TOPLEFT:
|
|
return(CreateRect( rcSel.left - m_nHandleSize, rcSel.top - m_nHandleSize, rcSel.left + sizeWidth, rcSel.top + sizeHeight ));
|
|
case HIT_TOPRIGHT:
|
|
return(CreateRect( rcSel.right - sizeWidth, rcSel.top - m_nHandleSize, rcSel.right + m_nHandleSize, rcSel.top + sizeHeight));
|
|
case HIT_BOTTOMRIGHT:
|
|
return(CreateRect( rcSel.right - sizeWidth, rcSel.bottom - sizeHeight, rcSel.right + m_nHandleSize, rcSel.bottom + m_nHandleSize ));
|
|
case HIT_BOTTOMLEFT:
|
|
return(CreateRect( rcSel.left - m_nHandleSize, rcSel.bottom - sizeHeight, rcSel.left + sizeWidth, rcSel.bottom + m_nHandleSize ));
|
|
default:
|
|
return(CreateRect(0,0,0,0));
|
|
}
|
|
}
|
|
|
|
|
|
RECT CWiaPreviewWindow::GetSelectionRect( RECT &rcSel, int iWhich )
|
|
{
|
|
switch (iWhich)
|
|
{
|
|
case HIT_LEFT:
|
|
return(CreateRect( rcSel.left-m_nHandleSize,rcSel.top-m_nHandleSize,rcSel.left+m_nHandleSize,rcSel.bottom+m_nHandleSize));
|
|
case HIT_RIGHT:
|
|
return(CreateRect( rcSel.right-m_nHandleSize, rcSel.top-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.bottom+m_nHandleSize ));
|
|
case HIT_TOP:
|
|
return(CreateRect( rcSel.left-m_nHandleSize, rcSel.top-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.top+m_nHandleSize ));
|
|
case HIT_BOTTOM:
|
|
return(CreateRect( rcSel.left-m_nHandleSize, rcSel.bottom-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.bottom+m_nHandleSize ));
|
|
default:
|
|
return(CreateRect(0,0,0,0));
|
|
}
|
|
}
|
|
|
|
|
|
POINT CWiaPreviewWindow::GetCornerPoint( int iWhich )
|
|
{
|
|
RECT rcTmp(m_rcCurrSel);
|
|
NormalizeRect(m_rcCurrSel);
|
|
POINT pt;
|
|
pt.x = pt.y = 0;
|
|
if (iWhich & HIT_TOP)
|
|
pt.y = rcTmp.top;
|
|
if (iWhich & HIT_BOTTOM)
|
|
pt.y = rcTmp.bottom;
|
|
if (iWhich & HIT_RIGHT)
|
|
pt.x = rcTmp.right;
|
|
if (iWhich & HIT_LEFT)
|
|
pt.x = rcTmp.left;
|
|
return(pt);
|
|
}
|
|
|
|
void CWiaPreviewWindow::DrawSizingFrame( HDC dc, RECT &rc, bool bHasFocus, bool bDisabled )
|
|
{
|
|
RECT rcTmp;
|
|
CopyRect(&rcTmp,&rc);
|
|
NormalizeRect(rcTmp);
|
|
|
|
int nState = Unselected;
|
|
if (bDisabled)
|
|
nState = Disabled;
|
|
else if (bHasFocus)
|
|
nState = Selected;
|
|
|
|
HPEN hOldPen = (HPEN)SelectObject(dc,m_aBorderPens[nState]);
|
|
HBRUSH hOldBrush = (HBRUSH)SelectObject(dc,GetStockObject(NULL_BRUSH));
|
|
COLORREF crOldColor = SetBkColor(dc,RGB(255,255,255));
|
|
int nOldROP2 = SetROP2(dc,R2_COPYPEN);
|
|
|
|
Rectangle(dc,rcTmp.left,rcTmp.top,rcTmp.right,rcTmp.bottom);
|
|
|
|
DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_TOPLEFT ), nState );
|
|
DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_TOPRIGHT ), nState );
|
|
DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_BOTTOMLEFT ), nState );
|
|
DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_BOTTOMRIGHT ), nState );
|
|
|
|
SetROP2(dc,nOldROP2);
|
|
SetBkColor(dc,crOldColor);
|
|
SelectObject(dc,hOldBrush);
|
|
SelectObject(dc,hOldPen);
|
|
}
|
|
|
|
bool CWiaPreviewWindow::IsAlphaBlendEnabled(void)
|
|
{
|
|
return(m_bfBlendFunction.SourceConstantAlpha != 0xFF);
|
|
}
|
|
|
|
HPALETTE CWiaPreviewWindow::SetHalftonePalette( HDC hDC )
|
|
{
|
|
if (m_hHalftonePalette)
|
|
{
|
|
HPALETTE hOldPalette = SelectPalette( hDC, m_hHalftonePalette, FALSE );
|
|
RealizePalette( hDC );
|
|
SetBrushOrgEx( hDC, 0,0, NULL );
|
|
return(hOldPalette);
|
|
}
|
|
else
|
|
{
|
|
HPALETTE hOldPalette = SelectPalette( hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE );
|
|
RealizePalette( hDC );
|
|
return(hOldPalette);
|
|
}
|
|
}
|
|
|
|
void CWiaPreviewWindow::PaintWindowTitle( HDC hDC )
|
|
{
|
|
//
|
|
// Get the length of the caption text
|
|
//
|
|
int nTextLen = (int)SendMessage( m_hWnd, WM_GETTEXTLENGTH, 0, 0 );
|
|
if (nTextLen >= 0)
|
|
{
|
|
//
|
|
// Allocate a buffer to hold it
|
|
//
|
|
LPTSTR pszText = new TCHAR[nTextLen+1];
|
|
if (pszText)
|
|
{
|
|
//
|
|
// Get the text
|
|
//
|
|
if (SendMessage( m_hWnd, WM_GETTEXT, nTextLen+1, (LPARAM)pszText ))
|
|
{
|
|
//
|
|
// Save the DC's state
|
|
//
|
|
int nDrawTextFlags = DT_CENTER|DT_NOPREFIX|DT_WORDBREAK;
|
|
COLORREF crOldTextColor = SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );
|
|
int nOldBkMode = SetBkMode( hDC, TRANSPARENT );
|
|
|
|
//
|
|
// Get the size of the image rectangle
|
|
//
|
|
RECT rcImage = GetImageRect();
|
|
RECT rcAvailable = rcImage;
|
|
|
|
//
|
|
// Leave some space for a margin
|
|
//
|
|
rcAvailable.right -= 20;
|
|
|
|
//
|
|
// Get the control's font, if there is one
|
|
//
|
|
HFONT hOldFont = NULL, hWndFont = WiaUiUtil::GetFontFromWindow( m_hWnd );
|
|
|
|
//
|
|
// Set the DC's font
|
|
//
|
|
if (hWndFont)
|
|
{
|
|
hOldFont = reinterpret_cast<HFONT>(SelectObject( hDC, hWndFont ));
|
|
}
|
|
|
|
//
|
|
// Calculate the size of the text
|
|
//
|
|
RECT rcText = {0};
|
|
if (DrawText( hDC, pszText, lstrlen(pszText), &rcAvailable, nDrawTextFlags|DT_CALCRECT ))
|
|
{
|
|
//
|
|
// add the extra margin back in and form the text rectangle
|
|
//
|
|
rcAvailable.right += 20;
|
|
|
|
//
|
|
// Calculate the text size
|
|
//
|
|
rcText.left = rcImage.left + (WiaUiUtil::RectWidth(rcImage) - WiaUiUtil::RectWidth(rcAvailable))/2;
|
|
rcText.top = rcImage.top + (WiaUiUtil::RectHeight(rcImage) - WiaUiUtil::RectHeight(rcAvailable))/2;
|
|
rcText.right = rcText.left + WiaUiUtil::RectWidth(rcAvailable);
|
|
rcText.bottom = rcText.top + WiaUiUtil::RectHeight(rcAvailable);
|
|
}
|
|
|
|
//
|
|
// See if the progress control is active
|
|
//
|
|
HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
|
|
if (hWndProgress)
|
|
{
|
|
//
|
|
// Get the window rect of the progress control
|
|
//
|
|
CSimpleRect ProgressRect( hWndProgress, CSimpleRect::WindowRect );
|
|
|
|
//
|
|
// Move the y origin of the text up
|
|
//
|
|
rcText.top = ProgressRect.ScreenToClient(m_hWnd).top - CDialogUnits(m_hWnd).Y(3) - WiaUiUtil::RectHeight(rcText);
|
|
|
|
//
|
|
// Resize the text rectangle to encompass the bottom of the progress control
|
|
//
|
|
rcText.bottom = ProgressRect.ScreenToClient(m_hWnd).bottom;
|
|
}
|
|
|
|
//
|
|
// Draw the background rectangle and the text
|
|
//
|
|
RECT rcBorder = { rcImage.left + CDialogUnits(m_hWnd).X(7), rcText.top - CDialogUnits(m_hWnd).X(3), rcImage.right - CDialogUnits(m_hWnd).X(7), rcText.bottom + CDialogUnits(m_hWnd).X(3) };
|
|
FillRect( hDC, &rcBorder, GetSysColorBrush(COLOR_WINDOW));
|
|
FrameRect( hDC, &rcBorder, GetSysColorBrush(COLOR_WINDOWFRAME));
|
|
DrawText( hDC, pszText, lstrlen(pszText), &rcText, nDrawTextFlags );
|
|
|
|
//
|
|
// Restore the DC to its original condition
|
|
//
|
|
if (hWndFont)
|
|
{
|
|
SelectObject( hDC, hOldFont );
|
|
}
|
|
SetTextColor( hDC, crOldTextColor );
|
|
SetBkMode( hDC, nOldBkMode );
|
|
}
|
|
delete[] pszText;
|
|
}
|
|
}
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnPaint( WPARAM, LPARAM )
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hDC;
|
|
RECT rcIntersection, rcImage = GetImageRect(), rcCurrentSelection;
|
|
|
|
hDC = BeginPaint(m_hWnd,&ps);
|
|
if (hDC)
|
|
{
|
|
if (!m_hBufferBitmap)
|
|
{
|
|
FillRect( hDC, &ps.rcPaint, m_hBackgroundBrush );
|
|
PaintWindowTitle( hDC );
|
|
}
|
|
else
|
|
{
|
|
// Select the halftone palette
|
|
HPALETTE hOldDCPalette = SetHalftonePalette( hDC );
|
|
HDC hdcMem = CreateCompatibleDC(hDC);
|
|
if (hdcMem)
|
|
{
|
|
HPALETTE hOldMemDCPalette = SetHalftonePalette( hdcMem );
|
|
HDC hdcBuffer = CreateCompatibleDC(hDC);
|
|
if (hdcBuffer)
|
|
{
|
|
HPALETTE hOldBufferDCPalette = SetHalftonePalette( hdcBuffer );
|
|
HBITMAP hOldBufferDCBitmap = (HBITMAP)SelectObject(hdcBuffer,m_hBufferBitmap);
|
|
|
|
CopyRect(&rcCurrentSelection,&m_rcCurrSel);
|
|
NormalizeRect(rcCurrentSelection);
|
|
if (IsDefaultSelectionRect(rcCurrentSelection))
|
|
rcCurrentSelection = rcImage;
|
|
// Prepare the double buffer bitmap by painting the selected and non-selected regions
|
|
if (m_hAlphaBitmap && m_bfBlendFunction.SourceConstantAlpha != 0xFF && !m_bPreviewMode)
|
|
{
|
|
HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject(hdcMem,m_hAlphaBitmap);
|
|
BitBlt(hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,WiaUiUtil::RectWidth(ps.rcPaint),WiaUiUtil::RectHeight(ps.rcPaint),hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
|
|
SelectObject(hdcMem,m_hPaintBitmap);
|
|
if (IntersectRect( &rcIntersection, &ps.rcPaint, &rcCurrentSelection ))
|
|
BitBlt(hdcBuffer,rcIntersection.left,rcIntersection.top,WiaUiUtil::RectWidth(rcIntersection),WiaUiUtil::RectHeight(rcIntersection),hdcMem,rcIntersection.left,rcIntersection.top,SRCCOPY);
|
|
SelectObject(hdcMem,hOldMemDCBitmap);
|
|
}
|
|
else if (m_hPaintBitmap)
|
|
{
|
|
HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject(hdcMem,m_hPaintBitmap);
|
|
BitBlt(hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,WiaUiUtil::RectWidth(ps.rcPaint),WiaUiUtil::RectHeight(ps.rcPaint),hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
|
|
SelectObject(hdcMem,hOldMemDCBitmap);
|
|
}
|
|
else
|
|
{
|
|
FillRect( hdcBuffer, &ps.rcPaint, m_hBackgroundBrush );
|
|
}
|
|
|
|
bool bDisabled = ((GetWindowLong(m_hWnd,GWL_STYLE)&WS_DISABLED) != 0);
|
|
#if defined(DITHER_DISABLED_CONTROL)
|
|
if (bDisabled)
|
|
{
|
|
// paint the disabled mask
|
|
if (IntersectRect( &rcIntersection, &rcImage, &ps.rcPaint ))
|
|
DitherRect(hdcBuffer,rcIntersection);
|
|
}
|
|
#endif // DITHER_DISABLED_CONTROL
|
|
//
|
|
// paint the selection rectangle
|
|
//
|
|
rcCurrentSelection = m_rcCurrSel;
|
|
NormalizeRect(rcCurrentSelection);
|
|
if (!IsDefaultSelectionRect( rcCurrentSelection ) && !m_bPreviewMode)
|
|
{
|
|
DrawSizingFrame( hdcBuffer, rcCurrentSelection, (GetFocus()==m_hWnd), bDisabled );
|
|
}
|
|
PaintWindowTitle( hdcBuffer );
|
|
// show it!
|
|
BitBlt( hDC, ps.rcPaint.left, ps.rcPaint.top, WiaUiUtil::RectWidth(ps.rcPaint), WiaUiUtil::RectHeight(ps.rcPaint),hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
|
|
|
|
// Paint all of the area outside the buffer bitmap
|
|
RECT rcClient;
|
|
GetClientRect( m_hWnd, &rcClient );
|
|
BITMAP bm;
|
|
if (GetObject( m_hBufferBitmap, sizeof(BITMAP), &bm ))
|
|
{
|
|
if (ps.rcPaint.right > bm.bmWidth)
|
|
{
|
|
RECT rc;
|
|
rc.left = bm.bmWidth;
|
|
rc.top = ps.rcPaint.top;
|
|
rc.right = rcClient.right;
|
|
rc.bottom = rcClient.bottom;
|
|
FillRect( hDC, &rc, m_hBackgroundBrush );
|
|
}
|
|
if (ps.rcPaint.bottom > bm.bmHeight)
|
|
{
|
|
RECT rc;
|
|
rc.left = ps.rcPaint.left;
|
|
rc.top = bm.bmHeight;
|
|
rc.right = bm.bmWidth;
|
|
rc.bottom = rcClient.bottom;
|
|
FillRect( hDC, &rc, m_hBackgroundBrush );
|
|
}
|
|
}
|
|
|
|
SelectObject( hdcBuffer, hOldBufferDCBitmap );
|
|
SelectPalette( hdcBuffer, hOldBufferDCPalette, FALSE );
|
|
DeleteDC(hdcBuffer);
|
|
}
|
|
SelectPalette( hdcMem, hOldMemDCPalette, FALSE );
|
|
DeleteDC( hdcMem );
|
|
}
|
|
SelectPalette( hDC, hOldDCPalette, FALSE );
|
|
}
|
|
EndPaint(m_hWnd,&ps);
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
|
|
BOOL CWiaPreviewWindow::RegisterClass( HINSTANCE hInstance )
|
|
{
|
|
WNDCLASS wc;
|
|
memset( &wc, 0, sizeof(wc) );
|
|
wc.style = CS_DBLCLKS;
|
|
wc.cbWndExtra = sizeof(CWiaPreviewWindow*);
|
|
wc.lpfnWndProc = WndProc;
|
|
wc.hInstance = hInstance;
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
|
wc.lpszClassName = PREVIEW_WINDOW_CLASS;
|
|
BOOL res = (::RegisterClass(&wc) != 0);
|
|
return(res != 0);
|
|
}
|
|
|
|
|
|
RECT CWiaPreviewWindow::GetImageRect(void)
|
|
{
|
|
RECT rcImg;
|
|
::GetClientRect( m_hWnd, &rcImg );
|
|
InflateRect( &rcImg, -static_cast<int>(m_nBorderSize), -static_cast<int>(m_nBorderSize) );
|
|
return(rcImg);
|
|
}
|
|
|
|
int CWiaPreviewWindow::GetHitArea( POINT &pt )
|
|
{
|
|
RECT rcTmp;
|
|
CopyRect(&rcTmp,&m_rcCurrSel);
|
|
NormalizeRect(rcTmp);
|
|
int Hit = 0;
|
|
|
|
if (PointInRect(GetSelectionRect(rcTmp,HIT_TOP),pt))
|
|
Hit |= HIT_TOP;
|
|
else if (PointInRect(GetSelectionRect(rcTmp,HIT_BOTTOM),pt))
|
|
Hit |= HIT_BOTTOM;
|
|
|
|
if (PointInRect(GetSelectionRect(rcTmp,HIT_LEFT),pt))
|
|
Hit |= HIT_LEFT;
|
|
else if (PointInRect(GetSelectionRect(rcTmp,HIT_RIGHT),pt))
|
|
Hit |= HIT_RIGHT;
|
|
|
|
if (!Hit && PointInRect(rcTmp,pt))
|
|
Hit = HIT_SELECTED;
|
|
|
|
if (!Hit && !PointInRect(GetImageRect(),pt))
|
|
Hit = HIT_BORDER;
|
|
return(Hit);
|
|
}
|
|
|
|
|
|
void CWiaPreviewWindow::NormalizeRect( RECT &r )
|
|
{
|
|
if (r.right < r.left)
|
|
{
|
|
int t = r.left;
|
|
r.left = r.right;
|
|
r.right = t;
|
|
}
|
|
if (r.bottom < r.top)
|
|
{
|
|
int t = r.top;
|
|
r.top = r.bottom;
|
|
r.bottom = t;
|
|
}
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnMouseMove( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
POINT point;
|
|
if (!m_hPreviewBitmap || m_SelectionDisabled || m_bPreviewMode)
|
|
{
|
|
SetCursor(m_hCursorArrow);
|
|
return(0);
|
|
}
|
|
point.x = (short int)LOWORD(lParam);
|
|
point.y = (short int)HIWORD(lParam);
|
|
RECT rcClient = GetImageRect();
|
|
|
|
RECT rcOldSel;
|
|
CopyRect(&rcOldSel,&m_rcCurrSel);
|
|
if (m_MovingSel != HIT_NONE)
|
|
{
|
|
switch (m_MovingSel)
|
|
{
|
|
case HIT_SELECTED:
|
|
{
|
|
int Width = WiaUiUtil::RectWidth(m_rcCurrSel);
|
|
int Height = WiaUiUtil::RectHeight(m_rcCurrSel);
|
|
if (point.x + m_Delta.cx < rcClient.left)
|
|
point.x = 0 - m_Delta.cx + rcClient.left;
|
|
else if (point.x + m_Delta.cx + Width > rcClient.right)
|
|
point.x = rcClient.right - Width - m_Delta.cx;
|
|
if (point.y + m_Delta.cy < rcClient.top)
|
|
point.y = 0 - m_Delta.cy + rcClient.top;
|
|
else if (point.y + m_Delta.cy + Height > rcClient.bottom)
|
|
point.y = rcClient.bottom - Height - m_Delta.cy;
|
|
m_rcCurrSel.left = point.x + m_Delta.cx;
|
|
m_rcCurrSel.right = m_rcCurrSel.left + Width;
|
|
m_rcCurrSel.top = point.y + m_Delta.cy;
|
|
m_rcCurrSel.bottom = m_rcCurrSel.top + Height;
|
|
}
|
|
break;
|
|
default:
|
|
if (m_MovingSel & HIT_TOP)
|
|
m_rcCurrSel.top = Boundary(point.y + m_Delta.cy,rcClient.top,rcClient.bottom);
|
|
if (m_MovingSel & HIT_BOTTOM)
|
|
m_rcCurrSel.bottom = Boundary(point.y + m_Delta.cy,rcClient.top,rcClient.bottom);
|
|
if (m_MovingSel & HIT_LEFT)
|
|
m_rcCurrSel.left = Boundary(point.x + m_Delta.cx,rcClient.left,rcClient.right);
|
|
if (m_MovingSel & HIT_RIGHT)
|
|
m_rcCurrSel.right = Boundary(point.x + m_Delta.cx,rcClient.left,rcClient.right);
|
|
break;
|
|
}
|
|
if (memcmp(&rcOldSel,&m_rcCurrSel,sizeof(RECT)))
|
|
{
|
|
RECT rcCurSel = m_rcCurrSel, rcInvalid;
|
|
NormalizeRect(rcOldSel);
|
|
NormalizeRect(rcCurSel);
|
|
TrueUnionRect(&rcInvalid,&rcCurSel,&rcOldSel);
|
|
rcInvalid.left-=m_nHandleSize;
|
|
rcInvalid.top-=m_nHandleSize;
|
|
rcInvalid.right+=m_nHandleSize;
|
|
rcInvalid.bottom+=m_nHandleSize;
|
|
SendSelChangeNotification();
|
|
Repaint(&rcInvalid,false);
|
|
UpdateWindow(m_hWnd);
|
|
}
|
|
}
|
|
int Hit;
|
|
if (m_MovingSel == HIT_NONE)
|
|
{
|
|
if (wParam & MK_CONTROL)
|
|
Hit = HIT_NONE;
|
|
else Hit = GetHitArea(point);
|
|
if (Hit == HIT_SELECTED)
|
|
SetCursor(m_hCursorMove);
|
|
else if (Hit == HIT_NONE)
|
|
SetCursor(m_hCursorCrossHairs);
|
|
else if (Hit == HIT_TOPLEFT || Hit == HIT_BOTTOMRIGHT)
|
|
SetCursor(m_hCursorSizeNwSe);
|
|
else if (Hit == HIT_TOPRIGHT || Hit == HIT_BOTTOMLEFT)
|
|
SetCursor(m_hCursorSizeNeSw);
|
|
else if (Hit == HIT_TOP || Hit == HIT_BOTTOM)
|
|
SetCursor(m_hCursorSizeNS);
|
|
else if (Hit == HIT_BORDER)
|
|
SetCursor(m_hCursorArrow);
|
|
else SetCursor(m_hCursorSizeWE);
|
|
}
|
|
else
|
|
{
|
|
Hit = m_MovingSel;
|
|
if (Hit == HIT_SELECTED)
|
|
SetCursor(m_hCursorMove);
|
|
else if (Hit == HIT_TOP || Hit == HIT_BOTTOM)
|
|
SetCursor(m_hCursorSizeNS);
|
|
else if (Hit == HIT_LEFT || Hit == HIT_RIGHT)
|
|
SetCursor(m_hCursorSizeWE);
|
|
else
|
|
{
|
|
if (m_rcCurrSel.top > m_rcCurrSel.bottom)
|
|
{
|
|
if (Hit & HIT_TOP)
|
|
{
|
|
Hit &= ~HIT_TOP;
|
|
Hit |= HIT_BOTTOM;
|
|
}
|
|
else if (Hit & HIT_BOTTOM)
|
|
{
|
|
Hit |= HIT_TOP;
|
|
Hit &= ~HIT_BOTTOM;
|
|
}
|
|
}
|
|
if (m_rcCurrSel.left > m_rcCurrSel.right)
|
|
{
|
|
if (Hit & HIT_LEFT)
|
|
{
|
|
Hit &= ~HIT_LEFT;
|
|
Hit |= HIT_RIGHT;
|
|
}
|
|
else if (Hit & HIT_RIGHT)
|
|
{
|
|
Hit |= HIT_LEFT;
|
|
Hit &= ~HIT_RIGHT;
|
|
}
|
|
}
|
|
if (Hit == HIT_TOPLEFT || Hit == HIT_BOTTOMRIGHT)
|
|
SetCursor(m_hCursorSizeNwSe);
|
|
else if (Hit == HIT_TOPRIGHT || Hit == HIT_BOTTOMLEFT)
|
|
SetCursor(m_hCursorSizeNeSw);
|
|
}
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnLButtonDown( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
|
|
return(0);
|
|
if (GetFocus() != m_hWnd)
|
|
SetFocus(m_hWnd);
|
|
POINT point;
|
|
point.x = LOWORD(lParam);
|
|
point.y = HIWORD(lParam);
|
|
int Hit = GetHitArea(point);
|
|
if (wParam & MK_CONTROL)
|
|
Hit = HIT_NONE;
|
|
if (Hit == HIT_SELECTED)
|
|
{
|
|
m_MovingSel = HIT_SELECTED;
|
|
POINT pt = GetCornerPoint(HIT_TOPLEFT);
|
|
m_Delta.cx = pt.x - point.x;
|
|
m_Delta.cy = pt.y - point.y;
|
|
SetCapture(m_hWnd);
|
|
}
|
|
else if (Hit == HIT_NONE)
|
|
{
|
|
m_MovingSel = HIT_TOPLEFT;
|
|
m_rcCurrSel.left = m_rcCurrSel.right = point.x;
|
|
m_rcCurrSel.top = m_rcCurrSel.bottom = point.y;
|
|
POINT pt = GetCornerPoint(m_MovingSel);
|
|
m_Delta.cx = pt.x - point.x;
|
|
m_Delta.cy = pt.y - point.y;
|
|
SendSelChangeNotification();
|
|
Repaint(NULL,false);
|
|
UpdateWindow(m_hWnd);
|
|
SetCapture(m_hWnd);
|
|
}
|
|
else
|
|
{
|
|
m_MovingSel = Hit;
|
|
POINT pt = GetCornerPoint(Hit);
|
|
m_Delta.cx = pt.x - point.x;
|
|
m_Delta.cy = pt.y - point.y;
|
|
SetCapture(m_hWnd);
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
void CWiaPreviewWindow::SendSelChangeNotification( bool bSetUserChangedSelection )
|
|
{
|
|
HWND hWndParent = GetParent(m_hWnd);
|
|
if (hWndParent && IsWindow(hWndParent))
|
|
{
|
|
SendNotifyMessage(hWndParent,WM_COMMAND,MAKEWPARAM(GetWindowLongPtr(m_hWnd,GWLP_ID),PWN_SELCHANGE),reinterpret_cast<LPARAM>(m_hWnd));
|
|
}
|
|
if (bSetUserChangedSelection)
|
|
{
|
|
m_bUserChangedSelection = true;
|
|
}
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnLButtonUp( WPARAM, LPARAM )
|
|
{
|
|
if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
|
|
return(0);
|
|
m_MovingSel = HIT_NONE;
|
|
ReleaseCapture();
|
|
NormalizeRect(m_rcCurrSel);
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnCreate( WPARAM, LPARAM )
|
|
{
|
|
SetWindowLong( m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL );
|
|
m_rcCurrSel = GetDefaultSelection();
|
|
CreateNewBitmaps();
|
|
return(0);
|
|
}
|
|
|
|
void CWiaPreviewWindow::CreateNewBitmaps(void)
|
|
{
|
|
DestroyBitmaps();
|
|
|
|
// No need to create the bitmaps if we have no bitmap to display
|
|
if (!m_hPreviewBitmap)
|
|
return;
|
|
|
|
// Get client window size
|
|
CSimpleRect rcClient( m_hWnd );
|
|
|
|
bool bSuccess = true;
|
|
|
|
// Get a client DC
|
|
HDC hdcClient = GetDC(m_hWnd);
|
|
if (hdcClient)
|
|
{
|
|
m_hBufferBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
|
|
if (m_hBufferBitmap)
|
|
{
|
|
m_hPaintBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
|
|
if (m_hPaintBitmap)
|
|
{
|
|
if (IsAlphaBlendEnabled())
|
|
{
|
|
m_hAlphaBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
|
|
if (!m_hAlphaBitmap)
|
|
bSuccess = false;
|
|
}
|
|
}
|
|
else bSuccess = false;
|
|
}
|
|
else bSuccess = false;
|
|
ReleaseDC(m_hWnd,hdcClient);
|
|
}
|
|
else bSuccess = false;
|
|
|
|
if (!bSuccess)
|
|
DestroyBitmaps();
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetImageSize( WPARAM, LPARAM lParam )
|
|
{
|
|
if (lParam)
|
|
{
|
|
*reinterpret_cast<SIZE*>(lParam) = m_BitmapSize;
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
bool CWiaPreviewWindow::GetOriginAndExtentInImagePixels( WORD nItem, POINT &ptOrigin, SIZE &sizeExtent )
|
|
{
|
|
SIZE sizeSavedResolution;
|
|
bool bResult = false;
|
|
if (WiaPreviewControl_GetResolution(m_hWnd,&sizeSavedResolution))
|
|
{
|
|
WiaPreviewControl_SetResolution(m_hWnd, &m_BitmapSize);
|
|
bResult = (WiaPreviewControl_GetSelOrigin( m_hWnd, nItem, 0, &ptOrigin ) && WiaPreviewControl_GetSelExtent( m_hWnd, nItem, 0, &sizeExtent ));
|
|
// Restore the old resolution
|
|
WiaPreviewControl_SetResolution(m_hWnd, &sizeSavedResolution);
|
|
}
|
|
return(bResult);
|
|
}
|
|
|
|
void CWiaPreviewWindow::DrawBitmaps(void)
|
|
{
|
|
// Don't bother painting the bitmap if we don't have an image.
|
|
if (!m_hPreviewBitmap)
|
|
return;
|
|
|
|
RECT rcImage = GetImageRect();
|
|
|
|
// Nuke old halftone palette
|
|
if (m_hHalftonePalette)
|
|
{
|
|
DeleteObject(m_hHalftonePalette);
|
|
m_hHalftonePalette = NULL;
|
|
}
|
|
|
|
// Get client window size
|
|
CSimpleRect rcClient( m_hWnd );
|
|
|
|
// Get a client DC
|
|
HDC hdcClient = GetDC(m_hWnd);
|
|
if (hdcClient)
|
|
{
|
|
// Recreate the halftone palette
|
|
m_hHalftonePalette = CreateHalftonePalette(hdcClient);
|
|
if (m_hHalftonePalette)
|
|
{
|
|
// Create a compatible dc
|
|
HDC hdcCompat = CreateCompatibleDC(hdcClient);
|
|
if (hdcCompat)
|
|
{
|
|
HBITMAP hOldBitmap = (HBITMAP)SelectObject( hdcCompat, m_hPaintBitmap );
|
|
HPALETTE hOldPalette = SetHalftonePalette( hdcCompat );
|
|
|
|
if (m_hPaintBitmap)
|
|
{
|
|
FillRect( hdcCompat, &rcClient, m_hBackgroundBrush );
|
|
|
|
HDC hdcMem = CreateCompatibleDC(hdcCompat);
|
|
if (hdcMem)
|
|
{
|
|
HPALETTE hOldMemDCPalette = SetHalftonePalette( hdcMem );
|
|
HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject( hdcMem, m_hPreviewBitmap );
|
|
int nOldStretchMode = SetStretchBltMode(hdcCompat,STRETCH_HALFTONE);
|
|
|
|
POINT ptSource = { 0, 0};
|
|
SIZE sizeSource = { m_BitmapSize.cx, m_BitmapSize.cy};
|
|
|
|
if (m_bPreviewMode)
|
|
{
|
|
POINT ptOrigin;
|
|
SIZE sizeExtent;
|
|
if (GetOriginAndExtentInImagePixels( 0, ptOrigin, sizeExtent ))
|
|
{
|
|
ptSource = ptOrigin;
|
|
sizeSource = sizeExtent;
|
|
}
|
|
}
|
|
|
|
StretchBlt(hdcCompat,rcImage.left,rcImage.top,WiaUiUtil::RectWidth(rcImage),WiaUiUtil::RectHeight(rcImage),hdcMem,ptSource.x,ptSource.y,sizeSource.cx,sizeSource.cy,SRCCOPY);
|
|
|
|
if (m_hAlphaBitmap)
|
|
{
|
|
SelectObject(hdcMem,m_hAlphaBitmap);
|
|
// First, lay down our lovely border
|
|
FillRect( hdcMem,&rcClient,m_hBackgroundBrush );
|
|
// The lay down the alpha blend background
|
|
FillRect( hdcMem,&rcImage,(HBRUSH)GetStockObject(WHITE_BRUSH) );
|
|
// Alpha blend it
|
|
AlphaBlend(hdcMem,rcImage.left,rcImage.top,WiaUiUtil::RectWidth(rcImage),WiaUiUtil::RectHeight(rcImage),hdcCompat,rcImage.left,rcImage.top,WiaUiUtil::RectWidth(rcImage),WiaUiUtil::RectHeight(rcImage),m_bfBlendFunction);
|
|
}
|
|
|
|
//
|
|
// Restore DC state and delete DC
|
|
//
|
|
SelectPalette(hdcMem,hOldMemDCPalette,FALSE);
|
|
SetStretchBltMode(hdcCompat,nOldStretchMode);
|
|
SelectObject(hdcMem,hOldMemDCBitmap);
|
|
DeleteDC(hdcMem);
|
|
}
|
|
}
|
|
//
|
|
// Restore DC state and delete DC
|
|
//
|
|
SelectObject( hdcCompat, hOldBitmap );
|
|
SelectPalette( hdcCompat, hOldPalette, FALSE );
|
|
DeleteDC(hdcCompat);
|
|
}
|
|
}
|
|
ReleaseDC(m_hWnd,hdcClient);
|
|
}
|
|
}
|
|
|
|
#ifndef RECT_WIDTH
|
|
#define RECT_WIDTH(x) ((x).right - (x).left)
|
|
#endif
|
|
|
|
#ifndef RECT_HEIGHT
|
|
#define RECT_HEIGHT(x) ((x).bottom - (x).top)
|
|
#endif
|
|
|
|
RECT CWiaPreviewWindow::ScaleSelectionRect( const RECT &rcOriginalImage, const RECT &rcCurrentImage, const RECT &rcOriginalSel )
|
|
{
|
|
RECT rcCurrentSel;
|
|
if (IsDefaultSelectionRect(rcOriginalSel))
|
|
return(rcOriginalSel);
|
|
if (RECT_WIDTH(rcOriginalImage) && RECT_HEIGHT(rcOriginalImage))
|
|
{
|
|
rcCurrentSel.left = rcCurrentImage.left + MulDiv(rcOriginalSel.left-rcOriginalImage.left,RECT_WIDTH(rcCurrentImage),RECT_WIDTH(rcOriginalImage));
|
|
rcCurrentSel.right = rcCurrentImage.left + MulDiv(rcOriginalSel.right-rcOriginalImage.left,RECT_WIDTH(rcCurrentImage),RECT_WIDTH(rcOriginalImage));
|
|
rcCurrentSel.top = rcCurrentImage.top + MulDiv(rcOriginalSel.top-rcOriginalImage.top,RECT_HEIGHT(rcCurrentImage),RECT_HEIGHT(rcOriginalImage));
|
|
rcCurrentSel.bottom = rcCurrentImage.top + MulDiv(rcOriginalSel.bottom-rcOriginalImage.top,RECT_HEIGHT(rcCurrentImage),RECT_HEIGHT(rcOriginalImage));
|
|
}
|
|
else rcCurrentSel = GetDefaultSelection();
|
|
// If we're gone, start over with max selection
|
|
if (rcCurrentSel.left >= rcCurrentSel.right || rcCurrentSel.top >= rcCurrentSel.bottom)
|
|
{
|
|
rcCurrentSel = GetDefaultSelection();
|
|
}
|
|
NormalizeRect(rcCurrentSel);
|
|
if (rcCurrentSel.left < rcCurrentImage.left)
|
|
rcCurrentSel.left = rcCurrentImage.left;
|
|
if (rcCurrentSel.top < rcCurrentImage.top)
|
|
rcCurrentSel.top = rcCurrentImage.top;
|
|
if (rcCurrentSel.right > rcCurrentImage.right)
|
|
rcCurrentSel.right = rcCurrentImage.right;
|
|
if (rcCurrentSel.bottom > rcCurrentImage.bottom)
|
|
rcCurrentSel.bottom = rcCurrentImage.bottom;
|
|
return(rcCurrentSel);
|
|
}
|
|
|
|
|
|
LRESULT CWiaPreviewWindow::OnSize( WPARAM wParam, LPARAM )
|
|
{
|
|
int nType = (int)wParam;
|
|
if ((nType == SIZE_RESTORED || nType == SIZE_MAXIMIZED))
|
|
{
|
|
//
|
|
// Resize the progress control if it exists
|
|
//
|
|
ResizeProgressBar();
|
|
if (!m_bSizing)
|
|
{
|
|
RECT rcCurrentImageRect = GetImageRect();
|
|
m_rcCurrSel = ScaleSelectionRect( m_rcSavedImageRect, rcCurrentImageRect, m_rcCurrSel );
|
|
m_rcSavedImageRect = rcCurrentImageRect;
|
|
CreateNewBitmaps();
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
SendSelChangeNotification(false);
|
|
}
|
|
else Repaint(NULL,false);
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetText( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LRESULT lResult = DefWindowProc( m_hWnd, WM_SETTEXT, wParam, lParam );
|
|
InvalidateRect( m_hWnd, NULL, FALSE );
|
|
UpdateWindow( m_hWnd );
|
|
return(lResult);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetDlgCode( WPARAM, LPARAM )
|
|
{
|
|
return(LRESULT)(DLGC_WANTARROWS);
|
|
}
|
|
|
|
|
|
LRESULT CWiaPreviewWindow::OnKeyDown( WPARAM wParam, LPARAM )
|
|
{
|
|
if (!m_hPreviewBitmap || m_SelectionDisabled || m_bPreviewMode || IsDefaultSelectionRect(m_rcCurrSel))
|
|
return(0);
|
|
int nVirtKey = (int)wParam;
|
|
int nAccelerate = 1;
|
|
if (GetKeyState(VK_CONTROL) & 0x8000)
|
|
nAccelerate = DEFAULT_ACCEL_FACTOR;
|
|
RECT rcImage = GetImageRect(), rcOldCurrSel;
|
|
CopyRect(&rcOldCurrSel,&m_rcCurrSel);
|
|
// If SHIFT key is pressed, but ALT is not
|
|
if (!(GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_SHIFT) & 0x8000))
|
|
{
|
|
switch (nVirtKey)
|
|
{
|
|
case VK_UP:
|
|
if (m_rcCurrSel.bottom > m_rcCurrSel.top+nAccelerate)
|
|
m_rcCurrSel.bottom -= nAccelerate;
|
|
else m_rcCurrSel.bottom = m_rcCurrSel.top;
|
|
break;
|
|
case VK_DOWN:
|
|
m_rcCurrSel.bottom += nAccelerate;
|
|
if (m_rcCurrSel.bottom > rcImage.bottom)
|
|
m_rcCurrSel.bottom = rcImage.bottom;
|
|
break;
|
|
case VK_RIGHT:
|
|
m_rcCurrSel.right += nAccelerate;
|
|
if (m_rcCurrSel.right > rcImage.right)
|
|
m_rcCurrSel.right = rcImage.right;
|
|
break;
|
|
case VK_LEFT:
|
|
if (m_rcCurrSel.right > m_rcCurrSel.left+nAccelerate)
|
|
m_rcCurrSel.right -= nAccelerate;
|
|
else m_rcCurrSel.right = m_rcCurrSel.left;
|
|
break;
|
|
}
|
|
}
|
|
// If SHIFT key not is pressed and ALT is not
|
|
if (!(GetKeyState(VK_MENU) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000))
|
|
{
|
|
switch (nVirtKey)
|
|
{
|
|
case VK_DELETE:
|
|
m_rcCurrSel = GetDefaultSelection();
|
|
break;
|
|
case VK_HOME:
|
|
OffsetRect( &m_rcCurrSel, rcImage.left-m_rcCurrSel.left, 0 );
|
|
break;
|
|
case VK_END:
|
|
OffsetRect( &m_rcCurrSel, rcImage.right-m_rcCurrSel.right, 0 );
|
|
break;
|
|
case VK_PRIOR:
|
|
OffsetRect( &m_rcCurrSel, 0, rcImage.top-m_rcCurrSel.top );
|
|
break;
|
|
case VK_NEXT:
|
|
OffsetRect( &m_rcCurrSel, 0, rcImage.bottom-m_rcCurrSel.bottom );
|
|
break;
|
|
case VK_UP:
|
|
OffsetRect(&m_rcCurrSel,0,-nAccelerate);
|
|
if (m_rcCurrSel.top < rcImage.top)
|
|
OffsetRect(&m_rcCurrSel,0,-m_rcCurrSel.top+rcImage.top);
|
|
break;
|
|
case VK_LEFT:
|
|
OffsetRect(&m_rcCurrSel,-nAccelerate,0);
|
|
if (m_rcCurrSel.left < rcImage.left)
|
|
OffsetRect(&m_rcCurrSel,-m_rcCurrSel.left+rcImage.left,0);
|
|
break;
|
|
case VK_DOWN:
|
|
OffsetRect(&m_rcCurrSel,0,nAccelerate);
|
|
if (m_rcCurrSel.bottom > rcImage.bottom)
|
|
OffsetRect(&m_rcCurrSel,0,-(m_rcCurrSel.bottom-rcImage.bottom));
|
|
break;
|
|
case VK_RIGHT:
|
|
OffsetRect(&m_rcCurrSel,nAccelerate,0);
|
|
if (m_rcCurrSel.right > rcImage.right)
|
|
OffsetRect(&m_rcCurrSel,-(m_rcCurrSel.right-rcImage.right),0);
|
|
break;
|
|
}
|
|
}
|
|
if (IsDefaultSelectionRect(m_rcCurrSel))
|
|
{
|
|
InvalidateRect( m_hWnd, NULL, FALSE );
|
|
UpdateWindow( m_hWnd );
|
|
SendSelChangeNotification();
|
|
}
|
|
else if (memcmp(&rcOldCurrSel,&m_rcCurrSel,sizeof(RECT)))
|
|
{
|
|
RECT rcCurSel = m_rcCurrSel, rcInvalid;
|
|
NormalizeRect(rcOldCurrSel);
|
|
NormalizeRect(rcCurSel);
|
|
TrueUnionRect(&rcInvalid,&rcCurSel,&rcOldCurrSel);
|
|
rcInvalid.left-=m_nHandleSize;
|
|
rcInvalid.top-=m_nHandleSize;
|
|
rcInvalid.right+=m_nHandleSize;
|
|
rcInvalid.bottom+=m_nHandleSize;
|
|
Repaint(&rcInvalid,false);
|
|
UpdateWindow(m_hWnd);
|
|
SendSelChangeNotification();
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
|
|
//wParam = 0, lParam = LPSIZE lpResolution
|
|
LRESULT CWiaPreviewWindow::OnSetResolution( WPARAM, LPARAM lParam )
|
|
{
|
|
if (lParam)
|
|
{
|
|
m_Resolution = *((LPSIZE)lParam);
|
|
}
|
|
else
|
|
{
|
|
m_Resolution.cx = m_Resolution.cy = 0;
|
|
}
|
|
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
//wParam = 0, lParam = LPSIZE lpResolution
|
|
LRESULT CWiaPreviewWindow::OnGetResolution( WPARAM, LPARAM lParam )
|
|
{
|
|
if (lParam)
|
|
{
|
|
*reinterpret_cast<SIZE*>(lParam) = m_Resolution;
|
|
return(LRESULT)1;
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
//wParam = 0, lParam = LPRECT lprcSelRect
|
|
LRESULT CWiaPreviewWindow::OnClearSelection( WPARAM, LPARAM )
|
|
{
|
|
m_rcCurrSel = GetDefaultSelection();
|
|
Repaint(NULL,false);
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
// wParam = (BOOL)MAKEWPARAM(bRepaint,bDontDestroy), lParam = (HBITMAP)hBmp
|
|
LRESULT CWiaPreviewWindow::OnSetBitmap( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
if (m_bDeleteBitmap && m_hPreviewBitmap)
|
|
DeleteObject(m_hPreviewBitmap);
|
|
|
|
m_hPreviewBitmap = (HBITMAP)lParam;
|
|
|
|
m_BitmapSize.cx = m_BitmapSize.cy = 0;
|
|
if (m_hPreviewBitmap)
|
|
{
|
|
BITMAP bm = {0};
|
|
if (GetObject(m_hPreviewBitmap,sizeof(BITMAP),&bm))
|
|
{
|
|
m_BitmapSize.cx = bm.bmWidth;
|
|
m_BitmapSize.cy = bm.bmHeight;
|
|
}
|
|
}
|
|
|
|
m_bDeleteBitmap = !HIWORD(wParam);
|
|
|
|
if (!m_hPaintBitmap || !m_hBufferBitmap || (!m_hAlphaBitmap && IsAlphaBlendEnabled()))
|
|
{
|
|
CreateNewBitmaps();
|
|
}
|
|
DrawBitmaps();
|
|
if (LOWORD(wParam))
|
|
{
|
|
Repaint(NULL,false);
|
|
}
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
|
|
// wParam = 0, lParam = 0
|
|
LRESULT CWiaPreviewWindow::OnGetBitmap( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
return(LRESULT)m_hPreviewBitmap;
|
|
}
|
|
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetFocus( WPARAM, LPARAM )
|
|
{
|
|
// If the rect isn't visible, recreate it.
|
|
if (m_rcCurrSel.left == m_rcCurrSel.right || m_rcCurrSel.top == m_rcCurrSel.bottom && !IsDefaultSelectionRect(m_rcCurrSel))
|
|
{
|
|
m_rcCurrSel = GetDefaultSelection();
|
|
}
|
|
Repaint(NULL,false);
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnKillFocus( WPARAM, LPARAM )
|
|
{
|
|
Repaint(NULL,false);
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnEnable( WPARAM, LPARAM )
|
|
{
|
|
Repaint(NULL,false);
|
|
return(LRESULT)0;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnEraseBkgnd( WPARAM, LPARAM )
|
|
{
|
|
return(LRESULT)1;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetBorderSize( WPARAM, LPARAM )
|
|
{
|
|
return(m_nBorderSize);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetHandleSize( WPARAM, LPARAM )
|
|
{
|
|
return(m_nHandleSize);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetBgAlpha( WPARAM, LPARAM )
|
|
{
|
|
return(m_bfBlendFunction.SourceConstantAlpha);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetHandleType( WPARAM, LPARAM )
|
|
{
|
|
return(m_nHandleType);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetBorderSize( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nOldBorder = m_nBorderSize;
|
|
m_nBorderSize = (UINT)lParam;
|
|
if (wParam)
|
|
{
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
}
|
|
return(nOldBorder);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetHandleSize( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nOldHandleSize = m_nHandleSize;
|
|
m_nHandleSize = (int)lParam;
|
|
if (wParam)
|
|
Repaint(NULL,false);
|
|
return(nOldHandleSize);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetBgAlpha( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nOldBgAlpha = m_bfBlendFunction.SourceConstantAlpha;
|
|
m_bfBlendFunction.SourceConstantAlpha = (BYTE)lParam;
|
|
if (wParam)
|
|
{
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
}
|
|
return(nOldBgAlpha);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetHandleType( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nOldHandleType = m_nHandleType;
|
|
m_nHandleType = (int)lParam;
|
|
if (wParam)
|
|
Repaint(NULL,false);
|
|
return(nOldHandleType);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnEnterSizeMove( WPARAM, LPARAM )
|
|
{
|
|
m_bSizing = true;
|
|
return(0);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnExitSizeMove( WPARAM, LPARAM )
|
|
{
|
|
if (m_bSizing)
|
|
{
|
|
m_bSizing = false;
|
|
RECT rcCurrentImageRect = GetImageRect();
|
|
if (memcmp(&rcCurrentImageRect,&m_rcSavedImageRect,sizeof(RECT)))
|
|
{
|
|
m_rcCurrSel = ScaleSelectionRect( m_rcSavedImageRect, rcCurrentImageRect, m_rcCurrSel );
|
|
m_rcSavedImageRect = rcCurrentImageRect;
|
|
CreateNewBitmaps();
|
|
DrawBitmaps();
|
|
SendSelChangeNotification(false);
|
|
}
|
|
Repaint(NULL,false);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PPOINT)pOrigin
|
|
LRESULT CWiaPreviewWindow::OnGetSelOrigin( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
|
|
int nItem = (int)LOWORD(wParam);
|
|
BOOL bPhysical = (BOOL)HIWORD(wParam);
|
|
PPOINT pOrigin = (PPOINT)lParam;
|
|
RECT rcImage = GetImageRect();
|
|
if (nCount <= 0 || nItem < 0 || nItem >= nCount || !pOrigin)
|
|
return(0);
|
|
RECT rcSel = m_rcCurrSel;
|
|
NormalizeRect(rcSel);
|
|
if (IsRectEmpty(&rcSel))
|
|
rcSel = rcImage;
|
|
if (bPhysical)
|
|
{
|
|
pOrigin->x = rcSel.left - rcImage.left;
|
|
pOrigin->y = rcSel.top - rcImage.top;
|
|
return(1);
|
|
}
|
|
else if (RECT_WIDTH(rcImage) && RECT_HEIGHT(rcImage)) // Make sure we get no divide by zero errors
|
|
{
|
|
pOrigin->x = WiaUiUtil::MulDivNoRound(m_Resolution.cx,rcSel.left-rcImage.left,RECT_WIDTH(rcImage));
|
|
pOrigin->y = WiaUiUtil::MulDivNoRound(m_Resolution.cy,rcSel.top-rcImage.top,RECT_HEIGHT(rcImage));
|
|
return(1);
|
|
}
|
|
else return(0);
|
|
}
|
|
|
|
// wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PSIZE)pExtent
|
|
LRESULT CWiaPreviewWindow::OnGetSelExtent( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
|
|
int nItem = (int)LOWORD(wParam);
|
|
BOOL bPhysical = (BOOL)HIWORD(wParam);
|
|
PSIZE pExtent = (PSIZE)lParam;
|
|
RECT rcImage = GetImageRect();
|
|
if (nCount <= 0 || nItem < 0 || nItem >= nCount || !pExtent)
|
|
return(0);
|
|
RECT rcSel = m_rcCurrSel;
|
|
NormalizeRect(rcSel);
|
|
if (IsRectEmpty(&rcSel))
|
|
rcSel = rcImage;
|
|
if (bPhysical)
|
|
{
|
|
pExtent->cx = RECT_WIDTH(rcSel);
|
|
pExtent->cy = RECT_HEIGHT(rcSel);
|
|
return(1);
|
|
}
|
|
else if (RECT_WIDTH(rcImage) && RECT_HEIGHT(rcImage)) // Make sure we get no divide by zero errors
|
|
{
|
|
pExtent->cx = WiaUiUtil::MulDivNoRound(m_Resolution.cx,RECT_WIDTH(rcSel),RECT_WIDTH(rcImage));
|
|
pExtent->cy = WiaUiUtil::MulDivNoRound(m_Resolution.cy,RECT_HEIGHT(rcSel),RECT_HEIGHT(rcImage));
|
|
return(1);
|
|
}
|
|
else return(0);
|
|
}
|
|
|
|
|
|
// wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PPOINT)pOrigin
|
|
LRESULT CWiaPreviewWindow::OnSetSelOrigin( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
|
|
int nItem = (int)LOWORD(wParam);
|
|
BOOL bPhysical = (BOOL)HIWORD(wParam);
|
|
PPOINT pOrigin = (PPOINT)lParam;
|
|
RECT rcImage = GetImageRect();
|
|
if (nCount <= 0 || nItem < 0 || nItem >= nCount)
|
|
{
|
|
return(0);
|
|
}
|
|
else if (!pOrigin)
|
|
{
|
|
m_rcCurrSel = rcImage;
|
|
Repaint( NULL, FALSE );
|
|
return(1);
|
|
}
|
|
else if (bPhysical)
|
|
{
|
|
m_rcCurrSel.left = rcImage.left + pOrigin->x;
|
|
m_rcCurrSel.top = rcImage.top + pOrigin->y;
|
|
Repaint( NULL, FALSE );
|
|
return(1);
|
|
}
|
|
else if (m_Resolution.cx && m_Resolution.cy) // Make sure we get no divide by zero errors
|
|
{
|
|
m_rcCurrSel.left = rcImage.left + MulDiv(pOrigin->x,RECT_WIDTH(rcImage),m_Resolution.cx);
|
|
m_rcCurrSel.top = rcImage.top + MulDiv(pOrigin->y,RECT_HEIGHT(rcImage),m_Resolution.cy);
|
|
Repaint( NULL, FALSE );
|
|
return(1);
|
|
}
|
|
else return(0);
|
|
}
|
|
|
|
// wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PSIZE)pExtent
|
|
LRESULT CWiaPreviewWindow::OnSetSelExtent( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
|
|
int nItem = static_cast<int>(LOWORD(wParam));
|
|
BOOL bPhysical = (BOOL)HIWORD(wParam);
|
|
PSIZE pExtent = (PSIZE)lParam;
|
|
RECT rcImage = GetImageRect();
|
|
if (nCount <= 0 || nItem < 0 || nItem >= nCount)
|
|
{
|
|
return(0);
|
|
}
|
|
else if (!pExtent)
|
|
{
|
|
m_rcCurrSel = rcImage;
|
|
Repaint( NULL, FALSE );
|
|
return(1);
|
|
}
|
|
else if (bPhysical)
|
|
{
|
|
m_rcCurrSel.right = m_rcCurrSel.left + pExtent->cx;
|
|
m_rcCurrSel.bottom = m_rcCurrSel.top + pExtent->cy;
|
|
Repaint(NULL,FALSE);
|
|
return(1);
|
|
}
|
|
else if (m_Resolution.cx && m_Resolution.cy) // Make sure we get no divide by zero errors
|
|
{
|
|
m_rcCurrSel.right = m_rcCurrSel.left + MulDiv(pExtent->cx,RECT_WIDTH(rcImage),m_Resolution.cx);
|
|
m_rcCurrSel.bottom = m_rcCurrSel.top + MulDiv(pExtent->cy,RECT_HEIGHT(rcImage),m_Resolution.cy);
|
|
Repaint( NULL, FALSE );
|
|
return(1);
|
|
}
|
|
else return(0);
|
|
}
|
|
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetSelCount( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
return(GetSelectionRectCount()); // For now...
|
|
}
|
|
|
|
BOOL CWiaPreviewWindow::IsDefaultSelectionRect( const RECT &rc )
|
|
{
|
|
if (!m_bAllowNullSelection)
|
|
return(FALSE);
|
|
RECT rcSel = rc;
|
|
NormalizeRect(rcSel);
|
|
RECT rcDefault = GetDefaultSelection();
|
|
return(rcSel.left == rcDefault.left &&
|
|
rcSel.top == rcDefault.top &&
|
|
rcSel.right == rcDefault.right &&
|
|
rcSel.bottom == rcDefault.bottom);
|
|
}
|
|
|
|
RECT CWiaPreviewWindow::GetDefaultSelection(void)
|
|
{
|
|
if (m_bAllowNullSelection)
|
|
{
|
|
RECT r = {-100,-100,-100,-100};
|
|
return(r);
|
|
}
|
|
else return(GetImageRect());
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetAllowNullSelection( WPARAM, LPARAM )
|
|
{
|
|
return(m_bAllowNullSelection != FALSE);
|
|
}
|
|
|
|
// wParam = (BOOL)bAllowNullSelection, lParam = 0
|
|
LRESULT CWiaPreviewWindow::OnSetAllowNullSelection( WPARAM wParam, LPARAM )
|
|
{
|
|
BOOL bOldAllowNullSelection = m_bAllowNullSelection;
|
|
if (wParam)
|
|
m_bAllowNullSelection = TRUE;
|
|
else m_bAllowNullSelection = FALSE;
|
|
return(bOldAllowNullSelection);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetDisableSelection( WPARAM, LPARAM )
|
|
{
|
|
return(m_SelectionDisabled != FALSE);
|
|
}
|
|
|
|
// wParam = (BOOL)bDisableSelection, lParam = 0
|
|
LRESULT CWiaPreviewWindow::OnSetDisableSelection( WPARAM wParam, LPARAM )
|
|
{
|
|
BOOL bReturn = (m_SelectionDisabled != FALSE);
|
|
m_SelectionDisabled = (wParam != 0);
|
|
Repaint(NULL,false);
|
|
return(bReturn);
|
|
}
|
|
|
|
|
|
int CWiaPreviewWindow::GetSelectionRectCount(void)
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
// wParam = 0, lParam = 0
|
|
LRESULT CWiaPreviewWindow::OnGetBkColor( WPARAM, LPARAM )
|
|
{
|
|
LOGBRUSH lb = { 0};
|
|
GetObject(m_hBackgroundBrush,sizeof(LOGBRUSH),&lb);
|
|
return(lb.lbColor);
|
|
}
|
|
|
|
// wParam = (BOOL)bRepaint, lParam = (COLORREF)color
|
|
LRESULT CWiaPreviewWindow::OnSetBkColor( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HBRUSH hBrush = CreateSolidBrush( static_cast<int>(lParam) );
|
|
if (hBrush)
|
|
{
|
|
if (m_hBackgroundBrush)
|
|
{
|
|
DeleteObject(m_hBackgroundBrush);
|
|
m_hBackgroundBrush = NULL;
|
|
}
|
|
m_hBackgroundBrush = hBrush;
|
|
if (wParam)
|
|
{
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
}
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetPreviewMode( WPARAM, LPARAM lParam )
|
|
{
|
|
m_bPreviewMode = (lParam != FALSE);
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
return(0);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnRefreshBitmap( WPARAM, LPARAM )
|
|
{
|
|
DrawBitmaps();
|
|
Repaint(NULL,false);
|
|
return(0);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetPreviewMode( WPARAM, LPARAM )
|
|
{
|
|
return(m_bPreviewMode != false);
|
|
}
|
|
|
|
void CWiaPreviewWindow::SetCursor( HCURSOR hCursor )
|
|
{
|
|
m_hCurrentCursor = hCursor;
|
|
::SetCursor(m_hCurrentCursor);
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetCursor( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
if (reinterpret_cast<HWND>(wParam) == m_hWnd && m_hCurrentCursor)
|
|
{
|
|
::SetCursor(m_hCurrentCursor);
|
|
return(TRUE);
|
|
}
|
|
else return(DefWindowProc( m_hWnd, WM_SETCURSOR, wParam, lParam ));
|
|
}
|
|
|
|
// wParam = MAKEWPARAM(bRepaint,0), lParam = MAKELPARAM(nBorderStyle,nBorderThickness)
|
|
LRESULT CWiaPreviewWindow::OnSetBorderStyle( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
// Recreate the handle border pens. Don't apply the line style, just the thickness.
|
|
for (int i=0;i<ARRAYSIZE(m_aHandlePens);i++)
|
|
{
|
|
LOGPEN LogPen;
|
|
ZeroMemory(&LogPen,sizeof(LOGPEN));
|
|
if (GetObject( m_aHandlePens[i], sizeof(LOGPEN), &LogPen ))
|
|
{
|
|
LogPen.lopnWidth.x = HIWORD(lParam);
|
|
if (m_aHandlePens[i])
|
|
DeleteObject(m_aHandlePens[i]);
|
|
m_aHandlePens[i] = CreatePenIndirect(&LogPen);
|
|
}
|
|
}
|
|
|
|
// Recreate the selection border pens. Apply the line style, just the thickness.
|
|
for (i=0;i<ARRAYSIZE(m_aBorderPens);i++)
|
|
{
|
|
LOGPEN LogPen;
|
|
ZeroMemory(&LogPen,sizeof(LOGPEN));
|
|
if (GetObject( m_aBorderPens[i], sizeof(LOGPEN), &LogPen ))
|
|
{
|
|
LogPen.lopnWidth.x = (UINT)HIWORD(lParam);
|
|
LogPen.lopnStyle = LOWORD(lParam);
|
|
if (m_aBorderPens[i])
|
|
DeleteObject(m_aBorderPens[i]);
|
|
m_aBorderPens[i] = CreatePenIndirect(&LogPen);
|
|
}
|
|
}
|
|
|
|
if (LOWORD(wParam))
|
|
{
|
|
Repaint(NULL,FALSE);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// wParam = MAKEWPARAM(bRepaint,nState), lParam = (COLORREF)crColor
|
|
LRESULT CWiaPreviewWindow::OnSetBorderColor( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nState = static_cast<int>(HIWORD(wParam));
|
|
if (nState >= 0 && nState < 3)
|
|
{
|
|
LOGPEN LogPen;
|
|
ZeroMemory(&LogPen,sizeof(LOGPEN));
|
|
if (GetObject( m_aHandlePens[nState], sizeof(LOGPEN), &LogPen ))
|
|
{
|
|
LogPen.lopnColor = static_cast<COLORREF>(lParam);
|
|
if (m_aHandlePens[nState])
|
|
DeleteObject(m_aHandlePens[nState]);
|
|
m_aHandlePens[nState] = CreatePenIndirect(&LogPen);
|
|
}
|
|
ZeroMemory(&LogPen,sizeof(LOGPEN));
|
|
if (GetObject( m_aBorderPens[nState], sizeof(LOGPEN), &LogPen ))
|
|
{
|
|
LogPen.lopnColor = static_cast<COLORREF>(lParam);
|
|
if (m_aBorderPens[nState])
|
|
DeleteObject(m_aBorderPens[nState]);
|
|
m_aBorderPens[nState] = CreatePenIndirect(&LogPen);
|
|
}
|
|
}
|
|
if (LOWORD(wParam))
|
|
{
|
|
Repaint(NULL,FALSE);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// wParam = MAKEWPARAM(bRepaint,nState), lParam = (COLORREF)crColor
|
|
LRESULT CWiaPreviewWindow::OnSetHandleColor( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nState = static_cast<int>(HIWORD(wParam));
|
|
if (nState >= 0 && nState < 3)
|
|
{
|
|
if (m_aHandleBrushes[nState])
|
|
{
|
|
DeleteObject(m_aHandleBrushes[nState]);
|
|
m_aHandleBrushes[nState] = NULL;
|
|
}
|
|
m_aHandleBrushes[nState] = CreateSolidBrush( static_cast<COLORREF>(lParam) );
|
|
}
|
|
if (LOWORD(wParam))
|
|
{
|
|
Repaint(NULL,FALSE);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void CWiaPreviewWindow::ResizeProgressBar()
|
|
{
|
|
HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
|
|
if (hWndProgress)
|
|
{
|
|
//
|
|
// Resize the progress control to fill the client
|
|
//
|
|
RECT rcImage = GetImageRect();
|
|
|
|
CDialogUnits DialogUnits( m_hWnd );
|
|
|
|
SIZE sizeProgress = { WiaUiUtil::RectWidth(rcImage) - DialogUnits.X(28), DialogUnits.Y(14) };
|
|
POINT ptProgress = { rcImage.left + (WiaUiUtil::RectWidth(rcImage) - sizeProgress.cx) / 2, rcImage.top + (WiaUiUtil::RectHeight(rcImage) - sizeProgress.cy) / 2 };
|
|
|
|
MoveWindow( hWndProgress, ptProgress.x, ptProgress.y, sizeProgress.cx, sizeProgress.cy, TRUE );
|
|
}
|
|
}
|
|
|
|
//
|
|
// wParam = bShow
|
|
//
|
|
LRESULT CWiaPreviewWindow::OnSetProgress( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
//
|
|
// Assume failure
|
|
//
|
|
LRESULT lResult = FALSE;
|
|
|
|
//
|
|
// If wParam is true, create the control
|
|
//
|
|
if (wParam)
|
|
{
|
|
//
|
|
// See if the control is already created.
|
|
//
|
|
HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
|
|
if (!hWndProgress)
|
|
{
|
|
//
|
|
// If it isn't, create it.
|
|
//
|
|
hWndProgress = CreateWindow( PROGRESS_CLASS, TEXT(""), WS_CHILD|WS_VISIBLE|PBS_MARQUEE, 0, 0, 0, 0, m_hWnd, reinterpret_cast<HMENU>(IDC_PROGRESSCONTROL), NULL, NULL );
|
|
if (hWndProgress)
|
|
{
|
|
//
|
|
// Put it in marquee mode
|
|
//
|
|
SendMessage( hWndProgress, PBM_SETMARQUEE, TRUE, 100 );
|
|
|
|
//
|
|
// Resize it
|
|
//
|
|
ResizeProgressBar();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Success = we have a progress bar
|
|
//
|
|
lResult = (hWndProgress != NULL);
|
|
}
|
|
//
|
|
// Otherwise, destroy the control if it exists
|
|
//
|
|
else
|
|
{
|
|
HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
|
|
if (hWndProgress)
|
|
{
|
|
//
|
|
// Nuke it
|
|
//
|
|
DestroyWindow(hWndProgress);
|
|
|
|
}
|
|
|
|
lResult = true;
|
|
}
|
|
|
|
//
|
|
// Force a repaint
|
|
//
|
|
InvalidateRect( m_hWnd, NULL, FALSE );
|
|
UpdateWindow(m_hWnd);
|
|
|
|
return lResult;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetProgress( WPARAM, LPARAM )
|
|
{
|
|
return (NULL != GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL ));
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnCtlColorStatic( WPARAM wParam, LPARAM )
|
|
{
|
|
SetBkColor( reinterpret_cast<HDC>( wParam ), GetSysColor( COLOR_WINDOW ) );
|
|
return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW));
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnSetUserChangedSelection( WPARAM wParam, LPARAM )
|
|
{
|
|
LRESULT lRes = m_bUserChangedSelection;
|
|
m_bUserChangedSelection = (wParam != 0);
|
|
return lRes;
|
|
}
|
|
|
|
LRESULT CWiaPreviewWindow::OnGetUserChangedSelection( WPARAM, LPARAM )
|
|
{
|
|
return static_cast<LRESULT>(m_bUserChangedSelection);
|
|
}
|
|
|
|
LRESULT CALLBACK CWiaPreviewWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
SC_BEGIN_MESSAGE_HANDLERS(CWiaPreviewWindow)
|
|
{
|
|
SC_HANDLE_MESSAGE( WM_CREATE, OnCreate );
|
|
SC_HANDLE_MESSAGE( WM_ERASEBKGND, OnEraseBkgnd );
|
|
SC_HANDLE_MESSAGE( WM_PAINT, OnPaint );
|
|
SC_HANDLE_MESSAGE( WM_MOUSEMOVE, OnMouseMove );
|
|
SC_HANDLE_MESSAGE( WM_LBUTTONDOWN, OnLButtonDown );
|
|
SC_HANDLE_MESSAGE( WM_LBUTTONUP, OnLButtonUp );
|
|
SC_HANDLE_MESSAGE( WM_LBUTTONDBLCLK , OnLButtonDblClk );
|
|
SC_HANDLE_MESSAGE( WM_SIZE, OnSize );
|
|
SC_HANDLE_MESSAGE( WM_GETDLGCODE, OnGetDlgCode );
|
|
SC_HANDLE_MESSAGE( WM_KEYDOWN, OnKeyDown );
|
|
SC_HANDLE_MESSAGE( WM_SETFOCUS, OnSetFocus );
|
|
SC_HANDLE_MESSAGE( WM_KILLFOCUS, OnKillFocus );
|
|
SC_HANDLE_MESSAGE( WM_ENABLE, OnEnable );
|
|
SC_HANDLE_MESSAGE( WM_SETTEXT, OnSetText );
|
|
SC_HANDLE_MESSAGE( WM_SETCURSOR, OnSetCursor );
|
|
SC_HANDLE_MESSAGE( WM_CTLCOLORSTATIC, OnCtlColorStatic );
|
|
SC_HANDLE_MESSAGE( PWM_CLEARSELECTION, OnClearSelection );
|
|
SC_HANDLE_MESSAGE( PWM_SETRESOLUTION, OnSetResolution );
|
|
SC_HANDLE_MESSAGE( PWM_GETRESOLUTION, OnGetResolution );
|
|
SC_HANDLE_MESSAGE( PWM_SETBITMAP, OnSetBitmap );
|
|
SC_HANDLE_MESSAGE( PWM_GETBITMAP, OnGetBitmap );
|
|
SC_HANDLE_MESSAGE( PWM_GETBORDERSIZE, OnGetBorderSize );
|
|
SC_HANDLE_MESSAGE( PWM_GETHANDLESIZE, OnGetHandleSize );
|
|
SC_HANDLE_MESSAGE( PWM_GETBGALPHA, OnGetBgAlpha );
|
|
SC_HANDLE_MESSAGE( PWM_GETHANDLETYPE, OnGetHandleType );
|
|
SC_HANDLE_MESSAGE( PWM_SETBORDERSIZE, OnSetBorderSize );
|
|
SC_HANDLE_MESSAGE( PWM_SETHANDLESIZE, OnSetHandleSize );
|
|
SC_HANDLE_MESSAGE( PWM_SETBGALPHA, OnSetBgAlpha );
|
|
SC_HANDLE_MESSAGE( PWM_SETHANDLETYPE, OnSetHandleType );
|
|
SC_HANDLE_MESSAGE( PWM_GETSELCOUNT, OnGetSelCount );
|
|
SC_HANDLE_MESSAGE( PWM_GETSELORIGIN, OnGetSelOrigin );
|
|
SC_HANDLE_MESSAGE( PWM_GETSELEXTENT, OnGetSelExtent );
|
|
SC_HANDLE_MESSAGE( PWM_SETSELORIGIN, OnSetSelOrigin );
|
|
SC_HANDLE_MESSAGE( PWM_SETSELEXTENT, OnSetSelExtent );
|
|
SC_HANDLE_MESSAGE( WM_ENTERSIZEMOVE, OnEnterSizeMove );
|
|
SC_HANDLE_MESSAGE( WM_EXITSIZEMOVE, OnExitSizeMove );
|
|
SC_HANDLE_MESSAGE( PWM_GETALLOWNULLSELECTION, OnGetAllowNullSelection );
|
|
SC_HANDLE_MESSAGE( PWM_SETALLOWNULLSELECTION, OnSetAllowNullSelection );
|
|
SC_HANDLE_MESSAGE( PWM_SELECTIONDISABLED, OnGetDisableSelection );
|
|
SC_HANDLE_MESSAGE( PWM_DISABLESELECTION, OnSetDisableSelection );
|
|
SC_HANDLE_MESSAGE( PWM_DETECTREGIONS, OnDetectRegions);
|
|
SC_HANDLE_MESSAGE( PWM_GETBKCOLOR, OnGetBkColor );
|
|
SC_HANDLE_MESSAGE( PWM_SETBKCOLOR, OnSetBkColor );
|
|
SC_HANDLE_MESSAGE( PWM_SETPREVIEWMODE, OnSetPreviewMode );
|
|
SC_HANDLE_MESSAGE( PWM_GETPREVIEWMODE, OnGetPreviewMode );
|
|
SC_HANDLE_MESSAGE( PWM_GETIMAGESIZE, OnGetImageSize );
|
|
SC_HANDLE_MESSAGE( PWM_SETBORDERSTYLE, OnSetBorderStyle );
|
|
SC_HANDLE_MESSAGE( PWM_SETBORDERCOLOR, OnSetBorderColor );
|
|
SC_HANDLE_MESSAGE( PWM_SETHANDLECOLOR, OnSetHandleColor );
|
|
SC_HANDLE_MESSAGE( PWM_REFRESHBITMAP, OnRefreshBitmap );
|
|
SC_HANDLE_MESSAGE( PWM_SETPROGRESS, OnSetProgress );
|
|
SC_HANDLE_MESSAGE( PWM_GETPROGRESS, OnGetProgress );
|
|
SC_HANDLE_MESSAGE( PWM_SETUSERCHANGEDSELECTION, OnSetUserChangedSelection );
|
|
SC_HANDLE_MESSAGE( PWM_GETUSERCHANGEDSELECTION, OnGetUserChangedSelection );
|
|
}
|
|
SC_END_MESSAGE_HANDLERS();
|
|
}
|
|
|
|
// Detects regions using the CRegionDetector class
|
|
// The region detection class is designed to detect
|
|
// multiple regions, but OnDetectRegions merges all of the regions
|
|
// down to one region which it saves as m_rcCurrSel
|
|
LRESULT CWiaPreviewWindow::OnDetectRegions( WPARAM, LPARAM )
|
|
{
|
|
WIA_PUSH_FUNCTION((TEXT("CWiaPreviewWindow::OnDetectRegions")));
|
|
|
|
//
|
|
// We are going to assume we can't detect a region
|
|
//
|
|
m_bSuccessfulRegionDetection = false;
|
|
|
|
//
|
|
// This could take a while
|
|
//
|
|
CWaitCursor wc;
|
|
|
|
//
|
|
// m_hPreviewBitmap holds the bitmap we wish to detect regions on.
|
|
//
|
|
if (m_hBufferBitmap && m_hPreviewBitmap)
|
|
{
|
|
//
|
|
// Get the bitmap info associated with m_hPreviewBitmap
|
|
//
|
|
BITMAP bitmap = {0};
|
|
if (GetObject(m_hPreviewBitmap,sizeof(BITMAP),&bitmap))
|
|
{
|
|
//
|
|
// Unless the preview image is of a reasonable size
|
|
// We are not only wasting the users time, but we are risking
|
|
// crashing his system with too large a file
|
|
//
|
|
if ((bitmap.bmWidth>MIN_REGION_DETECTION_X && bitmap.bmWidth<=MAX_REGION_DETECTION_X) &&
|
|
(bitmap.bmHeight>MIN_REGION_DETECTION_Y && bitmap.bmHeight<=MAX_REGION_DETECTION_Y))
|
|
{
|
|
//
|
|
// Create a region detector
|
|
//
|
|
CRegionDetector *pRegionDetector = new CRegionDetector(bitmap);
|
|
if (pRegionDetector)
|
|
{
|
|
pRegionDetector->FindSingleRegion();
|
|
|
|
//
|
|
// findRegions stores coordinates in a system that
|
|
// is a mirror image of the coordinate system used
|
|
// in CWiaPreviewWindow
|
|
//
|
|
pRegionDetector->m_pRegions->FlipVertically();
|
|
|
|
if (pRegionDetector->m_pRegions->m_validRects>0)
|
|
{
|
|
pRegionDetector->ConvertToOrigionalCoordinates();
|
|
m_rectSavedDetected=pRegionDetector->m_pRegions->unionAll();
|
|
|
|
//
|
|
// we do not call grow regions because the FindSingleRegion algorithm uses edge enhancement
|
|
// which makes GrowRegion unncessary
|
|
//
|
|
|
|
//
|
|
// there may not always be a 1-1 correlation between preview pixels and image pixels
|
|
// so to be on the safe side, grow the preview rect out by a couple of pixels
|
|
//
|
|
m_rectSavedDetected=GrowRegion(m_rectSavedDetected,REGION_DETECTION_BORDER);
|
|
m_rcCurrSel=m_rectSavedDetected;
|
|
|
|
//
|
|
// we also have to worry about the extra rounding error factor from converting to
|
|
// screen coordinates
|
|
//
|
|
m_rcSavedImageRect = GetImageRect();
|
|
|
|
//
|
|
// CWiaPreviewWindow stores the selection rectangle in terms of screen coordinates instead of bitmap coordinates
|
|
//
|
|
m_rcCurrSel=ConvertToScreenCoords(m_rcCurrSel);
|
|
|
|
//
|
|
// redisplay the window with the new selection rectangle
|
|
//
|
|
InvalidateRect( m_hWnd, NULL, FALSE );
|
|
UpdateWindow( m_hWnd );
|
|
SendSelChangeNotification(false);
|
|
|
|
//
|
|
// We were successful at detecting a region
|
|
//
|
|
m_bSuccessfulRegionDetection = true;
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("pRegionDetector->m_pRegions->m_validRects was <= 0")));
|
|
}
|
|
|
|
//
|
|
// free CRegionDetector
|
|
//
|
|
delete pRegionDetector;
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("new pRegionDetector returned NULL")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("Bitmap is too large for region detection to work efficiently (bitmap.bmWidth: %d, bitmap.bmHeight: %d)"), bitmap.bmWidth, bitmap.bmHeight));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("Unable to get the BITMAP for the hBitmap")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("No bitmap")));
|
|
}
|
|
return (m_bSuccessfulRegionDetection ? TRUE : FALSE);
|
|
}
|
|
|
|
RECT CWiaPreviewWindow::GrowRegion(RECT r, int border)
|
|
{
|
|
r.left-=border;
|
|
r.top-=border;
|
|
r.right+=border;
|
|
r.bottom+=border;
|
|
|
|
if (r.left<0) r.left=0;
|
|
if (r.right>=m_BitmapSize.cx) r.right=m_BitmapSize.cx-1;
|
|
|
|
if (r.top<0) r.top=0;
|
|
if (r.top>=m_BitmapSize.cy) r.top=m_BitmapSize.cy-1;
|
|
return(r);
|
|
}
|
|
|
|
int CWiaPreviewWindow::XConvertToBitmapCoords(int x)
|
|
{
|
|
return((x-m_rcSavedImageRect.left)*m_BitmapSize.cx)/WiaUiUtil::RectWidth(m_rcSavedImageRect);
|
|
}
|
|
|
|
int CWiaPreviewWindow::XConvertToScreenCoords(int x)
|
|
{
|
|
return(x*WiaUiUtil::RectWidth(m_rcSavedImageRect))/m_BitmapSize.cx+m_rcSavedImageRect.left;
|
|
}
|
|
|
|
int CWiaPreviewWindow::YConvertToBitmapCoords(int y)
|
|
{
|
|
return((y-m_rcSavedImageRect.top)*m_BitmapSize.cy)/WiaUiUtil::RectHeight(m_rcSavedImageRect);
|
|
}
|
|
int CWiaPreviewWindow::YConvertToScreenCoords(int y)
|
|
{
|
|
return(y*WiaUiUtil::RectHeight(m_rcSavedImageRect))/m_BitmapSize.cy+m_rcSavedImageRect.top;
|
|
}
|
|
|
|
|
|
// Convert between bitmap coordinates and screen coordinates
|
|
POINT CWiaPreviewWindow::ConvertToBitmapCoords(POINT p)
|
|
{
|
|
p.x=XConvertToBitmapCoords(p.x);
|
|
p.y=YConvertToBitmapCoords(p.y);
|
|
return(p);
|
|
}
|
|
|
|
POINT CWiaPreviewWindow::ConvertToScreenCoords(POINT p)
|
|
{
|
|
p.x=XConvertToScreenCoords(p.x);
|
|
p.y=YConvertToScreenCoords(p.y);
|
|
return(p);
|
|
}
|
|
|
|
RECT CWiaPreviewWindow::ConvertToBitmapCoords(RECT r)
|
|
{
|
|
r.left=XConvertToBitmapCoords(r.left);
|
|
r.top=YConvertToBitmapCoords(r.top);
|
|
r.right=XConvertToBitmapCoords(r.right);
|
|
r.bottom=YConvertToBitmapCoords(r.bottom);
|
|
return(r);
|
|
}
|
|
|
|
RECT CWiaPreviewWindow::ConvertToScreenCoords(RECT r)
|
|
{
|
|
RECT newRect;
|
|
newRect.left=XConvertToScreenCoords(r.left);
|
|
newRect.top=YConvertToScreenCoords(r.top);
|
|
newRect.right=XConvertToScreenCoords(r.right);
|
|
newRect.bottom=YConvertToScreenCoords(r.bottom);
|
|
return(newRect);
|
|
}
|
|
|
|
|
|
LRESULT CWiaPreviewWindow::OnLButtonDblClk( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
|
|
{
|
|
return(0);
|
|
}
|
|
if (GetFocus() != m_hWnd)
|
|
{
|
|
SetFocus(m_hWnd);
|
|
}
|
|
|
|
POINT point;
|
|
point.x = LOWORD(lParam);
|
|
point.y = HIWORD(lParam);
|
|
int Hit = GetHitArea(point);
|
|
if (wParam & MK_CONTROL)
|
|
{
|
|
Hit = HIT_NONE;
|
|
}
|
|
if (Hit != HIT_NONE && m_bSuccessfulRegionDetection)
|
|
{
|
|
m_rcCurrSel = m_rectSavedDetected; // reset to saved rectangle
|
|
m_rcSavedImageRect = GetImageRect();
|
|
m_rcCurrSel=ConvertToScreenCoords(m_rcCurrSel); // CWiaPreviewWindow stores the selection rectangle in terms of screen coordinates instead of bitmap coordinates
|
|
|
|
SendSelChangeNotification(false);
|
|
Repaint(NULL,false);
|
|
UpdateWindow(m_hWnd);
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|