检索窗口句柄whitin outlook

时间:2014-08-15 09:10:53

标签: c# com outlook vsto pinvoke

我正在开发一个自定义Outlook插件,我需要子类化约会窗口。这基本上很好地遵循以下ariticle中提到的原则:

http://www.codeproject.com/Articles/27262/Additional-custom-panel-in-Microsoft-Outlook

我通过在新约会窗口中获取社交连接器的句柄来解决问题。 enter image description here

我已经尝试了一些方法(FindWindow,FindWindowEx,EnumChildWindow)但是它们都没有给我正确的句柄。

在这里你可以找到一个小的插件项目来快速查看它。 Download

或者快速浏览一下这个摘要

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;

namespace FindSocialConnector._2013
{
    public partial class ThisAddIn
    {
        /// <summary>
        /// Delegate for the EnumChildWindows method
        /// </summary>
        /// <param name="hWnd">Window handle</param>
        /// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
        /// <returns>True to continue enumerating, false to bail.</returns>
        public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

        /// <summary>
        /// Hält den Klassennamen des NewAppointment Windows.
        /// </summary>
        public const string NewAppointmentWindowClass = "rctrl_renwnd32";

        private Inspectors _inspectors;

        /// <summary>
        /// The EnumChildWindows function enumerates the child windows that belong to the specified parent window by passing the handle to each child window, 
        /// in turn, to an application-defined callback function. EnumChildWindows continues until the last child window is enumerated or the callback function returns FALSE.
        /// </summary>
        /// <param name="parentHandle">
        /// Handle to the parent window whose child windows are to be enumerated.
        /// If this parameter is NULL, this function is equivalent to EnumWindows.
        /// Windows 95/98/Me: parentHandle cannot be NULL.
        /// </param>
        /// <param name="callbackFunction">
        /// Pointer to an application-defined callback function. For more information, see EnumChildProc.
        /// </param>
        /// <param name="param">
        /// Specifies an application-defined value to be passed to the callback function.
        /// </param>
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern int EnumChildWindows(IntPtr parentHandle, Delegate callbackFunction, IntPtr param);

        /// <summary>
        /// Retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows.
        /// This function does not perform a case-sensitive search. To search child windows, beginning with a specified child window, use the FindWindowEx function.
        /// <returns>
        /// <param name="className">
        /// The class name or a class atom created by a previous call to the RegisterClass or RegisterClassEx function.
        /// The atom must be in the low-order word of lpClassName; the high-order word must be zero.
        /// If lpClassName points to a string, it specifies the window class name.
        /// The class name can be any name registered with RegisterClass or RegisterClassEx, or any of the predefined control-class names.
        /// If lpClassName is NULL, it finds any window whose title matches the lpWindowName parameter.
        /// </param>
        /// <param name="windowName">The window name (the window's title). If this parameter is NULL, all window names match.</param>
        /// If the function succeeds, the return value is a handle to the window that has the specified class name and window name.
        /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. 
        /// </returns>
        /// </summary>
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string className, string windowName);

        /// <summary>
        /// The FindWindowEx function retrieves a handle to a window whose class name and window name match the specified strings.
        /// The function searches child windows, beginning with the one following the specified child window.
        /// This function does not perform a case-sensitive search. 
        /// </summary>
        /// <param name="parentHandle">
        /// Handle to the parent window whose child windows are to be searched. 
        /// If hwndParent is NULL, the function uses the desktop window as the parent window.
        /// The function searches among windows that are child windows of the desktop. 
        /// </param>
        /// <param name="childAfter">
        /// Handle to a child window. The search begins with the next child window in the Z order.
        /// The child window must be a direct child window of hwndParent, not just a descendant window.
        /// If hwndChildAfter is NULL, the search begins with the first child window of hwndParent.
        /// </param>
        /// <param name="className">
        /// Pointer to a null-terminated string that specifies the class name or a class atom created by a previous call to the RegisterClass or RegisterClassEx function.
        /// The atom must be placed in the low-order word of lpszClass; the high-order word must be zero.
        /// </param>
        /// <param name="windowTitle">
        /// Pointer to a null-terminated string that specifies the window name (the window's title).
        /// If this parameter is NULL, all window names match.
        /// </param>
        /// <returns>
        /// If the function succeeds, the return value is a handle to the window that has the specified class and window names.
        /// If the function fails, the return value is NULL. To get extended error information, call GetLastError. 
        /// </returns>
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

        /// <summary>
        /// Liefert das Handle des NewAppointmentWindow's.
        /// </summary>
        private static IntPtr FindNewAppointmentWindowByCaption(string caption)
        {
            IntPtr newAppointmentWindowHandle = FindWindow(NewAppointmentWindowClass, caption);
            if (newAppointmentWindowHandle == IntPtr.Zero)
            {
                throw new ArgumentException("NewAppointment Window wasn't found.");
            }
            return newAppointmentWindowHandle;
        }

        private void ThisAddIn_Startup(object sender, EventArgs e)
        {
            _inspectors = Application.Inspectors;
            _inspectors.NewInspector += Inspectors_NewInspector;
        }

        private void Inspectors_NewInspector(Inspector inspector)
        {
            AppointmentItem appointmentItem = inspector.CurrentItem as AppointmentItem;
            if (appointmentItem != null)
            {
                IntPtr appointmentWindow = FindNewAppointmentWindowByCaption(inspector.Caption);

                // Get all child windows based on the new appointment window
                // Unfortunately the social connector handle isn't returned
                GetChildWindows(appointmentWindow);

                // Directly get the social connector based on the class name
                // Unfortunately this returns 0
                IntPtr socialConnectorWindow = FindWindowEx(appointmentWindow, IntPtr.Zero, "MerenguePane", null);
            }
        }

        /// <summary>
        /// Callback method to be used when enumerating windows.
        /// </summary>
        /// <param name="handle">Handle of the next window</param>
        /// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
        /// <returns>True to continue the enumeration, false to bail</returns>
        private static bool EnumWindow(IntPtr handle, IntPtr pointer)
        {
            GCHandle gch = GCHandle.FromIntPtr(pointer);
            List<IntPtr> list = gch.Target as List<IntPtr>;
            if (list == null)
            {
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            }
            Debug.WriteLine("Current Window Handle: {0}, Hex: {1}", handle, handle.ToString("X"));
            list.Add(handle);

            // You can modify this to check to see if you want to cancel the operation, then return a null here
            return true;
        }

        /// <summary>
        /// Returns a list of child windows
        /// </summary>
        /// <param name="parent">Parent of the windows to return</param>
        /// <returns>List of child windows</returns>
        public static List<IntPtr> GetChildWindows(IntPtr parent)
        {
            List<IntPtr> result = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(result);
            try
            {
                EnumWindowProc childProc = EnumWindow;
                EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                if (listHandle.IsAllocated)
                {
                    listHandle.Free();
                }
            }
            return result;
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            Startup += ThisAddIn_Startup;
        }
    }
}

顺便说一下。只有在您直接创建会议请求时才会显示社交连接器,例如转到日历,右键单击 - &gt;新会议要求

对此有何想法?

此致 卢卡斯

0 个答案:

没有答案