📄 pjaimage.cpp
字号:
/****************************************************************************
PJAImage.cpp : implementation file for the PJAImage class
written by PJ Arends
pja@telus.net
For updates check http://www3.telus.net/pja/PJAImage.htm
-----------------------------------------------------------------------------
This code is provided as is, with no warranty as to it's suitability or usefulness
in any application in which it may be used. This code has not been tested for
UNICODE builds, nor has it been tested on a network ( with UNC paths ).
This code may be used in any way you desire. This file may be redistributed by any
means as long as it is not sold for profit, and providing that this notice and the
authors name are included.
If any bugs are found and fixed, a note to the author explaining the problem and
fix would be nice.
-----------------------------------------------------------------------------
****************************************************************************/
/////////////////////////////////////////////////////////////////////////////
// CPJAImage class
#include "stdafx.h"
#include "pjaimage.h"
#define BRUSHWIDTH 8
#define BRUSHHEIGHT 8
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage constructor (public member function)
// Initializes member variables
//
// Parameters :
// None
//
// Returns :
// Nothing
//
/////////////////////////////////////////////////////////////////////////////
CPJAImage::CPJAImage()
{
m_ImageFlags = 0;
m_DrawFlags = 0;
m_hImage = NULL;
m_size.cx = 0;
m_size.cy = 0;
m_TransparentColour = CLR_DEFAULT;
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage destructor (public member function)
// frees the memory held by the image handle
//
// Parameters :
// None
//
// Returns :
// Nothing
//
/////////////////////////////////////////////////////////////////////////////
CPJAImage::~CPJAImage()
{
if (m_ImageFlags & PJAI_AUTODELETE)
{
if (m_ImageFlags & PJAI_ICON)
DestroyIcon((HICON)m_hImage);
else
DeleteObject((HGDIOBJ)m_hImage);
}
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::DitherBlt (protected member function)
// Draws the image on the FromDC as a disabled (grayed) image onto the pToDC
//
// Parameters :
// pToDC [in] - pointer to the DC to draw the bitmap onto
// x [in] - the left side of the image on the destination DC
// y [in] - the top of the image on the destination DC
// w [in] - the width of the image on the destination DC
// h [in] - the height of the image on the destination DC
// FromDC [in] - The DC containing the bitmap to be grayed
//
// Returns :
// Nothing
//
// Note : modified from code found at http://www.codeguru.com/bitmap/dither_blt.shtml
// original author Jean-Edouard Lachand-Robert (iamwired@geocities.com)
//
/////////////////////////////////////////////////////////////////////////////
void CPJAImage::DitherBlt(CDC *pToDC, int x, int y, int w, int h, CDC *pFromDC)
{
CDC MonoDC;
if (MonoDC.CreateCompatibleDC(pToDC))
{
struct {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[2];
} RGBBWBITMAPINFO = { { sizeof(BITMAPINFOHEADER),
w,
h,
1,
1,
BI_RGB,
0,
0,
0,
0,
0},
{ { 0x00, 0x00, 0x00, 0x00 },
{ 0xFF, 0xFF, 0xFF, 0x00 }}};
VOID *pbitsBW;
HBITMAP hbmBW = CreateDIBSection(MonoDC.m_hDC,
(LPBITMAPINFO)&RGBBWBITMAPINFO,
DIB_RGB_COLORS,
&pbitsBW,
NULL,
0);
ASSERT(hbmBW);
if (hbmBW)
{
int SavedMonoDC = MonoDC.SaveDC();
int SavedpToDC = pToDC->SaveDC();
// Attach the monochrome DIB section to the MonoDC
MonoDC.SelectObject(hbmBW);
// BitBlt the bitmap into the monochrome DIB section
MonoDC.BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCCOPY);
// BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT bits in the destination DC
// The magic ROP comes from the Charles Petzold's book
HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
pToDC->SelectObject(hb);
pToDC->BitBlt(x + 1, y + 1, w, h, &MonoDC, 0, 0, 0x00B8074A);
// BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW bits in the destination DC
hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
DeleteObject(pToDC->SelectObject(hb));
pToDC->BitBlt(x, y, w, h, &MonoDC, 0, 0, 0x00B8074A);
pToDC->RestoreDC(SavedpToDC);
MonoDC.RestoreDC(SavedMonoDC);
DeleteObject(hb);
}
DeleteObject(hbmBW);
MonoDC.DeleteDC();
}
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::DrawImage (public member function)
// Draws the image (set with the SetImage() function) on the given device
// context
//
// Parameters :
// pDC [in] - a pointer to the the device context to draw the image on
// x [in] - the left side of the image on the destination DC
// y [in] - the top of the image on the destination DC
// w [in] - the width of the image on the destination DC
// h [in] - the height of the image on the destination DC
// DrawFlags [in] - How to draw the image
//
// Returns :
// Nothing
//
// Note :
// See the PJAImage.h file for a description of the flags used
//
// If the image is an icon or a transparent bitmap, the brush that is selected
// into the pDC will be used as the background. The brush can be a pattern
// or bitmap brush. This code assumes the brush is an 8x8 pixel brush
// (Set with the BUTTONWIDTH an BUTTONHEIGHT macros).
//
// The image will be drawn entirely within the rectangle specified by the
// x, y, w, and h parameters.
//
/////////////////////////////////////////////////////////////////////////////
void CPJAImage::DrawImage(CDC *pDC, int x, int y, int w, int h, DWORD DrawFlags /* = 0 */)
{ // sanity check
if (!m_hImage)
return;
// verify flags
#ifdef _DEBUG
if (DrawFlags & PJAI_DISABLED)
ASSERT (!(DrawFlags & PJAI_GRAYSCALE));
if (DrawFlags & PJAI_CENTERED)
ASSERT (!(DrawFlags & PJAI_STRETCHED));
#endif
m_DrawFlags = DrawFlags;
// Get the background brush for transparent images
CBrush *BackGround = pDC->GetCurrentBrush();
BackGround->UnrealizeObject();
// handle for the grayscale bitmap
HBITMAP GrayBmp = NULL;
// set the clip region to the specified rectangle
CRgn ClipRgn;
ClipRgn.CreateRectRgn(x, y, x + w, y + h);
pDC->SelectClipRgn(&ClipRgn);
ClipRgn.DeleteObject();
// create memory DC
CDC memDC;
memDC.CreateCompatibleDC(pDC);
int savedmemDC = memDC.SaveDC();
CBitmap memDCBmp;
CDC* pOutputDC = &memDC;
int left = x;
int top = y;
int width = m_size.cx;
int height = m_size.cy;
if (m_DrawFlags & PJAI_CENTERED)
{ // center the image on the output rectangle
left = x + (w / 2) - (m_size.cx / 2);
top = y + (h / 2) - (m_size.cy / 2);
}
// Create a DC and bitmap for the stretched image
CDC StretchDC;
int savedStretchDC = 0;
CBitmap stretchbmp;
if (m_DrawFlags & PJAI_STRETCHED)
{ // stretch image to fit output rectangle
width = w;
height = h;
}
// get the brush origins in case we are using a bitmap or pattern brush
CPoint BrushOrg;
CPoint Origin = pDC->GetBrushOrg();
BrushOrg.x = (BRUSHWIDTH - (left - Origin.x) % BRUSHWIDTH);
BrushOrg.y = (BRUSHHEIGHT - (top - Origin.y) % BRUSHHEIGHT);
// Create a DC and bitmap for the transparent image
CDC TransparentDC;
int savedTransparentDC = 0;
CBitmap Transparentbmp;
if (m_ImageFlags & PJAI_ICON)
{ // draw the icon onto the memory DC
HICON TheIcon = (HICON)m_hImage;
if (m_DrawFlags & PJAI_GRAYSCALE)
{ // convert the colour icon to grayscale
ICONINFO iconinfo;
GetIconInfo(TheIcon, &iconinfo);
if (iconinfo.hbmColor)
{
HBITMAP grayscale = GrayScale(pDC, iconinfo.hbmColor);
::DeleteObject(iconinfo.hbmColor);
iconinfo.hbmColor = grayscale;
TheIcon = ::CreateIconIndirect(&iconinfo);
::DeleteObject(iconinfo.hbmColor);
::DeleteObject(iconinfo.hbmMask);
}
}
memDCBmp.CreateCompatibleBitmap(pDC, width, height);
memDC.SelectObject(&memDCBmp);
memDC.SetBrushOrg(BrushOrg);
memDC.SelectObject(BackGround);
memDC.FillRect(CRect(0, 0, width + 1, height + 1), BackGround);
::DrawIconEx(memDC.m_hDC, 0, 0, TheIcon, width, height, 0, NULL, DI_NORMAL);
if (TheIcon != m_hImage)
::DestroyIcon(TheIcon);
}
else if (m_ImageFlags & PJAI_BITMAP)
{ // place bitmap image into the memory DC
memDC.SelectObject((HBITMAP)m_hImage);
if (m_TransparentColour == CLR_DEFAULT)
m_TransparentColour = memDC.GetPixel(0, 0);
if (m_DrawFlags & PJAI_STRETCHED)
{ // stretch the image
StretchDC.CreateCompatibleDC(pDC);
savedStretchDC = StretchDC.SaveDC();
stretchbmp.CreateCompatibleBitmap(pDC, w, h);
StretchDC.SelectObject(stretchbmp);
StretchDC.SetStretchBltMode(COLORONCOLOR);
StretchDC.StretchBlt(0, 0, width, height, &memDC, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
pOutputDC = &StretchDC;
}
if (m_DrawFlags & PJAI_TRANSPARENT)
{ // draw the image transparently
TransparentDC.CreateCompatibleDC(pDC);
savedTransparentDC = TransparentDC.SaveDC();
Transparentbmp.CreateCompatibleBitmap(pDC, width, height);
TransparentDC.SelectObject(&Transparentbmp);
TransparentDC.SetBrushOrg(BrushOrg);
TransparentDC.SelectObject(BackGround);
TransparentDC.FillRect(CRect(0, 0, width + 1, height + 1), BackGround);
DrawTransparent(&TransparentDC, width, height, pOutputDC);
pOutputDC = &TransparentDC;
}
else if (m_DrawFlags & PJAI_GRAYSCALE)
{ // convert the image to grayscale
GrayBmp = GrayScale(pDC, *pOutputDC->GetCurrentBitmap());
pOutputDC->SelectObject(GrayBmp);
}
}
else
{
ASSERT (FALSE); // m_Flags improperly set (should never get here)
}
if (m_DrawFlags & PJAI_DISABLED) // draw the image disabled
DitherBlt(pDC, left, top, width, height, pOutputDC);
else // draw the image
pDC->BitBlt(left, top, width, height, pOutputDC, 0, 0, SRCCOPY);
// clean up after ourselves
if (savedTransparentDC)
{
TransparentDC.RestoreDC(savedTransparentDC);
TransparentDC.DeleteDC();
}
if (savedStretchDC)
{
StretchDC.RestoreDC(savedStretchDC);
StretchDC.DeleteDC();
}
memDC.RestoreDC(savedmemDC);
memDC.DeleteDC();
if (GrayBmp)
::DeleteObject(GrayBmp);
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::DrawTransparent (protected member function)
// transparently draws the image in the source device context onto the
// destination device context
//
// Parameters :
// pToDC [in] - pointer to the destination device context
// w [in] - the width of the image
// h [in] - the height of the image
// pFromDC [in] - pointer to the source DC containing the bitmap to be drawn
//
// Returns :
// Nothing
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -