windows消息机制

2023-11-13

windows消息机制

1.创建基本的窗口程序
/*
基本的窗口程序的步骤:
1.注册窗口类(RegisterClass()),就像事件驱动一样,只有在相应的事件驱动里面注册了,分发的机制才会在事件触发时调用已经注册的对象,此对象成为实例对象hInstance
2.创建窗口( CreateWindow()),为实例对象hInstance创建一个窗口
3.显示窗口
4.接下来进入消息等待阶段,当所注册的事件被触发,那么在这个事件注册的过程将会被调用
*/
#include <windows.h>
#include <string>
#include <iostream>
#define WM_TEST_MSG (WM_USER+1)

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	//如果自己不进行处理就交给默认的处理函数处理,当然自己处理之后还是可以交给默认的处理函数

	bool b_ret = false;
	do {
		switch (message) {
		case WM_TEST_MSG: {
			int recv_data = (int)wParam;
			std::cout << "recv_data:" << recv_data;
			return (LRESULT)recv_data;//将接收的数据返回给sendMessage
			break;
		}
		case WM_PAINT:
			break;
		case WM_DESTROY: {
			MessageBoxA(NULL, "exit", "tips", 0);
			//b_ret = true;//这样就不交给默认处理函数处理,如果需要默认函数处理这里进行注释就好
			PostQuitMessage(0);//使用这个停止消息队列,不然只是关闭了窗口,但是消息队列仍然存在,程序未退出
			break;
		}
		}
	} while (false);
	if (!b_ret) b_ret = DefWindowProc(hwnd, message, wParam, lParam); //默认的处理函数
	return b_ret;
}

int main() {
	static TCHAR szAppName[] = TEXT("MyWindow");
	auto hInstance = GetModuleHandleA(NULL);
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;        //声明一个窗口类对象


	//以下为窗口类对象wndclass的属性
	wndclass.lpfnWndProc = WndProc;                                   //窗口处理函数
	wndclass.hInstance = hInstance;					  //窗口实例句柄
	wndclass.lpszClassName = szAppName;                               //窗口类名
	wndclass.style = CS_HREDRAW | CS_VREDRAW;                         //窗口样式
	wndclass.lpszMenuName = NULL;                                     //窗口菜单:无
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    //窗口背景颜色
	wndclass.cbWndExtra = 0;                                          //窗口实例扩展:无
	wndclass.cbClsExtra = 0;                                          //窗口类扩展:无
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);               //窗口最小化图标:使用缺省图标
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);                 //窗口采用箭头光标

	if (!RegisterClassW(&wndclass))
	{    //注册窗口类, 如果注册失败弹出错误提示
		MessageBox(NULL, TEXT("窗口注册失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindowW(               //创建窗口
		szAppName,                     //窗口类名
		TEXT("test_windows"),   //窗口标题
		WS_OVERLAPPEDWINDOW,           //窗口的风格
		CW_USEDEFAULT,                 //窗口初始显示位置x:使用缺省值
		CW_USEDEFAULT,                 //窗口初始显示位置y:使用缺省值
		CW_USEDEFAULT,                 //窗口的宽度:使用缺省值
		CW_USEDEFAULT,                 //窗口的高度:使用缺省值
		NULL,                          //父窗口:无
		NULL,                          //子菜单:无
		hInstance,                     //该窗口应用程序的实例句柄 
		NULL
	);

	ShowWindow(hwnd, SW_NORMAL);         //显示窗口

	while (GetMessageW(&msg, nullptr, 0, 0))        //从消息队列中获取消息,null则获取该进程所有的窗口的消息
	{
		TranslateMessage(&msg);                 //将虚拟键消息转换为字符消息
		DispatchMessage(&msg);                  //分发到回调函数(过程函数)
	}
	return msg.wParam;
}
2.消息传递的原理
(1)消息类型
消息
队列消息
非队列消息
系统队列消息
线程队列消息

<1> 所有线程产生时并没有消息队列,在第一次调用GDI时会产生线程消息队列.
<2> 队列消息到达系统队列消息,然后再到达线程队列消息.
<3> 非队列消息直接传递给窗口过程

(2)消息的传递

<1> 例如鼠标的单击,鼠标的驱动程序会把事件换成相应的消息,然后传到系统队列消息,系统会根据HWND,把消息传递到相应的窗口的线程队列消息.而进程使用GetMessage获取线程队列消息,然后进行翻译TranslateMessage,分发DispatchMessage,分发的过程就是将此消息传递给所有在进程这里注册的窗口类,然后就会触发窗口类绑定的回调函数
<2> 一般来讲,系统总是将消息Post在消息队列的末尾。这样保证窗口以先进先出的顺序接受消息。然而,WM_PAINT是一个例外,同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域。合并WM_PAIN的目的是为了减少刷新窗口的次数。

鼠标驱动程序转成相应的消息
根据HWND,把消息传递到相应的窗口的线程队列消息
GetMessage 获取线程消息队列第一个
分发给在消息队列中注册的窗口类,触发处理过程
鼠标左键单击
系统队列消息
进程(线程)队列消息
GetMessage/TranslateMessage/DispatchMessage
slef_proc
(3)相应的发送消息的函数SendMessage/PostMessage

<1>SendMessage 一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。如果是其他进程发送的则会加入到消息队列,等待执行,但是调用sendmessage的进程还是得继续等待返回.

<2> PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),该函数把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。需要注意的是,如果hWnd参数为 HWND_BROADCAST,那么,消息将被寄送给系统中的所有的重叠窗口和弹出窗口,但是子窗口不会收到该消息;如果hWnd参数为NULL,则该函数类似于将dwThreadID参数设置成当前线程的标志来调用PostThreadMessage函数。

