【MFC编程(三)】消息映射机制分析

文章目录

  • 什么是消息
  • Windows消息分类
  • 消息映射表
  • 常用消息
    • WM_CREATE
    • WM_SIZE
    • WM_PAINT
    • WM_DESTROY
    • WM_COMMAND
    • WM_NOTIFY
  • 用户自定义的消息
  • WindowProc


Windows应用程序是消息驱动的。在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作。比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应。

什么是消息

消息是系统定义的一个32位的值UINT message,它唯一地定义了一个事件,向Windows发出一个通知,告诉应用程序某个事情发生了。例如,双击鼠标、改变窗口位置、按下键盘上的一个键都会使Windows发送一个消息给应用程序。

消息本身是作为一系列值传递给应用程序的,其中包括消息的类型以及其他信息。例如,对于按下键盘上的一个键所产生的消息来说,这一系列值中包括了按下键的值。此一系列值的类型叫做MSG,MSG含有 Windows应用程序消息队列的消息信息,它在 Windows中声明如下:

/* Message structure */
typedef struct tagMSG {HWND        hwnd;		//接受该消息的窗口句柄UINT        message;	//消息常量标识符,也就是通常所说的消息号WPARAM      wParam;		//32位消息的特定附加信息,确切含义依赖于消息值LPARAM      lParam;		//32位消息的特定附加信息,确切含义依赖于消息值DWORD       time;		//消息创建时的时间POINT       pt;			//消息创建时的光标在屏幕坐标系中的位置
} MSG, *PMSG
  • hwnd表示消息所属的窗口。
    MFC程序都是窗口应用程序,一个消息一般都是与某个窗口相关联的。例如, 在某个活动窗口中单击鼠标右键, 产生的按键消息就是发给该窗口的。在MFC程序中,用 HWND类型的变量来标识窗口。
  • message指定了消息的标识符。
    在Windows中, 消息是由一个数值来表示的,不同的消息对应不同的数值。 但是由于数值不便于记忆,所以 Windows将消息对应的数值定义为WM_XXX宏(WM是Window Message的缩写)的形式,XXX对应某种消息的英文拼写的大写形式。例如,单击鼠标右键消息是 WM_RBUTTON_DOWN,键盘按下消息是WM_KEYDOWN等。在程序中,通常是以WM_XXX宏的形式来使用消息的。
  • wParamIParam用于指定消息的附加信息。
    例如, 当收到一个字符消息时,message成员变量的值就是WM_CHAR, 但用户到底输入的是什么字符,那么就由wParam和lParam来说明。wParam、 lParam表示的信息随 message的值不同而不同。从定义来看这两种类型实际上就是unsigned int和 long。
  • time表示消息投递到消息队列中的时间。
  • pt表示消息投递到消息队列中光标的当前位置。

Windows消息分类

Windows消息分为系统消息用户自定义消息

  • 系统保留的消息标识符值的范围是 0x00000x03FFWM_USER - 1)。应用不能使用这些值作为私有消息
  • 0x0400WM_USER)到 0x7FFFF 范围内的值用于私有窗口类的消息标识符。

Windows系统消息有三种:

  • 标准消息。除WM_COMMAND外以WM_开头的消息是标准消息。例如,WM_CREATE、WM_CLOSE。
  • 命令消息。消息名为WM_COMMAND,消息中附带了标识符ID来区分是来自哪个菜单、工具栏按钮或加速键的消息。
  • 通知消息。通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件。

CWnd的派生类都可以接收到标准消息、通知消息和命令消息。命令消息还可以由文档类等接收。
用户自定义消息是实际上就是用户定义一个宏作为消息,此宏的值应该大于等于WM_USER,然后此宏就可以跟系统消息一样使用,窗口类中可以定义它的处理函数。

根据Windows将消息派发给消息处理函数的方式,可以将消息分为队列(Queued)消息非队列(Nonqueued)消息

