这里是旧版,新版请在github下载:
https://github.com/zouhuidong/AHGraphics
AHGraphics.h Source and Download
download : AHGraphics.zip
source :
///////////////////////////////////////////////////////
//
// AHGraphics.h (All Hwnd Graphics with EasyX)
//
// by huidong <mailkey@yeah.net>
//
// 这个头文件可以帮助你将EasyX的绘图内容复制到任何窗口上
//
#pragma once
#include <easyx.h>
//////////////////// 全局变量 ////////////////////
// 内部变量
// 当前绘图窗口HWND
HWND m_wnd = NULL;
// 内部变量
// 当前绘图HDC
HDC m_hdc = NULL;
// 内部变量
// 当前绘图主IMAGE画布
IMAGE m_img;
// 内部变量
// 自动输出绘图内容的线程的句柄
HANDLE m_hThAutoFlush = NULL;
// 内部变量
// 和自动输出绘图内容的线程的通讯标志
// 指定是否自动绘图
bool m_isAutoFlush = false;
//////////////////// 函数定义 ////////////////////
//////////////////// 设置参数类函数
// 得到窗口位置、区域
RECT GetWindowRect(HWND wnd)
{
RECT rcClient;
GetClientRect(wnd, &rcClient);
return rcClient;
}
// 得到窗口大小
POINT GetWindowSize(HWND wnd)
{
POINT size;
RECT rct;
rct = GetWindowRect(wnd);
size = { rct.right - rct.left,rct.bottom - rct.top };
return size;
}
// 设置当前绘图目标窗口
// 请勿直接调用此函数,请使用InitDrawing
void SetWorkingHWnd(HWND wnd)
{
m_wnd = wnd;
m_hdc = GetDC(m_wnd);
}
// 得到当前绘图目标窗口
HWND GetWorkingHWnd()
{
return m_wnd;
}
// 设置当前绘图目标HDC
// 请勿直接调用此函数,请使用InitDrawing
void SetWorkingHDC(HDC hdc)
{
m_hdc = hdc;
SetWorkingHWnd(WindowFromDC(hdc));
}
// 得到当前绘图目标HDC
HDC GetWorkingHDC()
{
return m_hdc;
}
// 得到主画布
IMAGE* GetMainImage()
{
return &m_img;
}
//////////////////// 绘图函数
// 将绘制在easyx中的内容显示到目标窗口上
// img 要显示的绘图对象,默认为主画布
// wnd 目标绘图窗口,默认为主窗口
void FlushDrawingToWnd(IMAGE* img = NULL, HWND* wnd = NULL)
{
HDC me_hdc;
HDC img_hdc;
if (img == NULL)
{
img_hdc = GetImageHDC(GetMainImage());
}
else
{
img_hdc = GetImageHDC(img);
}
if (wnd == NULL)
{
me_hdc = GetWorkingHDC();
}
else
{
me_hdc = GetDC(*wnd);
}
POINT wnd_size = GetWindowSize(GetWorkingHWnd());
BitBlt(
me_hdc, // 目标绘图设备
0, // 目标区域左上角x坐标
0, // 目标区域左上角y坐标
wnd_size.x, // 目标区域宽度
wnd_size.y, // 目标区域高度
img_hdc, // 源绘图设备
0, // 源区域左上角x坐标
0, // 源区域左上角y坐标
SRCCOPY // 操作码。常用SRCCOPY(复制)
);
}
// 一直更新绘图内容(堵塞性的)
//
// delay 每次更新的延时(ms)
// flag 保持运作的标志,为false时停止
void KeepFlushDrawing(int delay = 60, bool* flag = &m_isAutoFlush)
{
while (true)
{
if (*flag == false)
{
return;
}
FlushDrawingToWnd();
Sleep(delay);
}
}
//////////////////// 绘图环境初始化类函数
// 使主IMAGE画布大小适应目标绘图窗口大小
void MainImageFitWindow()
{
POINT wnd_size = GetWindowSize(GetWorkingHWnd());
GetMainImage()->Resize(wnd_size.x, wnd_size.y);
}
// 对某一窗口绘图前的初始化
// wnd 窗口句柄
void InitDrawing(HWND wnd)
{
SetWorkingHWnd(wnd);
SetWorkingImage(GetMainImage());
MainImageFitWindow();
}
// 对某一HDC绘图前的初始化
// hdc DC句柄
void InitDrawing(HDC hdc)
{
SetWorkingHDC(hdc);
SetWorkingImage(GetMainImage());
MainImageFitWindow();
}
// 开启 / 关闭 自动输出绘图内容(无需在绘图后手动FlushDrawingToWnd)
// 注意:除非必要,否则不要开启自动输出绘图内容
//
// isAuto 关闭还是开启自动输出,默认为true
void AutoFlushDrawing(bool isAuto = true)
{
if (isAuto)
{
m_isAutoFlush = true;
m_hThAutoFlush = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)KeepFlushDrawing/* 函数名 */, 0, 0, NULL);
}
else
{
m_isAutoFlush = false;
// 关闭自动输出绘图内容的线程
if (m_hThAutoFlush != NULL)
{
CloseHandle(m_hThAutoFlush);
}
}
}
// 结束绘图
// 处理一些结束绘图的后续工作
void EndDrawing()
{
// 关闭自动输出绘图内容
AutoFlushDrawing(false);
//SetWorkingHWnd(NULL);
// 无需设置HWND为NULL,因为设置HDC会直接将HWND清空
SetWorkingHDC(NULL);
}
//////////////////// 其它函数
// 得到鼠标相对于窗口的位置
POINT GetMousePoint()
{
POINT point; // 保存鼠标位置
GetCursorPos(&point); // 获取鼠标指针位置(屏幕坐标)
ScreenToClient(GetWorkingHWnd(), &point); // 将鼠标指针位置转换为窗口坐标
return point;
}
Help and Samples
使用 AHGraphics ,首先include它,然后调用InitDrawing来设置目标绘图HWND或者HDC:
#include "AHGraphics.h"
#include <conio.h>
int main()
{
InitDrawing(GetConsoleWindow()/* 得到cmd句柄 */);
_getch();
EndDrawing();
return 0;
}
以上的代码设置了绘图目标窗口为cmd。
得到cmd句柄的方法http://www.huidong.xyz/?mode=2&id=82
设置了目标绘图窗口,就可以直接使用easyx函数绘图了,例子:
#include "AHGraphics.h"
#include <conio.h>
int main()
{
InitDrawing(GetConsoleWindow()/* 得到cmd句柄 */);
setlinestyle(PS_SOLID, 5);
setlinecolor(BLUE);
line(0, 0, 200, 200);
setlinecolor(RED);
line(30, 30, 200, 30);
// 绘图后要将绘图内容输出
FlushDrawingToWnd();
_getch();
EndDrawing();
return 0;
}
AHGraphics.h 可用函数表:
// 得到窗口位置、区域
RECT GetWindowRect(HWND wnd)
// 得到窗口大小
POINT GetWindowSize(HWND wnd)
// 得到当前绘图目标窗口
HWND GetWorkingHWnd()
// 得到当前绘图目标HDC
HDC GetWorkingHDC()
// 得到主画布
IMAGE* GetMainImage()
// 将绘制在easyx中的内容显示到目标窗口上
// img 要显示的绘图对象,默认为主画布
// wnd 目标绘图窗口,默认为主窗口
void FlushDrawingToWnd(IMAGE* img = NULL, HWND* wnd = NULL)
// 一直更新绘图内容(堵塞性的)
//
// delay 每次更新的延时(ms)
// flag 保持运作的标志,为false时停止
void KeepFlushDrawing(int delay = 60, bool* flag = &m_isAutoFlush)
// 使主IMAGE画布大小适应目标绘图窗口大小
void MainImageFitWindow()
// 对某一窗口绘图前的初始化
// wnd 窗口句柄
void InitDrawing(HWND wnd)
// 对某一HDC绘图前的初始化
// hdc DC句柄
void InitDrawing(HDC hdc)
// 开启 / 关闭 自动输出绘图内容(无需在绘图后手动FlushDrawingToWnd)
// 注意:除非必要,否则不要开启自动输出绘图内容
//
// isAuto 关闭还是开启自动输出,默认为true
void AutoFlushDrawing(bool isAuto = true)
/*
在例如cmd的窗口中,无法接受窗口WM_PAINT消息来FlushDrawingToWnd,就有必要开启AutoFlushDrawing,否则绘图内容容易被擦除
*/
// 结束绘图
// 处理一些结束绘图的后续工作
void EndDrawing()
// 得到鼠标相对于窗口的位置
POINT GetMousePoint()
一些示例:
1. cmd 安卓图标(绘图源码https://codebus.cn/yangw/a/android-robot?tdsourcetag=s_pctim_aiomsg )
#include "AHGraphics.h"
#include <conio.h>
int main()
{
system("mode con cols=100 lines=40");
InitDrawing(GetConsoleWindow());
double PI = 3.1415926;
// 设置原点 (0, 0) 为屏幕中央(Y轴默认向下为正)
setorigin(400, 300);
// 使用藏青色填充背景
setbkcolor(0x7c5731);
cleardevice();
// 设置绘图样式
setlinecolor(WHITE); // 设置线条颜色为白色
setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 10); // 设置线条样式为宽度 10 的实线,端点是平的
setfillcolor(0x24c097); // 设置填充颜色为绿色
// 画身体
fillroundrect(-75, -111, 75, 39, 36, 36);
// 画头
fillpie(-75, -166, 75, -30, 0, PI); // 脸
circle(-31, -131, 3); // 右眼
circle(31, -131, 3); // 左眼
// 画天线
fillellipse(-52, -181, -38, -167); // 右天线
line(-50, -169, -41, -156);
line(-38, -177, -28, -162);
fillellipse(52, -181, 38, -167); // 左天线
line(50, -169, 41, -156);
line(38, -177, 28, -162);
// 用绿色擦掉天线部分多余的线
setlinecolor(0x24c097); // 设置线条颜色为绿色
setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, 5); // 设置线条样式为宽度 5 的实线,端点为圆形
line(-44, -174, -23, -142); // 画右天线内部的绿线
line(44, -174, 23, -142); // 画左天线内部的绿线
setlinecolor(WHITE); // 恢复线条颜色为白色
setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 10); // 恢复线条样式为宽度 10 的实线,端点是平的
// 画胳膊
fillroundrect(-117, -99, -75, 7, 42, 42); // 右胳膊
fillroundrect(117, -99, 75, 7, 42, 42); // 左胳膊
// 画腿
fillpie(-50, 49, -8, 91, PI, PI * 2); // 右腿
line(-50, 40, -50, 70);
line(-8, 40, -8, 70);
solidroundrect(-45, 0, -13, 86, 32, 32);
fillpie(50, 49, 8, 91, PI, PI * 2); // 左腿
line(50, 40, 50, 70);
line(8, 40, 8, 70);
solidroundrect(45, 0, 13, 86, 32, 32);
// 画字母 A
arc(-185, 132, -144, 173, PI / 2, PI * 3 / 2);
line(-165, 132, -135, 132);
line(-165, 173, -154, 173);
line(-140, 127, -140, 178);
// 画字母 N
arc(-118, 131, -78, 171, 0, PI);
line(-118, 151, -118, 178);
line(-78, 151, -78, 178);
// 画字母 D
arc(-57, 132, -16, 173, PI * 3 / 2, PI / 2);
line(-60, 132, -37, 132);
line(-60, 173, -37, 173);
// 画字母 R
arc(14, 132, 40, 158, PI * 3 / 2, PI / 2);
arc(-2, 158, 38, 198, 0, PI / 2);
line(1, 132, 27, 132);
line(1, 158, 27, 158);
// 画字母 O
circle(81, 152, 21);
// 画字母 I
line(124, 127, 124, 178);
// 画字母 D
arc(144, 132, 185, 173, PI * 3 / 2, PI / 2);
line(141, 132, 164, 132);
line(141, 173, 164, 173);
setorigin(0, 0);
FlushDrawingToWnd();
_getch();
EndDrawing();
return 0;
}
2. 新建窗口绘图,得到鼠标位置
#include "AHGraphics.h"
// 保存窗口句柄
HWND wnd;
// 绘图
void Draw()
{
cleardevice();
line(0, 0, GetWindowSize(wnd).x, GetWindowSize(wnd).y);
POINT point = GetMousePoint();
WCHAR str_point[20] = { 0 };
wsprintf(str_point, L"%d, %d", point.x, point.y);
outtextxy(0, 0, str_point);
circle(getwidth() / 2, getheight() / 2, 10);
FlushDrawingToWnd();
}
LRESULT __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_SIZE:
// 调整IMAGE对象大小以适应窗口大小
MainImageFitWindow();
case WM_PAINT:
Draw();
default:
return DefWindowProc(window, msg, wp, lp);
}
}
HWND CreatWnd(LPCTSTR strTitle = _T("title"), LPCTSTR strClass = _T("WndClass"))
{
// 窗口类
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
/* Win 3.x */
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = WindowProcedure;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(0);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = 0;
wc.lpszClassName = strClass;
/* Win 4.0 */
wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
if (RegisterClassEx(&wc))
{
RECT rect;
rect.left = 300;
rect.top = 300;
rect.right = 640;
rect.bottom = 480;
HWND window = CreateWindowEx(0, strClass, strTitle,
WS_OVERLAPPEDWINDOW, rect.left, rect.top,
rect.right, rect.bottom, 0, 0, GetModuleHandle(0), 0);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
return window;
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
// 派发消息
void OnMsg()
{
MSG msg;
GetMessage(&msg, 0, 0, 0);
DispatchMessage(&msg);
}
int main()
{
wnd = CreatWnd(L"My Wnd");
InitDrawing(wnd);
setbkcolor(WHITE);
setlinecolor(BLACK);
settextcolor(BLACK);
while (true)
{
Draw();
OnMsg();
}
return 0;
}
注意事项
设置了绘图目标窗口后,
不要使用MouseHit和GetMouseMsg等函数,因为什么也得不到,请使用GetMousePoint来得到鼠标位置。
不要直接SetWorkingImage(NULL),因为设置了目标绘图窗口后,主画布(IMAGE对象)就不再是NULL可以表示的了,请将其改成SetWorkingImage(GetMainImage()/* 得到主画布的地址 */);