MFC窗口过程

从一个函数入手, 理解窗口过程

m_list.InsertColumn(0, _T(“工号”), 0, 80);

MFC中有很多诸如列表控件类CListCtrl这样的类来管理不同控件, CListCtrl类中又有很多诸如InsertColumn的函数来实现具体的管理行为

自然MFC的这些类中的这些函数都指望Win32中能有对应的API可以调用, 显然不现实, Win32承受不起

事实上它们都是统一调用的Win32中的SendMessage

比如InsertColumn内部实现就是:

::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn); }

可以看到, 它调用了WINAPI的SendMessage, 交给了SendMessge一个LVM_INSERTCOLUMN消息,以及一个列信息结构体, 让它帮忙完成插入操作

SendMessage是什么?

SendMessage是Win32的一个API, 非常重要, 宏观上它的功能是向窗口发送消息

SendMessage函数的格式:

LRESULT SendMessage(
  [in] HWND hWnd,			//HWND类型。接收消息的窗口的句柄。
  [in] UINT Msg,			//UINT类型。要发送的消息。系统提供的消息列表,参见系统定义的消息。
  [in] WPARAM wParam,		//WPARAM类型。附加的特定于消息的信息。
  [in] LPARAM lParam		//LPARAM类型。附加的特定于消息的信息。
);

当以上在调用InsertColumn函数时, hWnd是列表视图控件的句柄,即m_list对象附着的句柄; Msg是LVM_INSERTCOLUMN消息; wParam是新列的索引; lParam是一个指向LVCOLUMN结构体的指针,这个结构包含了新列的各项必要属性. 接下来就把任务交给SendMessage了

SendMessage把消息和数据发给了谁?

SendMessage会立即调用目标窗口的窗口过程,并等待窗口过程处理完消息后才返回(同步阻塞函数)

什么是窗口类?

Windows中每种窗口都对应着一种窗口类, 对于列表控件来说, 列表视图窗口类是SysListView32, 当创建一个CListCtrl对象时, MFC会在后台调用WINAPI来创建一个SysListView32窗口(即SysListView32类对象)

既然CListCtrl能代表列表窗口,为啥还需要SysListView32, 用同一个名字不好吗?

这是属于先后关系搞反了, 虽然CListCtrl和SysListView32都代表了列表视图控件, 但是要注意:

  • SysLiWistView32是在Windows API中使用的窗口类名, 而CListCtrl是在MFC中使用的.

  • Windows API是一个低级的编程接口,它提供了直接访问操作系统服务的能力, 而MFC是一个基于Windows API的高级编程框架,它提供了一组C++类,这些类封装了Windows API的功能,使得你可以更容易地创建Windows应用程序, 在MFC中,你不需要直接使用窗口类名,使用MFC封装后的控件类就可以, 也不需要直接处理窗口消息。

  • 也就是说MFC的CListCtrl是对SysListView32类更高层次的封装, CListCtrl内部调用的其实还是原生的WINAPI的SysListView32中的东西, 封装后可以方便用户使用, Qt中也有类似的QListView封装了SysListView32, 也就是说没了这些不同编程环境下的高级封装类可以, 但是没了SysListView32不行

  • SysListView32 提供了一种基于消息的方式来操作列表控件, 这是根本

  • CListCtrl提供了一种面向对象的方式来操作列表控件, 这只是一种对SysListView32 的一种封装而已

什么是窗口过程?

  • 窗口过程的本质是一个函数,是一个不依赖于具体对象, 被操作系统调用的回调函数, 英文是Window Procedure, 一般不翻译为窗口程序, 而翻译为窗口过程

  • 每个窗口都关联着对应的窗口过程, 同一类的窗口关联的是同一个窗口过程

  • 窗口过程负责接收并处理该窗口的所有消息, 这个函数往往会比较丰富, 因为窗口过程通常使用一个switch语句来根据消息的类型调用不同的代码块。每个代码块处理一种特定类型的消息, 一个窗口往往会有比较多种消息. 实际上,窗口过程的代码通常会被组织得很好,每种消息的处理代码都封装在一个单独的函数中, 所以从代码上看窗口过程函数也不会太大, 只是会调用比较多的对应于不同消息的消息处理函数

