#pragma once
#include "atlimage.h"
class Engine_2D
{
/*
备注:MFC在系统需要重画窗口的时候会自动用指定的背景色来搽除窗口。
可重载WM_ERASEBKGND函数,注释掉return CWnd::OnEraseBkgnd(pDC);
并直接return true;
禁止系统自动搽除窗口。
另,为避免控件的重画,可设置窗体的Clip Children 属性为真。
*/
public:
Engine_2D();
~Engine_2D(void);
void OnInit(CWnd* in_pCWnd, COLORREF BackColor = RGB(192,192,192));
void DrawText(CString sText,int x, int y, int w, int h, int in_LineWidth, COLORREF in_Color);
void DrawText(CString sText,RECT& rect,int in_LineWidth, COLORREF in_Color);
void Draw(CImage& in_Image, int in_x, int in_y, int in_w, int in_h);
void Draw(CImage& in_Image, int in_x, int in_y, int in_w, int in_h, int in_srcX, int in_srcY, int in_srcW, int in_srcH);
void DrawEllipse(int in_CenterX, int in_CenterY, int in_Radius, COLORREF color, int in_iPenType = PS_SOLID, bool in_bIsNull = true);
void DrawPie(int in_CenterX, int in_CenterY, int in_Radius, COLORREF color, int in_StartAngle = 0, int in_HaveAngle = 360);
void DrawLine(int in_X0, int in_Y0, int in_X1, int in_Y1, int in_LineWidth = 1, COLORREF in_Color = RGB(255,0,0), bool in_bIsAA = true);
void DrawPointLine(int in_X0, int in_Y0, int in_X1, int in_Y1, int in_LineWidth = 2, int in_PointWidth = 4, COLORREF in_Color = RGB(255,0,0));
void DrawRect(int in_x, int in_y, int in_w, int in_h, COLORREF color);
void Render();
void Clear();
void SaveSince(const LPCWSTR in_cPath, int in_x, int in_y, int in_w, int in_h);
void SaveClientSince(const LPCWSTR in_cPath, int in_x, int in_y, int in_w, int in_h);
inline HDC GetHDC() { return m_pMemDC->m_hDC; }
void Invalidate();
void Invalidate(int x, int y, int w, int h);
bool AngleToPostion(int& out_PosX, int& out_PosY,
int in_CenterX, int in_CenterY,
int in_Radius,int in_Angle = 0);
CString IntToCString(const int in_iNum);
CString DoubleToCString(const double in_dNum);
private:
HBITMAP CopyScreenToBitmap(LPRECT lpRect); //lpRect 代表选定区域
int SaveBitmapToFile(HBITMAP hBitmap, LPCWSTR lpFileName); //hBitmap 为刚才的屏幕位图句柄
void DoEvent();
CBitmap* m_pMemBitmap; //声明内存中承载临时图象的位图
CDC* m_pMemDC; //声明用于缓冲作图的内存DC
CWnd* m_pCWnd;
COLORREF m_BackColor;
int m_SinceW;
int m_SinceH;
};
//
#include "StdAfx.h"
#include "Engine_2D.h"
#include "TGraphics.h"
#include
Engine_2D::Engine_2D(void)
{
m_pMemBitmap = new CBitmap();
m_pMemDC = new CDC();
m_pCWnd = NULL;
}
Engine_2D::~Engine_2D(void)
{
delete m_pMemBitmap;
delete m_pMemDC;
m_pMemBitmap = NULL;
m_pMemDC = NULL;
}
CString Engine_2D::IntToCString(const int in_iNum)
{
TCHAR szString[MAX_PATH] = {0};
_sntprintf(szString,sizeof(szString)-sizeof(TCHAR),_T("%d"),in_iNum);
CString strRet = szString;
return strRet;
}
CString Engine_2D::DoubleToCString(const double in_dNum)
{
TCHAR szString[MAX_PATH] = {0};
_sntprintf(szString,sizeof(szString)-sizeof(TCHAR),_T("%f"),in_dNum);
CString strRet = szString;
return strRet;
}
void Engine_2D::OnInit(CWnd* in_pCWnd, COLORREF BackColor)
{
m_pCWnd = in_pCWnd;
m_BackColor = BackColor;
RECT rect;
in_pCWnd->GetWindowRect(&rect);
m_SinceW = rect.right - rect.left;
m_SinceH = rect.bottom - rect.top;
CDC* pDC = m_pCWnd->GetDC();
m_pMemDC->CreateCompatibleDC(pDC); //依附窗口DC创建兼容内存DC
m_pMemBitmap->CreateCompatibleBitmap(pDC,m_SinceW,m_SinceH); //创建兼容位图
CBitmap* m_pOldBitmap=m_pMemDC->SelectObject(m_pMemBitmap); //将位图选进内存DC,原位图保存到m_pOldBitmap
CBrush Brush(m_BackColor);
pDC->FillRect(CRect(0,0,m_SinceW,m_SinceH),&Brush); //设置当前区背景
m_pCWnd->ReleaseDC(pDC);
Clear();
}
void Engine_2D::Render()
{
CPaintDC dc(m_pCWnd);
CRect rc;
m_pCWnd->GetClientRect(&rc);
dc.BitBlt(0,0,rc.Width(),rc.Height(),m_pMemDC,0,0,SRCCOPY);
}
void Engine_2D::Clear()
{
CBrush Brush(m_BackColor);
m_pMemDC->FillRect(CRect(0,0,m_SinceW,m_SinceH),&Brush); //设置客户区背景
}
void Engine_2D::Draw(CImage& in_Image, int in_x, int in_y, int in_w, int in_h)
{
in_Image.Draw(m_pMemDC->m_hDC, in_x, in_y, in_w, in_h);
}
void Engine_2D::Draw(CImage& in_Image, int in_x, int in_y, int in_w, int in_h, int in_srcX, int in_srcY, int in_srcW, int in_srcH)
{
in_Image.Draw(m_pMemDC->m_hDC, in_x, in_y, in_w, in_h, in_srcX, in_srcY, in_srcW, in_srcH);
}
void Engine_2D::DrawRect(int in_x, int in_y, int in_w, int in_h, COLORREF color)
{
RECT rect;
rect.left = in_x;
rect.top = in_y;
rect.right = in_x+in_w;
rect.bottom = in_y+in_h;
CBrush brush(color);
m_pMemDC->FillRect(&rect,&brush);
}
void Engine_2D::DrawEllipse(int in_CenterX, int in_CenterY, int in_Radius, COLORREF color, int in_iPenType, bool in_bIsNull)
{
int px = in_CenterX-in_Radius;
int py = in_CenterY-in_Radius;
int px1 = in_CenterX+in_Radius;
int py1 = in_CenterY+in_Radius;
//选笔选刷
CPen pen(in_iPenType,1,color);
CBrush brush(color);
CPen* pOldpen = m_pMemDC->SelectObject(&pen);
CBrush* pOldbrush = m_pMemDC->SelectObject(&brush);
if( in_bIsNull) m_pMemDC->SelectObject(GetStockObject(NULL_BRUSH));
//画饼
m_pMemDC->Ellipse(px,py,px1,py1);
m_pMemDC->SelectObject(pOldpen);
m_pMemDC->SelectObject(pOldbrush);
}
void Engine_2D::DrawPie(int in_CenterX, int in_CenterY, int in_Radius, COLORREF color, int in_StartAngle, int in_HaveAngle)
{
if( in_HaveAngle <= 0) return; //不占有空间,返回
int px = in_CenterX-in_Radius;
int py = in_CenterY-in_Radius;
int px1 = in_CenterX+in_Radius;
int py1 = in_CenterY+in_Radius;
int rx, ry, rx1, ry1;
AngleToPostion(rx, ry, in_CenterX, in_CenterY, in_Radius, in_StartAngle);
AngleToPostion(rx1, ry1, in_CenterX, in_CenterY, in_Radius, in_StartAngle+in_HaveAngle);
//选笔选刷
CPen pen(PS_SOLID,1,color);
CBrush brush(color);
CPen* pOldpen = m_pMemDC->SelectObject(&pen);
CBrush* pOldbrush = m_pMemDC->SelectObject(&brush);
//画饼
m_pMemDC->Pie(px,py,px1,py1,rx1,ry1,rx,ry);
m_pMemDC->SelectObject(pOldpen);
m_pMemDC->SelectObject(pOldbrush);
}
bool Engine_2D::AngleToPostion(int& out_PosX, int& out_PosY,
int in_CenterX, int in_CenterY, int in_Radius,int in_Angle)
{
if( in_Angle < 0) return false; //不占有空间,返回
while(in_Angle > 360) in_Angle -= 360;
double ang = in_Angle/180.0*3.14159;
//以原点为坐标
int iStartPox_X = 0;
int iStartPox_y = in_Radius;
int rx = iStartPox_X*cos(ang)+iStartPox_y*sin(ang);
int ry = -iStartPox_X*sin(ang)+iStartPox_y*cos(ang);
//折算窗口坐标
ry *= -1;//windows窗口坐标Y是倒立的
out_PosX = in_CenterX+rx;
out_PosY = in_CenterY+ry;
return true;
}
void Engine_2D::DrawLine(int in_X0, int in_Y0, int in_X1, int in_Y1, int in_LineWidth, COLORREF in_Color, bool in_bIsAA)
{
if( in_bIsAA)
{
CTGraphics tGraphics;
for(int i=0; i {
tGraphics.DrawLine(*m_pMemDC, in_X0+i, in_Y0, in_X1+i, in_Y1, in_Color);
tGraphics.DrawLine(*m_pMemDC, in_X0-i, in_Y0, in_X1-i, in_Y1, in_Color);
}
}
else
{
CPen pen(PS_SOLID,in_LineWidth,in_Color);
CPen* pOldpen = m_pMemDC->SelectObject(&pen);
m_pMemDC->MoveTo(in_X0,in_Y0);
m_pMemDC->LineTo(in_X1,in_Y1);
m_pMemDC->SelectObject(pOldpen);
}
}
void Engine_2D::DrawPointLine(int in_X0, int in_Y0, int in_X1, int in_Y1, int in_LineWidth, int in_PointWidth, COLORREF in_Color)
{
DrawLine(in_X0,in_Y0,in_X1,in_Y1,in_LineWidth,in_Color);
DrawPie(in_X0,in_Y0,in_PointWidth,in_Color);
DrawPie(in_X1,in_Y1,in_PointWidth,in_Color);
}
void Engine_2D::Invalidate()
{
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = m_SinceW;
rect.bottom = m_SinceH;
m_pCWnd->InvalidateRect(&rect);
m_pCWnd->UpdateData();
DoEvent();
}
void Engine_2D::Invalidate(int x, int y, int w, int h)
{
RECT rect;
rect.left = x;
rect.top = y;
rect.right = x+w;
rect.bottom = y+h;
m_pCWnd->InvalidateRect(&rect);
m_pCWnd->UpdateData();
DoEvent();
}
void Engine_2D::DoEvent()
{
MSG msg;
while (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE) )//判断是否有消息
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void Engine_2D::SaveSince(const LPCWSTR in_cPath, int in_x, int in_y, int in_w, int in_h)
{
RECT rect;
rect.left = in_x;
rect.top = in_y;
rect.right = in_w;
rect.bottom = in_h;
SaveBitmapToFile(CopyScreenToBitmap(&rect),in_cPath);
}
void Engine_2D::SaveClientSince(const LPCWSTR in_cPath, int in_x, int in_y, int in_w, int in_h)
{
RECT rect;
rect.left = in_x;
rect.top = in_y;
rect.right = in_x+in_w;
rect.bottom = in_y+in_h;
m_pCWnd->ClientToScreen(&rect);
SaveBitmapToFile(CopyScreenToBitmap(&rect),in_cPath);
}
HBITMAP Engine_2D::CopyScreenToBitmap(LPRECT lpRect) //lpRect 代表选定区域
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 位图宽度和高度
int xScrn, yScrn;
// 屏幕分辨率
// 确保选定区域不为空矩形
if( IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC,hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,0,0, nWidth,nHeight, hScrDC, nX, nY, SRCCOPY);
//得到屏幕位图的句柄
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
int Engine_2D::SaveBitmapToFile(HBITMAP hBitmap, LPCWSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄
{
//lpFileName 为位图文件名
HDC hDC;
//设备描述表
int iBits;
//当前显示分辨率下每个像素所占字节数
WORD wBitCount;
//位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAP Bitmap;
//位图属性结构
BITMAPFILEHEADER bmfHdr;
//位图文件头结构
BITMAPINFOHEADER bi;
//位图信息头结构
LPBITMAPINFOHEADER lpbi;
//指向位图信息头结构
HANDLE fh, hDib, hPal;
HPALETTE hOldPal=NULL;
//定义文件,分配内存句柄,调色板句柄
//计算位图文件每个像素所占字节数
hDC = CreateDC(L"DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 16)
wBitCount = 16;
else if (iBits <= 24)
wBitCount = 24;
else
wBitCount = 32;
//计算调色板大小
if(wBitCount <= 8)
dwPaletteSize=(1< //设置位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = GetDC(NULL);
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
SelectPalette(hDC, hOldPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
}
//创建位图文件
fh=CreateFile(lpFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh==INVALID_HANDLE_VALUE)
return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
void Engine_2D::DrawText(CString sText,RECT& rect,int in_LineWidth, COLORREF in_Color)
{
CPen pen(PS_SOLID,in_LineWidth,in_Color);
CPen* pOldpen = m_pMemDC->SelectObject(&pen);
m_pMemDC->DrawText(sText, &rect, DT_LEFT);
m_pMemDC->SelectObject(pOldpen);
}
void Engine_2D::DrawText(CString sText,int x, int y, int w, int h, int in_LineWidth, COLORREF in_Color)
{
RECT rect;
rect.left = x;
rect.top = y;
rect.right = x+w;
rect.bottom = y+h;
DrawText(sText,rect,in_LineWidth, in_Color);
}
// TGraphics.cpp: implementation of the CTGraphics class.
//
//
#include "stdafx.h"
#include "TGraphics.h"
#include "math.h"
CTGraphics::CTGraphics()
{
}
CTGraphics::~CTGraphics()
{
}
void CTGraphics::DrawLine(HDC hDC, int x1, int y1, int x2, int y2, COLORREF color)
{
// Calculate line params
int dx = (x2 - x1);
int dy = (y2 - y1);
COLORREF bgColor;
int temp;
float k;
// Set start pixel
::SetPixel(hDC, x1, y1, color);
// X-dominant line
if (abs(dx) > abs(dy))
{
// Ex-change line end points
if (dx < 0)
{
temp = x1;
x1 = x2;
x2 = temp;
temp = y1;
y1 = y2;
y2 = temp;
}
k = (float)dy / (float)dx;
// Set middle pixels
int xs;
float yt = (float)y1 + k;
float distance;
UCHAR red, green, blue;
for (xs=x1+1; xs {
distance = (float)(yt - (int)(yt));
bgColor = ::GetPixel(hDC, xs, (int)yt);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, xs, (int)yt, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, xs, (int)yt+1);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, xs, (int)yt+1, RGB(red,green,blue));
yt += k;
}
}
// Y-dominant line
else
{
// Ex-change line end points
if (dy < 0)
{
temp = x1;
x1 = x2;
x2 = temp;
temp = y1;
y1 = y2;
y2 = temp;
}
k = (float)dx / (float)dy;
// Set middle pixels
int ys;
float xt = (float)x1 + k;
float distance;
UCHAR red, green, blue;
for (ys=y1+1; ys {
distance = (float)(xt - (int)(xt));
bgColor = ::GetPixel(hDC, (int)xt, ys);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, (int)xt, ys, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, (int)xt+1, ys);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, (int)xt+1, ys, RGB(red,green,blue));
xt += k;
}
}
// Set end pixel
::SetPixel(hDC, x2, y2, color);
}
void CTGraphics::DrawPolyline(HDC hDC, POINT* points, int numberPoints, COLORREF color)
{
for (int i=0; i {
DrawLine(hDC, points[i].x, points[i].y, points[i+1].x, points[i+1].y, color);
}
}
void CTGraphics::DrawPolygon(HDC hDC, POINT* points, int numberPoints, COLORREF color)
{
DrawPolyline(hDC, points, numberPoints, color);
DrawLine(hDC, points[0].x, points[0].y, points[numberPoints-1].x, points[numberPoints-1].y, color);
}
void CTGraphics::DrawEllipse(HDC hDC, int x1, int y1, int x2, int y2, COLORREF color)
{
int centerX = (x1 + x2) / 2;
int centerY = (y1 + y2) / 2;
int dx = (x2 - x1);
int dy = (y2 - y1);
int radiusX = (int)(fabs((float)dx) / 2.0f);
int radiusY = (int)(fabs((float)dy) / 2.0f);
float rel = (float)sqrt((float)radiusX*radiusX + radiusY*radiusY) / (float)radiusY;
COLORREF bgColor;
int temp;
float distance;
UCHAR red, green, blue;
if (x2 < x1)
{
temp = x1;
x1 = x2;
x2 = temp;
temp = y1;
y1 = y2;
y2 = temp;
}
int xs;
float yt;
for (xs=-radiusX; xs<=radiusX; xs++)
{
yt = (float)(radiusY * sqrt(1-(float)(xs*xs)/(float)(radiusX*radiusX)));
distance = (float)(yt - (int)yt);
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, centerX+xs, centerY+(int)yt, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt+1);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, centerX+xs, centerY+(int)yt+1, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX-xs, centerY-(int)yt);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, centerX-xs, centerY-(int)yt, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX-xs, centerY-(int)yt-1);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, centerX-xs, centerY-(int)yt-1, RGB(red,green,blue));
}
int ys;
float xt;
for (ys=-(int)((float)radiusY/rel); ys<=(int)((float)radiusY/rel); ys++)
{
xt = (float)(radiusX * sqrt(1-(float)(ys*ys)/(float)(radiusY*radiusY)));
distance = (float)(xt - (int)xt);
bgColor = ::GetPixel(hDC, centerX+(int)xt, centerY+ys);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, centerX+(int)xt, centerY+ys, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX+(int)xt+1, centerY+ys);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, centerX+(int)xt+1, centerY+ys, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX-(int)xt, centerY-ys);
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
::SetPixel(hDC, centerX-(int)xt, centerY-ys, RGB(red,green,blue));
bgColor = ::GetPixel(hDC, centerX-(int)xt-1, centerY-ys);
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
::SetPixel(hDC, centerX-(int)xt-1, centerY-ys, RGB(red,green,blue));
}
}
void CTGraphics::DrawArc(HDC hDC, int x1, int y1, int x2, int y2, float startAngle, float endAngle, COLORREF color)
{
int centerX = (x1 + x2) / 2;
int centerY = (y1 + y2) / 2;
int dx = (x2 - x1);
int dy = (y2 - y1);
int radiusX = (abs(dx) / 2);
int radiusY = (abs(dy) / 2);
COLORREF bgColor;
float distance;
UCHAR red, green, blue;
float angle = 0.0f;
while ((angle+90.0f) < startAngle)
angle += 90.0f;
while (angle < endAngle)
{
if (startAngle >= angle)
{
float eAngle;
if (endAngle <= angle+90.0f)
eAngle = endAngle;
else
eAngle = angle+90.0f;
float sx = (float)(radiusX*cos((startAngle/180.0f)*3.1415f));
if (sx > 0.0f)
sx += 0.5f;
else
sx -= 0.5f;
int startX = (int)sx;
int endX = (int)(radiusX*cos((eAngle/180.0f)*3.1415f));
int deltaX;
if (endX - startX != 0)
deltaX = (int)((endX-startX) / fabs((float)endX-startX));
else
deltaX = 0;
float sy = (float)(radiusY*sin((startAngle/180.0f)*3.1415f));
if (sy > 0.0f)
sy += 0.5f;
else
sy -= 0.5f;
int startY = (int)sy;
int endY = (int)(radiusY*sin((eAngle/180.0f)*3.1415f));
int deltaY;
if (endY - startY != 0)
deltaY = (int)((endY-startY) / fabs((float)endY-startY));
else
deltaY = 0;
if (deltaX != 0)
{
int oldY = startY;
int xs = startX;
float yt;
while (xs != endX)
{
yt = (float)(radiusY * sqrt(1.0f-(float)(xs*xs)/(float)(radiusX*radiusX)));
distance = (float)(yt - (int)yt);
if (abs(oldY - (int)yt) < 2)
{
if (deltaX < 0)
{
if (deltaY > 0)
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt);
else
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt);
}
else
{
if (deltaY < 0)
bgColor = ::GetPixel(hDC, centerX+xs, centerY-(int)yt);
else
bgColor = ::GetPixel(hDC, centerX+xs, centerY-(int)yt);
}
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
if (deltaX < 0)
{
if (deltaY > 0)
::SetPixel(hDC, centerX+xs, centerY+(int)yt, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+xs, centerY+(int)yt, RGB(red,green,blue));
}
else
{
if (deltaY < 0)
::SetPixel(hDC, centerX+xs, centerY-(int)yt, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+xs, centerY-(int)yt, RGB(red,green,blue));
}
if (deltaX < 0)
{
if (deltaY > 0)
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt+1);
else
bgColor = ::GetPixel(hDC, centerX+xs, centerY+(int)yt+1);
}
else
{
if (deltaY < 0)
bgColor = ::GetPixel(hDC, centerX+xs, centerY-(int)yt-1);
else
bgColor = ::GetPixel(hDC, centerX+xs, centerY-(int)yt-1);
}
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
if (deltaX < 0)
{
if (deltaY > 0)
::SetPixel(hDC, centerX+xs, centerY+(int)yt+1, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+xs, centerY+(int)yt+1, RGB(red,green,blue));
}
else
{
if (deltaY < 0)
::SetPixel(hDC, centerX+xs, centerY-(int)yt-1, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+xs, centerY-(int)yt-1, RGB(red,green,blue));
}
}
oldY = (int)yt;
xs += deltaX;
}
}
if (deltaY != 0)
{
int oldX = startX;
int ys = startY;
float xt;
while (ys != endY)
{
xt = (float)(radiusX * sqrt(1.0f-(float)(ys*ys)/(float)(radiusY*radiusY)));
distance = (float)(xt - (int)xt);
if (abs(oldX - (int)xt) < 2)
{
if (deltaX < 0)
{
if (deltaY > 0)
bgColor = ::GetPixel(hDC, centerX+(int)xt, centerY+ys);
else
bgColor = ::GetPixel(hDC, centerX-(int)xt, centerY+ys);
}
else
{
if (deltaY < 0)
bgColor = ::GetPixel(hDC, centerX-(int)xt, centerY+ys);
else
bgColor = ::GetPixel(hDC, centerX+(int)xt, centerY+ys);
}
red = (UCHAR)(distance*GetRValue(bgColor)) + (UCHAR)((1.0f-distance)*GetRValue(color));
green = (UCHAR)(distance*GetGValue(bgColor)) + (UCHAR)((1.0f-distance)*GetGValue(color));
blue = (UCHAR)(distance*GetBValue(bgColor)) + (UCHAR)((1.0f-distance)*GetBValue(color));
if (deltaX < 0)
{
if (deltaY > 0)
::SetPixel(hDC, centerX+(int)xt, centerY+ys, RGB(red,green,blue));
else
::SetPixel(hDC, centerX-(int)xt, centerY+ys, RGB(red,green,blue));
}
else
{
if (deltaY < 0)
::SetPixel(hDC, centerX-(int)xt, centerY+ys, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+(int)xt, centerY+ys, RGB(red,green,blue));
}
if (deltaX < 0)
{
if (deltaY > 0)
bgColor = ::GetPixel(hDC, centerX+(int)xt+1, centerY+ys);
else
bgColor = ::GetPixel(hDC, centerX-(int)xt-1, centerY+ys);
}
else
{
if (deltaY < 0)
bgColor = ::GetPixel(hDC, centerX-(int)xt-1, centerY+ys);
else
bgColor = ::GetPixel(hDC, centerX+(int)xt+1, centerY+ys);
}
red = (UCHAR)((1.0f-distance)*GetRValue(bgColor)) + (UCHAR)(distance*GetRValue(color));
green = (UCHAR)((1.0f-distance)*GetGValue(bgColor)) + (UCHAR)(distance*GetGValue(color));
blue = (UCHAR)((1.0f-distance)*GetBValue(bgColor)) + (UCHAR)(distance*GetBValue(color));
if (deltaX < 0)
{
if (deltaY > 0)
::SetPixel(hDC, centerX+(int)xt+1, centerY+ys, RGB(red,green,blue));
else
::SetPixel(hDC, centerX-(int)xt-1, centerY+ys, RGB(red,green,blue));
}
else
{
if (deltaY < 0)
::SetPixel(hDC, centerX-(int)xt-1, centerY+ys, RGB(red,green,blue));
else
::SetPixel(hDC, centerX+(int)xt+1, centerY+ys, RGB(red,green,blue));
}
}
oldX = (int)xt;
ys += deltaY;
}
}
}
angle += 90.0f;
startAngle = angle;
}
}
void CTGraphics::DrawPie(HDC hDC, int x1, int y1, int x2, int y2, float startAngle, float endAngle, COLORREF color)
{
int centerX = (x1 + x2) / 2;
int centerY = (y1 + y2) / 2;
int dx = (x2 - x1);
int dy = (y2 - y1);
int radiusX = (abs(dx) / 2);
int radiusY = (abs(dy) / 2);
int startX = (int)(radiusX*cos((startAngle/180.0f)*3.1415f));
int startY = (int)(radiusY*sin((startAngle/180.0f)*3.1415f));
int endX = (int)(radiusX*cos((endAngle/180.0f)*3.1415f));
int endY = (int)(radiusY*sin((endAngle/180.0f)*3.1415f));
if (endX < 0)
{
if (endY > 0)
endY++;
else
endX--;
}
else
{
if (endY < 0)
endY--;
else
endX++;
}
DrawArc(hDC, x1, y1, x2, y2, startAngle, endAngle, color);
DrawLine(hDC, centerX, centerY, centerX+startX, centerY+startY, color);
DrawLine(hDC, centerX, centerY, centerX+endX, centerY+endY, color);
}
void CTGraphics::DrawChord(HDC hDC, int x1, int y1, int x2, int y2, float startAngle, float endAngle, COLORREF color)
{
int centerX = (x1 + x2) / 2;
int centerY = (y1 + y2) / 2;
int dx = (x2 - x1);
int dy = (y2 - y1);
int radiusX = (abs(dx) / 2);
int radiusY = (abs(dy) / 2);
int startX = (int)(radiusX*cos((startAngle/180.0f)*3.1415f));
int startY = (int)(radiusY*sin((startAngle/180.0f)*3.1415f));
int endX = (int)(radiusX*cos((endAngle/180.0f)*3.1415f));
int endY = (int)(radiusY*sin((endAngle/180.0f)*3.1415f));
if (endX < 0)
{
if (endY > 0)
endY++;
else
endX--;
}
else
{
if (endY < 0)
endY--;
else
endX++;
}
DrawArc(hDC, x1, y1, x2, y2, startAngle, endAngle, color);
DrawLine(hDC, centerX+startX, centerY+startY, centerX+endX, centerY+endY, color);
}
void CTGraphics::DrawRoundRect(HDC hDC, int x1, int y1, int x2, int y2, int width, int height, COLORREF color)
{
int dx = (x2 - x1);
int dy = (y2 - y1);
int offsetX = width / 2;
width = offsetX * 2;
int offsetY = height / 2;
height = offsetY * 2;
if ((width > abs(dx)) || (height > abs(dy)))
{
DrawEllipse(hDC, x1, y1, x2, y2, color);
}
else
{
DrawLine(hDC, x1+offsetX, y1, x2-offsetX, y1, color);
DrawArc(hDC, x2-width, y1, x2, y1+height, 270.0f, 360.0f, color);
DrawLine(hDC, x2, y1+offsetY, x2, y2-offsetY, color);
DrawArc(hDC, x2-width, y2-height, x2, y2, 0.0f, 90.0f, color);
DrawLine(hDC, x2-offsetX, y2, x1+offsetX, y2, color);
DrawArc(hDC, x1, y2-height, x1+width, y2, 90.0f, 180.0f, color);
DrawLine(hDC, x1, y2-offsetY, x1, y1+offsetY, color);
DrawArc(hDC, x1, y1, x1+width, y1+height, 180.0f, 270.0f, color);
}
}
void CTGraphics::DrawBezier(HDC hDC, POINT* points, int numPoints, COLORREF color)
{
int numCurves = (numPoints-1) / 3;
int numReqPoints = numCurves*3 + 1;
if (numPoints >= numReqPoints)
{
POINT startPoint, endPoint, controlPoint1, controlPoint2;
float distance1, distance2, distance3, distanceX, distanceY;
float ax, bx, cx, ay, by, cy, t, step;
float xt, yt, k, k1;
int oldX, oldY, oldX1, oldY1;
for (int i=0; i {
startPoint = points[i*3];
controlPoint1 = points[i*3+1];
controlPoint2 = points[i*3+2];
endPoint = points[i*3+3];
if (controlPoint1.y == controlPoint2.y)
{
DrawLine(hDC, startPoint.x, startPoint.y, endPoint.x, endPoint.y, color);
}
else
{
distance1 = (float)sqrt(pow((float)controlPoint1.x-startPoint.x,2) + pow((float)controlPoint1.y-startPoint.y,2));
distance2 = (float)sqrt(pow((float)controlPoint2.x-controlPoint1.x,2) + pow((float)controlPoint2.y-controlPoint1.y,2));
distance3 = (float)sqrt(pow((float)endPoint.x-controlPoint2.x,2) + pow((float)endPoint.y-controlPoint2.y,2));
step = 1.0f / (distance1+distance2+distance3);
cx = 3.0f*(controlPoint1.x - startPoint.x);
bx = 3.0f*(controlPoint2.x - controlPoint1.x) - cx;
ax = endPoint.x - startPoint.x - bx - cx;
cy = 3.0f*(controlPoint1.y - startPoint.y);
by = 3.0f*(controlPoint2.y - controlPoint1.y) - cy;
ay = endPoint.y - startPoint.y - by - cy;
oldX = startPoint.x;
oldY = startPoint.y;
k1 = 0.0f;
for (t=0.0f; t<=1.0f; t+=step)
{
xt = ax*(t*t*t) + bx*(t*t) + cx*t + startPoint.x;
yt = ay*(t*t*t) + by*(t*t) + cy*t + startPoint.y;
distanceX = (float)(xt - (int)(xt));
distanceY = (float)(yt - (int)(yt));
if (((int)xt != oldX) && ((int)yt != oldY))
{
oldX1 = oldX;
oldY1 = oldY;
k = (float)((int)yt - oldY) / (float)((int)xt - oldX);
if (k != k1)
{
DrawLine(hDC, oldX, oldY, (int)xt, (int)yt, color);
k1 = k;
oldX = (int)xt;
oldY = (int)yt;
}
}
}
if (((int)xt != oldX1) || ((int)yt != oldY1))
{
int dx = ((int)xt - oldX1);
int dy = ((int)yt - oldY1);
if (abs(dx) > abs(dy))
{
if (dy > 0)
DrawLine(hDC, oldX, oldY, (int)xt, (int)yt+1, color);
else
DrawLine(hDC, oldX, oldY, (int)xt, (int)yt-1, color);
}
else
{
if (dx > 0)
DrawLine(hDC, oldX, oldY, (int)xt+1, (int)yt, color);
else
DrawLine(hDC, oldX, oldY, (int)xt-1, (int)yt, color);
}
}
}
}
}
}