有些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()退出前完成。