miranda/Hyphen/Plugins/Forms/Controls/ManagedMainMenu.cs
2013-06-25 22:53:41 +00:00

243 lines
9.2 KiB
C#

/***********************************************************************\
* Virtuoso.Miranda.Plugins (Hyphen) *
* Provides a managed wrapper for API of IM client Miranda. *
* Copyright (C) 2006-2009 virtuoso *
* deml.tomas@seznam.cz *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
\***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Virtuoso.Miranda.Plugins.Native;
using System.Drawing;
using Virtuoso.Miranda.Plugins.Infrastructure;
using Virtuoso.Miranda.Plugins.Resources;
using Virtuoso.Miranda.Plugins.Forms.Controls;
namespace Virtuoso.Miranda.Plugins.Forms.Controls
{
// Impl note: must be public, remoting rejects non-public method calls.
public sealed class ManagedMainMenu : ContextMenuStrip
{
#region Delegates
private delegate void AddMainMenuItemInvoker(ManagedMainMenu menu, ManagedMainMenuItem item);
private delegate void ModifyMenuItemInvoker(ManagedMainMenu menu, ref CLISTMENUITEM itemData, string handle);
#endregion
#region Fields
private static readonly Random HandleGenerator = new Random();
private static readonly AddMainMenuItemInvoker AddMainMenuItemDelegate = new AddMainMenuItemInvoker(AddMainMenuItem);
private static readonly ModifyMenuItemInvoker ModifyMenuItemDelegate = new ModifyMenuItemInvoker(ModifyMenuItem);
private static readonly ToolStripMenuItem EmptyItem;
private readonly int EmptyItemIndex;
#endregion
#region .ctors & .dctors
static ManagedMainMenu()
{
EmptyItem = new ToolStripMenuItem(TextResources.UI_Label_Empty);
EmptyItem.Visible = false;
}
internal ManagedMainMenu()
{
RenderMode = ToolStripRenderMode.System;
EmptyItemIndex = Items.Add(EmptyItem);
}
#endregion
#region Methods
#region Overrides
public override object InitializeLifetimeService()
{
return null;
}
#endregion
#region UI
internal void ShowUnderCursor()
{
if (Items.Count == 1)
Items[EmptyItemIndex].Visible = true;
else
Items[EmptyItemIndex].Visible = false;
Show(Cursor.Position);
}
#endregion
#region Interceptors
/// <summary>
///
/// </summary>
/// <param name="menu"></param>
/// <remarks>
/// This method is static to not let the execution run in default AppDomain but in a domain of the menu itself.
/// </remarks>
internal static void RegisterInterceptors(ManagedMainMenu menu)
{
MirandaContext context = MirandaContext.Current;
context.ServiceCallInterceptors.Register(MirandaServices.MS_CLIST_ADDMAINMENUITEM, menu.AddMainMenuItemServiceInterceptor);
context.ServiceCallInterceptors.Register(MirandaServices.MS_CLIST_MODIFYMENUITEM, menu.ModifyMenuItemInterceptor);
}
internal static void UnregisterInterceptors(ManagedMainMenu menu)
{
MirandaContext context = MirandaContext.Current;
context.ServiceCallInterceptors.Unregister(MirandaServices.MS_CLIST_ADDMAINMENUITEM);
context.ServiceCallInterceptors.Unregister(MirandaServices.MS_CLIST_MODIFYMENUITEM);
}
private int AddMainMenuItemServiceInterceptor(UIntPtr wParam, IntPtr lParam)
{
CLISTMENUITEM itemData = (CLISTMENUITEM)Marshal.PtrToStructure(lParam, typeof(CLISTMENUITEM));
ManagedMainMenuItem menuItem = null;
Image itemImage = null;
if (itemData.Icon != IntPtr.Zero)
itemImage = IconImageCache.Singleton.GetIconImage(itemData.Icon);
menuItem = new ManagedMainMenuItem(itemData.Text, itemData.PopUpMenu, itemData.Service, itemImage);
if (InvokeRequired)
Invoke(AddMainMenuItemDelegate, this, menuItem);
else
AddMainMenuItemDelegate(this, menuItem);
return menuItem.Handle;
}
private static void AddMainMenuItem(ManagedMainMenu menu, ManagedMainMenuItem item)
{
if (!String.IsNullOrEmpty(item.PopUpMenu))
{
string popupName = item.PopUpMenu;
ToolStripMenuItem popupItem = null;
ToolStripItem[] popupItems = menu.Items.Find(popupName, false);
if (popupItems.Length > 0)
popupItem = (ToolStripMenuItem)popupItems[0];
else
{
popupItem = new ToolStripMenuItem(popupName);
popupItem.Name = popupName;
menu.Items.Add(popupItem);
}
popupItem.DropDownItems.Add(item);
}
else
menu.Items.Add(item);
}
private int ModifyMenuItemInterceptor(UIntPtr wParam, IntPtr lParam)
{
try
{
CLISTMENUITEM itemData = (CLISTMENUITEM)Marshal.PtrToStructure(lParam, typeof(CLISTMENUITEM));
string handle = wParam.ToString();
if (!Items.ContainsKey(handle))
{
if (String.IsNullOrEmpty(itemData.PopUpMenu) ||
!Items.ContainsKey(itemData.PopUpMenu) ||
!((ToolStripMenuItem)Items[itemData.PopUpMenu]).DropDownItems.ContainsKey(handle))
return MirandaContext.Current.CallService(MirandaServices.MS_CLIST_MODIFYMENUITEM, wParam, lParam, true);
}
if (InvokeRequired)
Invoke(ModifyMenuItemDelegate, this, itemData, handle);
else
ModifyMenuItemDelegate(this, ref itemData, handle);
return 0;
}
catch
{
return -1;
}
}
private static void ModifyMenuItem(ManagedMainMenu menu, ref CLISTMENUITEM itemData, string handle)
{
ManagedMainMenuItem item = (ManagedMainMenuItem)menu.Items.Find(handle, itemData.PopUpMenu != null)[0];
MenuItemModifyFlags flags = (MenuItemModifyFlags)itemData.Flags;
if ((flags & MenuItemModifyFlags.CMIM_NAME) == MenuItemModifyFlags.CMIM_NAME)
item.Text = itemData.Text;
if ((flags & MenuItemModifyFlags.CMIM_ICON) == MenuItemModifyFlags.CMIM_ICON)
item.Image = IconImageCache.Singleton.GetIconImage(itemData.Icon);
if ((flags & MenuItemModifyFlags.CMIM_HOTKEY) == MenuItemModifyFlags.CMIM_HOTKEY)
item.ShortcutKeys = (Keys)itemData.HotKey;
if ((flags & MenuItemModifyFlags.CMIM_FLAGS) == MenuItemModifyFlags.CMIM_FLAGS)
{
MenuItemProperties itemFlags = (MenuItemProperties)(flags & ~MenuItemModifyFlags.CMIM_ALL);
switch (itemFlags)
{
case MenuItemProperties.Grayed:
item.Enabled = false;
break;
case MenuItemProperties.Hidden:
if (item.OwnerItem == null)
menu.Items.Remove(item);
else
{
ToolStripMenuItem popupItem = (ToolStripMenuItem)item.OwnerItem;
popupItem.DropDownItems.Remove(item);
if (popupItem.DropDownItems.Count == 0)
menu.Items.Remove(popupItem);
}
break;
case MenuItemProperties.Checked:
item.Checked = true;
break;
case MenuItemProperties.None:
item.Enabled = true;
item.Visible = true;
item.Checked = false;
break;
}
}
}
#endregion
#endregion
}
}