队列消息
Windows维护着一个系统消息队列,以及分别为每个GUI线程维护一个各自的线程消息队列。为了避免非GUI线程的创建线程消息队列的开销,所有线程创建初始化时,均不创建消息队列。只有当线程第一次调用GDI函数时,系统才会为线程创建消息队列。所以那些非GUI线程是没有消息队列的。

每当用户移动鼠标,点击按钮或键盘时,鼠标或键盘的设备驱动程序会将输入转换成消息,并将消息放在系统消息队列里。删windows会检查自己的消息队列,如果消息队列不为空,则每次取出并删除一个消息,然后确定消息的目标窗口,然后把消息放到创建这个窗口的线程的线程消息队列里。线程的消息队列接收由线程创建的窗口的所有的鼠标和键盘消息。然后线程会从队列中删除信息,并告诉系统把它们派发到对应的窗口消息处理函数。

除了WM_PAINT, WM_TIMER和WM_QUIT消息以外,系统总是派发放在在消息队列的末尾的消息。这将保证让一个窗口以first-in, first-out的顺序接收消息。WM_PAINT,WM_TIMER,和WM_QUIT消息,会一直被保存在队列中,只有在队列中没有其他消息时才会被派发到窗口消息处理函数。此外,同一个窗口的多个WM_PAINT消息被合并成一个WM_PAINT消息,客户区的所有无效部分也会被合并。这样是为了减少窗口重绘客户区的次数。

系统通过填充一个 MSG 结构来将消息投递到线程的消息队列,随后将其拷贝到消息队列中。通过使用 PostMessage (异步的)和 PostThreadMessage 函数,线程可以将一个消息投递到自己的消息队列或其他线程的消息队列。应用可以使用 GetMessage 来删除队列中的消息。要在不删除消息的情况下检查队列消息,应用可以使用 PeekMessage 函数,该函数会使用消息填充 MSG 。

在从队列删除消息后,应用可以使用 DispatchMessage 函数来指示系统把消息发送给窗口过程进行处理。DispatchMessage 接收一个 MSG 结构的指针,该结构已经使用 GetMessage 或 PeekMessage 填充过。DispatchMessage 将窗口句柄,消息标识符,和两个消息参数传递给窗口过程,但它不会传递时间和鼠标光标位置。应用在处理消息时可以通过 GetMessageTime 和 GetMessagePos 函数检索时间和位置信息。

非队列消息
非队列消息被立即送往目的地的窗口消息处理函数,绕过了系统的消息队列和线程消息队列。系统通常会发送非队列消息,来通知那些会影响窗口的事件。例如,当用户激活一个新的应用程序窗口时,系统会发送一些列消息到窗口,包括WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。这些消息通知窗口被激活,键盘输入被定向到窗口,并且鼠标光标也移到窗口的边界内。

非队列消息也有可能来源于应用程序调用系统函数。例如,系统调用SetWindowPos函数移动一个窗口后会发送WM_WINDOWPOSCHANGED消息。 一些函数也发送非队列消息, 有BroadcastSystemMessage,BroadcastSystemMessageEx,SendMessage(同步),SendMessageTimeout,和SendNotifyMessage。

消息映射表

MFC使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等代码。当窗口接收到消息时,会到消息映射表中查找该消息对应的消息处理函数,然后由消息处理函数进行相应的处理 。SDK编程时需要在窗口过程中Switch判断消息值进行相应的处理,相比之下MFC的消息映射机制更加方便好用。

DECLARE_MESSAGE_MAP()BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)ON_WM_CREATE()ON_WM_DESTROY()ON_WM_TIMER()ON_WM_CLOSE()ON_WM_SETTINGCHANGE()ON_COMMAND(ID_IMPORT_FILE, &MainFrame::OnImportFile)ON_UPDATE_COMMAND_UI(ID_IMPORT_FILE, &MainFrame::OnUpdateImportFile)ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_XP, ID_VIEW_APPLOOK_VS_2012_LIGHT, &MainFrame::OnApplicationLook)ON_MESSAGE(WM_ACTION_EXCEPTION, &MainFrame::OnException)
END_MESSAGE_MAP()
  • DECLARE_MESSAGE_MAP 声明将在类中使用消息映射来将消息映射到函数(在类声明中使用)。
  • BEGIN_MESSAGE_MAP 开始消息映射的定义(在类实现中使用)。
  • END_MESSAGE_MAP 结束消息映射的定义(在类实现中使用)。

