huidong

首页 | 会员登录 | 关于争取 2022 寒假做出汇东网 Ver3.0.0 !
搜索文章



这里是旧版,新版请在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;
}


图片.png



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;
}



图片.png


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;
}

录制_2020_07_08_13_37_37_486.gif


注意事项

设置了绘图目标窗口后,

不要使用MouseHit和GetMouseMsg等函数,因为什么也得不到,请使用GetMousePoint来得到鼠标位置。

不要直接SetWorkingImage(NULL),因为设置了目标绘图窗口后,主画布(IMAGE对象)就不再是NULL可以表示的了,请将其改成SetWorkingImage(GetMainImage()/* 得到主画布的地址 */);






返回首页


Copyright (C) 2018-2024 huidong