eduwin 画布绘图教程
eduwin 的画布(Canvas)组件提供完整的 2D 绘图能力,基于 GDI+ 实现,支持线、矩形、椭圆、多边形、扇形、贝塞尔曲线、路径、文本、图像等绘制,还内置双缓冲离屏渲染,天然无闪烁。
1. 创建画布
#include "eduwin.h"
HWND win = create_window(L"画布演示", 640, 480);
HWND canvas = create_canvas(win, 0, 0, 640, 480);
create_canvas 在窗口中创建一个画布控件,参数依次为父窗口、x、y、宽度、高度。
注意:所有绘图操作必须在
show_window之后调用!show_window触发WM_SIZE消息,画布会重新创建离屏位图,之前绘制的内容会被清空。
2. 基本绘图流程
show_window(win);
// 1. 清空画布背景
canvas_clear(canvas, 240, 240, 240, 255); // 灰色不透明背景
// 2. 设置画笔(轮廓)
canvas_set_pen(canvas, 0, 0, 255, 255, 3); // 蓝色 3px 不透明
// 3. 设置画刷(填充)
canvas_set_brush(canvas, 255, 200, 200, 255); // 粉色不透明
// 4. 绘图
canvas_draw_rect(canvas, 20, 20, 100, 80); // 矩形边框
canvas_fill_ellipse(canvas, 140, 20, 100, 80); // 填充椭圆
canvas_draw_line(canvas, 20, 120, 300, 120); // 直线
canvas_draw_text(canvas, L"Hello 画布", 20, 140, 0, 0, 0, 255, 20); // 文字
3. 绘图状态
void canvas_clear(HWND canvas, int r, int g, int b, int a);
void canvas_set_pen(HWND canvas, int r, int g, int b, int a, int width);
void canvas_set_brush(HWND canvas, int r, int g, int b, int a);
void canvas_set_font(HWND canvas, const WCHAR *family, int size);
canvas_clear用指定颜色填充整个画布(清除原有内容),参数为 RGBA,范围 0–255canvas_set_pen设置轮廓画笔的颜色、透明度和线宽(默认黑色 1px 不透明)canvas_set_brush设置填充画刷的颜色和透明度(默认白色不透明)canvas_set_font设置文本字体和字号(默认 Microsoft YaHei 14)
绘图状态是全局的——设置后影响后续所有绘制,直到再次修改。
canvas_set_pen(canvas, 255, 0, 0, 255, 5); // 红色 5px 画笔
canvas_draw_rect(canvas, 10, 10, 100, 100); // 红色5px边框
canvas_set_pen(canvas, 0, 128, 0, 200, 1); // 绿色半透明 1px 画笔
canvas_draw_rect(canvas, 130, 10, 100, 100); // 绿色1px边框
4. 基本几何图形
void canvas_draw_line(HWND canvas, int x1, int y1, int x2, int y2);
void canvas_draw_rect(HWND canvas, int x, int y, int w, int h);
void canvas_fill_rect(HWND canvas, int x, int y, int w, int h);
void canvas_draw_ellipse(HWND canvas, int x, int y, int w, int h);
void canvas_fill_ellipse(HWND canvas, int x, int y, int w, int h);
void canvas_fill_polygon(HWND canvas, const PointF *pts, int count);
void canvas_fill_pie(HWND canvas, int x, int y, int w, int h, float start_angle, float sweep_angle);
draw_line/draw_rect/draw_ellipse用当前画笔绘制轮廓fill_rect/fill_ellipse/fill_polygon/fill_pie用当前画刷填充
填充多边形示例:
/* 绘制一个蓝色三角形 */
PointF pts[3] = {
{200, 50}, /* 顶点 */
{150, 150}, /* 左下 */
{250, 150} /* 右下 */
};
canvas_set_brush(canvas, 50, 100, 200, 200); // 半透明蓝色
canvas_fill_polygon(canvas, pts, 3);
填充扇形示例:
/* 绘制一个从 0° 到 90° 的扇形 */
canvas_set_brush(canvas, 200, 100, 50, 220);
canvas_fill_pie(canvas, 300, 50, 120, 120, 0, 90);
5. 弧形与贝塞尔曲线
void canvas_draw_arc(HWND canvas, int x, int y, int w, int h, float start_angle, float sweep_angle);
void canvas_draw_bezier(HWND canvas, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
draw_arc绘制椭圆弧线段,start_angle为起始角度(度),sweep_angle为扫过的角度(逆时针为正)draw_bezier绘制三次贝塞尔曲线,4 个点依次为起点、控制点 1、控制点 2、终点
/* 弧线:从 0° 到 180° */
canvas_set_pen(canvas, 200, 50, 50, 255, 3);
canvas_draw_arc(canvas, 50, 200, 100, 80, 0, 180);
/* 贝塞尔曲线 */
canvas_draw_bezier(canvas, 200, 200, 250, 100, 350, 300, 400, 200);
6. 路径系统
路径(Path)允许你将多条线段、弧线、椭圆、矩形组合成一个图形,然后统一绘制或填充。
void *canvas_create_path(void);
void canvas_add_path_line(void *path, float x1, float y1, float x2, float y2);
void canvas_add_path_arc(void *path, float x, float y, float w, float h, float start_angle, float sweep_angle);
void canvas_add_path_ellipse(void *path, float x, float y, float w, float h);
void canvas_add_path_rect(void *path, float x, float y, float w, float h);
void canvas_close_path(void *path);
void canvas_draw_path(HWND canvas, void *path);
void canvas_fill_path(HWND canvas, void *path);
void canvas_delete_path(void *path);
使用模式:创建路径 → 添加图形 → 绘制/填充 → 销毁路径。
/* 创建一个心形路径 */
void *path = canvas_create_path();
canvas_add_path_ellipse(path, 0, 0, 80, 80); // 左圆
canvas_add_path_ellipse(path, 60, 0, 80, 80); // 右圆
canvas_add_path_line(path, 0, 50, 70, 140); // 左侧边
canvas_add_path_line(path, 70, 140, 140, 50); // 右侧边
canvas_close_path(path);
canvas_set_brush(canvas, 220, 60, 80, 255);
canvas_fill_path(canvas, path);
canvas_set_pen(canvas, 180, 30, 50, 255, 2);
canvas_draw_path(canvas, path);
canvas_delete_path(path);
7. 绘制文本
void canvas_set_font(HWND canvas, const WCHAR *family, int size);
void canvas_draw_text(HWND canvas, const WCHAR *text, int x, int y, int r, int g, int b, int a, int size);
canvas_set_font设置全局字体和字号(size为 0 时不影响后续单次绘制)canvas_draw_text的r g b a为文字颜色和透明度,size传 0 使用canvas_set_font设定的字号
/* 设置全局字体 */
canvas_set_font(canvas, L"SimSun", 24); // 宋体 24 号
canvas_draw_text(canvas, L"你好,eduwin", 50, 300, 50, 50, 50, 255, 0); // 用全局设置
/* 单次绘制指定字号 */
canvas_draw_text(canvas, L"大标题", 50, 340, 200, 50, 50, 255, 36);
canvas_draw_text(canvas, L"小标注", 50, 390, 128, 128, 128, 255, 12);
8. 绘制图像
void *load_image_from_file(const WCHAR *filepath, UINT *width, UINT *height);
void canvas_draw_image(HWND canvas, void *image, int x, int y, int w, int h);
UINT iw, ih;
void *img = load_image_from_file(L"photo.png", &iw, &ih);
if (img)
{
canvas_draw_image(canvas, img, 10, 10, (int)iw, (int)ih);
}
9. 局部清除与文件输出
void canvas_clear_rect(HWND canvas, int x, int y, int w, int h, int r, int g, int b, int a);
void canvas_save_image(HWND canvas, const WCHAR *filepath);
canvas_clear_rect 用颜色填充指定矩形区域(局部清除),a 为透明度。canvas_save_image 将画布当前内容保存为图像文件(根据扩展名自动选择编码器,支持 png/jpg/bmp)。
/* 在灰色区域中挖一个矩形 */
canvas_set_brush(canvas, 180, 180, 180, 255);
canvas_fill_rect(canvas, 10, 10, 200, 100);
/* 局部清除并填充绿色 */
canvas_clear_rect(canvas, 50, 30, 100, 40, 100, 200, 50, 255);
/* 保存为文件 */
canvas_save_image(canvas, L"output.png");
10. 画布尺寸
int canvas_get_width(HWND canvas);
int canvas_get_height(HWND canvas);
获取画布的实际像素尺寸,通常配合 show_window 之后使用:
int cw = canvas_get_width(canvas);
int ch = canvas_get_height(canvas);
canvas_draw_text(canvas, L"居中文字", cw / 2 - 60, ch / 2, 0, 0, 0, 255, 20);
完整示例
#include "eduwin.h"
int main(void)
{
init_app();
HWND win = create_window(L"画布绘图教程", 400, 400);
HWND canvas = create_canvas(win, 0, 0, 400, 400);
show_window(win);
/* 白色背景 */
canvas_clear(canvas, 255, 255, 255, 255);
/* 红色矩形边框 */
canvas_set_pen(canvas, 220, 50, 50, 255, 3);
canvas_draw_rect(canvas, 20, 20, 160, 100);
/* 蓝色填充椭圆 */
canvas_set_brush(canvas, 60, 120, 200, 200);
canvas_fill_ellipse(canvas, 220, 20, 160, 100);
/* 绿色直线 */
canvas_set_pen(canvas, 60, 160, 60, 255, 2);
canvas_draw_line(canvas, 20, 180, 380, 180);
/* 半透明填充三角形 */
canvas_set_brush(canvas, 200, 160, 60, 180);
PointF pts[3] = {{200, 220}, {100, 350}, {300, 350}};
canvas_fill_polygon(canvas, pts, 3);
/* 灰色文字 */
canvas_draw_text(canvas, L"eduwin 画布", 140, 370, 80, 80, 80, 255, 16);
run_app();
return 0;
}
编译命令:
cl canvas_demo.c /Feoutput.exe /I include /link eduwin.lib lib\*.lib