在64位程序中调用SetWindowLong指定窗口处理过程失效问题排查(附C++编译器数据模型)

C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html
       将32位程序升级到64位后,遇到了使用API函数SetWindowLong设置窗口窗口处理过程WindowProc失效的问题,需要替换成SetWindowLongPtr,能同时兼容32位和64程序。下面讲一下这个小问题的分析解决过程。

      有如下一段代码:

// 创建消息接收窗口
m_hRecvMsgWnd = ::CreateWindowEx( 0, _T("Static"), _T("MsgReciever"), WS_DISABLED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, 0, 0 );if (m_hRecvMsgWnd != NULL )
{m_wndprocOld = reinterpret_cast<WNDPROC>( GetWindowLong(m_hRecvMsgWnd, GWL_WNDPROC) );SetWindowLong(m_hRecvMsgWnd, GWL_WNDPROC, reinterpret_cast<int>(WndProc) );
} 
else
{m_wndprocOld = NULL;
}

代码中创建了一个掩藏的窗口,该窗口用于接收其他代码抛过来的消息。因为业务需要,我们需要在代码中拦截该窗口的消息,于是调用API函数SetWindowLong重新给窗口指定新的窗口消息处理函数,然后我们在新的窗口处理函数中拦截窗口消息,如下所示:

LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{// 拦截发给窗口的消息if (uMsg == CMainLogic::SYS_INNERMSG_COMING ){// ...}return 0;
}

上述代码在x64下编译时会报错:

即找不到GWL_WNDPROC宏的定义,这个就奇怪了,明明在Win32下编译是没问题的,
于是go到GWL_WNDPROC宏的定义处:

GWL_WNDPROC宏的定义在x64下被取消了,定义了新的宏GWLP_WNDPROC(多了一个P),其实GWLP_WNDPROC和GWL_WNDPROC宏的值是一模一样的,所以不管是32位还是64位,直接使用GWLP_WNDPROC就好了!于是将代码修改成:

m_wndprocOld = reinterpret_cast<WNDPROC>( GetWindowLongPtr(m_hRecvMsgWnd, GWLP_WNDPROC) );

这段代码在Win32下编译运行是正常的,但拿到x64下编译后运行就出问题了,好像失效了,在新的窗口消息处理函数中拦截不到消息

        于是以“SetWindowLong msdn”为关键字去搜索,找到MSDN上对API函数SetWindowLong的说明:

msdn上明确说了,为了兼容32位和64位程序,应使用SetWindowLongPtr函数。言下之意,SetWindowLong在x64下是有问题的,应该使用SetWindowLongPtr

       于是直接将上述代码中的GetWindowLong替换成GetWindowLongPtr、将SetWindowLong替换成SetWindowLongPtr。同时,在调用SetWindowLongPtr时,将第三个参数换成LONG_PTR。为什么要换成LONG_PTR呢?可以go到SetWindowLongPtr的定义处查看该函数的参数类型,如下所示:

也可以go到LONG_PTR定义处:

在64位下,LONG_PTR被定义为64位整型__int64,这和64位环境是一致的。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到430多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战经验为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对C++相关知识点进行详细地展开与剖析!专栏涉及了C/C++开发领域多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3: 

VC++常用功能开发汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

专栏将10多年C++开发实践中常用的功能,以高质量的代码展现出来,并对相关功能的实现细节进行了详细的说明。这些常用的代码,其质量与稳定性是有保证的,可以直接拿过去使用,可以有效地解决C++软件开发过程中遇到的问题。


       下面给出常见的int、long和Pointer指针在常见的编译器模型下的长度说明

大家可以参考一下。

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

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

相关文章

剖析vue中nextTick源码

代码逻辑梳理&#xff1a; callbacks 数组用于存储待执行的回调函数&#xff0c;waiting 变量用于标记是否有待执行的回调函数。 flushCallbacks 函数用于执行所有存储在 callbacks 数组中的回调函数&#xff0c;并在执行完成后将 waiting 设置为 false。 timer 函数根据环境…

手把手实现AVL——二叉平衡搜索树

概述&#xff1a;本文介绍AVL树的实现&#xff0c;从零构建一颗AVL树&#xff0c;以及对应的插入、删除、旋转操作 什么是AVL树&#xff1f; AVL树是带有平衡条件的二叉查找树&#xff0c;二叉查找树又区别于二叉树&#xff1a;保证有序 这个平衡条件是每个节点的左右子树高…

[数据集][目标检测]红外人狗检测数据集VOC+YOLO格式185张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;185 标注数量(xml文件个数)&#xff1a;185 标注数量(txt文件个数)&#xff1a;185 标注类别…

Python数据分析常用函数

Python基础 数字处理函数 Python提供了用于数字处理的内置函数和内置模块(math)&#xff0c;使用内置模块&#xff0c;需要先导入 import math。 内置函数math模块abs(-5)返回绝对值math.ceil(2.3)返回不小于x的最小整数divmod(9,4)返回商和余数math.floor(2.3)返回不大于x的…

第十三章:C# 封装

第十三章:C# 封装 封装是面向对象编程(OOP)的四大基本原则之一,它强调将数据和行为封装在对象内部,通过访问控制来保护数据的完整性和安全性。封装使得类的实现细节对外部隐藏,只暴露必要的接口,从而提高代码的可维护性和可重用性。 1. 封装的基本概念 封装的核心思想…

xrdp连接ubuntu

要通过xrdp连接Ubuntu&#xff0c;您需要在Ubuntu上安装xrdp服务&#xff0c;并且可能还需要配置一个桌面环境&#xff0c;如GNOME或XFCE。以下是安装和配置xrdp的步骤&#xff1a; 打开终端。 更新软件包列表&#xff1a; sudo apt update安装xrdp服务&#xff1a; sudo ap…

