Windows编程中回调函数的使用心得(MFC篇)

      回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

     Windows SDK中回调函数处处可见,MFC中使用回调函数要比纯Window SDK或C#,VB.net中麻烦许多,笔者想借这篇文章来总结MFC中回调函数的使用。

     本文以回调函数EnumWindows为例,介绍如何在MFC中使用回调函数:

     函数功能

     该函数枚举所有屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数。回调函数返回FALSE将停止枚举,否则EnumWindows函数继续到所有顶层窗口枚举完为止。 函数原型 BOOL EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam); 参数: lpEnumFunc:指向一个应用程序定义的回调函数指针,请参看EnumWindowsProc。 lPararm:指定一个传递给回调函数的应用程序定义值。 回调函数原型 BOOL CALLBACK EnumWindowsP

函数原型:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);

参数:
lpEnumFunc:指向一个应用程序定义的回调函数指针,请参看EnumWindowsProc。
lPararm:指定一个传递给回调函数的应用程序定义值。

回调函数原型
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);

参数:
hwnd:顶层窗口的句柄
lparam:应用程序定义的一个值(即EnumWindows中lParam)

回调函数注意:

     1. 回调函数函数必须修饰为CALLBACK并且只能声明类的为静态成员函数

static BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);//获取进程句柄中的主窗口句柄

     这种声明方式带来了一个问题,即EnumWindows只能使用类中的静态成员变量,如何解决这种矛盾呢?

    2. 可以使用lParam来传递指向该类的指针已访问类的非静态变量,即:

BOOL CALLBACK CSimInstDlg::EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
 DWORD id;
 HWND thwnd;
 CSimInstDlg* CurInst = (CSimInstDlg*)lParam;
 id=GetWindowThreadProcessId(hwnd,NULL);
 if (id==(DWORD)CurInst->m_dwInstTID)
 {
  while((thwnd=::GetParent(hwnd))!=NULL)
   hwnd=thwnd;
  CurInst->m_hWind = hwnd;
  ::SetLastError(0);// 设置无错误
  return FALSE; // 返回 false 以终止枚举窗口
 }
 return TRUE;
}

    3. EnumWindows函数不列举子窗口,只能列举所有的主窗口