【发布时间】:2012-02-15 12:07:13
【问题描述】:
我正在使用来自 c#.NET 4.0 的 2 个 Windows API 导出函数。
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
我正在搜索 Excel 主窗口的子窗口的窗口标题(Excel 有一个 XLMAIN 类的 MDI 窗口,其中包含 0、1 个或多个 EXCEL7 窗口类的子窗口)。
目标是查找是否在 Excel 应用程序的任何实例中打开了 Excel 工作簿。我通过查找所有 XLMAIN IntPtr(指针)并遍历子项来做到这一点,直到我得到一个带有 EXCEL7 窗口类的 IntPtr,此时我可以读取子窗口标题并确定是否打开了文件。
基本上这适用于 Windows XP,但不适用于 Windows 7。我没有在 Windows Vista 中尝试过。 发生了什么变化?有人可以调试这个问题,因为我没有 Windows 7。 谢谢 辐射
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ExcelChildWindowsTitle
{
public static void Main(string[] args)
{
//XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
//IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
//bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);
bool excelProofFound = WindowTitleSearcher.SearchForWindow("icui-20110331.xls");
if (excelProofFound)
Console.Write(":)))))))) Proof File opened in an Excel process;");
else
{
Console.Write(":|Proof File not found");
}
}
public static class WindowTitleSearcher
{
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
public static bool SearchForWindow(string title)
{
SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty};
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return (int)sd.hWnd > 0;
}
private static bool EnumProc(IntPtr hWnd, ref SearchData data)
{
const bool directOnly = false;
// Check classname and title
// This is different from FindWindow() in that the code below allows partial matches
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hWnd, sb1, sb1.Capacity);
Debug.WriteLine(sb1.ToString());
if (sb1.ToString().StartsWith(data.Wndclass))
{
RecursiveEnumChildWindows(hWnd, directOnly, ref data);
if ((int)data.hWnd > 0)
{
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
{
EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
{
bool add = true;
if (directOnly)
{
add = GetParent(hwnd) == parentHwnd;
}
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hwnd, sb1, sb1.Capacity);
Debug.WriteLine("Child:" + sb1.ToString());
if (add)
{
if (sb1.ToString().StartsWith(data1.ChildWndclass))
{
sb1 = new StringBuilder(1024);
//Window Caption
GetWindowText(hwnd, sb1, sb1.Capacity);
if (sb1.ToString().Contains(data1.ChildTitle))
{
data1.hWnd = hwnd;
data1.WorkbookTitle = sb1.ToString();
return false; // Found the wnd, halt enumeration
}
}
}
return true;
}, ref data);
}
private struct SearchData
{
// You can put any vars in here...
public string Wndclass;
public string ChildWndclass;
public string ChildTitle;
public IntPtr hWnd;
public string WorkbookTitle;
}
# region Windows API declarations
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
//private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
# endregion
}
}
【问题讨论】:
-
什么“不起作用”?我没有 Excel,所以无法为您调试代码。
-
试着给你的医生打电话,说“我的手臂不能用。怎么了?”看看你是否得到答案。我保证,如果没有提供更多信息,你不会。同样,您转储一堆代码并说“这不起作用”并在这里期待帮助。如果没有有关“不起作用”的详细信息,您将无法理解。您收到错误消息吗? Windows会蓝屏吗? Excel是否会弹出一个对话框,上面写着“Bzzzt!我不告诉你!Nanner nanner nanner!”?请记住,我们无法看到您的屏幕、读懂您的想法或知道您未告诉我们的任何问题。谢谢。 :)
-
XP 和 7 都是 32 位还是 64 位操作系统?
-
可能此代码在其他版本的 Office 上中断....
-
抱歉不清楚。 excelProofFound 对于 XP(32 位)机器为真,对于 Windows 7(64 位)为假。 Excel 自动化的问题是我只能访问一个 Excel 实例,而我的相关文件可能会在另一个实例中打开。我正准备使用远程调试来调试问题(因为 Windows 7 机器是测试/UAT 机器)
标签: c# windows windows-7 .net-4.0 windows-xp