我正在开发一个自定义Outlook插件,我需要子类化约会窗口。这基本上很好地遵循以下ariticle中提到的原则:
http://www.codeproject.com/Articles/27262/Additional-custom-panel-in-Microsoft-Outlook
我通过在新约会窗口中获取社交连接器的句柄来解决问题。
我已经尝试了一些方法(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;新会议要求
对此有何想法?
此致 卢卡斯