常用消息

WM_CREATE

当应用通过调用 CreateWindow 或 CreateWindow 要求创建一个窗口时,会发送这个消息(在函数返回前消息就被发送)。新窗口的窗口过程在窗口创建后会接收到这个消息,但是是在窗口可见之前

这是窗口过程接收到的第一个消息。接收该消息时,窗口过程的 wParam 参数值不被使用,它的 lParam 是一个指向 CREATESTRUCT 结构的指针。这个结构包含了窗口初始化的参数。

处理该消息后,窗口过程应该返回 0 以继续窗口的创建。如果窗口过程返回 -1,窗口会被销毁,CreateWindow 或 CreateWindowEx 会返回空句柄。

WM_SIZE

在窗口尺寸改变后向窗口发送该消息。
wParam 是尺寸改变的类型,它可以是下列值中的一个;

  • SIZE_MAXHIDE,当其他窗口最大化时,该消息会发送到所有弹出(pop-up)窗口
  • SIZE_MAXIMIZED,窗口已经最大化了
  • SIZE_MAXSHOW,当其他窗口恢复到之前尺寸时,该消息会发送到所有弹出窗口
  • SIZE_MINIMIZED,窗口已经最小化了
  • SIZE_RESTORED,窗口的尺寸改变了,但不是最大化和最小化

lParam 的低位是客户区的新宽度,高位是客户区的新高度。虽然窗口的宽度和高度是 32 位值,lParam 只包含宽高值的低 16 位。

窗口过程处理该消息后应该返回 0。

WM_PAINT

当系统或其他应用要求对应用窗口的部分进行绘制时,会发送该消息。调用 UpdateWindow 或 RedrawWindow 函数时,或在应用通过使用 GetMessage 或 PeekMessage 获得 WM_PAINT 并调用 DispatchMessage 函数后,消息会被发送到窗口过程。

lParam 和 wParam 都不被使用。

Invalidate在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区。
UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只有一条)的无效区。
效果很明显,调用Invalidate之后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部,而调用UpdateWindow会使WM_PAINT消息马上执行的,绕过了消息队列。如果你调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句。

WM_DESTROY

当窗口将被销毁时发送该消息。在窗口被从屏幕删除后,它会被发送到删除的窗口的窗口过程。

该消息首先被发送到被销毁的窗口,之后发送到子窗口(如果有的话)。在消息的主窗口处理过程中,可以假设所有子窗口还是存在的。

wParam 和 lParam 不被使用。如果处理了该消息,窗口过程应返回 0。

WM_COMMAND

发送命令消息的情况:

  • 当用户从菜单选中一个命令时会发送
  • 当控件向它的父窗口发送提醒消息时会发送
  • 当快捷键被翻译时会发送

如果应用处理了该消息,它应该返回 0。

  • 消息来源是菜单时,wParam 的高位是 0,低位是菜单标识符(IDM_*),lParam 是 0。
  • 消息来源是快捷键时,wParam 的高位是 1,低位是快捷键标识符(IDM_*),lParam 是 0。
  • 消息来源是控件时,wParam 的高位是控件特定的通知码,低位是控件标识符,lParam 是控件窗口句柄。

消息映射宏
命令消息的消息映射入口项形式如:

ON_COMMAND(ID_IMPORT_FILE, &MainFrame::OnImportFile)
ON_UPDATE_COMMAND_UI(ID_IMPORT_FILE, &MainFrame::OnUpdateImportFile)

ON_COMMAND
消息ID为ID_IMPORT_FILE,消息处理函数为OnImportFile

