#include <windows.h>

// 工具按钮ID定义:用于区分不同的绘图工具按钮
#define ID_TOOL_LINE    1001    // 直线工具ID
#define ID_TOOL_RECT    1002    // 矩形工具ID
#define ID_TOOL_ELLIPSE 1003    // 椭圆/圆形工具ID
#define ID_TOOL_ERASER  1005    // 橡皮擦工具ID
#define ID_TOOL_CLEAR   1004    // 清空画布工具ID

// 颜色按钮ID定义:用于区分不同的颜色选择按钮
#define ID_COLOR_RED    1010    // 红色ID
#define ID_COLOR_GREEN  1011    // 绿色ID
#define ID_COLOR_BLUE   1012    // 蓝色ID
#define ID_COLOR_BLACK  1013    // 黑色ID

// 全局变量:存储绘图程序的核心状态
int currentTool = 0;            // 当前选中的工具:0直线/1矩形/2椭圆/3橡皮擦
COLORREF currentColor = RGB(0,0,0); // 当前绘图颜色,默认黑色
BOOL isDrawing = FALSE;         // 是否正在绘图的标志:FALSE未绘制,TRUE正在绘制
int startX, startY, endX, endY; // 绘图起点(start)和终点(end)坐标

// 双缓冲绘图相关全局变量(解决绘图闪烁问题)
HBITMAP canvasBitmap = NULL;    // 画布位图:存储所有绘制的内容
HDC memDC = NULL;               // 内存DC:在内存中绘制,再一次性显示到窗口

