|
|
#include "stdafx.h"
#include "Base.h"
#include "GfxHelp.h"
/***************************************************************************\
* * GdDrawBlendRect * * GdDrawBlendRect draws a alpha-blended rectangle using the current brush * and specified alpha level * \***************************************************************************/
BOOL GdDrawBlendRect(HDC hdcDest, const RECT * prcDest, HBRUSH hbrFill, BYTE bAlpha, int wBrush, int hBrush) { HBITMAP hbmpSrc = NULL, hbmpOld = NULL; HDC hdcSrc = NULL; HBRUSH hbrOld; BOOL fSuccess = FALSE;
if ((wBrush == 0) || (hBrush == 0)) { wBrush = 100; hBrush = 100; }
hbmpSrc = CreateCompatibleBitmap(hdcDest, wBrush, hBrush); if (hbmpSrc == NULL) { goto cleanup; }
hdcSrc = CreateCompatibleDC(hdcDest); if (hdcSrc == NULL) { goto cleanup; }
hbmpOld = (HBITMAP) SelectObject(hdcSrc, hbmpSrc); hbrOld = (HBRUSH) SelectObject(hdcSrc, hbrFill); PatBlt(hdcSrc, 0, 0, wBrush, hBrush, PATCOPY); SelectObject(hdcSrc, hbrOld);
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.AlphaFormat = 0; blend.SourceConstantAlpha = bAlpha;
AlphaBlend(hdcDest, prcDest->left, prcDest->top, prcDest->right - prcDest->left, prcDest->bottom - prcDest->top, hdcSrc, 0, 0, wBrush, hBrush, blend);
fSuccess = TRUE;
cleanup: if (hdcSrc != NULL) { SelectObject(hdcSrc, hbmpOld); DeleteDC(hdcSrc); }
DeleteObject(hbmpSrc);
return fSuccess; }
/***************************************************************************\
* * GetSignFromMappingMode * * For the current mapping mode, find out the sign of x from left to right, * and the sign of y from top to bottom. * * History: * 2000-04-22 JStall Ported from NT-USER * \***************************************************************************/
BOOL GetSignFromMappingMode ( HDC hdc, PPOINT pptSign) { SIZE sizeViewPortExt; SIZE sizeWindowExt;
if (!GetViewportExtEx(hdc, &sizeViewPortExt) || !GetWindowExtEx(hdc, &sizeWindowExt)) {
return FALSE; }
pptSign->x = ((sizeViewPortExt.cx ^ sizeWindowExt.cx) < 0) ? -1 : 1;
pptSign->y = ((sizeViewPortExt.cy ^ sizeWindowExt.cy) < 0) ? -1 : 1;
return TRUE; }
BOOL GdDrawOutlineRect(Gdiplus::Graphics * pgpgr, const RECT * prcPxl, Gdiplus::Brush * pgpbr, int nThickness) { Gdiplus::RectF rc( (float) prcPxl->left, (float) prcPxl->top, (float) (prcPxl->right - prcPxl->left), (float) (prcPxl->bottom - prcPxl->top));
if ((rc.Width < 0) || (rc.Height < 0)) { return FALSE; } Gdiplus::RectF rcPxl(rc);
/*
* Factor in the thickness of the rectangle to be drawn. This will * automatically offset the edges so that the actual rectangle gets filled * "in" as it becomes thicker. */
Gdiplus::PointF ptEdge((float) nThickness, (float) nThickness);
Gdiplus::RectF rcFill; BOOL fSuccess = TRUE;
// Top border
rcFill.X = rc.X; rcFill.Y = rc.Y; rcFill.Width = rc.Width; rcFill.Height = ptEdge.Y; pgpgr->FillRectangle(pgpbr, rcFill);
// Bottom border
rc.Y = rcPxl.Y + rcPxl.Height - ptEdge.Y; rcFill.X = rc.X; rcFill.Y = rc.Y; rcFill.Width = rc.Width; rcFill.Height = ptEdge.Y; pgpgr->FillRectangle(pgpbr, rcFill);
/*
* Left Border * Don't xor the corners twice */ rc.Y = rcPxl.Y + ptEdge.Y; rc.Height -= 2 * ptEdge.Y; rcFill.X = rc.X; rcFill.Y = rc.Y; rcFill.Width = ptEdge.X; rcFill.Height = rc.Height; pgpgr->FillRectangle(pgpbr, rcFill);
// Right Border
rc.X = rcPxl.X + rcPxl.Width - ptEdge.X; rcFill.X = rc.X; rcFill.Y = rc.Y; rcFill.Width = ptEdge.X; rcFill.Height = rc.Height; pgpgr->FillRectangle(pgpbr, rcFill);
return fSuccess; }
/***************************************************************************\
* * GdDrawOutlineRect * * GdDrawOutlineRect draws the outline of a rectange using the specified * brush. This function uses the same "off-by-1" errors as GDI. * \***************************************************************************/
BOOL GdDrawOutlineRect(HDC hdc, const RECT * prcPxl, HBRUSH hbrDraw, int nThickness) { int w; int h; POINT point; POINT ptEdge;
if (!GetSignFromMappingMode(hdc, &ptEdge)) return FALSE;
h = prcPxl->bottom - (point.y = prcPxl->top); if (h < 0) { return FALSE; }
w = prcPxl->right - (point.x = prcPxl->left);
/*
* Check width and height signs */ if (((w ^ ptEdge.x) < 0) || ((h ^ ptEdge.y) < 0)) return FALSE;
/*
* Factor in the thickness of the rectangle to be drawn. This will * automatically offset the edges so that the actual rectangle gets filled * "in" as it becomes thicker. */ ptEdge.x *= nThickness; ptEdge.y *= nThickness;
RECT rcFill; BOOL fSuccess = TRUE;
// Top border
rcFill.left = point.x; rcFill.top = point.y; rcFill.right = point.x + w; rcFill.bottom = point.y + ptEdge.y; fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
// Bottom border
point.y = prcPxl->bottom - ptEdge.y; rcFill.left = point.x; rcFill.top = point.y; rcFill.right = point.x + w; rcFill.bottom = point.y + ptEdge.y; fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
/*
* Left Border * Don't xor the corners twice */ point.y = prcPxl->top + ptEdge.y; h -= 2 * ptEdge.y; rcFill.left = point.x; rcFill.top = point.y; rcFill.right = point.x + ptEdge.x; rcFill.bottom = point.y + h; fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
// Right Border
point.x = prcPxl->right - ptEdge.x; rcFill.left = point.x; rcFill.top = point.y; rcFill.right = point.x + ptEdge.x; rcFill.bottom = point.y + h; fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
return fSuccess; }
|