GUI02-在窗口上跟踪并输出鼠标位置(Win32版)

(1) 响应 WM_MOUSEMOVE 消息获得鼠标位置;

(2) 响应 WM_PAINT 将鼠标位置输出到窗口中;

(3) 学习二者之间的关键步骤:调用 InvalidateRect() 以通知窗口重绘。

零. 课堂视频

在窗口上跟踪输出鼠标位置-Win32版

一、关键知识点

1. BeginPaint() 对比 GetDC()

两个API都能得到指定窗口的 DC (设备上下文),供程序后续在 DC 上画图、输出文字等。二者区别在于,BeginPaint() 是在窗口收到 WM_PAINT 消息后使用。窗口收到 WM_PAINT 意味着:这个窗口当前展现的内容已经失效,确实需要重画。而 GetDC() 是直接获得一个窗口的DC,然后直接开画。

再往前推一步:一个程序有机会响应某个窗口的消息(比如这里的 WM_PAINT),通常就意味着这个窗口是该程序自己创建出来的。

二者在参数上也有明显不同,BeginPaint() 除窗口句柄外,还需要先创建一个 PAINTSTRCT 的变量。

2. EndPaint()

GetDC() 调用后,要记得配套地写上 ReleaseDC(),类似,我们从 BeginPaint() 得到一个 DC,在完成使用该 DC 之后,要记得配套调用 EndPaint()。

3. WM_MOUSEMOVE 消息

坐标点在该消息的响应函数的 lParam 参数,该参数的类型的是 LPARAM, 它是Windows开发库定义的一个宏。其中 L 表示 “long” ,也就是长整型。然而,在 Windows 上,哪怕是 64 位的系统,long 其实仍然一个 int ,因此还是四字节。当它用作 WM_MOUSEMOVE 的参数时,从左到右,前两个字节(低字),存储鼠标移动后的 x 坐标,高字存储 y 坐标。

对一个整数(int,long)取低字,可使用宏 LOWORD(),其中 LO 是 “low / 低” 的缩写,对应的取高字使用 HIWORD(), “HI” 是 “High / 高” 的缩写。

4. InvalidateRect

函数原型(声明)为:

BOOL InvalidateRect( HWND hWnd, const RECT *lpRect, BOOL bErase ); 

InvalidateRect 用于让指定窗口(hWnd)的指定区域(lpRect,说明见下)的绘图内容失效。

如果 lpRect 为空指针,则让整个窗口的(严格讲是客户区,即不包容标题栏、边框等)的绘图内容都失效。这样,窗口就会收到 WM_PAINT 消息,然后程序调用处理该消息的函数,开始重绘。

bErase 为真时,如果该窗口设置了合适的默认背景刷子(Brush,类似于 Pen,也是一种绘图资源 ), 系统将保证在重绘前,使用该刷子(特定颜色、样式),“刷掉” 原有内容。注意,窗口并不一定有合适的背景刷子。在我们的示例程序中,以下这一行保证了这一点:

/* Use Windows's default colour as the background of the window */wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

其中的 RECT 是一个结构(struct),定义为:

struct RECT 
{ long left, top, right, bottom;
}; 

即,通过 左、上、右、下 位置,定义一个矩形区域。

三、完整代码