窗口过程函数在哪里?

窗口过程函数是在窗口类中定义的, 同一窗口类创建的所有窗口共同使用一个窗口过程来响应消息, 对于CListCtrl控件,它的窗口过程是在系统提供的列表视图窗口类SysListView32中定义的.既然属于同一类的所有窗口都使用相同的默认窗口过程, 那么窗口过程就需要是静态的或者全局的, 因为非静态成员函数需要一个对象上下文,而窗口过程作为一个回调函数,是由操作系统调用的,操作系统并不知道这个对象上下文(回调函数一般都是跟对象无关)

SendMessage怎么知道要将消息等信息发送给哪个窗口过程?

根据第一个参数即窗口句柄得知的. 一个窗口(控件当然也是窗口)通常由一个窗口句柄(HWND)来表示。这个句柄是一个指向窗口内存结构的指针, 这个结构体包含了窗口的所有信息, 不仅有窗口的位置、大小、样式等, 还记录了窗口过程的地址, 窗口正是通过这样与对应的窗口过程关联的

具体到InsertColumn怎么执行?

当m_list.InsertColumn(0, _T(“工号”), 0, 80);时,hWnd是列表视图控件的句柄(即对象m_list中附着的列表控件句柄),Msg是LVM_INSERTCOLUMN消息,wParam是新列的索引(即第0列),lParam是一个指向LVCOLUMN结构体的指针,这个结构包含了创建新列的需要的属性(即使你调用InsertColumn的时候传入的列信息参数是好几个, InsertColumn内部也会给你整合成一个信息结构体交给SendMessage跟消息一起发过去, 这是InsertColumn内部代码逻辑,可以断点进去看)

首先, InsertColumn函数内部将列次, 列标题等要插入的新列相关信息整合成一个列信息结构体LVCOLUMN 以及 消息LVM_INSERTCOLUMN 以及 窗口句柄(列表控件句柄)等必要信息一起交给SendMessage

然后SendMessage从窗口句柄中提取出窗口过程的地址,操作系统根据地址调用窗口过程(回调函数), 窗口过程根据消息类型调用不同的消息处理函数, 窗口过程这个回调函数的代码是不对外开放的

SendMessage和PostMessage的区别

SendMessage和PostMessage都是Win32 API中用于向窗口发送消息的函数,但它们的工作方式有所不同:

  • SendMessage函数会将指定的消息发送到窗口的窗口过程,并等待窗口过程处理完消息后才返回, 当你调用SendMessage函数时,你的程序会被阻塞,直到消息被处理完毕. 同步阻塞.
  • PostMessage函数会将指定的消息发送到窗口的消息队列,并立即返回, 当你调用PostMessage函数时,你的程序不会被阻塞,你也不知道消息何时会被处理. 异步非阻塞.

