MFC的回调函数

MFC中应该有两类回调函数:一类是源自C的传统回调函数,此类回调函数若非定义为全局函数,而定义在类中的话,要添加static约束,常见的有EnumXXX();一类是消息响应函数,通过成员函数指针实现回调。

设想一种情况,基类A触发某事件E后,回调某定义好的函数F进行事件处理(MFC中表现为消息响应函数)。继承于类A的子类B和C,可能对于E有不同的处理方式,于是需要对基类A的函数F进行改写。自然而然的,我们想到将F定义为以virtual修饰的虚函数。

——————————————————————————————————————————————————————

回调函数的简单定义就是你定义的由Windows来调用。以下两个函数摘自《Programming Windows with MFC》,这里暂且不管函数的具体作用,在FillListBox中有一个API函数,它调用的回调函数是EnumFontFamProc,回调函数的声明形式一般都是相对固定的,具体可以参考MSDN。

[cpp] view plain copy

print?

  1. static int CALLBACK EnumFontFamProc (ENUMLOGFONT* lpelf,NEWTEXTMETRIC* lpntm, int nFontType, LPARAM lParam);
  2. void CMainWindow::FillListBox ()
  3. {
  4. m_wndListBox.ResetContent ();
  5. CClientDC dc (this);
  6. ::EnumFontFamilies ((HDC) dc, NULL, (FONTENUMPROC) EnumFontFamProc,(LPARAM) this);
  7. }
  8. int CALLBACK CMainWindow::EnumFontFamProc (ENUMLOGFONT* lpelf,NEWTEXTMETRIC* lpntm, int nFontType, LPARAM lParam)
  9. {
  10. CMainWindow* pWnd = (CMainWindow*) lParam;
  11. if ((pWnd->m_wndCheckBox.GetCheck () == BST_UNCHECKED) || (nFontType & TRUETYPE_FONTTYPE))
  12. pWnd->m_wndListBox.AddString (lpelf->elfLogFont.lfFaceName);
  13. return 1;
  14. }

请注意这里的函数EnumFontFamilies中的最后一个参数传递的是this即该CMainWindow对象的指针,为什么要这样呢,可以看到EnumFontFamProc的声明是static,在C++中static函数是不能调用非static成员的,所以这里传递一个this就不是很奇怪了。但是为什么要将该函数声明为static呢,这就要归咎于C++的特殊性了,众所周知C++编译器在编译的时候都会在对象中添加一个this指针,在成员函数调用中又会附加一个参数保存this指针,但是Windows的回调函数有严格的定义就是必须按照参数列表传递的参数,加了this指针后参数列表就会与Windows期望的参数列表不一致了,因此这里将其声明为static(static成员函数不会传递this指针,这点说起来总是知道,但是真正用时总是忘了,唉)。

另外在Windows中使用callback函数很常见,恰好许多支持回调函数的API函数都像这里的EnumFontFamilies一样支持自定义的LPARAM参数,刚好可以传递this,如果使用的API函数不支持这样的自定义的LPARAM参数,就需要其他的方法了,一种比较简单的方法是将this复制为global变量使得回调函数可以使用。

时间: 2024-10-20 15:38:21

MFC的回调函数的相关文章

MFC 定时器 SetTimer 如何使用回调函数

创建工程名TestCallBack 自定义回调函数   定义为全局函数 在TestCallBackDlg.h文件开头定义 #pragma once void CALLBACK EXPORT TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime); 在TestCallBackDlg.cpp文件末尾实现函数 void CALLBACK EXPORT TimerProc(HWND hwnd,UINT message,UINT iTimerID

详解回调函数——以JS为例解读异步、回调和EventLoop

转自:http://blog.csdn.net/tywinstark/article/details/48447135#comments 很多人在问什么是回调?百度出来的答案基本都不正确,看了只会让人更加迷惑.下文试着用尽量简单的例子帮大家梳理清楚,因为回调并不是一句话下定义就能明白的概念,需要用一段文字像讲故事一样来说明,回调如同很多重要的计算机概念一样,它是有历史文化的,你需要知道它从哪里来,用来干什么,才能理解及在实际生产中应用. 回调,是非常基本的概念,尤其在现今NodeJS诞生与蓬勃发

c/c++:回调函数

1:函数名为指针 首先,在C语言中函数是一种function-to-pointer的方式,即对于一个函数,会将其自动转换成指针的类型.如: 1 #include<stdio.h> 2 3 void fun() 4 { 5 } 6 7 int main() 8 { 9 printf("%p %p %p\n", &fun, fun, *fun); 10 return 0; 11 } 这三个值的结果是一样的. 其实对于最后的那个*fun, 即使前面加上很多个*号, 其结果

MFC的定时函数 SetTimer和结束killTimer

什么时候我们需要用到SetTimer函数呢?当你需要每个一段时间执行一件事的的时候就需要使用SetTimer函数了. 使用定时器的方法比较简单,通常告诉WINDOWS一个时间间隔,然后WINDOWS以此时间间隔周期性触发程序.通常有两种方法来实现:发送WM_TIMER消息和调用应用程序定义的回调函数. 1.1 用WM_TIMER来设置定时器 先请看SetTimer这个API函数的原型 UINT_PTR SetTimer(  HWND hWnd,              // 窗口句柄  UIN

Settimer及回调函数的用法

在网上看了settimer的一些用法发现能用的真没有,,,,可能是我没找对地方,大部分都是无脑复制粘贴,浪费了很多时间,如果你是一个对这种定时器一无所知的小白,那么请你看进来一定不会让你失望的! 实用settimer的第一步引入头文件:#include <Windows.h> 然后我们来看一下settimer及其回调函数的使用: 首先我们来看settimer的原型:(如下所示)(这个仅仅是窗口的一个定时器函数,我们现在是想把它用到控制台程序的而一般没有窗口的线程系统是不会给他指定消息队列的)

嵌入式&amp;iOS:回调函数(C)与block(OC)传 参/函数 对比

C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(int data_i32)); callBack.c 1).在doSomeThingCount函数,对运行次数自增,并调用参数--函数. void DSTCount(void(*CallBack)(int data_i32)) { static int numb = 0; numb++; (*Call

回调函数的本质,就是把函数当作参数(首先要定义函数类型)

//把一个方法当作另一个方法的参数, 就是回调方法, 大家习惯称作回调函数 type   TFunType = function(i: Integer): Integer; {声明一个方法类型} function MyFun(i: Integer): Integer;        {建立类型兼容的函数} begin   Result := i*2; end; {把函数当作参数, 再定义一个函数} function MyTest(x: Integer; F: TFunType): Integer

(转)回调函数

原文:http://blog.csdn.net/callmeback/article/details/4242260 其实回调就是一种利用函数指针进行函数调用的过程. 为什么要用回调呢?比如我要写一个子模块给你用,   来接收远程socket发来的命令.当我接收到命令后,   需要调用你的主模块的函数,   来进行相应的处理.但是我不知道你要用哪个函数来处理这个命令,     我也不知道你的主模块是什么.cpp或者.h,   或者说,   我根本不用关心你在主模块里怎么处理它,   也不应该关心

ajax返回的值有两种方法,一种是把async:true改为false。 另一种是回调函数。

function load_val(callback){//定义一个回调函数 $.getJSON('test.php' , function(dat){ callback(data);//将返回结果当作参数返回 }); } load_val(function(data){ alert(data);//这里可以得到值 }); //否则的话你需要这样用同步ajax来实现了 function load_val2(){ var result; $.ajax({ dataType:'json', url