ON_UPDATE_COMMAND_UI
UPDATE_COMMAND_UI消息用来维护菜单项的各项状态,包括激活、禁用、变灰、选中、未选中等。在下拉菜单每次打开的时候,所有菜单项的此消息都会被发送出去。如果所属类中为菜单项的该消息添加了处理函数,则执行相应函数更新菜单状态,如果菜单项没有此消息处理函数,也没有COMMAND消息的处理函数,那么它就会变灰。

对应消息处理函数

afx_msg void OnImportFile();
afx_msg void OnUpdateImportFile(CCmdUI* pCmdUI);void MainFrame::OnImportFile()
{//do something
}void MainFrame::OnUpdateImportFile( CCmdUI* pCmdUI )
{pCmdUI->Enable(TRUE);pCmdUI->SetCheck(TRUE);
}

消息映射范围宏

ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_XP, ID_VIEW_APPLOOK_VS_2012_LIGHT, &MainFrame::OnApplicationLook)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_XP, ID_VIEW_APPLOOK_VS_2012_LIGHT, &MainFrame::OnUpdateApplicationLook)

指示消息处理函数处理在宏的前两个参数中指定的命令 ID 的范围。
这样值在ID_VIEW_APPLOOK_WIN_XPID_VIEW_APPLOOK_VS_2012_LIGHT之间的菜单项等的命令消息都由对应消息处理函数处理。

对应消息处理函数

afx_msg void OnApplicationLook(UINT id);	//参数id为用户操作的菜单项的ID
afx_msg void OnUpdateApplicationLook(CCmdUI* pCmdUI);void MainFrame::OnApplicationLook(UINT id)
{theApp.m_nAppLook = id;//do something
}void MainFrame::OnUpdateApplicationLook( CCmdUI* pCmdUI )
{pCmdUI->Enable(isChecked == 1);pCmdUI->SetCheck(pCmdUI->m_nID == theApp.m_nAppLook);
}

WM_NOTIFY

ON_NOTIFY是控件向其父窗口发送消息处理的宏,扩展了ON_COMMAND的功能,使用了相应的NMHDR结构.

ON_NOTIFY( wNotifyCode, id, memberFxn )afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result );

在操作列表框等控件时往往会给父窗口发送WM_NOTIFY通知消息。WM_NOTIFY消息的wParam参数为发送通知消息的控件的ID,lParam参数指向一个结构体,可能是NMHDR结构体,也可能是第一个元素为NMHDR结构体变量的其他结构体。NMHDR结构体的定义如下(仅作了解):

Typedef sturct tagNMHDR{HWND hwndFrom;UINT idFrom;UINT code;
} NMHDR;
  • hwndFrom为发送通知消息控件的句柄
  • idFrom为控件ID
  • code为要处理的通知消息的通知码,例如NM_CLICK。

通知消息的消息映射入口项形式如:

ON_NOTIFY( wNotifyCode, id, memberFxn )

ON_NOTIFY是控件向其父窗口发送消息处理的宏,扩展了ON_COMMAND的功能,使用了相应的NMHDR结构。

  • wNotifyCode:要被处理的通告消息代码,如 LVN_KEYDOWN。
  • id:发送通告消息的控件ID。
  • memberFxn:通告消息发送后被调用的成员函数。

通知消息的处理函数的原型为:

afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result);

用户自定义的消息

ON_MESSAGE用来响应自定义消息,能够处理所有的消息响应,在程序中需要自己设定相应的消息响应函数。

ON_MESSAGE(message, memberFxn) 
  • message:消息的ID。
  • memberFxn :映射message的消息函数,该函数的类型必须是以下类型的
afx_msg LRESULT (CWnd::*)(WPARAM, LPARAM)