更高层次的总结和概括

  • SendMessage函数是Windows消息机制的核心
  • Windows是一个消息驱动系统, 应用程序之间, 应用程序与Windows系统之间的通信主要是通过发送和接收消息来完成的, 每当用户与程序交互(例如点击鼠标, 按下键盘等), 或者系统发生某些事件(例如窗口创建, 窗口关闭等)时, 都会产生相应的消息
  • 人造景观
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 外部程序嵌入MFC窗口是指将一个独立的外部程序嵌入到MFC(Microsoft Foundation Class)窗口中。这种技术通常被用于在应用程序中集成一些第三方的功能或工具。以下是一个大致的实现过程: 首先,需要创建一个MFC窗口,可以使用MFC的资源编辑器来创建一个对话框或其他窗口控件。 然后,在MFC窗口类中创建一个CWnd控件对象,这个对象将用于承载外部程序的窗口。 接下来,使用WinAPI函数来创建外部程序的窗口,并将其父窗口设置为CWnd对象的句柄。这样外部程序的窗口就会嵌入到MFC窗口中,成为其子窗口。 在实现过程中,可能需要处理一些与外部程序窗口的交互,例如获取外部程序的句柄,处理消息传递等。可以使用一些函数如FindWindow来获取外部程序的句柄,并通过重载MFC窗口的消息处理函数来处理与外部程序窗口的交互。 最后,需要在适当的时候销毁外部程序的窗口,并释放相关资源,以确保程序的正常运行和内存的管理。 总的来说,外部程序嵌入MFC窗口是一种将两个独立程序的界面进行整合的方法,通过合理地处理消息传递和交互逻辑,可以实现功能上的集成和用户体验的提升。 ### 回答2: 外部程序嵌入MFC窗口是指将一个独立的外部程序嵌入到MFC应用程序的窗口中显示,并且能够与应用程序进行交互。这样的嵌入可以提供更多的功能和服务,增强应用程序的功能性和用户体验。 实现外部程序嵌入MFC窗口的关键是利用MFC的类和函数来创建和管理嵌入的进程。下面是实现的基本步骤: 1. 创建一个MFC应用程序,并在窗口中添加一个控件(如一个 CStatic 控件)来充当嵌入的容器。 2. 在应用程序中引入系统的 COM 组件,如 OLE ,以便能够与外部程序进行交互。 3. 在应用程序中创建并启动外部程序,可以使用 MFC 提供的 CWinApp 类的 CreateProcess 函数或者使用 Windows API 中的 CreateProcess 函数。 4. 获取外部程序的窗口句柄,可以使用 Windows API 中的 FindWindow 函数或者使用外部程序的进程 ID。 5. 将外部程序的窗口句柄嵌入到应用程序窗口的容器控件中,可以使用 MFC 提供的 CWnd 类的 Attach 函数。 6. 根据需要,可以设置嵌入的程序的窗口位置和大小。 7. 在应用程序中处理嵌入程序的消息和事件,可以使用 MFC 提供的消息映射机制和事件处理函数。 8. 在应用程序关闭或嵌入程序退出时,释放相关的资源,可以使用 MFC 提供的相应函数(如 CWnd::Detach 、 TerminateProcess 等)。 总结:外部程序嵌入到MFC窗口是一种提供更多功能和增强用户体验的方法。通过使用MFC的类和函数,我们可以轻松地将外部程序嵌入到应用程序的窗口中,并与之进行交互。这样的嵌入给用户带来了更多的便利和功能性。 ### 回答3: 外部程序嵌入MFC窗口是指将一个独立的外部程序嵌入到MFC(Microsoft Foundation Class)窗口中进行显示和操作。这种技术常用于在MFC应用程序中集成其他应用程序的功能,并且能够与MFC应用程序进行交互。 要实现外部程序嵌入MFC窗口,可以按以下步骤进行: 1. 获取目标外部程序的句柄:通过使用Win32 API函数,如FindWindow函数,获取到目标外部程序的句柄。句柄是一个唯一标识符,用于标识一个窗口。 2. 创建子窗口:在MFC程序的窗口中,使用CreateEx函数创建一个子窗口来容纳外部程序。可以根据需要设置子窗口的样式和属性。 3. 设置窗口句柄:将外部程序的句柄设置为子窗口的句柄,使用SetParent函数实现。这样,外部程序的窗口就能嵌入到MFC程序的窗口中了。 4. 调整窗口大小和位置:根据需要,可以使用MoveWindow函数来调整外部程序窗口嵌入的位置和大小。 5. 处理交互事件:通过重写MFC程序的消息处理函数,处理与外部程序的交互事件。根据外部程序提供的消息、回调函数或API,来实现与外部程序的通信和交互。 6. 销毁子窗口:在不需要嵌入外部程序的窗口时,使用DestroyWindow函数来销毁子窗口,释放资源。 外部程序嵌入MFC窗口能够使得MFC应用程序具备更加丰富和强大的功能,提升用户体验,实现不同程序之间的无缝衔接。但也要注意兼容性和安全性问题,确保嵌入的外部程序不会对系统和数据造成损害。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值