Outlook 2010 插件错误 32770 window

Outlook 2010 plugin wrong 32770 window

我正在按照此处发布的 Helmut Oberdan 示例开发适用于 Outlook 2010 的自定义地址对话框

http://www.codeproject.com/Articles/21288/Customize-the-built-in-Outlook-Select-Names-dialog

我已经将项目迁移到框架 4.5 的 VS2015,但是 我在使用 findwindow 函数时遇到了麻烦

IntPtr hBuiltInDialog = WinApiProvider.FindWindow("#32770", "");

在某些计算机(我的)上运行良好,而在其他一些计算机(客户)上则不能。 该函数似乎找到了另一个不是 Outlook 的 32770 window,我试图枚举所有 32770 windows 但是当 InspectorWrapper_Deactivate 函数启动时,我的 32770 window 不在列表中。 一个奇怪的行为发生了,如果我在停用函数中放置一个消息框,它会弹出两次,在第二次之后正确的 window 被捕获并且我的自定义对话框打开。

这里是InspectorWrapper_Deactivate函数

</p> <pre><code>void InspectorWrapper_Deactivate() { _showOwnDialogOnActivate = false; // If there is an invisible ghost Window out there - close it if (_hWndInvisibleWindow != IntPtr.Zero) WinApiProvider.SendMessage(_hWndInvisibleWindow, WinApiProvider.WM_SYSCOMMAND, WinApiProvider.SC_CLOSE, 0); IntPtr hBuiltInDialog = WinApiProvider.FindWindow("#32770", ""); if (hBuiltInDialog != IntPtr.Zero) { // ok, found one // let's see what childwindows are there List<IntPtr> childWindows = WinApiProvider.EnumChildWindows(hBuiltInDialog); // Let's get a list of captions for the child windows List<string> childWindowNames = WinApiProvider.GetWindowNames(childWindows); //MessageBox.Show("Contact"); // now check some criteria to identify the build in dialog.. int languageId = Inspector.Application.LanguageSettings.get_LanguageID(Microsoft.Office.Core.MsoAppLanguageID.msoLanguageIDUI); switch (languageId) { case 1031: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!! This part is only valid for German Outlook 2007 Version !!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (!childWindowNames.Contains("Nur N&ame")) return; if (!childWindowNames.Contains("&Mehr Spalten")) return; if (!childWindowNames.Contains("A&dressbuch")) return; // you can even check more criteria break; case 1033: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!! This part is only valid for english Outlook 2007 Version !!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (!childWindowNames.Contains("&Name only")) return; if (!childWindowNames.Contains("Mo&re columns")) return; if (!childWindowNames.Contains("A&ddress Book")) return; break; case 1040: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!! This part is only valid for italian Outlook 2007 Version !!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (!childWindowNames.Contains("Solo n&ome")) return; if (!childWindowNames.Contains("Altre &colonne")) return; if (!childWindowNames.Contains("R&ubrica")) return; break; // TODO: place your language here.... default: return; } // OK - we have the built in Recipient Dialog // Create a new invisible window _hWndInvisibleWindow = WinApiProvider.CreateWindowEx(0, "Static", "BriaSOFT", 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); // use this window as new Parent for the original Dialog WinApiProvider.SetParent(hBuiltInDialog, _hWndInvisibleWindow); WinApiProvider.SendMessage(hBuiltInDialog, WinApiProvider.WM_SYSCOMMAND, WinApiProvider.SC_CLOSE, 0); // When our INspector becomes active again, we should show our own Dialog _showOwnDialogOnActivate = true; } }

如有任何建议,我们将不胜感激。 谢谢 弗拉维奥

遵循德米特里的建议 但仍然无法找到 32770 window,因为它的 window 名称为空(即使它存在)

</p> <pre><code> string windowName; IntPtr outlookHandle = (IntPtr)0; IOleWindow window = Inspector as IOleWindow; if (window != null) { window.GetWindow(out outlookHandle); List<IntPtr> subWindows = WinApiProvider.EnumChildWindows(outlookHandle); foreach (IntPtr hand in subWindows) { StringBuilder ClassName = new StringBuilder(256); int nRet = WinApiProvider.GetClassName(hand, ClassName, ClassName.Capacity); if (nRet != 0) { if (ClassName.ToString().Contains("#32770")) { windowName = WinApiProvider.GetWindowName(hand); if (windowName.Contains("Seleziona nomi")) { hBuiltInDialog = hand; break; } } } } }

而不是使用 FindWindow,您将需要找到托管该控件的 Outlook window(为 IOleWindow 和 cal lIOelWindow.GetWindow 转换 Inspector ),然后使用给定的 class 名称/标题/等查找 window (EnumChildWindows) 的 child。如果有多个 windows class 名称,您可能需要使用 parent / child / peer windows 的唯一组合以确保您拥有正确的名称。

经过几天的测试和尝试,解决方案(Microsoft 建议)是插入一个单独的线程,从检查器启动并在找到 window 时自动终止。

里面inspector_deactivate </p> <pre><code> if (workerThread.ThreadState == ThreadState.Unstarted) { // Start the worker thread. workerThread.Start(); while (!workerThread.IsAlive) ; // Put the main thread to sleep for 1 millisecond to // allow the worker thread to do some work: Thread.Sleep(1); } else if (!workerThread.IsAlive) { workerObject = new Worker(Inspector); workerThread = new Thread(workerObject.DoWork); workerThread.Start(); }

和线程内 </p> <pre><code> public Worker(Outlook.Inspector insp) { Inspector = insp; _shouldStop = false; } public void DoWork() { while (!_shouldStop) { SubstituteWindow(); } }