#include <string>
#include <sstream> // stringstream#if defined(UNICODE) && !defined(_UNICODE)#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)#define UNICODE
#endif#include <tchar.h>
#include <windows.h>/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");int WINAPI WinMain (HINSTANCE hThisInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{HWND hwnd;               /* This is the handle for our window */MSG messages;            /* Here messages to the application are saved */WNDCLASSEX wincl;        /* Data structure for the windowclass *//* The Window structure */wincl.hInstance = hThisInstance;wincl.lpszClassName = szClassName;wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */wincl.cbSize = sizeof (WNDCLASSEX);/* Use default icon and mouse-pointer */wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);wincl.hCursor = LoadCursor (NULL, IDC_ARROW);wincl.lpszMenuName = NULL;                 /* No menu */wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */wincl.cbWndExtra = 0;                      /* structure or the window instance *//* Use Windows's default colour as the background of the window */wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;/* Register the window class, and if it fails quit the program */if (!RegisterClassEx (&wincl))return 0;/* The class is registered, let's create the program*/hwnd = CreateWindowEx (0,                   /* Extended possibilites for variation */szClassName,         /* Classname */_T("Code::Blocks Template Windows App"),       /* Title Text */WS_OVERLAPPEDWINDOW, /* default window */CW_USEDEFAULT,       /* Windows decides the position */CW_USEDEFAULT,       /* where the window ends up on the screen */544,                 /* The programs width */375,                 /* and height in pixels */HWND_DESKTOP,        /* The window is a child-window to desktop */NULL,                /* No menu */hThisInstance,       /* Program Instance handler */NULL                 /* No Window Creation data */);/* Make the window visible on the screen */ShowWindow (hwnd, nCmdShow);/* Run the message loop. It will run until GetMessage() returns 0 */while (GetMessage (&messages, NULL, 0, 0)){/* Translate virtual-key messages into character messages */TranslateMessage(&messages);/* Send message to WindowProcedure */DispatchMessage(&messages);}/* The program return-value is 0 - The value that PostQuitMessage() gave */return messages.wParam;
}int xPos, yPos; // 用于记录鼠标的坐标x和y值LRESULT CALLBACK OnMouseMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{xPos = LOWORD(lParam); // 低字 是 xyPos = HIWORD(lParam); // 高字 是 y::InvalidateRect(hwnd, nullptr, true); // true: 宣告窗口整个区域的现有展现内容失效,并且自动擦除return DefWindowProc (hwnd, message, wParam, lParam);
}LRESULT CALLBACK OnPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{PAINTSTRUCT ps;HDC hDC = ::BeginPaint(hwnd, &ps);std::stringstream ss;ss << "[" << xPos << " | " << yPos << "]-Hello Win32-来自d2school的南老师";auto txt = ss.str();::TextOut(hDC, xPos, yPos, txt.c_str(), txt.size());::EndPaint(hwnd, &ps);return DefWindowProc (hwnd, message, wParam, lParam);
}/*  This function is called by the Windows function DispatchMessage()  */LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message)                  /* handle the messages */{case WM_MOUSEMOVE:return OnMouseMove(hwnd, message, wParam, lParam);case WM_PAINT :return OnPaint(hwnd, message, wParam, lParam);case WM_DESTROY:PostQuitMessage (0);       /* send a WM_QUIT to the message queue */break;default:                      /* for messages that we don't deal with */return DefWindowProc (hwnd, message, wParam, lParam);}return 0;
}

三、效果示例

效果示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android studio 报错无法找到android.support.v4.app.Fragment——终极解决方案

最近搞了一个小工具&#xff0c;UI界面使用了android.support.v4.app.Fragment&#xff0c;然后同事从服务器下载代码后编译报错无法找到android.support.v4.app.Fragment。 从网上找各种文章&#xff0c;国内国外都看了一遍&#xff0c;大部分解决方案原因都是说Android 9之后…

HANA SQL消耗内存和CPU线程的限制参数

HANA再处理大数据表相关的复杂Sql时&#xff0c;如果没有设置Memory和CPU线程上限的话&#xff0c;会将HANA的资源占用殆尽&#xff0c;造成HANA无法响应其他Sql请求&#xff0c;导致表现在应用服务器上就是系统卡顿的情况。解决上述问题的办法就是按照下图设置Memory(图1&…

【解决】Unity 编辑器内打开场景出现引擎崩溃问题

开发平台&#xff1a;2019.4.10f1   问题背景 1&#xff09;修改 Variant Prefab 变体制件时&#xff0c;出现外部引用的模型文件丢失导致引擎崩溃。 2&#xff09;二次打开工程时&#xff0c;在选中 该问题资产、问题资产所应用的场景等 文件对象时&#xff0c;Unity 编辑器…

Rust常见陷阱 | 不太勤快的迭代器

在Rust中,迭代器被设计为惰性的,意味着它们不会立即对所有元素进行操作。相反,只有在消费者(consumer)需要时,元素才会被处理。这种设计可以带来效率上的优势,因为它避免了不必要的计算和存储。然而,这也意味着使用迭代器时必须格外小心,以确保所有的元素都按预期被处…

穿越物联网的迷雾:深入理解MQTT协议

目录标题 1、MQTT简介核心特性 2、MQTT的工作原理通信过程 3、MQTT的消息质量&#xff08;QoS&#xff09;4、安全机制5、实践应用环境准备示例项目发布者客户端订阅者客户端 6、最佳实践7、结论8、参考资料 在物联网&#xff08;IoT&#xff09;的海洋中&#xff0c;数据像水流…

软考 - 系统架构设计师 - 设计模式

概念 每一个设计模式描述了一个在我们周围不断重复发生的问题&#xff0c;以及该问题解决方案的核心&#xff0c;这样&#xff0c;就可以在遇到相同的问题时使用该解决方案进行解决&#xff0c;不必进行重复的工作&#xff0c;设计模式的核心在于提供了问题的解决方案&#xff…

uni-admin中引入uni-cms的缺少schema及uni-media-library缺少云函数的问题

1. 在管理端运行提示一些表找不到&#xff0c;因为是uni-admin关联的uni-starter的服务空间&#xff0c;在uni-admin的uniCloud中没有内容&#xff0c;在uni-starter的uniCloud中也没有发现对应的表&#xff0c;后面干脆在云端找到对应的表之后新建了&#xff0c;然后再下载到本…

