有些Win32 API函數要求將一個函數指針作為自己的參數使用。Windows API函數隨後就可以調用自變量函數(通常是在以後發生特定的事件時)。這一技術就叫作“回調函數”。回調函數的例子包括窗口進程以及我們在打印過程中設置的回調(為後台打印程序提供回調函數的地址,使其能更新狀態,並在必要的時候中止打印)。
另一個例子是API函數EnumWindows(),它能枚舉目前系統內所有頂級窗口。EnumWindows()要求獲取一個函數指針作為自己的參數,然後搜索由Windows內部維護的一個列表。對於列表內的每個窗口,它都會調用回調函數,將窗口句柄作為一個自變量傳給回調。
為了在Java裡達到同樣的目的,必須使用com.ms.dll包裡的Callback類。我們從Callback裡繼承,並取消callback()。這個方法只能接近int參數,並會返回int或void。方法簽名和具體的實施取決於使用這個回調的Windows API函數。
現在,我們要進行的全部工作就是創建這個Callback衍生類的一個實例,並將其作為函數指針傳遞給API函數。隨後,J/Direct會幫助我們自動完成剩余的工作。
下面這個例子調用了Win32 API函數EnumWindows();EnumWindowsProc類裡的callback()方法會獲取每個頂級窗口的句柄,獲取標題文字,並將其打印到控制台窗口。
import com.ms.dll.*; import com.ms.win32.*; class EnumWindowsProc extends Callback { public boolean callback(int hwnd, int lparam) { StringBuffer text = new StringBuffer(50); User32.GetWindowText( hwnd, text, text.capacity()+1); if(text.length() != 0) System.out.println(text); return true; // to continue enumeration. } } public class ShowCallback { public static void main(String args[]) throws InterruptedException { boolean ok = User32.EnumWindows( new EnumWindowsProc(), 0); if(!ok) System.err.println("EnumWindows failed."); Thread.currentThread().sleep(3000); } }
對sleep()的調用允許窗口進程在main()退出前完成。