📄 advbitmap.cpp
字号:
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : advbitmap.cpp //
// Description: Advanced bitmap demo program, Chapter 11 //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define _WIN32_WINNT 0x0500
#define NOCRYPT
#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include <math.h>
#include "..\..\include\wingraph.h"
#include "Resource.h"
class KDIBView : public KScrollCanvas
{
typedef enum { GAP = 16 };
virtual void OnDraw(HDC hDC, const RECT * rcPaint);
virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void GetWndClassEx(WNDCLASSEX & wc);
HMENU m_hViewMenu;
int m_nViewOpt;
HWND m_hFrame;
public:
HINSTANCE m_hInst;
KDIB m_DIB;
KDIBView(void)
{
m_hViewMenu = NULL;
m_nViewOpt = IDM_VIEW_STRETCHDIBITS;
}
bool Initialize(const TCHAR * pFileName, HINSTANCE hInstance, KStatusWindow * pStatus, HWND hFrame)
{
m_hFrame = hFrame;
if ( m_DIB.LoadFile(pFileName) )
{
SetSize(m_DIB.GetWidth() + GAP*2,
m_DIB.GetHeight() + GAP*2, 5, 5);
m_hInst = hInstance;
m_pStatus = pStatus;
RegisterClass(_T("DIBView"), hInstance);
return true;
}
else
return false;
}
bool Initialize(BITMAPINFO * pDIB, HINSTANCE hInstance, KStatusWindow * pStatus, HWND hFrame)
{
m_hFrame = hFrame;
if ( m_DIB.AttachDIB(pDIB, NULL, DIB_BMI_NEEDFREE) )
{
SetSize(m_DIB.GetWidth() + GAP*2,
m_DIB.GetHeight() + GAP*2, 5, 5);
m_hInst = hInstance;
m_pStatus = pStatus;
RegisterClass(_T("DIBView"), hInstance);
return true;
}
else
return false;
}
bool GetTitle(const TCHAR * pFileName, TCHAR * pTitle)
{
if ( pFileName )
{
wsprintf(pTitle, "%s, %d x %d pixel, %d bits", pFileName,
m_DIB.GetWidth(), m_DIB.GetHeight(), m_DIB.GetDepth());
return true;
}
else
return false;
}
void CreateNewView(BITMAPINFO * pDIB, TCHAR * pTitle);
};
void KDIBView::GetWndClassEx(WNDCLASSEX & wc)
{
memset(& wc, 0, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_IMAGE));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_GRAYTEXT + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = NULL;
wc.hIconSm = NULL;
}
// Let the main frame window handle it
void KDIBView::CreateNewView(BITMAPINFO * pDIB, TCHAR * pTitle)
{
if ( pDIB )
SendMessage(m_hFrame, WM_USER, (WPARAM) pDIB, (LPARAM) pTitle);
}
LRESULT KDIBView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch( uMsg )
{
case WM_CREATE:
m_hWnd = hWnd;
m_hViewMenu = LoadMenu(m_hInst, MAKEINTRESOURCE(IDR_DIBVIEW));
return 0;
case WM_PAINT:
return KScrollCanvas::WndProc(hWnd, uMsg, wParam, lParam);
case WM_SIZE:
case WM_HSCROLL:
case WM_VSCROLL:
{
LRESULT lr = KScrollCanvas::WndProc(hWnd, uMsg, wParam, lParam);
int nMin, nMax, nPos;
GetScrollRange(m_hWnd, SB_VERT, &nMin, &nMax);
nPos = GetScrollPos(m_hWnd, SB_VERT);
TCHAR mess[32];
wsprintf(mess, "%d %d %d", nMin, nPos, nMax);
m_pStatus->SetText(0, mess);
return lr;
}
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDM_VIEW_OVALMASK:
case IDM_VIEW_STRETCHDIBCLIP:
case IDM_VIEW_STRETCHBLTOVAL:
case IDM_VIEW_STRETCHDIBITS:
case IDM_VIEW_STRETCHDIBITS4:
case IDM_VIEW_SETDIBITSTODEVICE:
case IDM_VIEW_FITWINDOW:
case IDM_VIEW_MASKRED:
case IDM_VIEW_MASKGREEN:
case IDM_VIEW_MASKBLUE:
case IDM_VIEW_FADEIN:
case IDM_VIEW_ALPHAFADE:
case IDM_VIEW_CUBE:
case IDM_VIEW_CUBEPIXEL:
case IDM_VIEW_SIMUPLGBLT:
if ( LOWORD(wParam)!= m_nViewOpt )
{
m_nViewOpt = LOWORD(wParam);
switch ( LOWORD(wParam) )
{
case IDM_VIEW_STRETCHDIBCLIP:
case IDM_VIEW_OVALMASK:
case IDM_VIEW_STRETCHBLTOVAL:
case IDM_VIEW_STRETCHDIBITS:
case IDM_VIEW_SETDIBITSTODEVICE:
case IDM_VIEW_FADEIN:
case IDM_VIEW_ALPHAFADE:
SetSize(m_DIB.GetWidth() + GAP*2, m_DIB.GetHeight() + GAP*2, 5, 5, true);
break;
case IDM_VIEW_CUBE:
case IDM_VIEW_CUBEPIXEL:
case IDM_VIEW_SIMUPLGBLT:
case IDM_VIEW_STRETCHDIBITS4:
SetSize(m_DIB.GetWidth()*2 + GAP*3, m_DIB.GetHeight()*2 + GAP*3, 5, 5, true);
break;
}
InvalidateRect(hWnd, NULL, TRUE);
}
return 0;
case IDM_VIEW_DIBHEXDUMP:
SendMessage(GetParent(GetParent(hWnd)), WM_USER+1, (WPARAM) & m_DIB, 0);
}
return 0;
default:
return CommonMDIChildProc(hWnd, uMsg, wParam, lParam, m_hViewMenu, 3);
}
}
void TransparentBltDrawIcon(HDC hDC, int x, int y, HICON hIcon)
{
ICONINFO iconinfo;
GetIconInfo(hIcon, & iconinfo);
BITMAP bmp;
GetObject(iconinfo.hbmMask, sizeof(bmp), & bmp);
HDC hMemDC = CreateCompatibleDC(NULL);
HGDIOBJ hOld = SelectObject(hMemDC, iconinfo.hbmColor);
COLORREF crTrans = GetPixel(hMemDC, 0, 0);
G_TransparentBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight,
hMemDC, 0, 0, bmp.bmWidth, bmp.bmHeight,
crTrans);
SelectObject(hMemDC, hOld);
DeleteObject(iconinfo.hbmMask);
DeleteObject(iconinfo.hbmColor);
DeleteObject(hMemDC);
}
void TestPlgBlt(HDC hDC, int x, int y, int w, int h, const BITMAPINFO * pBMI, const void * pBits, HINSTANCE hInstance, bool bSimulate)
{
HBITMAP hBmp = CreateDIBSection(hDC, pBMI, DIB_RGB_COLORS, NULL, NULL, NULL);
HDC hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBmp);
StretchDIBits(hMemDC, 0, 0, w, h, 0, 0, w, h, pBits, pBMI, DIB_RGB_COLORS, SRCCOPY);
HBITMAP hBack = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_WOOD01));
BITMAP bmp;
GetObject(hBack, sizeof(bmp), & bmp);
MaskCube(hDC, 200, x, y, bmp.bmWidth, bmp.bmHeight, hBack, hMemDC, false, bSimulate);
DeleteObject(hBack);
MaskCube(hDC, 200, x, y, w, h, hBmp, hMemDC, true, bSimulate);
DeleteObject(hMemDC);
DeleteObject(hBmp);
}
void TestDIBTransform(HDC hDC, int x, int y, int w, int h, KDIB * pSrc)
{
KAffine affine;
affine.Rotate(-15);
HBITMAP hBitmap = pSrc->TransformBitmap(& affine.m_xm, RGB(0xFF, 0xFF, 0), KDIB::method_direct);
HDC hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBitmap);
BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), & bmp);
BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hMemDC, 0, 0, SRCCOPY);
DeleteObject(hMemDC);
DeleteObject(hBitmap);
}
BOOL OvalStretchDIBits(HDC hDC, int XDest, int YDest, int nDestWidth, int nDestHeight,
int XSrc, int YSrc, int nSrcWidth, int nSrcHeight,
const void *pBits, const BITMAPINFO *pBMI, UINT iUsage)
{
StretchDIBits(hDC, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc,
nSrcWidth, nSrcHeight, pBits, pBMI, iUsage, SRCINVERT);
SaveDC(hDC);
SelectObject(hDC, GetStockObject(BLACK_BRUSH));
SelectObject(hDC, GetStockObject(BLACK_PEN));
Ellipse(hDC, XDest, YDest, XDest + nDestWidth, YDest + nDestHeight);
RestoreDC(hDC, -1);
return StretchDIBits(hDC, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc,
nSrcWidth, nSrcHeight, pBits, pBMI, iUsage, SRCINVERT);
}
BOOL ClipOvalStretchDIBits(HDC hDC, int XDest, int YDest, int nDestWidth, int nDestHeight,
int XSrc, int YSrc, int nSrcWidth, int nSrcHeight,
const void *pBits, const BITMAPINFO *pBMI, UINT iUsage)
{
RECT rect = { XDest, YDest, XDest + nDestWidth, YDest + nDestHeight };
LPtoDP(hDC, (POINT *) & rect, 2);
HRGN hRgn = CreateEllipticRgnIndirect(& rect);
SaveDC(hDC);
SelectClipRgn(hDC, hRgn);
DeleteObject(hRgn);
BOOL rslt = StretchDIBits(hDC, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc,
nSrcWidth, nSrcHeight, pBits, pBMI, iUsage, SRCCOPY);
RestoreDC(hDC, -1);
return rslt;
}
BOOL AlphaFade(HDC hDCDst, int XDst, int YDst, int nDstWidth, int nDstHeight,
HDC hDCSrc, int XSrc, int YSrc, int nSrcWidth, int nSrcHeight)
{
for (int i=5; i>=1; i--)
{
// 1/5, 1/4, 1/3, 1/2, 1/1
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255 / i , 0 };
AlphaBlend(hDCDst, XDst, YDst, nDstWidth, nDstHeight,
hDCSrc, YSrc, YSrc, nSrcWidth, nSrcHeight,
blend);
}
return TRUE;
}
BOOL OvalStretchBlt(HDC hDC, int XDest, int YDest, int nDestWidth, int nDestHeight,
HDC hDCSrc, int XSrc, int YSrc, int nSrcWidth, int nSrcHeight)
{
// Make the region outside the ellipse be BLACK in source surface
SaveDC(hDCSrc);
BeginPath(hDCSrc);
Rectangle(hDCSrc, XSrc, YSrc, XSrc + nSrcWidth+1, YSrc + nSrcHeight+1);
Ellipse(hDCSrc, XSrc, YSrc, XSrc + nSrcWidth, YSrc + nSrcHeight);
EndPath(hDCSrc);
SelectObject(hDCSrc, GetStockObject(BLACK_BRUSH));
SelectObject(hDCSrc, GetStockObject(BLACK_PEN));
FillPath(hDCSrc);
RestoreDC(hDCSrc, -1);
// Draw a BLACK ellipse in destination surface
SaveDC(hDC);
SelectObject(hDC, GetStockObject(BLACK_BRUSH));
SelectObject(hDC, GetStockObject(BLACK_PEN));
Ellipse(hDC, XDest, YDest, XDest + nDestWidth, YDest + nDestHeight);
RestoreDC(hDC, -1);
// Merge source surface to destination
return StretchBlt(hDC, XDest, YDest, nDestWidth, nDestHeight, hDCSrc, XSrc, YSrc,
nSrcWidth, nSrcHeight, SRCPAINT);
}
extern DWORD dibtick;
void KDIBView::OnDraw(HDC hDC, const RECT * rcPaint)
{
DWORD tm = GetTickCount();
dibtick = 0;
int w = m_DIB.GetWidth();
int h = m_DIB.GetHeight();
switch ( m_nViewOpt )
{
case IDM_VIEW_FITWINDOW:
{
RECT rect;
GetClientRect(m_hWnd, & rect);
m_DIB.DrawDIB(hDC, 0, 0, rect.right, rect.bottom, 0, 0, w, h, SRCCOPY);
}
break;
case IDM_VIEW_MASKRED:
{
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP hBmp = ChannelSplit(m_DIB.GetBMI(), m_DIB.GetBits(), RGB(0xFF, 0, 0), hMemDC);
BitBlt(hDC, 0, 0, w, h, hMemDC, 0, 0, SRCCOPY);
DeleteObject(hBmp);
DeleteObject(hMemDC);
// CGDIObject red(hDC, CreateSolidBrush(RGB(0xFF, 0, 0)));
// m_DIB.DrawDIB(hDC, GAP, GAP, w, h, 0, 0, w, h, MERGECOPY);
}
break;
case IDM_VIEW_MASKGREEN:
{
KGDIObject red(hDC, CreateSolidBrush(RGB(0, 0xFF, 0)));
m_DIB.DrawDIB(hDC, GAP, GAP, w, h, 0, 0, w, h, MERGECOPY);
}
break;
case IDM_VIEW_MASKBLUE:
{
KGDIObject red(hDC, CreateSolidBrush(RGB(0, 0, 0xFF )));
m_DIB.DrawDIB(hDC, GAP, GAP, w, h, 0, 0, w, h, MERGECOPY);
}
break;
case IDM_VIEW_FADEIN:
FadeIn(hDC, GAP, GAP, w, h, m_DIB.GetBMI(), m_DIB.GetBits());
break;
case IDM_VIEW_OVALMASK:
OvalStretchDIBits(hDC, GAP, GAP, w, h, 0, 0, w, h, m_DIB.GetBits(), m_DIB.GetBMI(), DIB_RGB_COLORS);
break;
case IDM_VIEW_STRETCHDIBCLIP:
ClipOvalStretchDIBits(hDC, GAP, GAP, w, h, 0, 0, w, h, m_DIB.GetBits(), m_DIB.GetBMI(), DIB_RGB_COLORS);
break;
case IDM_VIEW_ALPHAFADE:
{
HBITMAP hBmp = m_DIB.ConvertToDDB(hDC);
HDC hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBmp);
AlphaFade(hDC, GAP, GAP, w, h, hMemDC, 0, 0, w, h);
DeleteObject(hMemDC);
DeleteObject(hBmp);
}
break;
case IDM_VIEW_STRETCHBLTOVAL:
{
HBITMAP hBmp = m_DIB.ConvertToDDB(hDC);
HDC hMemDC = CreateCompatibleDC(hDC);
SelectObject(hMemDC, hBmp);
OvalStretchBlt(hDC, GAP, GAP, w, h, hMemDC, 0, 0, w, h);
DeleteObject(hMemDC);
DeleteObject(hBmp);
}
break;
case IDM_VIEW_STRETCHDIBITS:
m_DIB.DrawDIB(hDC, GAP, GAP, w, h, 0, 0, w, h, SRCCOPY);
break;
case IDM_VIEW_STRETCHDIBITS4:
m_DIB.DrawDIB(hDC, GAP, GAP, w, h, 0, 0, w, h, SRCCOPY);
m_DIB.DrawDIB(hDC, GAP*2+w, GAP, w, h, w, 0, -w, h, SRCCOPY);
m_DIB.DrawDIB(hDC, GAP, GAP*2+h, w, h, 0, h, w, -h, SRCCOPY);
m_DIB.DrawDIB(hDC, GAP*2+w, GAP*2+h, w, h, w, h, -w, -h, SRCCOPY);
break;
case IDM_VIEW_SETDIBITSTODEVICE:
if ( ! m_DIB.IsCompressed() )
{
int bps = m_DIB.GetBPS();
BYTE * buffer = new BYTE[bps];
for (int i=0; i<m_DIB.GetHeight(); i++)
{
memcpy(buffer, m_DIB.GetBits() + bps*i, bps);
for (int j=0; j<bps; j++)
buffer[j] = ~ buffer[j];
m_DIB.SetDIB(hDC, GAP, GAP, i, 1, buffer);
}
delete [] buffer;
}
break;
case IDM_VIEW_CUBE:
TestPlgBlt(hDC, GAP, GAP, w, h, m_DIB.GetBMI(), m_DIB.GetBits(), m_hInst, false);
break;
case IDM_VIEW_SIMUPLGBLT:
TestPlgBlt(hDC, GAP, GAP, w, h, m_DIB.GetBMI(), m_DIB.GetBits(), m_hInst, true);
break;
case IDM_VIEW_CUBEPIXEL:
TestDIBTransform(hDC, GAP, GAP, w, h, & m_DIB);
break;
}
RestoreDC(hDC, -1);
tm = GetTickCount() - tm;
if ( dibtick )
tm = dibtick;
TCHAR mess[32];
wsprintf(mess, "Time %d ms", tm);
m_pStatus->SetText(1, mess);
}
//////////////////////////////////////////////
void TestRop3(HINSTANCE hInstance, HDC hDC);
void TestIcons(HDC hDC)
{
static HINSTANCE hMod = NULL;
if ( hMod==NULL )
hMod = LoadLibrary("Shell32.dll");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -