如何找到案頭上報錯的視窗,不管是父視窗還是子視窗,而且獲得它的出錯資訊呢?
主要是利用API函數:
複製 儲存
[DllImport("user32.dll")]public static extern int FindWindowEx(int hwndParent, int hwndChildAfter, string lpszClass, string lpszWindow);[DllImport("user32.dll")]public static extern int FindWindow(string strclassName, string strWindowName);[DllImport("user32.dll")]public static extern int GetLastActivePopup(int hWnd);[DllImport("user32.dll")]public static extern int AnyPopup();[DllImport("user32.dll")]public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);[DllImport("user32.dll")]public static extern int EnumThreadWindows(int dwThreadId, CallBack lpfn, int lParam);[DllImport("user32.dll")]public static extern int EnumWindows(CallBack lpfn, int lParam);[DllImport("user32.dll")]public static extern int EnumChildWindows(int hWndParent, CallBack lpfn, int lParam);
最關鍵的是對windows作業系統中視窗本質的認識,使用Spy++工具,尋找視窗就可以發現,其實對於給定的對話方塊視窗,其中的任何控制項,標、文本、確定、取消按鈕等都是它的子視窗,本質上還是視窗,所不同的只是,頂級父視窗尋找時,用FindWindow函數,而尋找子視窗時用FindWindowEx。
另外比較有用的是EnumWindows,可以遍曆所有的頂級父視窗,而EnumChildWindows則是遍曆其子視窗。經過測試,EnumThreadWindows的回呼函數無法調用,不知道是什麼原因,望高手指教。
所以問題的解決思路就是使用EnumWindows遍曆所有的頂級父視窗,對每個頂級父視窗使用EnumChildWindows遍曆它的所有控制項,每個控制項其實也是視窗,拿到該控制項的控制代碼後,就可以調用GetWindowText來擷取文本資訊了。
具體實現時,首先需要定義以上API函數的回呼函數代理:
複製 儲存
/// <summary>/// 回呼函數代理/// </summary>public delegate bool CallBack(int hwnd, int lParam);
然後必須針對每個API函數定義代理的執行個體函數:
複製 儲存
/// <summary>/// 進程回調處理函數/// </summary>/// <param name="hwnd"></param>/// <param name="lParam"></param>/// <returns></returns>public static bool ThreadWindowProcess(int hwnd, int lParam){ EnumChildWindows(hwnd, callBackEnumChildWindows, 0); return true;}/// <summary>/// 視窗回調處理函數/// </summary>/// <param name="hwnd"></param>/// <param name="lParam"></param>/// <returns></returns>public static bool WindowProcess(int hwnd, int lParam){ EnumChildWindows(hwnd, callBackEnumChildWindows, 0); return true;}/// <summary>/// 子視窗回調處理函數/// </summary>/// <param name="hwnd"></param>/// <param name="lParam"></param>/// <returns></returns>public static bool ChildWindowProcess(int hwnd, int lParam){ StringBuilder title = new StringBuilder(200); int len; len = GetWindowText(hwnd, title, 200); if (len > 0) { if (title.ToString().IndexOf(GlobalManager.ErrorMessage) != -1) { FindError = true; } } return true;}
最後要定義回調代理的執行個體
複製 儲存
/// <summary>/// 進程視窗回呼函數代理/// </summary>public static CallBack callBackEnumThreadWindows = new CallBack(ThreadWindowProcess);/// <summary>/// 視窗回呼函數代理/// </summary>public static CallBack callBackEnumWindows = new CallBack(WindowProcess);/// <summary>/// 子視窗回呼函數代理/// </summary>public static CallBack callBackEnumChildWindows = new CallBack(ChildWindowProcess);
使用的例子:
複製 儲存
/// <summary>/// 用戶端是否彈出對話方塊/// </summary>/// <returns></returns>public bool IsClientPopupWindows(){ bool FindError = false; EnumWindows(callBackEnumWindows, 0); return FindError;}