Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2266 lines
73 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: PREVWND.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 10/9/1998
  12. *
  13. * DESCRIPTION: Scanner Preview Control
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include "prevwnd.h"
  19. #include "pviewids.h"
  20. #include "simcrack.h"
  21. #include "miscutil.h"
  22. #include "simrect.h"
  23. #include "waitcurs.h"
  24. #include "comctrlp.h"
  25. #include "dlgunits.h"
  26. #include "simrect.h"
  27. #define IDC_PROGRESSCONTROL 100
  28. #undef DITHER_DISABLED_CONTROL
  29. //
  30. // The range of image sizes for which we will detect regions.
  31. //
  32. #define MIN_REGION_DETECTION_X 100
  33. #define MIN_REGION_DETECTION_Y 100
  34. #define MAX_REGION_DETECTION_X 1275
  35. #define MAX_REGION_DETECTION_Y 2100
  36. #if defined(OLD_CRAPPY_HOME_SETUP)
  37. static HINSTANCE g_hMsImgInst=LoadLibrary( TEXT("msimg32.dll") );
  38. static AlphaBlendFn AlphaBlend=(AlphaBlendFn)GetProcAddress( g_hMsImgInst, "AlphaBlend" );
  39. #endif
  40. /*
  41. * Mouse hit test codes
  42. */
  43. #define HIT_NONE 0x0000
  44. #define HIT_BORDER 0x0001
  45. #define HIT_TOP 0x0002
  46. #define HIT_BOTTOM 0x0004
  47. #define HIT_LEFT 0x0008
  48. #define HIT_RIGHT 0x0010
  49. #define HIT_SELECTED 0x0020
  50. #define HIT_TOPLEFT (HIT_TOP|HIT_LEFT)
  51. #define HIT_TOPRIGHT (HIT_TOP|HIT_RIGHT)
  52. #define HIT_BOTTOMLEFT (HIT_BOTTOM|HIT_LEFT)
  53. #define HIT_BOTTOMRIGHT (HIT_BOTTOM|HIT_RIGHT)
  54. /*
  55. * Defaults
  56. */
  57. #define DEFAULT_ACCEL_FACTOR 8
  58. #define DEFAULT_HANDLE_SIZE 6
  59. #define DEFAULT_BORDER 6
  60. #define DEFAULT_BG_ALPHA 96
  61. #define DEFAULT_SELECTED_HANDLE_FILL_COLOR RGB(0,128,0)
  62. #define DEFAULT_UNSELECTED_HANDLE_FILL_COLOR RGB(128,0,0)
  63. #define DEFAULT_DISABLED_HANDLE_FILL_COLOR GetSysColor(COLOR_3DSHADOW)
  64. #define DEFAULT_SELECTED_BORDER_COLOR RGB(0,0,0)
  65. #define DEFAULT_UNSELECTED_BORDER_COLOR RGB(0,0,0)
  66. #define DEFAULT_DISABLED_BORDER_COLOR GetSysColor(COLOR_3DSHADOW)
  67. #define DEFAULT_SELECTION_HANDLE_SHADOW RGB(128,128,128)
  68. #define DEFAULT_SELECTION_HANDLE_HIGHLIGHT RGB(255,255,255)
  69. #define DEFAULT_HANDLE_TYPE (PREVIEW_WINDOW_SQUAREHANDLES|PREVIEW_WINDOW_FILLEDHANDLES)
  70. #define DEFAULT_BORDER_STYLE PS_DOT
  71. #define BORDER_SELECTION_PEN_THICKNESS 0
  72. #define REGION_DETECTION_BORDER 1
  73. static inline RECT CreateRect( int left, int top, int right, int bottom )
  74. {
  75. RECT r;
  76. r.left = left;
  77. r.top = top;
  78. r.right = right;
  79. r.bottom = bottom;
  80. return(r);
  81. }
  82. static HBRUSH CreateDitheredPatternBrush(void)
  83. {
  84. const BYTE s_GrayBitmapBits[] = {
  85. 0xAA, 0x00,
  86. 0x55, 0x00,
  87. 0xAA, 0x00,
  88. 0x55, 0x00,
  89. 0xAA, 0x00,
  90. 0x55, 0x00,
  91. 0xAA, 0x00,
  92. 0x55, 0x00
  93. };
  94. HBITMAP hBmp = CreateBitmap( 8, 8, 1, 1, s_GrayBitmapBits );
  95. if (hBmp)
  96. {
  97. HBRUSH hbrPatBrush = CreatePatternBrush(hBmp);
  98. DeleteObject(hBmp);
  99. return(hbrPatBrush);
  100. }
  101. return(NULL);
  102. }
  103. static void DitherRect( HDC hDC, RECT &rc )
  104. {
  105. const DWORD ROP_DPNA = 0x000A0329;
  106. HBRUSH hbr = CreateDitheredPatternBrush();
  107. if (hbr)
  108. {
  109. HBRUSH hbrOld = (HBRUSH)SelectObject(hDC, hbr);
  110. PatBlt( hDC, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ROP_DPNA );
  111. SelectObject( hDC, hbrOld );
  112. DeleteObject( hbr );
  113. }
  114. }
  115. static inline int PointInRect( const RECT &rc, const POINT &pt )
  116. {
  117. return(PtInRect(&rc,pt));
  118. }
  119. static inline int Boundary( int val, int min, int max )
  120. {
  121. if (val < min)
  122. return(min);
  123. if (val > max)
  124. return(max);
  125. return(val);
  126. }
  127. template <class T>
  128. static inline T Minimum( const T &a, const T &b )
  129. {
  130. return(a < b) ? a : b;
  131. }
  132. template <class T>
  133. static inline T Maximum( const T &a, const T &b )
  134. {
  135. return(a > b) ? a : b;
  136. }
  137. // Just like API UnionRect, but handles empty rects
  138. static void TrueUnionRect( RECT *prcDest, const RECT *prcSrc1, const RECT *prcSrc2 )
  139. {
  140. prcDest->left = Minimum( prcSrc1->left, prcSrc2->left );
  141. prcDest->right = Maximum( prcSrc1->right, prcSrc2->right );
  142. prcDest->top = Minimum( prcSrc1->top, prcSrc2->top );
  143. prcDest->bottom = Maximum( prcSrc1->bottom, prcSrc2->bottom );
  144. }
  145. // Constructor
  146. CWiaPreviewWindow::CWiaPreviewWindow( HWND hWnd )
  147. : m_hWnd(hWnd),
  148. m_bDeleteBitmap(TRUE),
  149. m_bSizing(FALSE),
  150. m_bAllowNullSelection(FALSE),
  151. m_hBufferBitmap(NULL),
  152. m_hPaintBitmap(NULL),
  153. m_hAlphaBitmap(NULL),
  154. m_hPreviewBitmap(NULL),
  155. m_hCursorArrow(LoadCursor(NULL,IDC_ARROW)),
  156. m_hCursorCrossHairs(LoadCursor(NULL,IDC_CROSS)),
  157. m_hCursorMove(LoadCursor(NULL,IDC_SIZEALL)),
  158. m_hCursorSizeNS(LoadCursor(NULL,IDC_SIZENS)),
  159. m_hCursorSizeNeSw(LoadCursor(NULL,IDC_SIZENESW)),
  160. m_hCursorSizeNwSe(LoadCursor(NULL,IDC_SIZENWSE)),
  161. m_hCursorSizeWE(LoadCursor(NULL,IDC_SIZEWE)),
  162. m_MovingSel(HIT_NONE),
  163. m_nBorderSize(DEFAULT_BORDER),
  164. m_nHandleType(DEFAULT_HANDLE_TYPE),
  165. m_nHandleSize(DEFAULT_HANDLE_SIZE),
  166. m_hHalftonePalette(NULL),
  167. m_nCurrentRect(0),
  168. m_hBackgroundBrush(CreateSolidBrush(GetSysColor(COLOR_WINDOW))),
  169. m_bPreviewMode(false),
  170. m_bSuccessfulRegionDetection(false),
  171. m_bUserChangedSelection(false)
  172. {
  173. ZeroMemory(&m_rcCurrSel,sizeof(m_rcCurrSel));
  174. ZeroMemory(&m_rcSavedImageRect,sizeof(m_rcSavedImageRect));
  175. ZeroMemory(&m_Resolution,sizeof(m_Resolution));
  176. ZeroMemory(&m_Delta,sizeof(m_Delta));
  177. ZeroMemory(&m_bfBlendFunction,sizeof(m_bfBlendFunction));
  178. ZeroMemory(&m_rcSavedImageRect,sizeof(m_rcSavedImageRect));
  179. m_bfBlendFunction.BlendOp = AC_SRC_OVER;
  180. m_bfBlendFunction.SourceConstantAlpha = DEFAULT_BG_ALPHA;
  181. m_aHandlePens[Selected] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTED_BORDER_COLOR );
  182. m_aHandlePens[Unselected] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_UNSELECTED_BORDER_COLOR );
  183. m_aHandlePens[Disabled] = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_DISABLED_BORDER_COLOR );
  184. m_aBorderPens[Selected] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTED_BORDER_COLOR );
  185. m_aBorderPens[Unselected] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_UNSELECTED_BORDER_COLOR );
  186. m_aBorderPens[Disabled] = CreatePen( DEFAULT_BORDER_STYLE, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_DISABLED_BORDER_COLOR );
  187. m_aHandleBrushes[Selected] = CreateSolidBrush( DEFAULT_SELECTED_HANDLE_FILL_COLOR );
  188. m_aHandleBrushes[Unselected] = CreateSolidBrush( DEFAULT_UNSELECTED_HANDLE_FILL_COLOR );
  189. m_aHandleBrushes[Disabled] = CreateSolidBrush( DEFAULT_DISABLED_HANDLE_FILL_COLOR );
  190. m_hHandleShadow = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTION_HANDLE_SHADOW);
  191. m_hHandleHighlight = CreatePen( PS_SOLID|PS_INSIDEFRAME, BORDER_SELECTION_PEN_THICKNESS, DEFAULT_SELECTION_HANDLE_HIGHLIGHT);
  192. }
  193. void CWiaPreviewWindow::DestroyBitmaps(void)
  194. {
  195. if (m_hPaintBitmap)
  196. {
  197. DeleteObject(m_hPaintBitmap);
  198. m_hPaintBitmap = NULL;
  199. }
  200. if (m_hBufferBitmap)
  201. {
  202. DeleteObject(m_hBufferBitmap);
  203. m_hBufferBitmap = NULL;
  204. }
  205. if (m_hAlphaBitmap)
  206. {
  207. DeleteObject(m_hAlphaBitmap);
  208. m_hAlphaBitmap = NULL;
  209. }
  210. }
  211. CWiaPreviewWindow::~CWiaPreviewWindow()
  212. {
  213. DestroyBitmaps();
  214. if (m_bDeleteBitmap && m_hPreviewBitmap)
  215. {
  216. DeleteObject(m_hPreviewBitmap);
  217. m_hPreviewBitmap = NULL;
  218. }
  219. else
  220. {
  221. m_hPreviewBitmap = NULL;
  222. }
  223. if (m_hHalftonePalette)
  224. {
  225. DeleteObject(m_hHalftonePalette);
  226. m_hHalftonePalette = NULL;
  227. }
  228. // Destroy all of the handle pens
  229. for (int i=0;i<ARRAYSIZE(m_aHandlePens);i++)
  230. {
  231. if (m_aHandlePens[i])
  232. {
  233. DeleteObject(m_aHandlePens[i]);
  234. m_aHandlePens[i] = NULL;
  235. }
  236. }
  237. // Destroy all of the selection rectangle pens
  238. for (i=0;i<ARRAYSIZE(m_aBorderPens);i++)
  239. {
  240. if (m_aBorderPens[i])
  241. {
  242. DeleteObject(m_aBorderPens[i]);
  243. m_aBorderPens[i] = NULL;
  244. }
  245. }
  246. // Destroy all of the brushes
  247. for (i=0;i<ARRAYSIZE(m_aHandleBrushes);i++)
  248. {
  249. if (m_aHandleBrushes[i])
  250. {
  251. DeleteObject(m_aHandleBrushes[i]);
  252. m_aHandleBrushes[i] = NULL;
  253. }
  254. }
  255. if (m_hHandleHighlight)
  256. {
  257. DeleteObject(m_hHandleHighlight);
  258. m_hHandleHighlight = NULL;
  259. }
  260. if (m_hHandleShadow)
  261. {
  262. DeleteObject(m_hHandleShadow);
  263. m_hHandleShadow = NULL;
  264. }
  265. if (m_hBackgroundBrush)
  266. {
  267. DeleteObject(m_hBackgroundBrush);
  268. m_hBackgroundBrush = NULL;
  269. }
  270. m_hWnd = NULL;
  271. // Zero out all of the cursors. No need to free them
  272. m_hCursorSizeNeSw = NULL;
  273. m_hCursorSizeNwSe = NULL;
  274. m_hCursorCrossHairs = NULL;
  275. m_hCursorMove = NULL;
  276. m_hCursorSizeNS = NULL;
  277. m_hCursorSizeWE = NULL;
  278. m_hCursorArrow = NULL;
  279. }
  280. void CWiaPreviewWindow::Repaint( PRECT pRect, bool bErase )
  281. {
  282. InvalidateRect( m_hWnd, pRect, (bErase != false) );
  283. UpdateWindow( m_hWnd );
  284. }
  285. void CWiaPreviewWindow::DrawHandle( HDC dc, const RECT &r, int nState )
  286. {
  287. HPEN hOldPen = (HPEN)SelectObject( dc, m_aHandlePens[nState] );
  288. HBRUSH hOldBrush = (HBRUSH)SelectObject( dc, m_aHandleBrushes[nState] );
  289. if (PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType)
  290. {
  291. SelectObject( dc, GetStockObject(NULL_BRUSH) );
  292. }
  293. if (PREVIEW_WINDOW_ROUNDHANDLES&m_nHandleType)
  294. {
  295. Ellipse(dc,r.left,r.top,r.right,r.bottom);
  296. if (!(PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType))
  297. {
  298. RECT rcHighlight = r;
  299. InflateRect(&rcHighlight,-1,-1);
  300. SelectObject(dc,GetStockObject(NULL_BRUSH));
  301. SelectObject(dc,m_hHandleShadow);
  302. Arc(dc,rcHighlight.left,rcHighlight.top,rcHighlight.right,rcHighlight.bottom,rcHighlight.left,rcHighlight.bottom,rcHighlight.right,rcHighlight.top);
  303. SelectObject(dc,m_hHandleHighlight);
  304. Arc(dc,rcHighlight.left,rcHighlight.top,rcHighlight.right,rcHighlight.bottom,rcHighlight.right,rcHighlight.top,rcHighlight.left,rcHighlight.bottom);
  305. }
  306. }
  307. else
  308. {
  309. Rectangle(dc,r.left,r.top,r.right,r.bottom);
  310. if (!(PREVIEW_WINDOW_HOLLOWHANDLES&m_nHandleType))
  311. {
  312. RECT rcHighlight = r;
  313. InflateRect(&rcHighlight,-1,-1);
  314. rcHighlight.right--;
  315. rcHighlight.bottom--;
  316. if (!IsRectEmpty(&rcHighlight))
  317. {
  318. SelectObject(dc,m_hHandleHighlight);
  319. MoveToEx(dc,rcHighlight.left,rcHighlight.bottom,NULL);
  320. LineTo(dc,rcHighlight.left,rcHighlight.top);
  321. LineTo(dc,rcHighlight.right,rcHighlight.top);
  322. SelectObject(dc,m_hHandleShadow);
  323. LineTo(dc,rcHighlight.right,rcHighlight.bottom);
  324. LineTo(dc,rcHighlight.left,rcHighlight.bottom);
  325. }
  326. }
  327. }
  328. SelectObject( dc, hOldPen );
  329. SelectObject( dc, hOldBrush );
  330. }
  331. RECT CWiaPreviewWindow::GetSizingHandleRect( const RECT &rcSelection, int iWhich )
  332. {
  333. RECT rcSel;
  334. CopyRect(&rcSel,&rcSelection);
  335. NormalizeRect(rcSel);
  336. int sizeWidth = Minimum<int>(m_nHandleSize,WiaUiUtil::RectWidth(rcSel)/2);
  337. int sizeHeight = Minimum<int>(m_nHandleSize,WiaUiUtil::RectHeight(rcSel)/2);
  338. switch (iWhich)
  339. {
  340. case HIT_TOPLEFT:
  341. return(CreateRect( rcSel.left - m_nHandleSize, rcSel.top - m_nHandleSize, rcSel.left + sizeWidth, rcSel.top + sizeHeight ));
  342. case HIT_TOPRIGHT:
  343. return(CreateRect( rcSel.right - sizeWidth, rcSel.top - m_nHandleSize, rcSel.right + m_nHandleSize, rcSel.top + sizeHeight));
  344. case HIT_BOTTOMRIGHT:
  345. return(CreateRect( rcSel.right - sizeWidth, rcSel.bottom - sizeHeight, rcSel.right + m_nHandleSize, rcSel.bottom + m_nHandleSize ));
  346. case HIT_BOTTOMLEFT:
  347. return(CreateRect( rcSel.left - m_nHandleSize, rcSel.bottom - sizeHeight, rcSel.left + sizeWidth, rcSel.bottom + m_nHandleSize ));
  348. default:
  349. return(CreateRect(0,0,0,0));
  350. }
  351. }
  352. RECT CWiaPreviewWindow::GetSelectionRect( RECT &rcSel, int iWhich )
  353. {
  354. switch (iWhich)
  355. {
  356. case HIT_LEFT:
  357. return(CreateRect( rcSel.left-m_nHandleSize,rcSel.top-m_nHandleSize,rcSel.left+m_nHandleSize,rcSel.bottom+m_nHandleSize));
  358. case HIT_RIGHT:
  359. return(CreateRect( rcSel.right-m_nHandleSize, rcSel.top-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.bottom+m_nHandleSize ));
  360. case HIT_TOP:
  361. return(CreateRect( rcSel.left-m_nHandleSize, rcSel.top-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.top+m_nHandleSize ));
  362. case HIT_BOTTOM:
  363. return(CreateRect( rcSel.left-m_nHandleSize, rcSel.bottom-m_nHandleSize, rcSel.right+m_nHandleSize, rcSel.bottom+m_nHandleSize ));
  364. default:
  365. return(CreateRect(0,0,0,0));
  366. }
  367. }
  368. POINT CWiaPreviewWindow::GetCornerPoint( int iWhich )
  369. {
  370. RECT rcTmp(m_rcCurrSel);
  371. NormalizeRect(m_rcCurrSel);
  372. POINT pt;
  373. pt.x = pt.y = 0;
  374. if (iWhich & HIT_TOP)
  375. pt.y = rcTmp.top;
  376. if (iWhich & HIT_BOTTOM)
  377. pt.y = rcTmp.bottom;
  378. if (iWhich & HIT_RIGHT)
  379. pt.x = rcTmp.right;
  380. if (iWhich & HIT_LEFT)
  381. pt.x = rcTmp.left;
  382. return(pt);
  383. }
  384. void CWiaPreviewWindow::DrawSizingFrame( HDC dc, RECT &rc, bool bHasFocus, bool bDisabled )
  385. {
  386. RECT rcTmp;
  387. CopyRect(&rcTmp,&rc);
  388. NormalizeRect(rcTmp);
  389. int nState = Unselected;
  390. if (bDisabled)
  391. nState = Disabled;
  392. else if (bHasFocus)
  393. nState = Selected;
  394. HPEN hOldPen = (HPEN)SelectObject(dc,m_aBorderPens[nState]);
  395. HBRUSH hOldBrush = (HBRUSH)SelectObject(dc,GetStockObject(NULL_BRUSH));
  396. COLORREF crOldColor = SetBkColor(dc,RGB(255,255,255));
  397. int nOldROP2 = SetROP2(dc,R2_COPYPEN);
  398. Rectangle(dc,rcTmp.left,rcTmp.top,rcTmp.right,rcTmp.bottom);
  399. DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_TOPLEFT ), nState );
  400. DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_TOPRIGHT ), nState );
  401. DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_BOTTOMLEFT ), nState );
  402. DrawHandle( dc, GetSizingHandleRect( rcTmp, HIT_BOTTOMRIGHT ), nState );
  403. SetROP2(dc,nOldROP2);
  404. SetBkColor(dc,crOldColor);
  405. SelectObject(dc,hOldBrush);
  406. SelectObject(dc,hOldPen);
  407. }
  408. bool CWiaPreviewWindow::IsAlphaBlendEnabled(void)
  409. {
  410. return(m_bfBlendFunction.SourceConstantAlpha != 0xFF);
  411. }
  412. HPALETTE CWiaPreviewWindow::SetHalftonePalette( HDC hDC )
  413. {
  414. if (m_hHalftonePalette)
  415. {
  416. HPALETTE hOldPalette = SelectPalette( hDC, m_hHalftonePalette, FALSE );
  417. RealizePalette( hDC );
  418. SetBrushOrgEx( hDC, 0,0, NULL );
  419. return(hOldPalette);
  420. }
  421. else
  422. {
  423. HPALETTE hOldPalette = SelectPalette( hDC, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE );
  424. RealizePalette( hDC );
  425. return(hOldPalette);
  426. }
  427. }
  428. void CWiaPreviewWindow::PaintWindowTitle( HDC hDC )
  429. {
  430. //
  431. // Get the length of the caption text
  432. //
  433. int nTextLen = (int)SendMessage( m_hWnd, WM_GETTEXTLENGTH, 0, 0 );
  434. if (nTextLen >= 0)
  435. {
  436. //
  437. // Allocate a buffer to hold it
  438. //
  439. LPTSTR pszText = new TCHAR[nTextLen+1];
  440. if (pszText)
  441. {
  442. //
  443. // Get the text
  444. //
  445. if (SendMessage( m_hWnd, WM_GETTEXT, nTextLen+1, (LPARAM)pszText ))
  446. {
  447. //
  448. // Save the DC's state
  449. //
  450. int nDrawTextFlags = DT_CENTER|DT_NOPREFIX|DT_WORDBREAK;
  451. COLORREF crOldTextColor = SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );
  452. int nOldBkMode = SetBkMode( hDC, TRANSPARENT );
  453. //
  454. // Get the size of the image rectangle
  455. //
  456. RECT rcImage = GetImageRect();
  457. RECT rcAvailable = rcImage;
  458. //
  459. // Leave some space for a margin
  460. //
  461. rcAvailable.right -= 20;
  462. //
  463. // Get the control's font, if there is one
  464. //
  465. HFONT hOldFont = NULL, hWndFont = WiaUiUtil::GetFontFromWindow( m_hWnd );
  466. //
  467. // Set the DC's font
  468. //
  469. if (hWndFont)
  470. {
  471. hOldFont = reinterpret_cast<HFONT>(SelectObject( hDC, hWndFont ));
  472. }
  473. //
  474. // Calculate the size of the text
  475. //
  476. RECT rcText = {0};
  477. if (DrawText( hDC, pszText, lstrlen(pszText), &rcAvailable, nDrawTextFlags|DT_CALCRECT ))
  478. {
  479. //
  480. // add the extra margin back in and form the text rectangle
  481. //
  482. rcAvailable.right += 20;
  483. //
  484. // Calculate the text size
  485. //
  486. rcText.left = rcImage.left + (WiaUiUtil::RectWidth(rcImage) - WiaUiUtil::RectWidth(rcAvailable))/2;
  487. rcText.top = rcImage.top + (WiaUiUtil::RectHeight(rcImage) - WiaUiUtil::RectHeight(rcAvailable))/2;
  488. rcText.right = rcText.left + WiaUiUtil::RectWidth(rcAvailable);
  489. rcText.bottom = rcText.top + WiaUiUtil::RectHeight(rcAvailable);
  490. }
  491. //
  492. // See if the progress control is active
  493. //
  494. HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
  495. if (hWndProgress)
  496. {
  497. //
  498. // Get the window rect of the progress control
  499. //
  500. CSimpleRect ProgressRect( hWndProgress, CSimpleRect::WindowRect );
  501. //
  502. // Move the y origin of the text up
  503. //
  504. rcText.top = ProgressRect.ScreenToClient(m_hWnd).top - CDialogUnits(m_hWnd).Y(3) - WiaUiUtil::RectHeight(rcText);
  505. //
  506. // Resize the text rectangle to encompass the bottom of the progress control
  507. //
  508. rcText.bottom = ProgressRect.ScreenToClient(m_hWnd).bottom;
  509. }
  510. //
  511. // Draw the background rectangle and the text
  512. //
  513. 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) };
  514. FillRect( hDC, &rcBorder, GetSysColorBrush(COLOR_WINDOW));
  515. FrameRect( hDC, &rcBorder, GetSysColorBrush(COLOR_WINDOWFRAME));
  516. DrawText( hDC, pszText, lstrlen(pszText), &rcText, nDrawTextFlags );
  517. //
  518. // Restore the DC to its original condition
  519. //
  520. if (hWndFont)
  521. {
  522. SelectObject( hDC, hOldFont );
  523. }
  524. SetTextColor( hDC, crOldTextColor );
  525. SetBkMode( hDC, nOldBkMode );
  526. }
  527. delete[] pszText;
  528. }
  529. }
  530. }
  531. LRESULT CWiaPreviewWindow::OnPaint( WPARAM, LPARAM )
  532. {
  533. PAINTSTRUCT ps;
  534. HDC hDC;
  535. RECT rcIntersection, rcImage = GetImageRect(), rcCurrentSelection;
  536. hDC = BeginPaint(m_hWnd,&ps);
  537. if (hDC)
  538. {
  539. if (!m_hBufferBitmap)
  540. {
  541. FillRect( hDC, &ps.rcPaint, m_hBackgroundBrush );
  542. PaintWindowTitle( hDC );
  543. }
  544. else
  545. {
  546. // Select the halftone palette
  547. HPALETTE hOldDCPalette = SetHalftonePalette( hDC );
  548. HDC hdcMem = CreateCompatibleDC(hDC);
  549. if (hdcMem)
  550. {
  551. HPALETTE hOldMemDCPalette = SetHalftonePalette( hdcMem );
  552. HDC hdcBuffer = CreateCompatibleDC(hDC);
  553. if (hdcBuffer)
  554. {
  555. HPALETTE hOldBufferDCPalette = SetHalftonePalette( hdcBuffer );
  556. HBITMAP hOldBufferDCBitmap = (HBITMAP)SelectObject(hdcBuffer,m_hBufferBitmap);
  557. CopyRect(&rcCurrentSelection,&m_rcCurrSel);
  558. NormalizeRect(rcCurrentSelection);
  559. if (IsDefaultSelectionRect(rcCurrentSelection))
  560. rcCurrentSelection = rcImage;
  561. // Prepare the double buffer bitmap by painting the selected and non-selected regions
  562. if (m_hAlphaBitmap && m_bfBlendFunction.SourceConstantAlpha != 0xFF && !m_bPreviewMode)
  563. {
  564. HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject(hdcMem,m_hAlphaBitmap);
  565. BitBlt(hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,WiaUiUtil::RectWidth(ps.rcPaint),WiaUiUtil::RectHeight(ps.rcPaint),hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
  566. SelectObject(hdcMem,m_hPaintBitmap);
  567. if (IntersectRect( &rcIntersection, &ps.rcPaint, &rcCurrentSelection ))
  568. BitBlt(hdcBuffer,rcIntersection.left,rcIntersection.top,WiaUiUtil::RectWidth(rcIntersection),WiaUiUtil::RectHeight(rcIntersection),hdcMem,rcIntersection.left,rcIntersection.top,SRCCOPY);
  569. SelectObject(hdcMem,hOldMemDCBitmap);
  570. }
  571. else if (m_hPaintBitmap)
  572. {
  573. HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject(hdcMem,m_hPaintBitmap);
  574. BitBlt(hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,WiaUiUtil::RectWidth(ps.rcPaint),WiaUiUtil::RectHeight(ps.rcPaint),hdcMem,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
  575. SelectObject(hdcMem,hOldMemDCBitmap);
  576. }
  577. else
  578. {
  579. FillRect( hdcBuffer, &ps.rcPaint, m_hBackgroundBrush );
  580. }
  581. bool bDisabled = ((GetWindowLong(m_hWnd,GWL_STYLE)&WS_DISABLED) != 0);
  582. #if defined(DITHER_DISABLED_CONTROL)
  583. if (bDisabled)
  584. {
  585. // paint the disabled mask
  586. if (IntersectRect( &rcIntersection, &rcImage, &ps.rcPaint ))
  587. DitherRect(hdcBuffer,rcIntersection);
  588. }
  589. #endif // DITHER_DISABLED_CONTROL
  590. //
  591. // paint the selection rectangle
  592. //
  593. rcCurrentSelection = m_rcCurrSel;
  594. NormalizeRect(rcCurrentSelection);
  595. if (!IsDefaultSelectionRect( rcCurrentSelection ) && !m_bPreviewMode)
  596. {
  597. DrawSizingFrame( hdcBuffer, rcCurrentSelection, (GetFocus()==m_hWnd), bDisabled );
  598. }
  599. PaintWindowTitle( hdcBuffer );
  600. // show it!
  601. BitBlt( hDC, ps.rcPaint.left, ps.rcPaint.top, WiaUiUtil::RectWidth(ps.rcPaint), WiaUiUtil::RectHeight(ps.rcPaint),hdcBuffer,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
  602. // Paint all of the area outside the buffer bitmap
  603. RECT rcClient;
  604. GetClientRect( m_hWnd, &rcClient );
  605. BITMAP bm;
  606. if (GetObject( m_hBufferBitmap, sizeof(BITMAP), &bm ))
  607. {
  608. if (ps.rcPaint.right > bm.bmWidth)
  609. {
  610. RECT rc;
  611. rc.left = bm.bmWidth;
  612. rc.top = ps.rcPaint.top;
  613. rc.right = rcClient.right;
  614. rc.bottom = rcClient.bottom;
  615. FillRect( hDC, &rc, m_hBackgroundBrush );
  616. }
  617. if (ps.rcPaint.bottom > bm.bmHeight)
  618. {
  619. RECT rc;
  620. rc.left = ps.rcPaint.left;
  621. rc.top = bm.bmHeight;
  622. rc.right = bm.bmWidth;
  623. rc.bottom = rcClient.bottom;
  624. FillRect( hDC, &rc, m_hBackgroundBrush );
  625. }
  626. }
  627. SelectObject( hdcBuffer, hOldBufferDCBitmap );
  628. SelectPalette( hdcBuffer, hOldBufferDCPalette, FALSE );
  629. DeleteDC(hdcBuffer);
  630. }
  631. SelectPalette( hdcMem, hOldMemDCPalette, FALSE );
  632. DeleteDC( hdcMem );
  633. }
  634. SelectPalette( hDC, hOldDCPalette, FALSE );
  635. }
  636. EndPaint(m_hWnd,&ps);
  637. }
  638. return(LRESULT)0;
  639. }
  640. BOOL CWiaPreviewWindow::RegisterClass( HINSTANCE hInstance )
  641. {
  642. WNDCLASS wc;
  643. memset( &wc, 0, sizeof(wc) );
  644. wc.style = CS_DBLCLKS;
  645. wc.cbWndExtra = sizeof(CWiaPreviewWindow*);
  646. wc.lpfnWndProc = WndProc;
  647. wc.hInstance = hInstance;
  648. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  649. wc.lpszClassName = PREVIEW_WINDOW_CLASS;
  650. BOOL res = (::RegisterClass(&wc) != 0);
  651. return(res != 0);
  652. }
  653. RECT CWiaPreviewWindow::GetImageRect(void)
  654. {
  655. RECT rcImg;
  656. ::GetClientRect( m_hWnd, &rcImg );
  657. InflateRect( &rcImg, -static_cast<int>(m_nBorderSize), -static_cast<int>(m_nBorderSize) );
  658. return(rcImg);
  659. }
  660. int CWiaPreviewWindow::GetHitArea( POINT &pt )
  661. {
  662. RECT rcTmp;
  663. CopyRect(&rcTmp,&m_rcCurrSel);
  664. NormalizeRect(rcTmp);
  665. int Hit = 0;
  666. if (PointInRect(GetSelectionRect(rcTmp,HIT_TOP),pt))
  667. Hit |= HIT_TOP;
  668. else if (PointInRect(GetSelectionRect(rcTmp,HIT_BOTTOM),pt))
  669. Hit |= HIT_BOTTOM;
  670. if (PointInRect(GetSelectionRect(rcTmp,HIT_LEFT),pt))
  671. Hit |= HIT_LEFT;
  672. else if (PointInRect(GetSelectionRect(rcTmp,HIT_RIGHT),pt))
  673. Hit |= HIT_RIGHT;
  674. if (!Hit && PointInRect(rcTmp,pt))
  675. Hit = HIT_SELECTED;
  676. if (!Hit && !PointInRect(GetImageRect(),pt))
  677. Hit = HIT_BORDER;
  678. return(Hit);
  679. }
  680. void CWiaPreviewWindow::NormalizeRect( RECT &r )
  681. {
  682. if (r.right < r.left)
  683. {
  684. int t = r.left;
  685. r.left = r.right;
  686. r.right = t;
  687. }
  688. if (r.bottom < r.top)
  689. {
  690. int t = r.top;
  691. r.top = r.bottom;
  692. r.bottom = t;
  693. }
  694. }
  695. LRESULT CWiaPreviewWindow::OnMouseMove( WPARAM wParam, LPARAM lParam )
  696. {
  697. POINT point;
  698. if (!m_hPreviewBitmap || m_SelectionDisabled || m_bPreviewMode)
  699. {
  700. SetCursor(m_hCursorArrow);
  701. return(0);
  702. }
  703. point.x = (short int)LOWORD(lParam);
  704. point.y = (short int)HIWORD(lParam);
  705. RECT rcClient = GetImageRect();
  706. RECT rcOldSel;
  707. CopyRect(&rcOldSel,&m_rcCurrSel);
  708. if (m_MovingSel != HIT_NONE)
  709. {
  710. switch (m_MovingSel)
  711. {
  712. case HIT_SELECTED:
  713. {
  714. int Width = WiaUiUtil::RectWidth(m_rcCurrSel);
  715. int Height = WiaUiUtil::RectHeight(m_rcCurrSel);
  716. if (point.x + m_Delta.cx < rcClient.left)
  717. point.x = 0 - m_Delta.cx + rcClient.left;
  718. else if (point.x + m_Delta.cx + Width > rcClient.right)
  719. point.x = rcClient.right - Width - m_Delta.cx;
  720. if (point.y + m_Delta.cy < rcClient.top)
  721. point.y = 0 - m_Delta.cy + rcClient.top;
  722. else if (point.y + m_Delta.cy + Height > rcClient.bottom)
  723. point.y = rcClient.bottom - Height - m_Delta.cy;
  724. m_rcCurrSel.left = point.x + m_Delta.cx;
  725. m_rcCurrSel.right = m_rcCurrSel.left + Width;
  726. m_rcCurrSel.top = point.y + m_Delta.cy;
  727. m_rcCurrSel.bottom = m_rcCurrSel.top + Height;
  728. }
  729. break;
  730. default:
  731. if (m_MovingSel & HIT_TOP)
  732. m_rcCurrSel.top = Boundary(point.y + m_Delta.cy,rcClient.top,rcClient.bottom);
  733. if (m_MovingSel & HIT_BOTTOM)
  734. m_rcCurrSel.bottom = Boundary(point.y + m_Delta.cy,rcClient.top,rcClient.bottom);
  735. if (m_MovingSel & HIT_LEFT)
  736. m_rcCurrSel.left = Boundary(point.x + m_Delta.cx,rcClient.left,rcClient.right);
  737. if (m_MovingSel & HIT_RIGHT)
  738. m_rcCurrSel.right = Boundary(point.x + m_Delta.cx,rcClient.left,rcClient.right);
  739. break;
  740. }
  741. if (memcmp(&rcOldSel,&m_rcCurrSel,sizeof(RECT)))
  742. {
  743. RECT rcCurSel = m_rcCurrSel, rcInvalid;
  744. NormalizeRect(rcOldSel);
  745. NormalizeRect(rcCurSel);
  746. TrueUnionRect(&rcInvalid,&rcCurSel,&rcOldSel);
  747. rcInvalid.left-=m_nHandleSize;
  748. rcInvalid.top-=m_nHandleSize;
  749. rcInvalid.right+=m_nHandleSize;
  750. rcInvalid.bottom+=m_nHandleSize;
  751. SendSelChangeNotification();
  752. Repaint(&rcInvalid,false);
  753. UpdateWindow(m_hWnd);
  754. }
  755. }
  756. int Hit;
  757. if (m_MovingSel == HIT_NONE)
  758. {
  759. if (wParam & MK_CONTROL)
  760. Hit = HIT_NONE;
  761. else Hit = GetHitArea(point);
  762. if (Hit == HIT_SELECTED)
  763. SetCursor(m_hCursorMove);
  764. else if (Hit == HIT_NONE)
  765. SetCursor(m_hCursorCrossHairs);
  766. else if (Hit == HIT_TOPLEFT || Hit == HIT_BOTTOMRIGHT)
  767. SetCursor(m_hCursorSizeNwSe);
  768. else if (Hit == HIT_TOPRIGHT || Hit == HIT_BOTTOMLEFT)
  769. SetCursor(m_hCursorSizeNeSw);
  770. else if (Hit == HIT_TOP || Hit == HIT_BOTTOM)
  771. SetCursor(m_hCursorSizeNS);
  772. else if (Hit == HIT_BORDER)
  773. SetCursor(m_hCursorArrow);
  774. else SetCursor(m_hCursorSizeWE);
  775. }
  776. else
  777. {
  778. Hit = m_MovingSel;
  779. if (Hit == HIT_SELECTED)
  780. SetCursor(m_hCursorMove);
  781. else if (Hit == HIT_TOP || Hit == HIT_BOTTOM)
  782. SetCursor(m_hCursorSizeNS);
  783. else if (Hit == HIT_LEFT || Hit == HIT_RIGHT)
  784. SetCursor(m_hCursorSizeWE);
  785. else
  786. {
  787. if (m_rcCurrSel.top > m_rcCurrSel.bottom)
  788. {
  789. if (Hit & HIT_TOP)
  790. {
  791. Hit &= ~HIT_TOP;
  792. Hit |= HIT_BOTTOM;
  793. }
  794. else if (Hit & HIT_BOTTOM)
  795. {
  796. Hit |= HIT_TOP;
  797. Hit &= ~HIT_BOTTOM;
  798. }
  799. }
  800. if (m_rcCurrSel.left > m_rcCurrSel.right)
  801. {
  802. if (Hit & HIT_LEFT)
  803. {
  804. Hit &= ~HIT_LEFT;
  805. Hit |= HIT_RIGHT;
  806. }
  807. else if (Hit & HIT_RIGHT)
  808. {
  809. Hit |= HIT_LEFT;
  810. Hit &= ~HIT_RIGHT;
  811. }
  812. }
  813. if (Hit == HIT_TOPLEFT || Hit == HIT_BOTTOMRIGHT)
  814. SetCursor(m_hCursorSizeNwSe);
  815. else if (Hit == HIT_TOPRIGHT || Hit == HIT_BOTTOMLEFT)
  816. SetCursor(m_hCursorSizeNeSw);
  817. }
  818. }
  819. return(LRESULT)0;
  820. }
  821. LRESULT CWiaPreviewWindow::OnLButtonDown( WPARAM wParam, LPARAM lParam )
  822. {
  823. if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
  824. return(0);
  825. if (GetFocus() != m_hWnd)
  826. SetFocus(m_hWnd);
  827. POINT point;
  828. point.x = LOWORD(lParam);
  829. point.y = HIWORD(lParam);
  830. int Hit = GetHitArea(point);
  831. if (wParam & MK_CONTROL)
  832. Hit = HIT_NONE;
  833. if (Hit == HIT_SELECTED)
  834. {
  835. m_MovingSel = HIT_SELECTED;
  836. POINT pt = GetCornerPoint(HIT_TOPLEFT);
  837. m_Delta.cx = pt.x - point.x;
  838. m_Delta.cy = pt.y - point.y;
  839. SetCapture(m_hWnd);
  840. }
  841. else if (Hit == HIT_NONE)
  842. {
  843. m_MovingSel = HIT_TOPLEFT;
  844. m_rcCurrSel.left = m_rcCurrSel.right = point.x;
  845. m_rcCurrSel.top = m_rcCurrSel.bottom = point.y;
  846. POINT pt = GetCornerPoint(m_MovingSel);
  847. m_Delta.cx = pt.x - point.x;
  848. m_Delta.cy = pt.y - point.y;
  849. SendSelChangeNotification();
  850. Repaint(NULL,false);
  851. UpdateWindow(m_hWnd);
  852. SetCapture(m_hWnd);
  853. }
  854. else
  855. {
  856. m_MovingSel = Hit;
  857. POINT pt = GetCornerPoint(Hit);
  858. m_Delta.cx = pt.x - point.x;
  859. m_Delta.cy = pt.y - point.y;
  860. SetCapture(m_hWnd);
  861. }
  862. return(LRESULT)0;
  863. }
  864. void CWiaPreviewWindow::SendSelChangeNotification( bool bSetUserChangedSelection )
  865. {
  866. HWND hWndParent = GetParent(m_hWnd);
  867. if (hWndParent && IsWindow(hWndParent))
  868. {
  869. SendNotifyMessage(hWndParent,WM_COMMAND,MAKEWPARAM(GetWindowLongPtr(m_hWnd,GWLP_ID),PWN_SELCHANGE),reinterpret_cast<LPARAM>(m_hWnd));
  870. }
  871. if (bSetUserChangedSelection)
  872. {
  873. m_bUserChangedSelection = true;
  874. }
  875. }
  876. LRESULT CWiaPreviewWindow::OnLButtonUp( WPARAM, LPARAM )
  877. {
  878. if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
  879. return(0);
  880. m_MovingSel = HIT_NONE;
  881. ReleaseCapture();
  882. NormalizeRect(m_rcCurrSel);
  883. return(LRESULT)0;
  884. }
  885. LRESULT CWiaPreviewWindow::OnCreate( WPARAM, LPARAM )
  886. {
  887. SetWindowLong( m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd,GWL_EXSTYLE) & ~WS_EX_LAYOUTRTL );
  888. m_rcCurrSel = GetDefaultSelection();
  889. CreateNewBitmaps();
  890. return(0);
  891. }
  892. void CWiaPreviewWindow::CreateNewBitmaps(void)
  893. {
  894. DestroyBitmaps();
  895. // No need to create the bitmaps if we have no bitmap to display
  896. if (!m_hPreviewBitmap)
  897. return;
  898. // Get client window size
  899. CSimpleRect rcClient( m_hWnd );
  900. bool bSuccess = true;
  901. // Get a client DC
  902. HDC hdcClient = GetDC(m_hWnd);
  903. if (hdcClient)
  904. {
  905. m_hBufferBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
  906. if (m_hBufferBitmap)
  907. {
  908. m_hPaintBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
  909. if (m_hPaintBitmap)
  910. {
  911. if (IsAlphaBlendEnabled())
  912. {
  913. m_hAlphaBitmap = CreateCompatibleBitmap(hdcClient,WiaUiUtil::RectWidth(rcClient),WiaUiUtil::RectHeight(rcClient));
  914. if (!m_hAlphaBitmap)
  915. bSuccess = false;
  916. }
  917. }
  918. else bSuccess = false;
  919. }
  920. else bSuccess = false;
  921. ReleaseDC(m_hWnd,hdcClient);
  922. }
  923. else bSuccess = false;
  924. if (!bSuccess)
  925. DestroyBitmaps();
  926. }
  927. LRESULT CWiaPreviewWindow::OnGetImageSize( WPARAM, LPARAM lParam )
  928. {
  929. if (lParam)
  930. {
  931. *reinterpret_cast<SIZE*>(lParam) = m_BitmapSize;
  932. return(1);
  933. }
  934. return(0);
  935. }
  936. bool CWiaPreviewWindow::GetOriginAndExtentInImagePixels( WORD nItem, POINT &ptOrigin, SIZE &sizeExtent )
  937. {
  938. SIZE sizeSavedResolution;
  939. bool bResult = false;
  940. if (WiaPreviewControl_GetResolution(m_hWnd,&sizeSavedResolution))
  941. {
  942. WiaPreviewControl_SetResolution(m_hWnd, &m_BitmapSize);
  943. bResult = (WiaPreviewControl_GetSelOrigin( m_hWnd, nItem, 0, &ptOrigin ) && WiaPreviewControl_GetSelExtent( m_hWnd, nItem, 0, &sizeExtent ));
  944. // Restore the old resolution
  945. WiaPreviewControl_SetResolution(m_hWnd, &sizeSavedResolution);
  946. }
  947. return(bResult);
  948. }
  949. void CWiaPreviewWindow::DrawBitmaps(void)
  950. {
  951. // Don't bother painting the bitmap if we don't have an image.
  952. if (!m_hPreviewBitmap)
  953. return;
  954. RECT rcImage = GetImageRect();
  955. // Nuke old halftone palette
  956. if (m_hHalftonePalette)
  957. {
  958. DeleteObject(m_hHalftonePalette);
  959. m_hHalftonePalette = NULL;
  960. }
  961. // Get client window size
  962. CSimpleRect rcClient( m_hWnd );
  963. // Get a client DC
  964. HDC hdcClient = GetDC(m_hWnd);
  965. if (hdcClient)
  966. {
  967. // Recreate the halftone palette
  968. m_hHalftonePalette = CreateHalftonePalette(hdcClient);
  969. if (m_hHalftonePalette)
  970. {
  971. // Create a compatible dc
  972. HDC hdcCompat = CreateCompatibleDC(hdcClient);
  973. if (hdcCompat)
  974. {
  975. HBITMAP hOldBitmap = (HBITMAP)SelectObject( hdcCompat, m_hPaintBitmap );
  976. HPALETTE hOldPalette = SetHalftonePalette( hdcCompat );
  977. if (m_hPaintBitmap)
  978. {
  979. FillRect( hdcCompat, &rcClient, m_hBackgroundBrush );
  980. HDC hdcMem = CreateCompatibleDC(hdcCompat);
  981. if (hdcMem)
  982. {
  983. HPALETTE hOldMemDCPalette = SetHalftonePalette( hdcMem );
  984. HBITMAP hOldMemDCBitmap = (HBITMAP)SelectObject( hdcMem, m_hPreviewBitmap );
  985. int nOldStretchMode = SetStretchBltMode(hdcCompat,STRETCH_HALFTONE);
  986. POINT ptSource = { 0, 0};
  987. SIZE sizeSource = { m_BitmapSize.cx, m_BitmapSize.cy};
  988. if (m_bPreviewMode)
  989. {
  990. POINT ptOrigin;
  991. SIZE sizeExtent;
  992. if (GetOriginAndExtentInImagePixels( 0, ptOrigin, sizeExtent ))
  993. {
  994. ptSource = ptOrigin;
  995. sizeSource = sizeExtent;
  996. }
  997. }
  998. StretchBlt(hdcCompat,rcImage.left,rcImage.top,WiaUiUtil::RectWidth(rcImage),WiaUiUtil::RectHeight(rcImage),hdcMem,ptSource.x,ptSource.y,sizeSource.cx,sizeSource.cy,SRCCOPY);
  999. if (m_hAlphaBitmap)
  1000. {
  1001. SelectObject(hdcMem,m_hAlphaBitmap);
  1002. // First, lay down our lovely border
  1003. FillRect( hdcMem,&rcClient,m_hBackgroundBrush );
  1004. // The lay down the alpha blend background
  1005. FillRect( hdcMem,&rcImage,(HBRUSH)GetStockObject(WHITE_BRUSH) );
  1006. // Alpha blend it
  1007. 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);
  1008. }
  1009. //
  1010. // Restore DC state and delete DC
  1011. //
  1012. SelectPalette(hdcMem,hOldMemDCPalette,FALSE);
  1013. SetStretchBltMode(hdcCompat,nOldStretchMode);
  1014. SelectObject(hdcMem,hOldMemDCBitmap);
  1015. DeleteDC(hdcMem);
  1016. }
  1017. }
  1018. //
  1019. // Restore DC state and delete DC
  1020. //
  1021. SelectObject( hdcCompat, hOldBitmap );
  1022. SelectPalette( hdcCompat, hOldPalette, FALSE );
  1023. DeleteDC(hdcCompat);
  1024. }
  1025. }
  1026. ReleaseDC(m_hWnd,hdcClient);
  1027. }
  1028. }
  1029. #ifndef RECT_WIDTH
  1030. #define RECT_WIDTH(x) ((x).right - (x).left)
  1031. #endif
  1032. #ifndef RECT_HEIGHT
  1033. #define RECT_HEIGHT(x) ((x).bottom - (x).top)
  1034. #endif
  1035. RECT CWiaPreviewWindow::ScaleSelectionRect( const RECT &rcOriginalImage, const RECT &rcCurrentImage, const RECT &rcOriginalSel )
  1036. {
  1037. RECT rcCurrentSel;
  1038. if (IsDefaultSelectionRect(rcOriginalSel))
  1039. return(rcOriginalSel);
  1040. if (RECT_WIDTH(rcOriginalImage) && RECT_HEIGHT(rcOriginalImage))
  1041. {
  1042. rcCurrentSel.left = rcCurrentImage.left + MulDiv(rcOriginalSel.left-rcOriginalImage.left,RECT_WIDTH(rcCurrentImage),RECT_WIDTH(rcOriginalImage));
  1043. rcCurrentSel.right = rcCurrentImage.left + MulDiv(rcOriginalSel.right-rcOriginalImage.left,RECT_WIDTH(rcCurrentImage),RECT_WIDTH(rcOriginalImage));
  1044. rcCurrentSel.top = rcCurrentImage.top + MulDiv(rcOriginalSel.top-rcOriginalImage.top,RECT_HEIGHT(rcCurrentImage),RECT_HEIGHT(rcOriginalImage));
  1045. rcCurrentSel.bottom = rcCurrentImage.top + MulDiv(rcOriginalSel.bottom-rcOriginalImage.top,RECT_HEIGHT(rcCurrentImage),RECT_HEIGHT(rcOriginalImage));
  1046. }
  1047. else rcCurrentSel = GetDefaultSelection();
  1048. // If we're gone, start over with max selection
  1049. if (rcCurrentSel.left >= rcCurrentSel.right || rcCurrentSel.top >= rcCurrentSel.bottom)
  1050. {
  1051. rcCurrentSel = GetDefaultSelection();
  1052. }
  1053. NormalizeRect(rcCurrentSel);
  1054. if (rcCurrentSel.left < rcCurrentImage.left)
  1055. rcCurrentSel.left = rcCurrentImage.left;
  1056. if (rcCurrentSel.top < rcCurrentImage.top)
  1057. rcCurrentSel.top = rcCurrentImage.top;
  1058. if (rcCurrentSel.right > rcCurrentImage.right)
  1059. rcCurrentSel.right = rcCurrentImage.right;
  1060. if (rcCurrentSel.bottom > rcCurrentImage.bottom)
  1061. rcCurrentSel.bottom = rcCurrentImage.bottom;
  1062. return(rcCurrentSel);
  1063. }
  1064. LRESULT CWiaPreviewWindow::OnSize( WPARAM wParam, LPARAM )
  1065. {
  1066. int nType = (int)wParam;
  1067. if ((nType == SIZE_RESTORED || nType == SIZE_MAXIMIZED))
  1068. {
  1069. //
  1070. // Resize the progress control if it exists
  1071. //
  1072. ResizeProgressBar();
  1073. if (!m_bSizing)
  1074. {
  1075. RECT rcCurrentImageRect = GetImageRect();
  1076. m_rcCurrSel = ScaleSelectionRect( m_rcSavedImageRect, rcCurrentImageRect, m_rcCurrSel );
  1077. m_rcSavedImageRect = rcCurrentImageRect;
  1078. CreateNewBitmaps();
  1079. DrawBitmaps();
  1080. Repaint(NULL,false);
  1081. SendSelChangeNotification(false);
  1082. }
  1083. else Repaint(NULL,false);
  1084. }
  1085. return(LRESULT)0;
  1086. }
  1087. LRESULT CWiaPreviewWindow::OnSetText( WPARAM wParam, LPARAM lParam )
  1088. {
  1089. LRESULT lResult = DefWindowProc( m_hWnd, WM_SETTEXT, wParam, lParam );
  1090. InvalidateRect( m_hWnd, NULL, FALSE );
  1091. UpdateWindow( m_hWnd );
  1092. return(lResult);
  1093. }
  1094. LRESULT CWiaPreviewWindow::OnGetDlgCode( WPARAM, LPARAM )
  1095. {
  1096. return(LRESULT)(DLGC_WANTARROWS);
  1097. }
  1098. LRESULT CWiaPreviewWindow::OnKeyDown( WPARAM wParam, LPARAM )
  1099. {
  1100. if (!m_hPreviewBitmap || m_SelectionDisabled || m_bPreviewMode || IsDefaultSelectionRect(m_rcCurrSel))
  1101. return(0);
  1102. int nVirtKey = (int)wParam;
  1103. int nAccelerate = 1;
  1104. if (GetKeyState(VK_CONTROL) & 0x8000)
  1105. nAccelerate = DEFAULT_ACCEL_FACTOR;
  1106. RECT rcImage = GetImageRect(), rcOldCurrSel;
  1107. CopyRect(&rcOldCurrSel,&m_rcCurrSel);
  1108. // If SHIFT key is pressed, but ALT is not
  1109. if (!(GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(VK_SHIFT) & 0x8000))
  1110. {
  1111. switch (nVirtKey)
  1112. {
  1113. case VK_UP:
  1114. if (m_rcCurrSel.bottom > m_rcCurrSel.top+nAccelerate)
  1115. m_rcCurrSel.bottom -= nAccelerate;
  1116. else m_rcCurrSel.bottom = m_rcCurrSel.top;
  1117. break;
  1118. case VK_DOWN:
  1119. m_rcCurrSel.bottom += nAccelerate;
  1120. if (m_rcCurrSel.bottom > rcImage.bottom)
  1121. m_rcCurrSel.bottom = rcImage.bottom;
  1122. break;
  1123. case VK_RIGHT:
  1124. m_rcCurrSel.right += nAccelerate;
  1125. if (m_rcCurrSel.right > rcImage.right)
  1126. m_rcCurrSel.right = rcImage.right;
  1127. break;
  1128. case VK_LEFT:
  1129. if (m_rcCurrSel.right > m_rcCurrSel.left+nAccelerate)
  1130. m_rcCurrSel.right -= nAccelerate;
  1131. else m_rcCurrSel.right = m_rcCurrSel.left;
  1132. break;
  1133. }
  1134. }
  1135. // If SHIFT key not is pressed and ALT is not
  1136. if (!(GetKeyState(VK_MENU) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000))
  1137. {
  1138. switch (nVirtKey)
  1139. {
  1140. case VK_DELETE:
  1141. m_rcCurrSel = GetDefaultSelection();
  1142. break;
  1143. case VK_HOME:
  1144. OffsetRect( &m_rcCurrSel, rcImage.left-m_rcCurrSel.left, 0 );
  1145. break;
  1146. case VK_END:
  1147. OffsetRect( &m_rcCurrSel, rcImage.right-m_rcCurrSel.right, 0 );
  1148. break;
  1149. case VK_PRIOR:
  1150. OffsetRect( &m_rcCurrSel, 0, rcImage.top-m_rcCurrSel.top );
  1151. break;
  1152. case VK_NEXT:
  1153. OffsetRect( &m_rcCurrSel, 0, rcImage.bottom-m_rcCurrSel.bottom );
  1154. break;
  1155. case VK_UP:
  1156. OffsetRect(&m_rcCurrSel,0,-nAccelerate);
  1157. if (m_rcCurrSel.top < rcImage.top)
  1158. OffsetRect(&m_rcCurrSel,0,-m_rcCurrSel.top+rcImage.top);
  1159. break;
  1160. case VK_LEFT:
  1161. OffsetRect(&m_rcCurrSel,-nAccelerate,0);
  1162. if (m_rcCurrSel.left < rcImage.left)
  1163. OffsetRect(&m_rcCurrSel,-m_rcCurrSel.left+rcImage.left,0);
  1164. break;
  1165. case VK_DOWN:
  1166. OffsetRect(&m_rcCurrSel,0,nAccelerate);
  1167. if (m_rcCurrSel.bottom > rcImage.bottom)
  1168. OffsetRect(&m_rcCurrSel,0,-(m_rcCurrSel.bottom-rcImage.bottom));
  1169. break;
  1170. case VK_RIGHT:
  1171. OffsetRect(&m_rcCurrSel,nAccelerate,0);
  1172. if (m_rcCurrSel.right > rcImage.right)
  1173. OffsetRect(&m_rcCurrSel,-(m_rcCurrSel.right-rcImage.right),0);
  1174. break;
  1175. }
  1176. }
  1177. if (IsDefaultSelectionRect(m_rcCurrSel))
  1178. {
  1179. InvalidateRect( m_hWnd, NULL, FALSE );
  1180. UpdateWindow( m_hWnd );
  1181. SendSelChangeNotification();
  1182. }
  1183. else if (memcmp(&rcOldCurrSel,&m_rcCurrSel,sizeof(RECT)))
  1184. {
  1185. RECT rcCurSel = m_rcCurrSel, rcInvalid;
  1186. NormalizeRect(rcOldCurrSel);
  1187. NormalizeRect(rcCurSel);
  1188. TrueUnionRect(&rcInvalid,&rcCurSel,&rcOldCurrSel);
  1189. rcInvalid.left-=m_nHandleSize;
  1190. rcInvalid.top-=m_nHandleSize;
  1191. rcInvalid.right+=m_nHandleSize;
  1192. rcInvalid.bottom+=m_nHandleSize;
  1193. Repaint(&rcInvalid,false);
  1194. UpdateWindow(m_hWnd);
  1195. SendSelChangeNotification();
  1196. }
  1197. return(LRESULT)0;
  1198. }
  1199. //wParam = 0, lParam = LPSIZE lpResolution
  1200. LRESULT CWiaPreviewWindow::OnSetResolution( WPARAM, LPARAM lParam )
  1201. {
  1202. if (lParam)
  1203. {
  1204. m_Resolution = *((LPSIZE)lParam);
  1205. }
  1206. else
  1207. {
  1208. m_Resolution.cx = m_Resolution.cy = 0;
  1209. }
  1210. return(LRESULT)0;
  1211. }
  1212. //wParam = 0, lParam = LPSIZE lpResolution
  1213. LRESULT CWiaPreviewWindow::OnGetResolution( WPARAM, LPARAM lParam )
  1214. {
  1215. if (lParam)
  1216. {
  1217. *reinterpret_cast<SIZE*>(lParam) = m_Resolution;
  1218. return(LRESULT)1;
  1219. }
  1220. return(LRESULT)0;
  1221. }
  1222. //wParam = 0, lParam = LPRECT lprcSelRect
  1223. LRESULT CWiaPreviewWindow::OnClearSelection( WPARAM, LPARAM )
  1224. {
  1225. m_rcCurrSel = GetDefaultSelection();
  1226. Repaint(NULL,false);
  1227. return(LRESULT)0;
  1228. }
  1229. // wParam = (BOOL)MAKEWPARAM(bRepaint,bDontDestroy), lParam = (HBITMAP)hBmp
  1230. LRESULT CWiaPreviewWindow::OnSetBitmap( WPARAM wParam, LPARAM lParam )
  1231. {
  1232. if (m_bDeleteBitmap && m_hPreviewBitmap)
  1233. DeleteObject(m_hPreviewBitmap);
  1234. m_hPreviewBitmap = (HBITMAP)lParam;
  1235. m_BitmapSize.cx = m_BitmapSize.cy = 0;
  1236. if (m_hPreviewBitmap)
  1237. {
  1238. BITMAP bm = {0};
  1239. if (GetObject(m_hPreviewBitmap,sizeof(BITMAP),&bm))
  1240. {
  1241. m_BitmapSize.cx = bm.bmWidth;
  1242. m_BitmapSize.cy = bm.bmHeight;
  1243. }
  1244. }
  1245. m_bDeleteBitmap = !HIWORD(wParam);
  1246. if (!m_hPaintBitmap || !m_hBufferBitmap || (!m_hAlphaBitmap && IsAlphaBlendEnabled()))
  1247. {
  1248. CreateNewBitmaps();
  1249. }
  1250. DrawBitmaps();
  1251. if (LOWORD(wParam))
  1252. {
  1253. Repaint(NULL,false);
  1254. }
  1255. return(LRESULT)0;
  1256. }
  1257. // wParam = 0, lParam = 0
  1258. LRESULT CWiaPreviewWindow::OnGetBitmap( WPARAM wParam, LPARAM lParam )
  1259. {
  1260. return(LRESULT)m_hPreviewBitmap;
  1261. }
  1262. LRESULT CWiaPreviewWindow::OnSetFocus( WPARAM, LPARAM )
  1263. {
  1264. // If the rect isn't visible, recreate it.
  1265. if (m_rcCurrSel.left == m_rcCurrSel.right || m_rcCurrSel.top == m_rcCurrSel.bottom && !IsDefaultSelectionRect(m_rcCurrSel))
  1266. {
  1267. m_rcCurrSel = GetDefaultSelection();
  1268. }
  1269. Repaint(NULL,false);
  1270. return(LRESULT)0;
  1271. }
  1272. LRESULT CWiaPreviewWindow::OnKillFocus( WPARAM, LPARAM )
  1273. {
  1274. Repaint(NULL,false);
  1275. return(LRESULT)0;
  1276. }
  1277. LRESULT CWiaPreviewWindow::OnEnable( WPARAM, LPARAM )
  1278. {
  1279. Repaint(NULL,false);
  1280. return(LRESULT)0;
  1281. }
  1282. LRESULT CWiaPreviewWindow::OnEraseBkgnd( WPARAM, LPARAM )
  1283. {
  1284. return(LRESULT)1;
  1285. }
  1286. LRESULT CWiaPreviewWindow::OnGetBorderSize( WPARAM, LPARAM )
  1287. {
  1288. return(m_nBorderSize);
  1289. }
  1290. LRESULT CWiaPreviewWindow::OnGetHandleSize( WPARAM, LPARAM )
  1291. {
  1292. return(m_nHandleSize);
  1293. }
  1294. LRESULT CWiaPreviewWindow::OnGetBgAlpha( WPARAM, LPARAM )
  1295. {
  1296. return(m_bfBlendFunction.SourceConstantAlpha);
  1297. }
  1298. LRESULT CWiaPreviewWindow::OnGetHandleType( WPARAM, LPARAM )
  1299. {
  1300. return(m_nHandleType);
  1301. }
  1302. LRESULT CWiaPreviewWindow::OnSetBorderSize( WPARAM wParam, LPARAM lParam )
  1303. {
  1304. int nOldBorder = m_nBorderSize;
  1305. m_nBorderSize = (UINT)lParam;
  1306. if (wParam)
  1307. {
  1308. DrawBitmaps();
  1309. Repaint(NULL,false);
  1310. }
  1311. return(nOldBorder);
  1312. }
  1313. LRESULT CWiaPreviewWindow::OnSetHandleSize( WPARAM wParam, LPARAM lParam )
  1314. {
  1315. int nOldHandleSize = m_nHandleSize;
  1316. m_nHandleSize = (int)lParam;
  1317. if (wParam)
  1318. Repaint(NULL,false);
  1319. return(nOldHandleSize);
  1320. }
  1321. LRESULT CWiaPreviewWindow::OnSetBgAlpha( WPARAM wParam, LPARAM lParam )
  1322. {
  1323. int nOldBgAlpha = m_bfBlendFunction.SourceConstantAlpha;
  1324. m_bfBlendFunction.SourceConstantAlpha = (BYTE)lParam;
  1325. if (wParam)
  1326. {
  1327. DrawBitmaps();
  1328. Repaint(NULL,false);
  1329. }
  1330. return(nOldBgAlpha);
  1331. }
  1332. LRESULT CWiaPreviewWindow::OnSetHandleType( WPARAM wParam, LPARAM lParam )
  1333. {
  1334. int nOldHandleType = m_nHandleType;
  1335. m_nHandleType = (int)lParam;
  1336. if (wParam)
  1337. Repaint(NULL,false);
  1338. return(nOldHandleType);
  1339. }
  1340. LRESULT CWiaPreviewWindow::OnEnterSizeMove( WPARAM, LPARAM )
  1341. {
  1342. m_bSizing = true;
  1343. return(0);
  1344. }
  1345. LRESULT CWiaPreviewWindow::OnExitSizeMove( WPARAM, LPARAM )
  1346. {
  1347. if (m_bSizing)
  1348. {
  1349. m_bSizing = false;
  1350. RECT rcCurrentImageRect = GetImageRect();
  1351. if (memcmp(&rcCurrentImageRect,&m_rcSavedImageRect,sizeof(RECT)))
  1352. {
  1353. m_rcCurrSel = ScaleSelectionRect( m_rcSavedImageRect, rcCurrentImageRect, m_rcCurrSel );
  1354. m_rcSavedImageRect = rcCurrentImageRect;
  1355. CreateNewBitmaps();
  1356. DrawBitmaps();
  1357. SendSelChangeNotification(false);
  1358. }
  1359. Repaint(NULL,false);
  1360. }
  1361. return(0);
  1362. }
  1363. // wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PPOINT)pOrigin
  1364. LRESULT CWiaPreviewWindow::OnGetSelOrigin( WPARAM wParam, LPARAM lParam )
  1365. {
  1366. int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
  1367. int nItem = (int)LOWORD(wParam);
  1368. BOOL bPhysical = (BOOL)HIWORD(wParam);
  1369. PPOINT pOrigin = (PPOINT)lParam;
  1370. RECT rcImage = GetImageRect();
  1371. if (nCount <= 0 || nItem < 0 || nItem >= nCount || !pOrigin)
  1372. return(0);
  1373. RECT rcSel = m_rcCurrSel;
  1374. NormalizeRect(rcSel);
  1375. if (IsRectEmpty(&rcSel))
  1376. rcSel = rcImage;
  1377. if (bPhysical)
  1378. {
  1379. pOrigin->x = rcSel.left - rcImage.left;
  1380. pOrigin->y = rcSel.top - rcImage.top;
  1381. return(1);
  1382. }
  1383. else if (RECT_WIDTH(rcImage) && RECT_HEIGHT(rcImage)) // Make sure we get no divide by zero errors
  1384. {
  1385. pOrigin->x = WiaUiUtil::MulDivNoRound(m_Resolution.cx,rcSel.left-rcImage.left,RECT_WIDTH(rcImage));
  1386. pOrigin->y = WiaUiUtil::MulDivNoRound(m_Resolution.cy,rcSel.top-rcImage.top,RECT_HEIGHT(rcImage));
  1387. return(1);
  1388. }
  1389. else return(0);
  1390. }
  1391. // wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PSIZE)pExtent
  1392. LRESULT CWiaPreviewWindow::OnGetSelExtent( WPARAM wParam, LPARAM lParam )
  1393. {
  1394. int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
  1395. int nItem = (int)LOWORD(wParam);
  1396. BOOL bPhysical = (BOOL)HIWORD(wParam);
  1397. PSIZE pExtent = (PSIZE)lParam;
  1398. RECT rcImage = GetImageRect();
  1399. if (nCount <= 0 || nItem < 0 || nItem >= nCount || !pExtent)
  1400. return(0);
  1401. RECT rcSel = m_rcCurrSel;
  1402. NormalizeRect(rcSel);
  1403. if (IsRectEmpty(&rcSel))
  1404. rcSel = rcImage;
  1405. if (bPhysical)
  1406. {
  1407. pExtent->cx = RECT_WIDTH(rcSel);
  1408. pExtent->cy = RECT_HEIGHT(rcSel);
  1409. return(1);
  1410. }
  1411. else if (RECT_WIDTH(rcImage) && RECT_HEIGHT(rcImage)) // Make sure we get no divide by zero errors
  1412. {
  1413. pExtent->cx = WiaUiUtil::MulDivNoRound(m_Resolution.cx,RECT_WIDTH(rcSel),RECT_WIDTH(rcImage));
  1414. pExtent->cy = WiaUiUtil::MulDivNoRound(m_Resolution.cy,RECT_HEIGHT(rcSel),RECT_HEIGHT(rcImage));
  1415. return(1);
  1416. }
  1417. else return(0);
  1418. }
  1419. // wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PPOINT)pOrigin
  1420. LRESULT CWiaPreviewWindow::OnSetSelOrigin( WPARAM wParam, LPARAM lParam )
  1421. {
  1422. int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
  1423. int nItem = (int)LOWORD(wParam);
  1424. BOOL bPhysical = (BOOL)HIWORD(wParam);
  1425. PPOINT pOrigin = (PPOINT)lParam;
  1426. RECT rcImage = GetImageRect();
  1427. if (nCount <= 0 || nItem < 0 || nItem >= nCount)
  1428. {
  1429. return(0);
  1430. }
  1431. else if (!pOrigin)
  1432. {
  1433. m_rcCurrSel = rcImage;
  1434. Repaint( NULL, FALSE );
  1435. return(1);
  1436. }
  1437. else if (bPhysical)
  1438. {
  1439. m_rcCurrSel.left = rcImage.left + pOrigin->x;
  1440. m_rcCurrSel.top = rcImage.top + pOrigin->y;
  1441. Repaint( NULL, FALSE );
  1442. return(1);
  1443. }
  1444. else if (m_Resolution.cx && m_Resolution.cy) // Make sure we get no divide by zero errors
  1445. {
  1446. m_rcCurrSel.left = rcImage.left + MulDiv(pOrigin->x,RECT_WIDTH(rcImage),m_Resolution.cx);
  1447. m_rcCurrSel.top = rcImage.top + MulDiv(pOrigin->y,RECT_HEIGHT(rcImage),m_Resolution.cy);
  1448. Repaint( NULL, FALSE );
  1449. return(1);
  1450. }
  1451. else return(0);
  1452. }
  1453. // wParam = (BOOL)MAKEWPARAM((WORD)nItem,(BOOL)bPhysical), lParam = (PSIZE)pExtent
  1454. LRESULT CWiaPreviewWindow::OnSetSelExtent( WPARAM wParam, LPARAM lParam )
  1455. {
  1456. int nCount = static_cast<int>(SendMessage( m_hWnd, PWM_GETSELCOUNT, 0, 0 ));
  1457. int nItem = static_cast<int>(LOWORD(wParam));
  1458. BOOL bPhysical = (BOOL)HIWORD(wParam);
  1459. PSIZE pExtent = (PSIZE)lParam;
  1460. RECT rcImage = GetImageRect();
  1461. if (nCount <= 0 || nItem < 0 || nItem >= nCount)
  1462. {
  1463. return(0);
  1464. }
  1465. else if (!pExtent)
  1466. {
  1467. m_rcCurrSel = rcImage;
  1468. Repaint( NULL, FALSE );
  1469. return(1);
  1470. }
  1471. else if (bPhysical)
  1472. {
  1473. m_rcCurrSel.right = m_rcCurrSel.left + pExtent->cx;
  1474. m_rcCurrSel.bottom = m_rcCurrSel.top + pExtent->cy;
  1475. Repaint(NULL,FALSE);
  1476. return(1);
  1477. }
  1478. else if (m_Resolution.cx && m_Resolution.cy) // Make sure we get no divide by zero errors
  1479. {
  1480. m_rcCurrSel.right = m_rcCurrSel.left + MulDiv(pExtent->cx,RECT_WIDTH(rcImage),m_Resolution.cx);
  1481. m_rcCurrSel.bottom = m_rcCurrSel.top + MulDiv(pExtent->cy,RECT_HEIGHT(rcImage),m_Resolution.cy);
  1482. Repaint( NULL, FALSE );
  1483. return(1);
  1484. }
  1485. else return(0);
  1486. }
  1487. LRESULT CWiaPreviewWindow::OnGetSelCount( WPARAM wParam, LPARAM lParam )
  1488. {
  1489. return(GetSelectionRectCount()); // For now...
  1490. }
  1491. BOOL CWiaPreviewWindow::IsDefaultSelectionRect( const RECT &rc )
  1492. {
  1493. if (!m_bAllowNullSelection)
  1494. return(FALSE);
  1495. RECT rcSel = rc;
  1496. NormalizeRect(rcSel);
  1497. RECT rcDefault = GetDefaultSelection();
  1498. return(rcSel.left == rcDefault.left &&
  1499. rcSel.top == rcDefault.top &&
  1500. rcSel.right == rcDefault.right &&
  1501. rcSel.bottom == rcDefault.bottom);
  1502. }
  1503. RECT CWiaPreviewWindow::GetDefaultSelection(void)
  1504. {
  1505. if (m_bAllowNullSelection)
  1506. {
  1507. RECT r = {-100,-100,-100,-100};
  1508. return(r);
  1509. }
  1510. else return(GetImageRect());
  1511. }
  1512. LRESULT CWiaPreviewWindow::OnGetAllowNullSelection( WPARAM, LPARAM )
  1513. {
  1514. return(m_bAllowNullSelection != FALSE);
  1515. }
  1516. // wParam = (BOOL)bAllowNullSelection, lParam = 0
  1517. LRESULT CWiaPreviewWindow::OnSetAllowNullSelection( WPARAM wParam, LPARAM )
  1518. {
  1519. BOOL bOldAllowNullSelection = m_bAllowNullSelection;
  1520. if (wParam)
  1521. m_bAllowNullSelection = TRUE;
  1522. else m_bAllowNullSelection = FALSE;
  1523. return(bOldAllowNullSelection);
  1524. }
  1525. LRESULT CWiaPreviewWindow::OnGetDisableSelection( WPARAM, LPARAM )
  1526. {
  1527. return(m_SelectionDisabled != FALSE);
  1528. }
  1529. // wParam = (BOOL)bDisableSelection, lParam = 0
  1530. LRESULT CWiaPreviewWindow::OnSetDisableSelection( WPARAM wParam, LPARAM )
  1531. {
  1532. BOOL bReturn = (m_SelectionDisabled != FALSE);
  1533. m_SelectionDisabled = (wParam != 0);
  1534. Repaint(NULL,false);
  1535. return(bReturn);
  1536. }
  1537. int CWiaPreviewWindow::GetSelectionRectCount(void)
  1538. {
  1539. return(1);
  1540. }
  1541. // wParam = 0, lParam = 0
  1542. LRESULT CWiaPreviewWindow::OnGetBkColor( WPARAM, LPARAM )
  1543. {
  1544. LOGBRUSH lb = { 0};
  1545. GetObject(m_hBackgroundBrush,sizeof(LOGBRUSH),&lb);
  1546. return(lb.lbColor);
  1547. }
  1548. // wParam = (BOOL)bRepaint, lParam = (COLORREF)color
  1549. LRESULT CWiaPreviewWindow::OnSetBkColor( WPARAM wParam, LPARAM lParam )
  1550. {
  1551. HBRUSH hBrush = CreateSolidBrush( static_cast<int>(lParam) );
  1552. if (hBrush)
  1553. {
  1554. if (m_hBackgroundBrush)
  1555. {
  1556. DeleteObject(m_hBackgroundBrush);
  1557. m_hBackgroundBrush = NULL;
  1558. }
  1559. m_hBackgroundBrush = hBrush;
  1560. if (wParam)
  1561. {
  1562. DrawBitmaps();
  1563. Repaint(NULL,false);
  1564. }
  1565. return(1);
  1566. }
  1567. return(0);
  1568. }
  1569. LRESULT CWiaPreviewWindow::OnSetPreviewMode( WPARAM, LPARAM lParam )
  1570. {
  1571. m_bPreviewMode = (lParam != FALSE);
  1572. DrawBitmaps();
  1573. Repaint(NULL,false);
  1574. return(0);
  1575. }
  1576. LRESULT CWiaPreviewWindow::OnRefreshBitmap( WPARAM, LPARAM )
  1577. {
  1578. DrawBitmaps();
  1579. Repaint(NULL,false);
  1580. return(0);
  1581. }
  1582. LRESULT CWiaPreviewWindow::OnGetPreviewMode( WPARAM, LPARAM )
  1583. {
  1584. return(m_bPreviewMode != false);
  1585. }
  1586. void CWiaPreviewWindow::SetCursor( HCURSOR hCursor )
  1587. {
  1588. m_hCurrentCursor = hCursor;
  1589. ::SetCursor(m_hCurrentCursor);
  1590. }
  1591. LRESULT CWiaPreviewWindow::OnSetCursor( WPARAM wParam, LPARAM lParam )
  1592. {
  1593. if (reinterpret_cast<HWND>(wParam) == m_hWnd && m_hCurrentCursor)
  1594. {
  1595. ::SetCursor(m_hCurrentCursor);
  1596. return(TRUE);
  1597. }
  1598. else return(DefWindowProc( m_hWnd, WM_SETCURSOR, wParam, lParam ));
  1599. }
  1600. // wParam = MAKEWPARAM(bRepaint,0), lParam = MAKELPARAM(nBorderStyle,nBorderThickness)
  1601. LRESULT CWiaPreviewWindow::OnSetBorderStyle( WPARAM wParam, LPARAM lParam )
  1602. {
  1603. // Recreate the handle border pens. Don't apply the line style, just the thickness.
  1604. for (int i=0;i<ARRAYSIZE(m_aHandlePens);i++)
  1605. {
  1606. LOGPEN LogPen;
  1607. ZeroMemory(&LogPen,sizeof(LOGPEN));
  1608. if (GetObject( m_aHandlePens[i], sizeof(LOGPEN), &LogPen ))
  1609. {
  1610. LogPen.lopnWidth.x = HIWORD(lParam);
  1611. if (m_aHandlePens[i])
  1612. DeleteObject(m_aHandlePens[i]);
  1613. m_aHandlePens[i] = CreatePenIndirect(&LogPen);
  1614. }
  1615. }
  1616. // Recreate the selection border pens. Apply the line style, just the thickness.
  1617. for (i=0;i<ARRAYSIZE(m_aBorderPens);i++)
  1618. {
  1619. LOGPEN LogPen;
  1620. ZeroMemory(&LogPen,sizeof(LOGPEN));
  1621. if (GetObject( m_aBorderPens[i], sizeof(LOGPEN), &LogPen ))
  1622. {
  1623. LogPen.lopnWidth.x = (UINT)HIWORD(lParam);
  1624. LogPen.lopnStyle = LOWORD(lParam);
  1625. if (m_aBorderPens[i])
  1626. DeleteObject(m_aBorderPens[i]);
  1627. m_aBorderPens[i] = CreatePenIndirect(&LogPen);
  1628. }
  1629. }
  1630. if (LOWORD(wParam))
  1631. {
  1632. Repaint(NULL,FALSE);
  1633. }
  1634. return(0);
  1635. }
  1636. // wParam = MAKEWPARAM(bRepaint,nState), lParam = (COLORREF)crColor
  1637. LRESULT CWiaPreviewWindow::OnSetBorderColor( WPARAM wParam, LPARAM lParam )
  1638. {
  1639. int nState = static_cast<int>(HIWORD(wParam));
  1640. if (nState >= 0 && nState < 3)
  1641. {
  1642. LOGPEN LogPen;
  1643. ZeroMemory(&LogPen,sizeof(LOGPEN));
  1644. if (GetObject( m_aHandlePens[nState], sizeof(LOGPEN), &LogPen ))
  1645. {
  1646. LogPen.lopnColor = static_cast<COLORREF>(lParam);
  1647. if (m_aHandlePens[nState])
  1648. DeleteObject(m_aHandlePens[nState]);
  1649. m_aHandlePens[nState] = CreatePenIndirect(&LogPen);
  1650. }
  1651. ZeroMemory(&LogPen,sizeof(LOGPEN));
  1652. if (GetObject( m_aBorderPens[nState], sizeof(LOGPEN), &LogPen ))
  1653. {
  1654. LogPen.lopnColor = static_cast<COLORREF>(lParam);
  1655. if (m_aBorderPens[nState])
  1656. DeleteObject(m_aBorderPens[nState]);
  1657. m_aBorderPens[nState] = CreatePenIndirect(&LogPen);
  1658. }
  1659. }
  1660. if (LOWORD(wParam))
  1661. {
  1662. Repaint(NULL,FALSE);
  1663. }
  1664. return(0);
  1665. }
  1666. // wParam = MAKEWPARAM(bRepaint,nState), lParam = (COLORREF)crColor
  1667. LRESULT CWiaPreviewWindow::OnSetHandleColor( WPARAM wParam, LPARAM lParam )
  1668. {
  1669. int nState = static_cast<int>(HIWORD(wParam));
  1670. if (nState >= 0 && nState < 3)
  1671. {
  1672. if (m_aHandleBrushes[nState])
  1673. {
  1674. DeleteObject(m_aHandleBrushes[nState]);
  1675. m_aHandleBrushes[nState] = NULL;
  1676. }
  1677. m_aHandleBrushes[nState] = CreateSolidBrush( static_cast<COLORREF>(lParam) );
  1678. }
  1679. if (LOWORD(wParam))
  1680. {
  1681. Repaint(NULL,FALSE);
  1682. }
  1683. return(0);
  1684. }
  1685. void CWiaPreviewWindow::ResizeProgressBar()
  1686. {
  1687. HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
  1688. if (hWndProgress)
  1689. {
  1690. //
  1691. // Resize the progress control to fill the client
  1692. //
  1693. RECT rcImage = GetImageRect();
  1694. CDialogUnits DialogUnits( m_hWnd );
  1695. SIZE sizeProgress = { WiaUiUtil::RectWidth(rcImage) - DialogUnits.X(28), DialogUnits.Y(14) };
  1696. POINT ptProgress = { rcImage.left + (WiaUiUtil::RectWidth(rcImage) - sizeProgress.cx) / 2, rcImage.top + (WiaUiUtil::RectHeight(rcImage) - sizeProgress.cy) / 2 };
  1697. MoveWindow( hWndProgress, ptProgress.x, ptProgress.y, sizeProgress.cx, sizeProgress.cy, TRUE );
  1698. }
  1699. }
  1700. //
  1701. // wParam = bShow
  1702. //
  1703. LRESULT CWiaPreviewWindow::OnSetProgress( WPARAM wParam, LPARAM lParam )
  1704. {
  1705. //
  1706. // Assume failure
  1707. //
  1708. LRESULT lResult = FALSE;
  1709. //
  1710. // If wParam is true, create the control
  1711. //
  1712. if (wParam)
  1713. {
  1714. //
  1715. // See if the control is already created.
  1716. //
  1717. HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
  1718. if (!hWndProgress)
  1719. {
  1720. //
  1721. // If it isn't, create it.
  1722. //
  1723. hWndProgress = CreateWindow( PROGRESS_CLASS, TEXT(""), WS_CHILD|WS_VISIBLE|PBS_MARQUEE, 0, 0, 0, 0, m_hWnd, reinterpret_cast<HMENU>(IDC_PROGRESSCONTROL), NULL, NULL );
  1724. if (hWndProgress)
  1725. {
  1726. //
  1727. // Put it in marquee mode
  1728. //
  1729. SendMessage( hWndProgress, PBM_SETMARQUEE, TRUE, 100 );
  1730. //
  1731. // Resize it
  1732. //
  1733. ResizeProgressBar();
  1734. }
  1735. }
  1736. //
  1737. // Success = we have a progress bar
  1738. //
  1739. lResult = (hWndProgress != NULL);
  1740. }
  1741. //
  1742. // Otherwise, destroy the control if it exists
  1743. //
  1744. else
  1745. {
  1746. HWND hWndProgress = GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL );
  1747. if (hWndProgress)
  1748. {
  1749. //
  1750. // Nuke it
  1751. //
  1752. DestroyWindow(hWndProgress);
  1753. }
  1754. lResult = true;
  1755. }
  1756. //
  1757. // Force a repaint
  1758. //
  1759. InvalidateRect( m_hWnd, NULL, FALSE );
  1760. UpdateWindow(m_hWnd);
  1761. return lResult;
  1762. }
  1763. LRESULT CWiaPreviewWindow::OnGetProgress( WPARAM, LPARAM )
  1764. {
  1765. return (NULL != GetDlgItem( m_hWnd, IDC_PROGRESSCONTROL ));
  1766. }
  1767. LRESULT CWiaPreviewWindow::OnCtlColorStatic( WPARAM wParam, LPARAM )
  1768. {
  1769. SetBkColor( reinterpret_cast<HDC>( wParam ), GetSysColor( COLOR_WINDOW ) );
  1770. return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW));
  1771. }
  1772. LRESULT CWiaPreviewWindow::OnSetUserChangedSelection( WPARAM wParam, LPARAM )
  1773. {
  1774. LRESULT lRes = m_bUserChangedSelection;
  1775. m_bUserChangedSelection = (wParam != 0);
  1776. return lRes;
  1777. }
  1778. LRESULT CWiaPreviewWindow::OnGetUserChangedSelection( WPARAM, LPARAM )
  1779. {
  1780. return static_cast<LRESULT>(m_bUserChangedSelection);
  1781. }
  1782. LRESULT CALLBACK CWiaPreviewWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1783. {
  1784. SC_BEGIN_MESSAGE_HANDLERS(CWiaPreviewWindow)
  1785. {
  1786. SC_HANDLE_MESSAGE( WM_CREATE, OnCreate );
  1787. SC_HANDLE_MESSAGE( WM_ERASEBKGND, OnEraseBkgnd );
  1788. SC_HANDLE_MESSAGE( WM_PAINT, OnPaint );
  1789. SC_HANDLE_MESSAGE( WM_MOUSEMOVE, OnMouseMove );
  1790. SC_HANDLE_MESSAGE( WM_LBUTTONDOWN, OnLButtonDown );
  1791. SC_HANDLE_MESSAGE( WM_LBUTTONUP, OnLButtonUp );
  1792. SC_HANDLE_MESSAGE( WM_LBUTTONDBLCLK , OnLButtonDblClk );
  1793. SC_HANDLE_MESSAGE( WM_SIZE, OnSize );
  1794. SC_HANDLE_MESSAGE( WM_GETDLGCODE, OnGetDlgCode );
  1795. SC_HANDLE_MESSAGE( WM_KEYDOWN, OnKeyDown );
  1796. SC_HANDLE_MESSAGE( WM_SETFOCUS, OnSetFocus );
  1797. SC_HANDLE_MESSAGE( WM_KILLFOCUS, OnKillFocus );
  1798. SC_HANDLE_MESSAGE( WM_ENABLE, OnEnable );
  1799. SC_HANDLE_MESSAGE( WM_SETTEXT, OnSetText );
  1800. SC_HANDLE_MESSAGE( WM_SETCURSOR, OnSetCursor );
  1801. SC_HANDLE_MESSAGE( WM_CTLCOLORSTATIC, OnCtlColorStatic );
  1802. SC_HANDLE_MESSAGE( PWM_CLEARSELECTION, OnClearSelection );
  1803. SC_HANDLE_MESSAGE( PWM_SETRESOLUTION, OnSetResolution );
  1804. SC_HANDLE_MESSAGE( PWM_GETRESOLUTION, OnGetResolution );
  1805. SC_HANDLE_MESSAGE( PWM_SETBITMAP, OnSetBitmap );
  1806. SC_HANDLE_MESSAGE( PWM_GETBITMAP, OnGetBitmap );
  1807. SC_HANDLE_MESSAGE( PWM_GETBORDERSIZE, OnGetBorderSize );
  1808. SC_HANDLE_MESSAGE( PWM_GETHANDLESIZE, OnGetHandleSize );
  1809. SC_HANDLE_MESSAGE( PWM_GETBGALPHA, OnGetBgAlpha );
  1810. SC_HANDLE_MESSAGE( PWM_GETHANDLETYPE, OnGetHandleType );
  1811. SC_HANDLE_MESSAGE( PWM_SETBORDERSIZE, OnSetBorderSize );
  1812. SC_HANDLE_MESSAGE( PWM_SETHANDLESIZE, OnSetHandleSize );
  1813. SC_HANDLE_MESSAGE( PWM_SETBGALPHA, OnSetBgAlpha );
  1814. SC_HANDLE_MESSAGE( PWM_SETHANDLETYPE, OnSetHandleType );
  1815. SC_HANDLE_MESSAGE( PWM_GETSELCOUNT, OnGetSelCount );
  1816. SC_HANDLE_MESSAGE( PWM_GETSELORIGIN, OnGetSelOrigin );
  1817. SC_HANDLE_MESSAGE( PWM_GETSELEXTENT, OnGetSelExtent );
  1818. SC_HANDLE_MESSAGE( PWM_SETSELORIGIN, OnSetSelOrigin );
  1819. SC_HANDLE_MESSAGE( PWM_SETSELEXTENT, OnSetSelExtent );
  1820. SC_HANDLE_MESSAGE( WM_ENTERSIZEMOVE, OnEnterSizeMove );
  1821. SC_HANDLE_MESSAGE( WM_EXITSIZEMOVE, OnExitSizeMove );
  1822. SC_HANDLE_MESSAGE( PWM_GETALLOWNULLSELECTION, OnGetAllowNullSelection );
  1823. SC_HANDLE_MESSAGE( PWM_SETALLOWNULLSELECTION, OnSetAllowNullSelection );
  1824. SC_HANDLE_MESSAGE( PWM_SELECTIONDISABLED, OnGetDisableSelection );
  1825. SC_HANDLE_MESSAGE( PWM_DISABLESELECTION, OnSetDisableSelection );
  1826. SC_HANDLE_MESSAGE( PWM_DETECTREGIONS, OnDetectRegions);
  1827. SC_HANDLE_MESSAGE( PWM_GETBKCOLOR, OnGetBkColor );
  1828. SC_HANDLE_MESSAGE( PWM_SETBKCOLOR, OnSetBkColor );
  1829. SC_HANDLE_MESSAGE( PWM_SETPREVIEWMODE, OnSetPreviewMode );
  1830. SC_HANDLE_MESSAGE( PWM_GETPREVIEWMODE, OnGetPreviewMode );
  1831. SC_HANDLE_MESSAGE( PWM_GETIMAGESIZE, OnGetImageSize );
  1832. SC_HANDLE_MESSAGE( PWM_SETBORDERSTYLE, OnSetBorderStyle );
  1833. SC_HANDLE_MESSAGE( PWM_SETBORDERCOLOR, OnSetBorderColor );
  1834. SC_HANDLE_MESSAGE( PWM_SETHANDLECOLOR, OnSetHandleColor );
  1835. SC_HANDLE_MESSAGE( PWM_REFRESHBITMAP, OnRefreshBitmap );
  1836. SC_HANDLE_MESSAGE( PWM_SETPROGRESS, OnSetProgress );
  1837. SC_HANDLE_MESSAGE( PWM_GETPROGRESS, OnGetProgress );
  1838. SC_HANDLE_MESSAGE( PWM_SETUSERCHANGEDSELECTION, OnSetUserChangedSelection );
  1839. SC_HANDLE_MESSAGE( PWM_GETUSERCHANGEDSELECTION, OnGetUserChangedSelection );
  1840. }
  1841. SC_END_MESSAGE_HANDLERS();
  1842. }
  1843. // Detects regions using the CRegionDetector class
  1844. // The region detection class is designed to detect
  1845. // multiple regions, but OnDetectRegions merges all of the regions
  1846. // down to one region which it saves as m_rcCurrSel
  1847. LRESULT CWiaPreviewWindow::OnDetectRegions( WPARAM, LPARAM )
  1848. {
  1849. WIA_PUSH_FUNCTION((TEXT("CWiaPreviewWindow::OnDetectRegions")));
  1850. //
  1851. // We are going to assume we can't detect a region
  1852. //
  1853. m_bSuccessfulRegionDetection = false;
  1854. //
  1855. // This could take a while
  1856. //
  1857. CWaitCursor wc;
  1858. //
  1859. // m_hPreviewBitmap holds the bitmap we wish to detect regions on.
  1860. //
  1861. if (m_hBufferBitmap && m_hPreviewBitmap)
  1862. {
  1863. //
  1864. // Get the bitmap info associated with m_hPreviewBitmap
  1865. //
  1866. BITMAP bitmap = {0};
  1867. if (GetObject(m_hPreviewBitmap,sizeof(BITMAP),&bitmap))
  1868. {
  1869. //
  1870. // Unless the preview image is of a reasonable size
  1871. // We are not only wasting the users time, but we are risking
  1872. // crashing his system with too large a file
  1873. //
  1874. if ((bitmap.bmWidth>MIN_REGION_DETECTION_X && bitmap.bmWidth<=MAX_REGION_DETECTION_X) &&
  1875. (bitmap.bmHeight>MIN_REGION_DETECTION_Y && bitmap.bmHeight<=MAX_REGION_DETECTION_Y))
  1876. {
  1877. //
  1878. // Create a region detector
  1879. //
  1880. CRegionDetector *pRegionDetector = new CRegionDetector(bitmap);
  1881. if (pRegionDetector)
  1882. {
  1883. pRegionDetector->FindSingleRegion();
  1884. //
  1885. // findRegions stores coordinates in a system that
  1886. // is a mirror image of the coordinate system used
  1887. // in CWiaPreviewWindow
  1888. //
  1889. pRegionDetector->m_pRegions->FlipVertically();
  1890. if (pRegionDetector->m_pRegions->m_validRects>0)
  1891. {
  1892. pRegionDetector->ConvertToOrigionalCoordinates();
  1893. m_rectSavedDetected=pRegionDetector->m_pRegions->unionAll();
  1894. //
  1895. // we do not call grow regions because the FindSingleRegion algorithm uses edge enhancement
  1896. // which makes GrowRegion unncessary
  1897. //
  1898. //
  1899. // there may not always be a 1-1 correlation between preview pixels and image pixels
  1900. // so to be on the safe side, grow the preview rect out by a couple of pixels
  1901. //
  1902. m_rectSavedDetected=GrowRegion(m_rectSavedDetected,REGION_DETECTION_BORDER);
  1903. m_rcCurrSel=m_rectSavedDetected;
  1904. //
  1905. // we also have to worry about the extra rounding error factor from converting to
  1906. // screen coordinates
  1907. //
  1908. m_rcSavedImageRect = GetImageRect();
  1909. //
  1910. // CWiaPreviewWindow stores the selection rectangle in terms of screen coordinates instead of bitmap coordinates
  1911. //
  1912. m_rcCurrSel=ConvertToScreenCoords(m_rcCurrSel);
  1913. //
  1914. // redisplay the window with the new selection rectangle
  1915. //
  1916. InvalidateRect( m_hWnd, NULL, FALSE );
  1917. UpdateWindow( m_hWnd );
  1918. SendSelChangeNotification(false);
  1919. //
  1920. // We were successful at detecting a region
  1921. //
  1922. m_bSuccessfulRegionDetection = true;
  1923. }
  1924. else
  1925. {
  1926. WIA_TRACE((TEXT("pRegionDetector->m_pRegions->m_validRects was <= 0")));
  1927. }
  1928. //
  1929. // free CRegionDetector
  1930. //
  1931. delete pRegionDetector;
  1932. }
  1933. else
  1934. {
  1935. WIA_TRACE((TEXT("new pRegionDetector returned NULL")));
  1936. }
  1937. }
  1938. else
  1939. {
  1940. WIA_TRACE((TEXT("Bitmap is too large for region detection to work efficiently (bitmap.bmWidth: %d, bitmap.bmHeight: %d)"), bitmap.bmWidth, bitmap.bmHeight));
  1941. }
  1942. }
  1943. else
  1944. {
  1945. WIA_TRACE((TEXT("Unable to get the BITMAP for the hBitmap")));
  1946. }
  1947. }
  1948. else
  1949. {
  1950. WIA_TRACE((TEXT("No bitmap")));
  1951. }
  1952. return (m_bSuccessfulRegionDetection ? TRUE : FALSE);
  1953. }
  1954. RECT CWiaPreviewWindow::GrowRegion(RECT r, int border)
  1955. {
  1956. r.left-=border;
  1957. r.top-=border;
  1958. r.right+=border;
  1959. r.bottom+=border;
  1960. if (r.left<0) r.left=0;
  1961. if (r.right>=m_BitmapSize.cx) r.right=m_BitmapSize.cx-1;
  1962. if (r.top<0) r.top=0;
  1963. if (r.top>=m_BitmapSize.cy) r.top=m_BitmapSize.cy-1;
  1964. return(r);
  1965. }
  1966. int CWiaPreviewWindow::XConvertToBitmapCoords(int x)
  1967. {
  1968. return((x-m_rcSavedImageRect.left)*m_BitmapSize.cx)/WiaUiUtil::RectWidth(m_rcSavedImageRect);
  1969. }
  1970. int CWiaPreviewWindow::XConvertToScreenCoords(int x)
  1971. {
  1972. return(x*WiaUiUtil::RectWidth(m_rcSavedImageRect))/m_BitmapSize.cx+m_rcSavedImageRect.left;
  1973. }
  1974. int CWiaPreviewWindow::YConvertToBitmapCoords(int y)
  1975. {
  1976. return((y-m_rcSavedImageRect.top)*m_BitmapSize.cy)/WiaUiUtil::RectHeight(m_rcSavedImageRect);
  1977. }
  1978. int CWiaPreviewWindow::YConvertToScreenCoords(int y)
  1979. {
  1980. return(y*WiaUiUtil::RectHeight(m_rcSavedImageRect))/m_BitmapSize.cy+m_rcSavedImageRect.top;
  1981. }
  1982. // Convert between bitmap coordinates and screen coordinates
  1983. POINT CWiaPreviewWindow::ConvertToBitmapCoords(POINT p)
  1984. {
  1985. p.x=XConvertToBitmapCoords(p.x);
  1986. p.y=YConvertToBitmapCoords(p.y);
  1987. return(p);
  1988. }
  1989. POINT CWiaPreviewWindow::ConvertToScreenCoords(POINT p)
  1990. {
  1991. p.x=XConvertToScreenCoords(p.x);
  1992. p.y=YConvertToScreenCoords(p.y);
  1993. return(p);
  1994. }
  1995. RECT CWiaPreviewWindow::ConvertToBitmapCoords(RECT r)
  1996. {
  1997. r.left=XConvertToBitmapCoords(r.left);
  1998. r.top=YConvertToBitmapCoords(r.top);
  1999. r.right=XConvertToBitmapCoords(r.right);
  2000. r.bottom=YConvertToBitmapCoords(r.bottom);
  2001. return(r);
  2002. }
  2003. RECT CWiaPreviewWindow::ConvertToScreenCoords(RECT r)
  2004. {
  2005. RECT newRect;
  2006. newRect.left=XConvertToScreenCoords(r.left);
  2007. newRect.top=YConvertToScreenCoords(r.top);
  2008. newRect.right=XConvertToScreenCoords(r.right);
  2009. newRect.bottom=YConvertToScreenCoords(r.bottom);
  2010. return(newRect);
  2011. }
  2012. LRESULT CWiaPreviewWindow::OnLButtonDblClk( WPARAM wParam, LPARAM lParam )
  2013. {
  2014. if (!m_hPreviewBitmap || m_bPreviewMode || m_SelectionDisabled)
  2015. {
  2016. return(0);
  2017. }
  2018. if (GetFocus() != m_hWnd)
  2019. {
  2020. SetFocus(m_hWnd);
  2021. }
  2022. POINT point;
  2023. point.x = LOWORD(lParam);
  2024. point.y = HIWORD(lParam);
  2025. int Hit = GetHitArea(point);
  2026. if (wParam & MK_CONTROL)
  2027. {
  2028. Hit = HIT_NONE;
  2029. }
  2030. if (Hit != HIT_NONE && m_bSuccessfulRegionDetection)
  2031. {
  2032. m_rcCurrSel = m_rectSavedDetected; // reset to saved rectangle
  2033. m_rcSavedImageRect = GetImageRect();
  2034. m_rcCurrSel=ConvertToScreenCoords(m_rcCurrSel); // CWiaPreviewWindow stores the selection rectangle in terms of screen coordinates instead of bitmap coordinates
  2035. SendSelChangeNotification(false);
  2036. Repaint(NULL,false);
  2037. UpdateWindow(m_hWnd);
  2038. return(1);
  2039. }
  2040. return(0);
  2041. }