代表和回调如何工作?

时间:2011-12-17 18:46:13

标签: c# winapi delegates callback

我不完全理解这些主题。

我使用几种WinAPI方法

public delegate bool Win32Callback(IntPtr hwnd, ref IntPtr lParam);

[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);

public static bool BrowserEnumChildrenCallback(IntPtr hWnd, ref IntPtr lParam)
{
    if (hWndMeetsConditions)
        return true;
    //code
    return false;
}

hWnd

是否可以从BrowserEnumChildrenCallback获得Win32Callback callBack = new MainWindow.Win32Callback(BrowserEnumChildrenCallback); if (EnumChildWindows(hWnd, callBack, hWnd)) { //here }
{{1}}

2 个答案:

答案 0 :(得分:3)

几个问题:

  • 委托声明错误,最后一个参数是IntPtr,而不是 ref IntPtr
  • 回调应该返回true以继续迭代,你正在向后执行
  • 在EnumChildWindows()调用之后写GC.KeepAlive(callBack)以防止委托对象被垃圾回收。
  • 不要使用EnumChildWindows()的返回值,SDK文档说明它未使用。您通过找不到窗口来检测故障。

回答实际问题:将窗口句柄存储在班级的某个字段中。因此:

private IntPtr windowFound;

private void iterateChildWindows(IntPtr parent) {
    windowFound = IntPtr.Zero;
    var callBack = new MainWindow.Win32Callback(BrowserEnumChildrenCallback);
    EnumChildWindows(parent, callBack, IntPtr.Zero);
    GC.KeepAlive(callBack);
    if (windowFound != IntPtr.Zero) {
       // etc..
    }
}

private bool BrowserEnumChildrenCallback(IntPtr hWnd, IntPtr lParam)
{
    if (hWndMeetsConditions(hWnd)) {
        windowFound = hWnd;
        return false;
    }
    return true;
}

lambda也很有用。

答案 1 :(得分:1)

List<IntPtr> _hwnds = new List<IntPtr>();
public static bool BrowserEnumChildrenCallback(IntPtr hWnd, ref IntPtr lParam) 
{     
     if (hWndMeetsConditions)         
     {
          _hwnds.Add( hWnd );
          return true;     
     }

     //code     
     return false; 
} 

Win32Callback callBack = new MainWindow.Win32Callback(BrowserEnumChildrenCallback);  
if (EnumChildWindows(hWnd, callBack, hWnd))  
{      
    // here  
    // you have it in _hwnd
}