#ifndef _WND_H_
#define _WND_H_
#define _CRT_SECURE_NO_WARNINGS
#define NO_WARN_MBCS_MFC_DEPRECATION
#include <SDKDDKVer.h>
#include <afxwin.h>
//默认情况下所有继承Wnd的控件都是透明状态,需要自己绘画, alpha通道被置0了
#define RGBA(r,g,b,a) (COLORREF)(((BYTE)(b) |((WORD)((BYTE)(g)) << 8)) |(((DWORD)((BYTE)(r)) << 16)) |(((DWORD)((BYTE)(a)) << 24)))
namespace MPlus
{
#pragma pack(push,1)
typedef struct tagWndProcThunk
{
DWORD mov; // 修改堆栈中的参数 mov [esp+4], 0xC7 0x44 0x24 0x04 = 0x042444C7
DWORD thiz; // 存储 this 指针 ?? ?? ?? ?? (DWORD)this
BYTE jmp; // 跳转指令 jmp 0xE9
DWORD relproc; // 相对跳转地址 ?? ?? ?? ?? staic_WndProc-(thunk + sizeof WndProcThunk)
}WndProcThunk;
typedef WndProcThunk* LPWNDPROCTHUNK;
#pragma pack(pop)
template<class T>
T* AllocVirtualMemory()
{
void* mem = VirtualAlloc(NULL, sizeof(T), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!mem) return nullptr;
memset(mem, 0, sizeof(T));
return (T*)mem;
}
template<class T>
void Free(T* _pMemory)
{
if (_pMemory)
{
VirtualFree(_pMemory, sizeof T, MEM_RELEASE);
}
}
class Wnd : public CWnd
{
DECLARE_DYNAMIC(Wnd)
protected:
CDC m_MemDC; //绘图二级缓存DC
BITMAPINFO m_BMI; //绘图位图的基本信息
HBITMAP m_hBitmap; //位图的句柄
BYTE* m_pvBits; //位图的裸内存首地址
CRect m_rcWnd; //控件的画布范围
CFont m_Font; //二级DC所使用的字体
CPoint m_ptOrigin; //窗口当前的坐标
int* m_vecRows; //位图的行列表
public:
LPCTSTR m_szClassName; //默认提供的类名,创建窗口时要使用
protected:
void fast_stack_blur(unsigned char* pix, unsigned int w, unsigned int h, unsigned int comp, int radius);//快速栈模糊算法
virtual bool OnValidBlur(const CPoint& _ptPix);
void SetAlphaRect(const CRect _rect, BYTE _alpha);
public:
Wnd();
~Wnd();
void Clear();
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};
}
void _output_debug(const char* _format, ...);
#ifdef _DEBUG
#define outputdebug_default(_format, ...)_output_debug("[Default] "##_format, ##__VA_ARGS__)
#define outputdebug_warning(_format, ...)_output_debug("[Warning] "##_format, ##__VA_ARGS__)
#define outputdebug_error(_format, ...)_output_debug("[Error] "##_format, ##__VA_ARGS__)
#else
#define outputdebug_default(format, ...)
#define outputdebug_warning(_format, ...)
#define outputdebug_error(_format, ...)
#endif
#endif
#include "Wnd.h"
void _output_debug(const char* _format, ...)
{
#define __DstSize__ 1024
char strMsgBuffer[__DstSize__];
va_list list;
va_start(list, _format);
vsnprintf(strMsgBuffer, __DstSize__, _format, list);
va_end(list);
//强行加换行符
int last = strlen(strMsgBuffer);
if (strMsgBuffer[last - 1] != '\n')
{
strMsgBuffer[last] = '\n';
strMsgBuffer[last + 1] = 0;
}
OutputDebugStringA(strMsgBuffer);//win api
}
namespace MPlus
{
IMPLEMENT_DYNAMIC(Wnd, CWnd)
}
MPlus::Wnd::Wnd():
m_hBitmap(NULL),
m_pvBits(NULL),
m_rcWnd(0, 0, 0, 0),
m_ptOrigin(0, 0),
m_vecRows(NULL)
{
m_szClassName = AfxRegisterWndClass(0); //注册默认类名
}
MPlus::Wnd::~Wnd()
{
Wnd::Clear();
}
void MPlus::Wnd::Clear()
{
m_Font.DeleteObject();//释放字体内存
DeleteObject(m_hBitmap);//释放位图内存
m_MemDC.DeleteDC();//二级缓存释放
m_pvBits = NULL;
ZeroMemory(&m_BMI, sizeof(BITMAPINFO));//重置位图信息
if (m_vecRows)
{
delete[] m_vecRows;
m_vecRows = NULL;
}
}
// Stack Blur v1.1
//
// Author: Mario Klingemann <mario@quasimondo.com>
// http://incubator.quasimondo.com
// created Feburary 29, 2004
// C version updated and performance optimization by tntmonks(http://tntmonks.cnblogs.com)
// This is a compromise between Gaussian Blur and Box blur
// It creates much better looking blurs than Box Blur, but is
// 7x faster than my Gaussian Blur implementation.
//
// I called it Stack Blur because this describes best how this
// filter works internally: it creates a kind of moving stack
// of colors whilst scanning through the image. Thereby it
// just has to add one new block of color to the right side
// of the stack and remove the leftmost color. The remaining
// colors on the topmost layer of the stack are either added on
// or reduced by one, depending on if they are on the right or
// on the left side of the stack.
//
// If you are using this algorithm in your code please add
// the following line:
//
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
//#define MAX(x,y) (x>y?x:y)
//#define MIN(x,y) (x>y?y:x)
#include <math.h>
void MPlus::Wnd::fast_stack_blur(unsigned char* pix, unsigned int w, unsigned int h, unsigned int comp, int radius)
{
#pragma warning(disable:4018)
unsigned int wm = w - 1;
unsigned int hm = h - 1;
unsigned int imageSize = w * h;
unsigned int div = radius * 2 + 1;
unsigned char* rgb = (unsigned char*)malloc(sizeof(unsigned char) * imageSize * 4);
unsigned char* r = rgb;
unsigned char* g = rgb + imageSize;
unsigned char* b = rgb + imageSize * 2;
unsigned char* a = rgb + imageSize * 3;
int rsum, gsum, bsum, asum, x, y, i, p, yp, yi, yw;
unsigned int* vmin = (unsigned int*)malloc(max(w, h) * sizeof(unsigned int));
int divsum = (div + 1) >> 1;
divsum *= divsum;
int* dv = (int*)malloc(256 * divsum * sizeof(int));
for (i = 0; i < 256 * divsum; i++)
{
dv[i] = (i / divsum);
}
yw = yi = 0;
int(*stack)[4] = (int(*)[4])malloc(div * 4 * sizeof(int));
unsigned int stackpointer;
unsigned int stackstart;
int* sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum, aoutsum;
int rinsum, ginsum, binsum, ainsum;
for (y = 0; y < h; y++)
{
rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0;
for (i = -radius; i <= radius; i++)
{
p = yi + (min(wm, max(i, 0)));
sir = stack[i + radius];
sir[0] = pix[(p * comp)];
sir[1] = pix[(p * comp) + 1];
sir[2] = pix[(p * comp) + 2];
sir[3] = pix[(p * comp) + 3];
rbs = r1 - abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
asum += sir[3] * rbs;
if (i > 0)
{
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
}
else
{
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
}
stackpointer = radius;
for (x = 0; x < w; x++)
{
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
a[yi] = dv[asum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (y == 0)
{
vmin[x] = min(x + radius + 1, wm);
}
p = yw + vmin[x];
sir[0] = pix[(p * comp)];
sir[1] = pix[(p * comp) + 1];
sir[2] = pix[(p * comp) + 2];
sir[3] = pix[(p * comp) + 3];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
yi++;
}
yw += w;
}
for (int x = 0; x < w; x++)
{
rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++)
{
yi = max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
sir[3] = a[yi];
rbs = r1 - abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
asum += a[yi] * rbs;
if (i > 0)
{
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
}
else
{
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
if (i < hm)
{
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++)
{
if (OnValidBlur({ x,y }))
{
pix[(yi * comp) + 0] = dv[rsum];
pix[(yi * comp) + 1] = dv[gsum];
pix[(yi * comp) + 2] = dv[bsum];
pix[(yi * comp) + 3] = dv[asum];
}
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (x == 0)
{
vmin[y] = min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
sir[3] = a[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
yi += w;
}
}
free(rgb);
free(vmin);
free(dv);
free(stack);
#pragma warning(default:4018)
}
void MPlus::Wnd::SetAlphaRect(const CRect _rect, BYTE _alpha)
{
int iAlpha = _alpha;
iAlpha <<= 24;
int* pRow = NULL;
for (int i = _rect.top; i < _rect.bottom; ++i)
{
pRow = (int*)m_vecRows[i];//取出一行数据
for (int j = _rect.left; j < _rect.right; ++j)
{
*(pRow + j) |= iAlpha;//设置每个ARGB颜色的alpha通道
}
}
}
bool MPlus::Wnd::OnValidBlur(const CPoint& _ptPix)
{
return true;
}
BEGIN_MESSAGE_MAP(MPlus::Wnd, CWnd)
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
int MPlus::Wnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
m_rcWnd = { 0, 0, lpCreateStruct->cx, lpCreateStruct->cy };//保存控件画布范围
m_ptOrigin.x = lpCreateStruct->x;
m_ptOrigin.y = lpCreateStruct->y;
ZeroMemory(&m_BMI, sizeof(BITMAPINFO)); //初始化位置信息
m_BMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //给定位图信息类的大小
m_BMI.bmiHeader.biWidth = m_rcWnd.Width(); //位图的长度
m_BMI.bmiHeader.biHeight = m_rcWnd.Height(); //位图的宽度
m_BMI.bmiHeader.biPlanes = 1;
m_BMI.bmiHeader.biBitCount = 32; // four 8-bit components
m_BMI.bmiHeader.biCompression = BI_RGB;
m_BMI.bmiHeader.biSizeImage = m_BMI.bmiHeader.biWidth * m_BMI.bmiHeader.biHeight * 4; //位图内存的大小
m_hBitmap = CreateDIBSection(NULL, &m_BMI, DIB_RGB_COLORS, (void**)&m_pvBits, NULL, 0); //创建DIB无关联位图
//二级缓存DC初始化
m_MemDC.CreateCompatibleDC(NULL); //创建二级缓存DC
HGDIOBJ hdc = m_MemDC.SelectObject(m_hBitmap); //DC选择指定位图
m_Font.CreatePointFont( (m_rcWnd.Height()-2) * 5, "微软雅黑", NULL); //默认字体
m_MemDC.SelectObject(&m_Font);
m_MemDC.FillSolidRect(m_rcWnd, RGBA(0,0,0,0));
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));//修复鼠标
//开始把位图每行标记储存起来
int iRows = m_BMI.bmiHeader.biWidth;
int iCols = m_BMI.bmiHeader.biHeight;
m_vecRows = new int[iCols];
//m_pvBits的位图内存分布是倒序的,所以最后一行数据就是位图的第一行数据,进行倒序储存
for (int i = (iCols - 1), j=0; i >= 0; --i, ++j)
{
m_vecRows[i] = int(m_pvBits + (iRows * 4 * j) );
}
return 0;
}
void MPlus::Wnd::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd* pWnd = SetFocus();
CWnd::OnLButtonDown(nFlags, point);
}
void MPlus::Wnd::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd::OnLButtonUp(nFlags, point);
}
BOOL MPlus::Wnd::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return CWnd::OnEraseBkgnd(pDC);
}
我要扩展LineTo支持alpha通道