如果需要使用用户自定义消息,,如:#define WM_UPDATE_WND (WM_USER+1),ON_MESSAGE(WM_UPDATE_WND, &CMainFrame::OnUpdateWnd),afx_msg LRESULT OnUpdateWnd(WPARAM wParam, LPARAM lParam);,最后在MainFrm.cpp中实现此函数。

  1. 首先要定义消息宏:在头文件定义 消息id
    #define WM_MYMESSAGE (WM_USER + 100)
    
  2. 再到消息映射表中添加消息映射入口项:
    BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)ON_MESSAGE(WM_UPDATE_WND, &CMainFrame::OnUpdateWnd)
    END_MESSAGE_MAP()
    
  3. 然后在MainFrm.h中添加消息处理函数的函数声明
    afx_msg LRESULT OnUpdateWnd(WPARAM wParam, LPARAM lParam);
    
  4. 最后在MainFrm.cpp中实现此函数。

需要调用postMessage 或者 SendMessage 实现关联。

WindowProc

WindowProc回调函数,处理发送给窗口的消息 手段更丰富了。
是一个虚函数,可以通过类向导添加。

LRESULT CALLBACK WindowProc(HWND hwnd,           UINT uMsg,WPARAM wParam,LPARAM lParam
);
  • hwnd:指向窗口的句柄。
  • uMsg:指定消息类型。uMsg可以是WM_COMMAND、 WM_NOTIFY 从而可以实现ON_NOTIFY ON_COMMAND的处理。
  • wParam:指定其余的、消息特定的信息。该参数的内容与UMsg参数值有关。
  • IParam:指定其余的、消息特定的信息。该参数的内容与uMsg参数值有关

CWnd::WindowProc 调用 OnWndMsg 用来分辨并处理消息;
如果是命令消息,交给 OnCommand 处理;
如果是通知消息,交给 OnNotify 处理。

而一般的 Windows 消息,就直接在消息映射表中上溯,寻找其归宿(消息处理程序)

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

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

相关文章

一文搞懂Linux kernel编译步骤

一、前言 什么是Linux的内核编译呢?简单来说,Linux内核编译是一个将内核源代码转换成可在特定的硬件架构上运行的二进制文件的过程。通过编译内核,我们可以根据自己的需求和兴趣对内核进行定制和优化,以满足特定的应用场景。下文…

CST汽车天线仿真(双向混合求解)

