Outlook 2010插件错误3​​2770窗口

时间:2016-08-03 19:12:38

标签: visual-studio-2015 vsto outlook-addin outlook-2010 findwindow

按照此处发布的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窗口,我试图枚举所有32770窗口但是当InspectorWrapper_Deactivate函数启动时,我的32770窗口不在列表中。 出现奇怪的行为,如果我将一个消息框放在去激活功能中,它会弹出两次,然后第二次右边的窗口被捕获,我的自定义对话框就会打开。

这是InspectorWrapper_Deactivate函数

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;
    }
}

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窗口,因为它有空窗口名称(即使它存在)

    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;
                    }
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

您需要找到托管该控件的Outlook窗口(为FindWindow和cal Inspector强制转换IOleWindow),而不是使用lIOelWindow.GetWindow,然后查找该窗口的子项(EnumChildWindows)具有给定的类名称/标题/等。如果有多个具有该类名称的窗口,您可能需要使用父/子/对等窗口的唯一组合来确保您有正确的。

答案 1 :(得分:0)

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

在inspector_deactivate中

    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();
    }

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(); } 并在线程内部

   public Worker(Outlook.Inspector insp)
    {
        Inspector = insp;
        _shouldStop = false;
    }

    public void DoWork()
    {
        while (!_shouldStop)
        {
            SubstituteWindow();
        }
    }