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.
246 lines
6.4 KiB
246 lines
6.4 KiB
#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;
|
|
}
|
|
|
|
|