Windows API窗口绘图程序设计

Windows API窗口绘图程序设计

设计一个简单的Windows 窗口程序,在程序窗口内任意位置按下鼠标左键,可绘制范围在10-100之间随机大小的正方形。并且显示的正方形用红色填充。

1、窗口过程函数

本次实验涉及主要消息类型:
1、WM_CREATE:初始化全局变量
2、WM_LBUTTONDOWN:处理鼠标左键按下的消息
3、WM_PAINT:处理窗口重绘的消息

//窗口过程函数:处理窗口接收的消息
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        //关闭窗口
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
        //通知窗口需要重绘
    case WM_PAINT: {
        DrawRect(hwnd);
        break;
    }
    case WM_CREATE:
        // 初始化全局变量
        start.x = 0;
        start.y = 0;
        squareSize = 0;
        break;
        //鼠标左键
    case WM_LBUTTONDOWN:
        OnLButtonDown(hwnd,lParam);
        break;
        //都不符合
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);//转给windows处理,默认的窗口过程
    }
    return 0;
}

2、WM_LBUTTONDOWN:处理鼠标左键按下的消息

期望得到鼠标左键单击时的坐标作为绘制正方形的起始坐标,因此可以使用LOWORD(lParam)获得x坐标,HIWORD(lParam)获得y坐标,然后随机生成正方形的边长,通过全局变量RECT rect存储矩形的边界信息,然后InvalidateRect(hwnd, NULL, TRUE);通知窗口立即重绘。

void OnLButtonDown(HWND hwnd, LPARAM lParam)
{
    start.x= LOWORD(lParam);//鼠标X坐标
    start.y = HIWORD(lParam);//鼠标Y坐标
    squareSize = rand() % 91 + 10;//正方形的边长
    rect = { start.x, start.y, start.x + squareSize, start.y + squareSize };//正方形的边界信息
    InvalidateRect(hwnd, NULL, TRUE);
}

鼠标消息相关知识点

基本鼠标消息

WM_LBUTTONDOWN:鼠标左键按下
WM_LBUTTONUP:鼠标左键抬起
WM_RBUTTONDOWN:鼠标右键按下
WM_RBUTTONUP:鼠标右键抬起
WM_MOUSEMOVE:鼠标移动消息

双击消息

使用时要在注册窗口类时添加CS_DBLCLKS风格

WM_LBUTTONDBLCLK:鼠标左键双击
WM_RBUTTONDBLCLK:鼠标右键双击

消息产生顺序(左键双击):WM_LBUTTONDOWN->WM_LBUTTONUP->WM_LBUTTONDBLCLK->WM_LBUTTONUP

附带信息

wPARAM:其他按键的状态,如CTRl(包括鼠标本身按键)
lPARAM:鼠标的位置,窗口客户窗坐标系
        LOWORD(lPARAM) X坐标
        HIWORD(lPARAM)  Y坐标

滚轮消息

WM_MOUSEWHEEL:鼠标滚轮消息
附带信息:
wPARAM:
        LOWORD(wPARAM) 其他按键的状态,如CTRl(包括鼠标本身按键)
        HIWORD(wPARAM) 滚轮的偏移量,正:向前滚动;负:向后滚动
lPARAM:鼠标当前的位置,屏幕坐标系
        LOWORD(lPARAM) X坐标
        HIWORD(lPARAM)  Y坐标

3、WM_PAINT:处理窗口重绘的消息

我们要使用红色实线画笔和红色画刷根据rect存储的正方形信息绘制一个红色实心正方形Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);//根据获得的矩形绘制一个矩形。

void DrawRect(HWND hwnd)
{
    PAINTSTRUCT ps;//存储绘画操作的信息。
    HDC hdc = BeginPaint(hwnd, &ps);//得到绘图设备

    if (squareSize > 0) {
        HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));//创建红色实心画笔
        HGDIOBJ hOldPen = SelectObject(hdc,hPen);//应用画笔到DC
        HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));//创建红色画刷
        HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);//应用画刷到DC
        //绘图
        Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);//根据获得的矩形绘制一个矩形
        SelectObject(hdc, hOldPen);//取出画笔
        SelectObject(hdc, hOldBrush);//取出画刷
        DeleteObject(hPen);//释放画笔
        DeleteObject(hBrush);//释放画刷
    }

    //结束绘画操作,将绘画结果提交到屏幕上。
    EndPaint(hwnd, &ps);
}

