首页 > 系统相关 >Windows API窗口绘图程序设计

Windows API窗口绘图程序设计

时间:2024-11-11 21:40:37浏览次数:1  
标签:窗口 鼠标 Windows 句柄 WM API 绘图 GDI

目录

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

标签:窗口,鼠标,Windows,句柄,WM,API,绘图,GDI
From: https://www.cnblogs.com/wa2211lq/p/18540588

相关文章

  • libwebp在windows下构建及编译运行
    因为正在进行WEBP图像的学习,因此有必要对WEBP的官方实现——libwebp进行本地构建和编译,以方便对标准及代码的理解。下面记录一下,在本地Windows电脑上,构建并编译libwebp的过程。步骤一:下载源码首先,获取libwebp的最新源码:从官方Git仓库克隆:gitclonehttps://chromium......
  • 常见 setup.exe 参数 有关 Setup 命令行参数的其他信息,请参阅 Setup Help 文件。有
    Windows安装程序安装或升级Windows。Setup.exe[/debughelp][/auto<upgrade;dataonly;clean>][/quiet][/installdrivers<driver_folder_path>][/noreboot][/installangpacks<language_packfolder_path>][/showoobe<none;full>][/unattend:<ans......
  • 如何设计PHP的API返回结果
    设计PHPAPI的返回结果是开发RESTfulAPI或任何基于HTTP协议的API时的重要步骤。良好的API设计不仅能使API易于使用,还能提高开发效率和用户体验。以下是一些设计PHPAPI返回结果时的最佳实践:1.使用HTTP状态码200OK:请求成功。201Created:创建成功(常用于POST请求)。204NoCon......
  • 推荐一款Windows卸载工具:
    GlaryAbsoluteUninstaller类似于标准的Windows添加/删除程序,但功能更强大。标准的添加/删除程序无法完全卸载应用程序,这通常会在硬盘上留下损坏的注册表项和不需要的文件。您的计算机拥有的垃圾文件越多,运行速度就越慢。AbsoluteUninstaller可以在几秒钟内清除所有垃圾文件......
  • win 11 开发板,windows,ubuntu虚拟机网络互通
    确保在同一个网段里面就行如果ping开发板不通,将win防火墙关闭了试一试虚拟机使用桥接模式,桥接到正确的网卡上,此处使用的是usb网卡编辑->虚拟机网络编辑器ubuntu手动设置桥接的网卡信息此处ens32是桥接的网卡ens33是NAT网卡windows也是同样设置,注意网段保持一致虚拟......
  • 标题:Windows系统启动流程
      Windows的启动过程包括以下几个阶段: 一,启动自检阶段 这个阶段主要是读取 BIOS ,然后内存,CPU,硬盘,键盘等设备进行自检。这个阶段在屏幕上显示就是自检的那些打印信息。在打开计算机电源时,首先开始电源启动自检过程。在BIOS中包含一些基本的指令,能够帮助计算机在没有......
  • 【原创】基于 face-api.js 的HTML,PHP人脸识别系统实现
    声明:本程序仅仅只是实现了PHP、HTML页面拉取手机/电脑摄像头,进行实时拍照获取人脸,可根据你的开发需求进行进一步的实现所需功能。使用截图电脑我没装摄像头,所以就是能调取提示,其他不演示了手机端如图技术栈前端:HTML5,JavaScript人脸识别:face-api.js视频流处......
  • 带你了解API测试的方法
    以下是常见的API测试方法:一、冒烟测试:目的:在API开发完成后快速验证其是否能够正常工作,属于一种初步的、表面级的测试,用于确定是否值得进行更深入的测试。测试要点:只需关注API的基本功能是否可用,例如能否成功调用、是否有明显的调用不通或报错等严重故障。该测试通常使......
  • 【分享】电商商品采集商品数据分析需要用到的API
    商品采集API接口是一种应用程序接口(API),它使得开发者能够从电商平台、数据库或其他服务中快速获取商品信息。这些接口通常由电商平台或数据提供商以RESTfulAPI或SOAPAPI等形式对外开放。通过商品采集API接口,开发者可以轻松地获取商品的详细信息,如价格、库存、描述、图片等,进而在......
  • Java 日期 API
    JDK8之前日期与时间戳之间的转换publicclassTest{publicstaticvoidmain(String[]args){Datedate=newDate();System.out.println("date="+date);//date=SunSep2614:48:52CST2021Datedate1=newDate(1632638970000L......