//程序1,SendMessagge
#include <iostream>
#include "log/logx.h"
#include <windows.h>
#include <unordered_map>
using namespace std;

#define WM_TEST_MSG (WM_USER+1)

int main(int argc, char** argv) {
	std::string window_name("test_windows");
	HWND window = FindWindowA(NULL, "test_windows");
	LOGXD(VAR_DATA(window),VAR_DATA(window_name));
	UINT value = 123;
	auto ret= SendMessageA(window, WM_TEST_MSG,(WPARAM)value ,NULL);
	LOGXD(VAR_DATA(ret));

	return 0;
}
/*
[+] log construction, can use it  C:\Desktop\code\test\exe/_log/log.html
[0]08:12:40[debg][9628] [main]  window:  00E70506  window_name:  test_windows   (wtest_main.cpp:12)
[1]08:12:40[debg][9628] [main]  ret:  123   (wtest_main.cpp:15)
[+] ~log deconstruction
*/

//程序2 接收消息的窗口(例子1.创建基本的窗口程序)
/*
recv_data:123
*/


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

windows消息机制 的相关文章

  • 为什么我会收到未找到分析器的警告?

    我创建了一个玩具项目来检查最新的 NET 7 预览版 5 和正则表达式代码生成 它效果很好 所以我对现有项目应用了相同的更改 不是为了生产 而是为了个人生产力 由于某种原因 我收到这些警告 CS8032 An instance of ana
  • 如何在特定时间以毫秒精度触发 C# 函数?

    我有两台计算机 它们的时间通过 NTP 同步 确保时间仅相差几毫秒 其中一台计算机将通过 TCP 向另一台计算机发送一条消息 以在两台计算机上的未来指定时间启动某个 c 函数 我的问题是 如何在特定时间以毫秒精度 或更好 触发 C 中的函数
  • Go 编译器有窗口化设置选项吗?

    我正在使用 Go 6g 编译 GTK 应用程序 我想知道是否有编译器 链接器选项使其成为 Windows 可执行文件而不是控制台可执行文件 MinGW 有一个 mwindows 选项来实现此目的 目前我必须使用十六进制编辑器手动更改 PE
  • C# 无法捕获 SerializationException

    我的程序在加载序列化文件的部分遇到问题 如果文件无法反序列化 我希望很好地失败 但由于某种原因 我的程序将中断而不是进入 catch 子句 这是我的代码 using FileStream fs new FileStream openFile
  • ContentDialog 未与 UWP 中心对齐

    据我所知 ContentDialog的默认行为应该是使其在 PC 上居中并在移动设备上与顶部对齐 但就我而言 即使在 PC 上我也将其与顶部对齐 但我不明白发生了什么 我正在使用代码隐藏来创建它 这是我正在使用的代码片段 Creates t
  • 组合框下拉位置

    我有一个最大化的表单 其中包含 500px 的组合框控件 停靠在右上角 Width 尝试打开组合框后 列表的一半超出了屏幕 如何强制列表显示在表单中 棘手的问题 我找不到解决这个问题的好办法 只是一个解决方法 添加一个新类并粘贴如下所示的代
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • 在 C# 中使用命名空间别名有什么好处? [复制]

    这个问题在这里已经有答案了 使用命名空间别名有什么好处 仅仅是为了简化编码吗 仅当与类发生冲突时我才使用名称空间别名 对我来说 这根本没有简化 我的意见是 如果没有必要 就不要使用
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • C 变量声明的效率 [重复]

    这个问题在这里已经有答案了 例如 在 C 中声明一个变量需要多长时间int x or unsigned long long var 我想知道它是否会让我的代码在类似的事情中更快 for conditions int var 0 code 这
  • “1个未解决的外部”C++

    我已经检查了所有文件之间的连接以及类和函数定义 但每次我尝试运行我的程序时 它都会阻止我并告诉我它有 1 个未解析的外部 该程序应该打开多个文件 一个 学生 文件和一个 成绩 文件 从中读取数据 然后使用 查询文件 来查找数据 找到查询中要
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 具有四个 && 的 LINQ Where 子句

    我正在尝试在Where 子句中创建一个带有4 个参数的LINQ 查询 这是一个 Windows 8 应用程序项目 我正在使用 SQLite 数据库 SQLite 实现 https github com praeclarum sqlite n
  • Boost.asio和异步链,unique_ptr?

    我对异步编程不太熟悉 我有一个问题 我的问题如下 给出 boost asio 中 C 11 的 echo server 示例 http www boost org doc libs 1 60 0 doc html boost asio ex
  • 使用 CodeDOM 将程序集添加到 BuildManager 会导致间歇性错误

    我正在使用 CodeDOM 在运行时创建内存中程序集 如下所示 public Assembly Compile CodeCompileUnit targetUnit string path Path GetDirectoryName new
  • 如何使用 C# 为 azure devops 变量赋值

    我有 selenium C 测试脚本 可以从浏览器获取令牌 我有两个 azure devops 任务 一个用于执行 selenium 测试 另一个用于执行 API 测试 我想将 selenium 测试获取的令牌传递给 API 测试执行任务