GLCM 特征和LBP特征提取

GLCM 特征 GLCM&#xff08;灰度共生矩阵&#xff09;特征用于描述图像中像素灰度级之间的空间关系&#xff0c;常用于纹理分析。GLCM特征通过统计图像中各个灰度级对之间的出现频率来描述图像的纹理特征。GLCM特征包括能量&#xff08;ASM&#xff09;、对比度&#xff08;Co…

Host头攻击-禁止空主机头请求

1. 原理 空主机头请求&#xff1a;在某些情况下&#xff0c;HTTP请求可能没有包含Host头字段&#xff0c;或者Host头字段的值为空。这可能是由于客户端的错误配置、旧版本的HTTP客户端或恶意攻击导致的。安全风险&#xff1a;服务器在处理没有Host头字段或Host头字段为空的请求…

AutoCAD许可证服务器

在工程设计与仿真领域&#xff0c;AutoCAD软件已成为行业内的标准。然而&#xff0c;随着企业规模的不断扩大和项目复杂性的增加&#xff0c;AutoCAD许可证的管理和分配也变得越来越重要。本文将为您揭示AutoCAD许可证服务器的价值&#xff0c;以及如何通过合理的配置和管理实现…

linux定时清理docker日志脚本

Linux 定时清理 Docker 日志的脚本与配置指南 在使用 Docker 容器化应用程序时,日志文件可能会迅速增长,占用大量磁盘空间。为了保持系统的稳定性和高效运行,定期清理 Docker 日志文件是必要的。本文将介绍如何编写一个 Linux 脚本来清理 Docker 日志文件,并通过 cron 定时…

对于创建相关项目时,项目出现红色感叹号,且无jre环境显示,应该怎么解决?

首先&#xff0c;假设你已经下载好了相关你的jre环境&#xff0c;注意&#xff1a;如果你的jre不想用之前用的默认的话&#xff0c;你应该新建一个新的文件路径来存储你的新的jre环境下的项目文件。 先直接new->project->javaproject 点击next: 显示如下&#xff1a;&…

docker 目录overlay2

overlay2 是 Docker 存储驱动程序之一&#xff0c;它用于在 Linux 主机上管理 Docker 容器的文件系统层。overlay2 是 overlay 存储驱动程序的改进版本&#xff0c;提供了更好的性能和更多的特性。 当你在 Docker 中使用 overlay2 作为存储驱动程序时&#xff0c;你会在 Docke…

JavaScript表达式语句二

异常处理语句 异常标识一种非中正常得信息&#xff0c;它提示程序在运行过程中发生了意外或错误&#xff0c;然后JavaScript通过一定的方式把它暴露出来&#xff0c;这叫做抛出异常。抛出异常操作表示系统告诉我们当前程序出现了问题&#xff0c;JavaScript使用异常处理语句来…

以一道简单的例题计算灵敏性分析

在例1.1中&#xff0c;全部的变量包括&#xff1a;猪的重量w(磅),从现在到出售猪期间经历的时间t(天),t天内饲养猪的花费C(美元),猪的市场价格p(美元/磅),售出生猪所获得的收益R(美元),我们最终获得的净收益P(美元).这里还有一些其他的有关量&#xff0c;如猪的初始重量(200磅)…

Python 全栈体系【四阶】(五十四)

第五章 深度学习 十二、光学字符识别&#xff08;OCR&#xff09; 3. 文字识别技术 3.1 CRNNCTC(2015) CRNN&#xff08;Convolutional Recurrent Neural Network&#xff09;即卷积递归神经网络&#xff0c;是DCNN和RNN的组合&#xff0c;专门用于识别图像中的序列式对象。…

掌握常用的域信息收集的方法和域控制器攻击的方法(渗透课程)

域信息收集 【实验目的】 通过利用PsExec命令远程连接内网主机&#xff0c;分别收集查询域用户信息和域控制器相关信息&#xff0c;了解并掌握如何收集域内的信息命令。 【知识点】 域信息收集 【实验原理】 NET命令是功能强大的以命令行方式执行的工具。它包含了管理网络…

Nginx企业级负载均衡:技术详解系列(11)—— 实战一机多站部署技巧

你好&#xff0c;我是赵兴晨&#xff0c;97年文科程序员。 工作中你是否遇到过这种情况&#xff1a;公司业务拓展&#xff0c;新增一个域名&#xff0c;但服务器资源有限&#xff0c;只能跟原有的网站共用同一台Nginx服务器。 也就是说两个网站的域名都指向同一台Nginx服务器…

过滤器Filter

目录 概述 Filter快速入门 概述 概念&#xff1a;Filter过滤器&#xff0c;是JavaWeb三大组件&#xff08;Servlet,Filter,Listener&#xff09;之一。 过滤器可以把对资源的请求拦截下来&#xff0c;从而实一些特殊的功能。 过滤器一般完成一些通用的操作&#xff0c;比如…

python选择框和对话框

目录 1.文件打开和保存的选择框 2.选择或者输入对话框 1.文件打开和保存的选择框 tkinter.filedialog 模块中的 askopenfilename 函数和 asksaveasfilename 函数来显示文件打开和保存的选择框。 这两个函数的作用都是返回一个文件名。如果选择了一个文件&#xff0c;则会返回…

如何找到好的量化交易策略

目录 1 寻找量化交易策略的渠道2 如何筛选适合自己的量化交易策略3 量化交易策略的比较与评估4 人工智能和股票选择 1 寻找量化交易策略的渠道 可以从互联网&#xff0c;公共图书馆&#xff0c;交易员论坛&#xff0c;博客等渠道获取。下面是提供的一些具体资源网址&#xff1…