AHGraphics.h , 让你快速设置easyx的绘图目标窗口(HWND)或HDC
[編輯] [转简体] (简体译文)
|
作者:huidong
| 分類:【編程】EasyX
[
7 瀏覽
0 評論
0 贊
0 踩
]
概要
设置easyx的绘图目标窗口(HWND)或HDC
正文
这里是旧版,新版请在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()/* 得到主画布的地址 */);