随机推荐

  • 上传本地新项目到SVN服务器

    1 在一个已有检出的项目文件夹 如下的文件夹 1 就是我从svn检出的项目 中 在空白处 右键 gt TortoiseSVN gt Repo browser 这样就到了svn服务器的目录了 打开远程地址目录 2 创建一个文件夹给即将上传的项
  • 一文拿下弱网测试:3大弱网模拟工具的配置、场景弱网原因分析、面试题目……

    软件质量不是口头说说 要实际做起来 正文开始 如果app没有对各种网络异常进行兼容处理 那么用户可能在日常生活中遇到APP闪退 ANR 数据丢失等问题 因此 app网络测试 特别是弱网测试尤为重要 本文梳理了app网络测试要点和弱网测试常用
  • 2023年1月16日--2023年1月22日(osg+glsl+socket+ue, 本周20小时,合计1879小时,剩余8121小时)

    目前 ue视频教程进行到了zccs 预1 mysql 7 1 tf1 4 11 o s s 12 2 蓝图反射 1 9 moba 1 5 webapp 2 4 mmoarpg 00A 04 socket 2 57 Opengl 5 9 GL
  • 十三、传智书城项目设计

    项目源代码及sql脚本 一 项目概述 近年来 随着Internet的迅速崛起 互联网已成为收集信息的最佳渠道并逐步进入传统的流通领域 于是电子商务开始流行起来 越来越多的商家在网上建起在线商店 向消费者展示出一种新颖的购物理念 网上购物系统
  • yolo中iou_thres的含义及作用

    yolo中iou thres的含义及作用 iou thres 参数用于控制非极大值抑制 NMS 中的边界框合并阈值 较大的 iou thres 值会导致更多的边界框被合并 从而减少最终输出的边界框数量 是否将 iou thres 设置得更大
  • 图论进阶指南-银河(差分约束/DAG/tarjan)

    测评地址 题目大意 第一行给出两个整数N和M 之后M行 每行三个整数T A B 表示一对恒星 A B 之间的亮度关系 恒星的编号从1开始 如果T 1 说明A和B亮度相等 如果T 2 说明A的亮度小于B的亮度 如果T 3 说明A的亮度不小于B
  • 【STM32】串口初步使用

    本文只作为学习笔记 对串口进行一个简单的介绍 正确的使用方式还需要进行实际的调试 通信的类型 同步 异步 单工 双工 串行 并行 STM32的串口通信 配置片上外设的控制寄存器 通信双方进行相同的配置 约定共同的起始位 停止位 校验位 使得
  • Postman接口测试 —— 设置全局变量、参数传递、断言

    在能熟练使用postman运行接口请求后 会遇到一些问题 例如 我们的web网站一共有几十个接口 测试的时候如果要切换环境 这个时候要每个接口都要修改url的根路径 一个一个的改也太麻烦了 还有时候我们经常需要用到上一个接口的返回值 来作为
  • jQuery隔行变色

  • vant d的地址组件中文操作手册

    vant d的 学习手册 中文操作文档 开发指南 快速上手 基础组件 Empty 空状态 业务组件 地址列表 地址编辑 Area 省市区选择 Card 卡片 Contact 联系人 Coupon 优惠券选择器 GoodsAction 商品导
  • Oracle性能调整的误区

    共享服务器模式 MTS 集群技术 Clustering RAC 分区 并行处理 主要是并行查询 Oracle提供的这些特性确实是用来进行性能改善的 但我们往往忽略了对自身应用特性的分析 它们是否适合于我们 最近 通过对这方面知识的深入了解
  • 简析TCP的三次握手与四次分手原理

    简析TCP的三次握手与四次分手 TCP建立连接过程 第一次握手 建立连接 客户端发送连接请求报文段 将SYN位置为1 Sequence Number为x 然后 客户端进入SYN SEND状态 等待服务器的确认 第二次握手 服务器收到SYN报
  • Linux设备模型4 kobj_attribute

    在上文Linux设备模型 3 Kobject 实例中 我们介绍到如何使用default attribute Default attribute使用很方便 但不够灵活 比如上篇文章在Kobject一节中提到的那个例子 name和val这两个a
  • 单链表的操作(超详细),保证你看完不后悔

    新人小白的博客 希望大家多多关注 一起加油 共同成长 以后会经常更新哒 个人主页 收藏加关注 永远不迷路 数据结构系列 一 顺序表的操作 你真的学会了吗 二 顺序栈的基本操作 三 循环队列的基本操作 你学会了吗 文章目录 数据结构系列 前言
  • 2023浙江省赛“信息安全管理与评估“--Web渗透测试(高职组)

    2022全国职业技能大赛 信息安全管理与评估 高职组 任务书 2022全国职业技能大赛 信息安全管理与评估 任务书 第一阶段竞赛项目试题 第二阶段竞赛项目试题 第三阶段竞赛项目试题 任务2 Web渗透测试 2022全国职业技能大赛 信息安全
  • 发电厂指针仪表检测(YOLOv5训练)

    数据获取 最近在做工业指针仪表检测的项目 自己在网上爬取了3000多张图片 最后经过筛选得到了1214张质量好的图片 自己再进行精心标注 生成VOV格式的xml文件 训练 本人对其用yolov5进行训练后 效果显著 能够精准检测真实场景下仪
  • charles的使用

    一 charles的原理 1 1 Charles的原理 客户端向服务器发起HTTPS请求 Charles拦截客户端的请求 伪装成客户端向服务器进行请求 服务器向 客户端 实际上是Charles 返回服务器的CA证书 Charles拦截服务器
  • SQL学习记录1 --环境搭建, 初识数据库

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 ch00 环境搭建 0 1 MySQL 8 0 的安装 按照提示安装 几乎没遇到问题 有一步显示the specified port is already in use 是和
  • java基础-inputStream两次读取的方法

    场景描述 我们需要对同一个InputStream对象使用多次 比如 客户端从服务器获取数据 利用HttpURLConnection的getInputStream 方法获得Stream对象 需要将InputStream流读取获取相关参数 第一
  • windows消息机制

    windows消息机制 文章目录 windows消息机制 1 创建基本的窗口程序 2 消息传递的原理 1 消息类型 2 消息的传递 3 相应的发送消息的函数SendMessage PostMessage 1 创建基本的窗口程序 基本的窗口程