MapReduce——数据切片与MapTask并行度决定机制

MapReduce——数据切片与MapTask并行度决定机制 MapReduce 数据切片和 Map 任务的并行度决定机制是 MapReduce 框架中两个重要的概念&#xff0c;它们直接影响作业的执行效率和性能。 1.数据切片&#xff08;Data Splits&#xff09; 数据切片是指将输入数据拆分成更小的块或片…

开发语言漫谈-Object C

C的家族还有个另类&#xff0c;Object C int main(int argc, char *argv[]) { autoreleasepool { NSLog("Hello World!"); } return 0; } 这里还能看到C的风采&#xff0c;但到这里就偏离了&#xff1a; [obj method: argument]; 这也体现了这门语言…

Python 入门指南(四)

原文&#xff1a;zh.annas-archive.org/md5/97bc15629f1b51a0671040c56db61b92 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十章&#xff1a;哈希和符号表 我们之前看过列表&#xff0c;其中项目按顺序存储并通过索引号访问。索引号对计算机来说很有效。它们是整…

Linux命令学习—Apache 服务器(上)

1.1、http 服务原理 http 超文本传送协议 80 端口 https 安全的超文本传输协议 443 端口 基于 C/S(客户端/服务端)模型 协议流程&#xff1a; 连接&#xff1a;客户端与服务端建立连接 请求&#xff1a;客户端向服务端发送请求 应答&#xff1a;服务端响应&#xff0c;将结果…

美团财务科技后端一面:如何保证数据一致性?延时双删第二次失败如何解决?

更多大厂面试内容可见 -> http://11come.cn 美团财务科技后端一面&#xff1a;项目内容拷打 美团财务科技后端一面&#xff1a;项目相关面试题&#xff0c;主要包含 Zset、延时双删失败重试、热点数据解决、ThreadLocal 这几个方面相关的内容 由于前几个问题是对个人项目的…

C++ STL 容器 list

目录 1. list 对象2. list 迭代器2.1 实现2.2 迭代器失效 本文测试环境为 gcc 13.1 1. list 对象 std::list 底层是一个双向循环链表 list 对象本身包含一个头节点&#xff0c;通过指针指向元素节点&#xff0c;节点定义如下 头节点 header 和元素节点 node 都继承于基类 no…

历史遗留问题1-Oracle Mysql如何存储数据、索引

在学习到Oracle redo和undo时&#xff0c;涉及到很多存储结构的知识&#xff0c;但是网上的教程都不是很详细&#xff0c;就去复习了一下mysql&#xff0c;感觉是不是开源的问题&#xff0c;Mysql的社区和知识沉淀远高于Oracle&#xff0c; 对于初学者很友好&#xff0c;我想请…

2025考研数学武忠祥强化班视频,百度网盘课程+讲义PDF更新

25考研的小伙伴们现在应该基础都学习的差不多了吧&#xff01; 是时候进入强化阶段的学习啦。 2025考研数学强化班全程网盘&#xff1a;https://pan.baidu.com/s/1Z029fuCLkyyhIRFqd5QKcg 提取码&#xff1a;p3ue 晚上好&#xff0c;聊聊17堂课的看课攻略。 今年的17堂课还…

IP-guard WebServer 权限绕过漏洞复现(QVD-2024-14103)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

Mac下brew安装php7.4

这里作者挂了梯子&#xff0c;所以很流畅&#xff01; brew的下载&#xff0c;可参考另外一篇博文&#xff5e;Homebrew 安装与卸载 1、将第三方仓库加入brew brew tap shivammathur/php2、安装指定版本的PHP brew install php7.43、替换Mac自带PHP环境并刷新环境变量 -> …

【ACM列表推荐会议 | EI稳定检索】2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)

2024年第四届人工智能、自动化与高性能计算国际会议&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)将于20…

在mac上安装好python开发环境(pyenv、pyenv-virtualenv、docker-desktop、mysql5.7),一文解决环境问题

前言 python各种版本管理器、包管理器实在是太多了&#xff0c;感兴趣的可以看我的另一篇博客&#xff1a;http://t.csdnimg.cn/SRRyC 但是说实话&#xff0c;建议不要看&#xff0c;直接入手本文如下的环境配置就好了。 保证都是比较前沿&#xff0c;运用范围都比较广的&#…

clickhouse ttl不生效

现象&#xff1a; 日志保留31天&#xff0c; 但是发现1年前的数据还有。 表结构&#xff1a; CREATE TABLEads_xxxx_metrics_1m_local (static_time String COMMENT 统计时间,......) ENGINE ReplacingMergeTree (process_time) PARTITION BYtoYYYYMMDD (toDate (static_tim…