回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。
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函數不列舉子窗口,只能列舉所有的主窗口