窗口绘图相关知识点

窗口绘图基本流程

绘图设备 DC(Device Context),绘图上下文,绘图描述表
HDC:DC句柄

绘图步骤:
1、得到绘图设备

HDC BeginPaint(
    HWND hWnd,               //窗口句柄
    LPPAINTSTRUCT lpPaint   //存储绘画操作的指针
    );

2、开始绘画
3、结束绘画,将绘画结果提交到屏幕上。

BOOL EndPaint(
     HWND hWnd,                  //窗口句柄
     CONST PAINTSTRUCT *lpPaint  //存储绘画操作的指针
);

开始绘画

绘制封闭图形(能使用画刷填充的图形)

矩形:Rectangle

 BOOL Rectangle(
    HDC hdc,        //绘图设备句柄
    int left,       //矩形的左
    int top,        //矩形的上
    int right,      //矩形的右
    int bottom      //矩形的下
    );

通常和结构体RECT配合使用,RECT用于定义要绘制的矩形的边界,而Rectangle函数则根据这些边界信息在屏幕上绘制矩形。

typedef struct RECT {
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
} ;
GDI绘图对象

HGDIOBJ:GDI绘图对象句柄,兼容画笔句柄,画刷句柄等
HPEN:画笔句柄,描绘线的样式(虚线、点线、实线)、线粗、颜色
HBRUSH:画刷句柄,给封闭图形(不管线型)填充颜色和图案
步骤:
1、创建GDI绘图对象句柄(画笔、画刷)

// 画笔
 HPEN CreatePen(
    int iStyle,     //样式    PS_SOLID:实心线,可以支持多个像素宽,其他类型只能支持一个像素宽
    int cWidth,     //线粗
    COLORREF color  //颜色
 );
// 画刷
 HBRUSH CreateSolidBrush(   //创建实心画刷,填充单一颜色
    COLORREF color          //颜色
 );
 HBRUSH CreateHatchBrush(   //创建纹理画刷,填充纹理线
    int iHatch,             //纹理样式
    COLORREF color          //颜色
    );

2、将创建的GDI绘图对象句柄应用到DC(绘图设备)中,此时自动取出原来的GDI绘图对象句柄
只能置换同种GDI绘图对象,即画刷换画刷,画笔换画笔

 HGDIOBJ SelectObject(      //返回值为原来的GDI绘图对象句柄
    HDC hdc,                //绘图设备句柄
    HGDIOBJ hgdiobj         //GDI绘图对象句柄(画笔句柄、画刷句柄)
 );

3、绘图
4、取出DC(绘图设备)中的GDI绘图对象句柄
使用SelectObject(hdc,原来的GDI绘图对象句柄),即可将之前创建的GDI绘图对象句柄(画笔、画刷)取出
且不需要接收返回值,因为之前创建GDI绘图对象时已有此对象句柄,此时只是将此GDI绘图对象从DC中取出
5、释放GDI绘图对象句柄
只能删除现在不被DC使用的GDI绘图对象,所以释放前要取出创建的GDI绘图对象

 BOOL DeleteObject(
    HGDIOBJ hgdiobj         //GDI绘图对象句柄(画笔句柄、画刷句柄)
 );

实验结果

实验小结

本次实验主要处理WM_LBUTTONDOWNWM_PAINT这两类消息类型,通过获得鼠标左击时的坐标作为正方形的起始坐标,通过随机数获取正方形的边长,然后在窗口重绘时使用红色画笔和画刷绘制并填充矩形。

相关链接

win32窗口创建流程

https://www.cnblogs.com/wa2211lq/p/18540536

win32绘图

https://www.cnblogs.com/wa2211lq/p/18540637

posted @ 2024-11-11 21:52  刘倩_网安2211  阅读(14)  评论(0编辑  收藏  举报