CST从2018版本开始具有双向混合求解,到2019版已经通用微波工作室的各个求解器之间的双向混合。具体的混合对象如下图: 对天线的安装和耦合仿真,意味着对复杂结构(天线)和电大尺寸环境(安装平台,…

leetcode-5-最长回文子串

题解: 回文串:如果一个字符串正着读和反着读都是一样的那这个字符串就是回文串。 对于一个子串而言,如果它是回文串,并且长度大于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。 1、初始化字典d…

Python反射API:面向对象编程的“魔法镜”

在Python的世界里,面向对象编程(OOP)就像是一场盛大的化妆舞会,每个对象都穿着华丽的外衣,隐藏着自己的真实面目。而Python的反射API,就像是一面“魔法镜”,能够让我们窥探这些对象的真实身份和…

Python练习8

Python日常练习 题目: 编写函数,接收两个正整数作为参数,返回一个元组, 其中第一个元数为最大公约数,第二个元素为最小公倍数。 例如: 若输入12,8,则输出如下 【请输入一个…

推荐程序员好用的浏览器插件

推荐程序员好用的浏览器插件 1. 网页颜色控制:Dark Reader安装效果 2. 前端助手:FeHelper安装效果 3. markdown可视化:Markdown Reader安装效果 4. ES插件:Multi Elasticsearch Heads安装效果 1. 网页颜色控制:Dark Re…

希尔排序算法

1、基本思想 希尔排序也称缩小增量排序,是插入排序的一种更高效的改进版本。它的基本思想是先将待排序的数组元素按照一定的间隔(称为增量)分成若干个子序列,分别对这些子序列进行插入排序,随着迭代的进行,…

太速科技-634-基于3U PXIe的VU3P FMC+数据接口板

基于3U PXIe的VU3P FMC数据接口板 一、产品概述 板卡是一款基于 3U PXIE 总线架构的高性能数据预处理FMC 载板,具有 1 个 FMC(HPC)接口,1 个 X8 GTH 背板互联接口,可以实现 1 路 PCIe x8。板卡主控芯片采用Xilin…

OpenCV基本操作(python开发)——(8)实现芯片瑕疵检测

OpenCV基本操作(python开发)——(1) 读取图像、保存图像 OpenCV基本操作(python开发)——(2)图像色彩操作 OpenCV基本操作(python开发)——(3&…

MySQL数据库中的视图

视图 ​ 本篇将开始介绍有关数据库中视图的相关知识点,其中主要包含视图的基本使用,视图规则和限制。 ​ 视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据,视图的数据变化会…

Docker 镜像拉不动?自建 Docker Hub 加速站 解决镜像拉取失败

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 众所周知,6 月份的时候,Docker Hub 的镜像就已经无法正常拉取,那会随手用 Nginx 反代了一下 Docker Hub,建了个自用的镜像站,一直用到了 9 月份&…

应对传统能源企业管理人员青黄不接问题:搭建系统完善的招聘管理体系

应对传统能源企业管理人员青黄不接问题:搭建系统完善的招聘管理体系 对于很多传统能源企业由于成立时间久,发展到现在,往往都面临着一个共性问题,即未来三到五年,老员工退休后,新员工如何接续的问题。这个…

C++进阶-->红黑树的实现

1、红黑树的概念 红黑树是一棵二叉搜索树,他和前面AVL树不同的是红黑树不是通过平衡因子来保证树的平衡,而是在树结点的处加多了个记录颜色的变量,这个变量可以是红色或者黑色。通过对任何一条从根到叶子的路径上各个结点的颜色进行约束&…

Linux操作系统开机引导

linux操作系统的开机引导的过程 linux操作系统开机流程图 1、开机自检:根据bios的设置,对cpu、内存、显卡、键盘等设备进行初步检测,如果以上检测设备正常工作,系统会把控制权移交到硬盘 总结:检测包含系统启动操作系…

DataX 的安装配置和使用 (详细版)

1,上传解压 1,开始上传安装包到你虚拟机上放置安装包的文件夹 2,开始解压 ,配置环境变量 1、上传 /opt/modules 2、解压 tar -zxvf datax.tar.gz -C /opt/installs 3、修改 vi /etc/profile 配置环境变量: export DAT…

蓝桥杯第21场小白入门赛补题

5.蓝桥派对 思路 :一个区间与多少个其他区间有关联,先对所有区间左端点和右端点从小到大排序,对于每个询问,我们先算出[1,r]这个区间里有多少个区间的起点即区间总数,使用upper_bound函数,然后使用lower_bo…

Linux篇(常见入门命令)

目录 一、开启终端 二、Linux命令格式 1. 什么是Linux 的命令? 三、Linux下的命令补全 四、切换用户 五、uname:查看操作系统信息 六、ls:查看目录下文件 1. 用法一 2. 用法二 3. 用法三 七、pwd:显示当前路径 八、cd&…

7.qsqlquerymodel 与 qtableview使用

目录 qtableview 委托QStyledItemDelegateQAbstractItemDelegateCheckBoxItemDelegate使用 qtableview 委托 //设置单元格委托 void setItemDelegate(QAbstractItemDelegate *delegate); QAbstractItemDelegate *itemDelegate() const;//设置列委托 void setItemDelegateForCol…

AMD显卡低负载看视频掉驱动(chrome edge浏览器) 高负载玩游戏却稳定 解决方法——关闭MPO

2024.11.6更新 关闭MPO有点用但是还是驱动掉到恶心,找到终极方法了视频输出直接插主板走核显,稳得一笔,3dmark跑了个分几乎没变化。核显负责桌面浏览器,独显就专心只跑游戏。等24.11驱动再看看 问题 折磨的开始是天下苦黄狗久矣&…

VS2022远程连接调试编译Linux环境下的C++代码

工具:VS2022 虚拟机:RHEL 8.0 一、下载必要工具 1.VS2022组件安装 打开VS2022Installer,点击修改下载必要工具。 选择Linux 和嵌入式开发,然后点击右下角的修改! 等待安装........ 安装完成后,创建Linu…