// 窗口过程函数:处理窗口所有消息(核心回调函数)
// hWnd:窗口句柄  msg:消息类型  wParam/lParam:消息附加参数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;             // 绘图结构体:用于WM_PAINT消息绘图
    HDC hdc;                    // 设备上下文句柄:绘图的核心接口

    switch(msg)                 // 根据消息类型执行不同操作
    {
        case WM_CREATE:         // 窗口创建时触发:初始化界面+画布
        {
            // 获取应用程序实例句柄
            HINSTANCE hInst = ((LPCREATESTRUCT)lParam)->hInstance;

            // ========== 创建绘图工具按钮 ==========
            // 创建"直线"按钮:可见+子窗口,坐标(20,10),大小60x25
            CreateWindowA("BUTTON","直线",WS_VISIBLE|WS_CHILD,20,10,60,25,hWnd,(HMENU)ID_TOOL_LINE,hInst,0);
            // 创建"矩形"按钮
            CreateWindowA("BUTTON","矩形",WS_VISIBLE|WS_CHILD,90,10,60,25,hWnd,(HMENU)ID_TOOL_RECT,hInst,0);
            // 创建"圆形"按钮
            CreateWindowA("BUTTON","圆形",WS_VISIBLE|WS_CHILD,160,10,60,25,hWnd,(HMENU)ID_TOOL_ELLIPSE,hInst,0);
            // 创建"橡皮擦"按钮
            CreateWindowA("BUTTON","橡皮擦",WS_VISIBLE|WS_CHILD,230,10,60,25,hWnd,(HMENU)ID_TOOL_ERASER,hInst,0);
            // 创建"清空画布"按钮
            CreateWindowA("BUTTON","清空画布",WS_VISIBLE|WS_CHILD,300,10,80,25,hWnd,(HMENU)ID_TOOL_CLEAR,hInst,0);

            // ========== 创建颜色选择按钮 ==========
            // 创建"红"色按钮
            CreateWindowA("BUTTON","红",WS_VISIBLE|WS_CHILD,20,45,40,25,hWnd,(HMENU)ID_COLOR_RED,hInst,0);
            // 创建"绿"色按钮
            CreateWindowA("BUTTON","绿",WS_VISIBLE|WS_CHILD,70,45,40,25,hWnd,(HMENU)ID_COLOR_GREEN,hInst,0);
            // 创建"蓝"色按钮
            CreateWindowA("BUTTON","蓝",WS_VISIBLE|WS_CHILD,120,45,40,25,hWnd,(HMENU)ID_COLOR_BLUE,hInst,0);
            // 创建"黑"色按钮
            CreateWindowA("BUTTON","黑",WS_VISIBLE|WS_CHILD,170,45,40,25,hWnd,(HMENU)ID_COLOR_BLACK,hInst,0);

            // ========== 初始化双缓冲画布 ==========
            RECT r;                     // 定义矩形结构体,存储窗口客户区大小
            GetClientRect(hWnd, &r);     // 获取窗口客户区坐标(可绘图区域)
            hdc = GetDC(hWnd);          // 获取窗口DC
            memDC = CreateCompatibleDC(hdc); // 创建与窗口兼容的内存DC
            // 创建与窗口兼容的位图,作为画布,大小=窗口大小
            canvasBitmap = CreateCompatibleBitmap(hdc, r.right, r.bottom);
            SelectObject(memDC, canvasBitmap); // 将位图选入内存DC

            // 把画布背景填充为白色
            HBRUSH whiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); // 获取白色画刷
            SelectObject(memDC, whiteBrush);                        // 选入内存DC
            Rectangle(memDC, 0, 0, r.right, r.bottom);              // 绘制白色背景矩形

            ReleaseDC(hWnd, hdc);      // 释放窗口DC
            break;
        }

        case WM_COMMAND:        // 按钮点击消息:处理工具/颜色选择
        {
            switch(LOWORD(wParam)) // LOWORD(wParam)获取按钮ID
            {
                case ID_TOOL_LINE:    // 点击直线按钮
                    currentTool = 0;  // 设置当前工具为直线
                    break;
                case ID_TOOL_RECT:    // 点击矩形按钮
                    currentTool = 1;  // 设置当前工具为矩形
                    break;
                case ID_TOOL_ELLIPSE: // 点击圆形按钮
                    currentTool = 2;  // 设置当前工具为椭圆
                    break;
                case ID_TOOL_ERASER:  // 点击橡皮擦按钮
                    currentTool = 3;  // 设置当前工具为橡皮擦
                    break;
                case ID_TOOL_CLEAR:   // 点击清空画布按钮
                {
                    RECT r;                     // 获取窗口客户区
                    GetClientRect(hWnd, &r);
                    HBRUSH whiteBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); // 白色画刷
                    SelectObject(memDC, whiteBrush);
                    Rectangle(memDC, 0, 0, r.right, r.bottom); // 全屏绘制白色
                    InvalidateRect(hWnd, NULL, TRUE); // 刷新窗口,显示清空效果
                    break;
                }
                case ID_COLOR_RED:     // 点击红色按钮
                    currentColor = RGB(255,0,0); // 设置当前颜色为红色
                    break;
                case ID_COLOR_GREEN:   // 点击绿色按钮
                    currentColor = RGB(0,255,0); // 设置当前颜色为绿色
                    break;
                case ID_COLOR_BLUE:    // 点击蓝色按钮
                    currentColor = RGB(0,0,255); // 设置当前颜色为蓝色
                    break;
                case ID_COLOR_BLACK:   // 点击黑色按钮
                    currentColor = RGB(0,0,0);   // 设置当前颜色为黑色
                    break;
            }
            break;
        }

        case WM_LBUTTONDOWN:    // 鼠标左键按下:开始绘图
            isDrawing = TRUE;               // 标记正在绘图
            startX = LOWORD(lParam);       // 获取鼠标按下X坐标(起点)
            startY = HIWORD(lParam);       // 获取鼠标按下Y坐标(起点)
            break;

        case WM_MOUSEMOVE:      // 鼠标移动:实时预览/擦除
            if(isDrawing)       // 判断是否按住左键拖动
            {
                endX = LOWORD(lParam);   // 更新鼠标当前X坐标(终点)
                endY = HIWORD(lParam);   // 更新鼠标当前Y坐标(终点)

                // 橡皮擦功能:按住拖动实时擦除
                if(currentTool == 3)
                {
                    // 定义橡皮擦大小:24x24的白色矩形
                    RECT rect = { endX-12, endY-12, endX+12, endY+12 };
                    // 用白色填充矩形,实现擦除效果
                    FillRect(memDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
                }

                InvalidateRect(hWnd, NULL, FALSE); // 刷新窗口,显示实时效果
            }
            break;

        case WM_LBUTTONUP:      // 鼠标左键抬起:完成绘图
            if(isDrawing)       // 判断之前是在绘图状态
            {
                isDrawing = FALSE;              // 结束绘图
                endX = LOWORD(lParam);         // 获取鼠标抬起X坐标(终点)
                endY = HIWORD(lParam);         // 获取鼠标抬起Y坐标(终点)

                if(currentTool != 3)           // 非橡皮擦工具:执行绘图
                {
                    // 创建画笔:实线,宽度2,当前选择的颜色
                    HPEN pen = CreatePen(PS_SOLID, 2, currentColor);
                    SelectObject(memDC, pen);  // 将画笔选入内存DC
                    // 选择空画刷:图形只描边,不填充
                    SelectObject(memDC, GetStockObject(NULL_BRUSH));

                    if(currentTool == 0)       // 直线工具
                    {
                        MoveToEx(memDC, startX, startY, NULL); // 移动到起点
                        LineTo(memDC, endX, endY);             // 绘制直线到终点
                    }
                    if(currentTool == 1)       // 矩形工具
                    {
                        // 绘制矩形:起点+终点确定矩形大小
                        Rectangle(memDC, startX, startY, endX, endY);
                    }
                    if(currentTool == 2)       // 椭圆/圆形工具
                    {
                        // 绘制椭圆:外接矩形为起点到终点
                        Ellipse(memDC, startX, startY, endX, endY);
                    }
                    DeleteObject(pen);         // 删除画笔,释放资源
                }
                InvalidateRect(hWnd, NULL, TRUE); // 刷新窗口显示最终图形
            }
            break;

        case WM_PAINT:          // 窗口绘图消息:窗口刷新时执行
            hdc = BeginPaint(hWnd, &ps); // 开始绘图,获取DC
            // 将内存DC的画布内容,一次性复制到窗口DC(双缓冲核心)
            BitBlt(hdc, 0, 0, 1000, 600, memDC, 0, 0, SRCCOPY);

            // 正在绘图且不是橡皮擦:显示实时预览图形
            if(isDrawing && currentTool != 3)
            {
                HPEN pen = CreatePen(PS_SOLID, 2, currentColor);
                SelectObject(hdc, pen);
                SelectObject(hdc, GetStockObject(NULL_BRUSH));

                if(currentTool == 0)       // 预览直线
                {
                    MoveToEx(hdc, startX, startY, NULL);
                    LineTo(hdc, endX, endY);
                }
                if(currentTool == 1)       // 预览矩形
                {
                    Rectangle(hdc, startX, startY, endX, endY);
                }
                if(currentTool == 2)       // 预览椭圆
                {
                    Ellipse(hdc, startX, startY, endX, endY);
                }
                DeleteObject(pen);
            }

            EndPaint(hWnd, &ps);   // 结束绘图
            break;

        case WM_DESTROY:        // 窗口销毁:释放资源+退出程序
            DeleteObject(canvasBitmap); // 删除画布位图
            DeleteDC(memDC);           // 删除内存DC
            PostQuitMessage(0);        // 发送退出消息,关闭程序
            break;

        default:                // 其他消息:交给系统默认处理
            return DefWindowProcA(hWnd, msg, wParam, lParam);
    }
    return 0;
}

// 主函数:程序入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR cmd, int nShow)
{
    WNDCLASSA wc = {0};        // 定义窗口类结构体并初始化
    wc.lpfnWndProc = WndProc;  // 绑定窗口过程函数
    wc.hInstance = hInstance;  // 设置应用程序实例句柄
    wc.lpszClassName = "SimplePaint"; // 窗口类名
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 窗口背景色

    RegisterClassA(&wc);      // 注册窗口类

    // 创建窗口
    HWND hWnd = CreateWindowA(
        "SimplePaint",         // 窗口类名
        "简易画图软件",        // 窗口标题
        WS_OVERLAPPEDWINDOW,   // 窗口样式(带标题栏+边框)
        100,100,800,550,       // 窗口坐标(100,100),大小800x550
        NULL,NULL,hInstance,NULL
    );

    ShowWindow(hWnd, nShow);   // 显示窗口
    UpdateWindow(hWnd);        // 刷新窗口

    MSG msg;                   // 消息结构体
    // 消息循环:持续获取并处理消息
    while(GetMessage(&msg, NULL, 0,0))
    {
        TranslateMessage(&msg); // 翻译消息
        DispatchMessage(&msg);  // 分发消息到窗口过程
    }
    return 0;
}