dibsection.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 373 行
CPP
373 行
//-----------------------------------------------------------------------------------//
// 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 : dibsection.cpp //
// Description: KDIBSection class, EMF rendering, AirBrush //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <assert.h>
#include <tchar.h>
#include <math.h>
#include "DIBSection.h"
#include "BitmapInfo.h"
// Copy from DIB section color table to DIB color table
UINT KDIBSection::GetColorTable(void)
{
int width, height;
if ( (GetDepth()>8) || ! Prepare(width, height) ) // create memory DC
return 0;
return GetDIBColorTable(m_hMemDC, 0, m_nClrUsed, m_pRGBQUAD);
}
// Copy from DIB's color table to DIB section's color table
UINT KDIBSection::SetColorTable(void)
{
int width, height;
if ( (GetDepth()>8) || ! Prepare(width, height) ) // create memory DC
return 0;
return SetDIBColorTable(m_hMemDC, 0, m_nClrUsed, m_pRGBQUAD);
}
void KDIBSection::DecodeDIBSectionFormat(TCHAR desp[])
{
DIBSECTION dibsec;
if ( GetObject(m_hBitmap, sizeof(DIBSECTION), & dibsec) )
{
KDIB::DecodeDIBFormat(desp);
_tcscat(desp, _T(" "));
DecodeDDB(GetBitmap(), desp + _tcslen(desp));
}
else
_tcscpy(desp, _T("Invalid DIB Section"));
}
BOOL KDIBSection::CreateDIBSection(HDC hDC, CONST BITMAPINFO * pBMI, UINT iUsage, HANDLE hSection, DWORD dwOffset)
{
PVOID pBits = NULL;
HBITMAP hBmp = ::CreateDIBSection(hDC, pBMI, iUsage, & pBits, hSection, dwOffset);
int typ = GetObjectType(hBmp);
int size = GetObject(hBmp, 0, NULL);
if ( hBmp )
{
ReleaseDDB(); // free the previous object
ReleaseDIB();
m_hBitmap = hBmp; // Use DDB handle to store DIB Section Handle
// MEMORY_BASIC_INFORMATION mbi;
// VirtualQuery(pBits, & mbi, sizeof(mbi));
int nColor = GetDIBColorCount(pBMI->bmiHeader);
int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColor;
BITMAPINFO * pDIB = (BITMAPINFO *) new BYTE[nSize];
if ( pDIB==NULL )
return FALSE;
memcpy(pDIB, pBMI, nSize); // copy header and color table
AttachDIB(pDIB, (PBYTE) pBits, DIB_BMI_NEEDFREE);
GetColorTable();
return TRUE;
}
else
return FALSE;
}
// Search for the largest DIBSection
HBITMAP LargestDIBSection(BITMAPINFO * pBMI)
{
HBITMAP hBmp;
int mins = 1; // 1 pixel
int maxs = 1024 * 128; // 16 Giga pixels
while ( true ) // search for largest DDB
{
int mid = (mins + maxs)/2;
pBMI->bmiHeader.biWidth = mid;
pBMI->bmiHeader.biHeight= mid;
hBmp = CreateDIBSection(NULL, pBMI, DIB_RGB_COLORS, NULL, NULL, NULL);
if ( hBmp )
{
pBMI->bmiHeader.biWidth = mid+1;
pBMI->bmiHeader.biHeight= mid+1;
HBITMAP h = CreateDIBSection(NULL, pBMI, DIB_RGB_COLORS, NULL, NULL, NULL);
if ( h==NULL )
return hBmp;
DeleteObject(h);
DeleteObject(hBmp);
mins = mid+1;
}
else
maxs = mid;
}
return NULL;
}
// Draw a 3D rectangle frame with color shades
void Frame(HDC hDC, int nFrame, COLORREF crFrame, int left, int top, int right, int bottom)
{
int red = GetRValue(crFrame);
int green = GetGValue(crFrame);
int blue = GetBValue(crFrame);
RECT rect = { left, top, right, bottom };
for (int i=0; i<nFrame; i++)
{
HBRUSH hBrush = CreateSolidBrush(RGB(red, green, blue));
FrameRect(hDC, & rect, hBrush);
DeleteObject(hBrush);
if ( i<nFrame/2 )
{
red = red * 19/20; // darker
green = green * 19/20;
blue = blue * 19/20;
}
else
{
red = red * 19/18; if ( red>255 ) red = 255; // lighter
green = green * 19/18; if ( green>255 ) green= 255;
blue = blue * 19/18; if ( blue>255 ) blue = 255;
}
InflateRect(&rect, -1, -1);
}
}
// Window contents saver using DIBSECTION
BOOL SaveWindow(HWND hWnd, bool bClient, int nFrame, COLORREF crFrame)
{
RECT wnd;
if ( bClient )
{
if ( ! GetClientRect(hWnd, & wnd) )
return FALSE;
}
else
{
if ( ! GetWindowRect(hWnd, & wnd) )
return FALSE;
}
KBitmapInfo bmi;
KDIBSection dibsec;
bmi.SetFormat(wnd.right - wnd.left + nFrame * 2, wnd.bottom - wnd.top + nFrame *2, 24, BI_RGB);
if ( dibsec.CreateDIBSection(NULL, bmi.GetBMI(), DIB_RGB_COLORS, NULL, NULL) )
{
int width, height;
dibsec.Prepare(width, height); // creates memory DC, select dibsec into memDC
if ( nFrame )
{
Frame(dibsec.m_hMemDC, nFrame, crFrame, 0, 0, width, height);
TCHAR Title[128];
GetWindowText(hWnd, Title, sizeof(Title)/sizeof(Title[0]));
SetBkMode(dibsec.m_hMemDC, TRANSPARENT);
SetTextColor(dibsec.m_hMemDC, RGB(0xFF, 0xFF, 0xFF));
TextOut(dibsec.m_hMemDC, nFrame, (nFrame-20)/2, Title, _tcslen(Title));
}
HDC hDC;
if ( bClient )
hDC = GetDC(hWnd);
else
hDC = GetWindowDC(hWnd);
BitBlt(dibsec.m_hMemDC, nFrame, nFrame, width - nFrame * 2, height - nFrame * 2, hDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hDC);
return dibsec.SaveFile(NULL);
}
return FALSE;
}
KTarga24::KTarga24()
{
m_hFile = INVALID_HANDLE_VALUE;
m_hFileMapping = INVALID_HANDLE_VALUE;
}
KTarga24::~KTarga24()
{
ReleaseDDB();
ReleaseDIB();
if ( m_hFileMapping!=INVALID_HANDLE_VALUE )
CloseHandle(m_hFileMapping);
if ( m_hFile != INVALID_HANDLE_VALUE )
CloseHandle(m_hFile);
}
BOOL KTarga24::Create(int width, int height, const TCHAR * pFileName)
{
if ( width & 3 ) // avoid compatiblity problem with TGA
return FALSE;
ImageHeader tgaheader;
memset(& tgaheader, 0, sizeof(tgaheader));
tgaheader.IDLength = sizeof(tgaheader.ID);
tgaheader.ImgType = 2;
tgaheader.Width = width;
tgaheader.Height = height;
tgaheader.PixelSize = 24;
strcpy(tgaheader.ID, "BitmapShop");
m_hFile = CreateFile(pFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ( m_hFile==INVALID_HANDLE_VALUE )
return FALSE;
int imagesize = (width*3+3)/4*4 * height;
m_hFileMapping = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE, 0, sizeof(tgaheader) + imagesize, NULL);
if ( m_hFileMapping==INVALID_HANDLE_VALUE )
return FALSE;
DWORD dwWritten = NULL;
WriteFile(m_hFile, & tgaheader, sizeof(tgaheader), &dwWritten, NULL);
SetFilePointer(m_hFile, sizeof(tgaheader) + imagesize, 0, FILE_BEGIN);
SetEndOfFile(m_hFile);
KBitmapInfo bmi;
bmi.SetFormat(width, height, 24, BI_RGB);
return CreateDIBSection(NULL, bmi.GetBMI(), DIB_RGB_COLORS, m_hFileMapping, sizeof(tgaheader));
}
BOOL RenderEMF(HENHMETAFILE hemf, int width, int height, const TCHAR * tgaFileName)
{
KTarga24 targa;
int w = (width+3)/4*4;
if ( targa.Create(w, height, tgaFileName) )
{
targa.Prepare(w, height);
// DIBSECTION dibsec;
// GetObject(targa.GetBitmap(), sizeof(DIBSECTION), & dibsec);
BitBlt(targa.m_hMemDC, 0, 0, width, height, NULL, 0, 0, WHITENESS); // clear
RECT rect = { 0, 0, width, height };
for (int h=0; h<=height; h+=128 )
{
HRGN hRgn = CreateRectRgn(0, h, width, h+128);
SelectClipRgn(targa.m_hMemDC, hRgn);
DeleteObject(hRgn);
if ( ! PlayEnhMetaFile(targa.m_hMemDC, hemf, &rect) )
return FALSE;
}
}
return FALSE;
}
void KAirBrush::Apply(HDC hDC, int x, int y)
{
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(hDC, x-m_nWidth/2, y-m_nHeight/2, m_nWidth, m_nHeight, m_hMemDC, 0, 0, m_nWidth, m_nHeight, blend);
}
void KAirBrush::Create(int width, int height, COLORREF color)
{
Release();
BYTE * pBits;
BITMAPINFO Bmi = { { sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB } };
m_hBrush = CreateDIBSection(NULL, & Bmi, DIB_RGB_COLORS, (void **) & pBits, NULL, NULL);
m_hMemDC = CreateCompatibleDC(NULL);
m_hOld = (HBITMAP) SelectObject(m_hMemDC, m_hBrush);
m_nWidth = width;
m_nHeight = height;
// solid color circle, on white background
{
PatBlt(m_hMemDC, 0, 0, width, height, WHITENESS);
HBRUSH hBrush = CreateSolidBrush(color);
SelectObject(m_hMemDC, hBrush);
SelectObject(m_hMemDC, GetStockObject(NULL_PEN));
Ellipse(m_hMemDC, 0, 0, width, height);
SelectObject(m_hMemDC, GetStockObject(WHITE_BRUSH));
DeleteObject(hBrush);
}
BYTE * pPixel = pBits;
double xx;
for (int y=0; y<height; y++)
for (int x=0; x<width; x++, pPixel+=4)
{
xx=( (x-width/2) * (x-width/2) + (y-height/2) * (y-height/2) ) * 255 / (max(width, height)/2);
int dis = (int) sqrt(xx );
BYTE alpha = (BYTE) max(min(255-dis, 255), 0);
pPixel[0] = pPixel[0] * alpha / 255;
pPixel[1] = pPixel[1] * alpha / 255;
pPixel[2] = pPixel[2] * alpha / 255;
pPixel[3] = alpha;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?