Cleaned up OutlookImageList

This commit is contained in:
Patrick Simpson 2017-02-10 11:01:19 +01:00
parent 46c3caf960
commit 0eb4412ed4
12 changed files with 272 additions and 144 deletions

View File

@ -281,10 +281,15 @@
<Compile Include="OutlookConstants.cs" />
<Compile Include="Stubs\IAddIn.cs" />
<Compile Include="Stubs\IAddressEntry.cs" />
<Compile Include="Stubs\ICommandBars.cs" />
<Compile Include="Stubs\IComWrapper.cs" />
<Compile Include="Stubs\IExplorer.cs" />
<Compile Include="Stubs\IOutlookWindow.cs" />
<Compile Include="Stubs\IRecipient.cs" />
<Compile Include="Stubs\OutlookWrappers\AddInWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\AddressEntryWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\CommandBarsWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\ExplorerWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\OutlookItemWrapper.cs" />
<Compile Include="Stubs\OutlookWrappers\RecipientWrapper.cs" />
<Compile Include="UI\Outlook\OutlookImageList.cs" />
@ -293,6 +298,7 @@
<Compile Include="UI\Outlook\CommandElement.cs" />
<Compile Include="UI\Outlook\MenuItem.cs" />
<Compile Include="UI\Outlook\Types.cs" />
<Compile Include="Utils\ImageUtils.cs" />
<Compile Include="Utils\RegistryUtil.cs" />
<Compile Include="ZPush\API\SharedFolders\AvailableFolder.cs" />
<Compile Include="ZPush\API\SharedFolders\SharedFolder.cs" />

View File

@ -22,9 +22,14 @@ namespace Acacia.Stubs
IEnumerable<KeyValuePair<string,string>> COMAddIns { get; }
string Version { get; }
IWin32Window Window { get; }
#region UI
OutlookUI OutlookUI { get; }
IWin32Window Window { get; }
IExplorer GetActiveExplorer();
#endregion
#region Event handlers

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Acacia.Stubs
{
public interface IMSOCommand
{
Bitmap GetImage(Size imageSize);
}
public interface ICommandBars : IComWrapper
{
/// <summary>
/// Returns the command with the specified id.
/// </summary>
/// <param name="id">The id.</param>
/// <returns>The command, or null if it does not exist.</returns>
IMSOCommand GetMso(string id);
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Acacia.Stubs
{
public interface IExplorer : IOutlookWindow
{
/// <summary>
/// Returns the command bars.
/// </summary>
/// <returns>The command bars. The caller is responsible for disposing.</returns>
ICommandBars GetCommandBars();
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Acacia.Stubs
{
public interface IOutlookWindow : IComWrapper
{
}
}

View File

@ -82,8 +82,62 @@ namespace Acacia.Stubs.OutlookWrappers
}
}
#region UI
public OutlookUI OutlookUI { get { return _thisAddIn.OutlookUI; } }
public IExplorer GetActiveExplorer()
{
using (ComRelease com = new ComRelease())
{
return new ExplorerWrapper(com.Add(_thisAddIn.Application).ActiveExplorer());
}
}
#region Window handle
private class WindowHandle : IWin32Window
{
private IntPtr hWnd;
public WindowHandle(IntPtr hWnd)
{
this.hWnd = hWnd;
}
public IntPtr Handle
{
get
{
return hWnd;
}
}
}
public IWin32Window Window
{
get
{
IOleWindow win = _app.ActiveWindow() as IOleWindow;
if (win == null)
return null;
try
{
IntPtr hWnd;
win.GetWindow(out hWnd);
return new WindowHandle(hWnd);
}
finally
{
ComRelease.Release(win);
}
}
}
#endregion
#endregion
public ZPushWatcher Watcher { get { return _thisAddIn.Watcher; } }
public MailEvents MailEvents { get { return _thisAddIn.MailEvents; } }
public IEnumerable<Feature> Features { get { return _thisAddIn.Features; } }
@ -148,48 +202,6 @@ namespace Acacia.Stubs.OutlookWrappers
}
}
#region Window handle
private class WindowHandle : IWin32Window
{
private IntPtr hWnd;
public WindowHandle(IntPtr hWnd)
{
this.hWnd = hWnd;
}
public IntPtr Handle
{
get
{
return hWnd;
}
}
}
public IWin32Window Window
{
get
{
IOleWindow win = _app.ActiveWindow() as IOleWindow;
if (win == null)
return null;
try
{
IntPtr hWnd;
win.GetWindow(out hWnd);
return new WindowHandle(hWnd);
}
finally
{
ComRelease.Release(win);
}
}
}
#endregion
public IRecipient ResolveRecipient(string name)
{

View File

@ -0,0 +1,59 @@
using Acacia.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NSOffice = Microsoft.Office.Core;
using System.Drawing;
using stdole;
namespace Acacia.Stubs.OutlookWrappers
{
class CommandBarsWrapper : ComWrapper, ICommandBars
{
private class MSOCommand : IMSOCommand
{
private readonly CommandBarsWrapper _commands;
private readonly string _id;
public MSOCommand(CommandBarsWrapper commands, string id)
{
this._commands = commands;
this._id = id;
}
public Bitmap GetImage(Size imageSize)
{
IPictureDisp pict = _commands._item.GetImageMso(_id, imageSize.Width, imageSize.Height);
try
{
return ImageUtils.GetBitmapFromHBitmap(new IntPtr(pict.Handle));
}
finally
{
ComRelease.Release(pict);
}
}
}
private NSOffice.CommandBars _item;
public CommandBarsWrapper(NSOffice.CommandBars item)
{
this._item = item;
}
public IMSOCommand GetMso(string id)
{
return new MSOCommand(this, id);
}
// TODO: make TypedComWrapper
protected override void DoRelease()
{
ComRelease.Release(_item);
_item = null;
}
}
}

View File

@ -0,0 +1,31 @@
using Acacia.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NSOutlook = Microsoft.Office.Interop.Outlook;
namespace Acacia.Stubs.OutlookWrappers
{
class ExplorerWrapper : ComWrapper, IExplorer
{
private NSOutlook.Explorer _item;
public ExplorerWrapper(NSOutlook.Explorer item)
{
this._item = item;
}
protected override void DoRelease()
{
ComRelease.Release(_item);
_item = null;
}
public ICommandBars GetCommandBars()
{
return new CommandBarsWrapper(_item.CommandBars);
}
}
}

View File

@ -44,10 +44,6 @@ namespace Acacia.Stubs.OutlookWrappers
this._item = item;
}
~OutlookWrapper()
{
}
protected override void DoRelease()
{
if (_props != null)

View File

@ -1,4 +1,7 @@
/// Copyright 2016 Kopano b.v.

using Acacia.Stubs;
using Acacia.Utils;
/// Copyright 2016 Kopano b.v.
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3,
@ -13,7 +16,6 @@
/// along with this program.If not, see<http://www.gnu.org/licenses/>.
///
/// Consult LICENSE file for details
using Microsoft.Office.Core;
using stdole;
using System;
@ -35,93 +37,6 @@ namespace Acacia.UI.Outlook
{
public ImageList Images { get; private set; }
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
private Bitmap GetBitmapFromHBitmap2(IntPtr nativeHBitmap)
{
Bitmap bmp = Bitmap.FromHbitmap(nativeHBitmap);
if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32)
return bmp;
// Special handling is required to convert a bitmap with alpha channel, FromHBitmap doesn't
// set the correct pixel format
Rectangle bmBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(bmBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
Bitmap bmp2 = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
BitmapData bmpData2 = bmp2.LockBits(bmBounds, ImageLockMode.WriteOnly, bmp2.PixelFormat);
try
{
for (int y = 0; y < bmp.Height; ++y)
{
IntPtr target = bmpData2.Scan0 + bmpData2.Stride * y;
IntPtr source = bmpData.Scan0 + bmpData.Stride * y;
CopyMemory(target, source, (uint)Math.Abs(bmpData2.Stride));
}
}
finally
{
bmp2.UnlockBits(bmpData2);
bmp.UnlockBits(bmpData);
}
return bmp2;
}
private static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap)
{
Bitmap bmp = Bitmap.FromHbitmap(nativeHBitmap);
if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32)
return bmp;
BitmapData bmpData;
if (IsAlphaBitmap(bmp, out bmpData))
return GetlAlphaBitmapFromBitmapData(bmpData);
return bmp;
}
private static Bitmap GetlAlphaBitmapFromBitmapData(BitmapData bmpData)
{
return new Bitmap(
bmpData.Width,
bmpData.Height,
bmpData.Stride,
PixelFormat.Format32bppArgb,
bmpData.Scan0);
}
private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
{
Rectangle bmBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmpData = bmp.LockBits(bmBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
for (int y = 0; y <= bmpData.Height - 1; y++)
{
for (int x = 0; x <= bmpData.Width - 1; x++)
{
Color pixelColor = Color.FromArgb(
Marshal.ReadInt32(bmpData.Scan0, (bmpData.Stride * y) + (4 * x)));
if (pixelColor.A > 0 & pixelColor.A < 255)
{
return true;
}
}
}
}
finally
{
bmp.UnlockBits(bmpData);
}
return false;
}
public OutlookImageList(params string[] icons)
{
Images = new ImageList();
@ -129,12 +44,13 @@ namespace Acacia.UI.Outlook
Images.ImageSize = new Size(16, 16);
// TODO: memory management
CommandBars cmdBars = ThisAddIn.Instance.RawApp.ActiveWindow().CommandBars;
foreach (string id in icons)
using (IExplorer explorer = ThisAddIn.Instance.GetActiveExplorer())
using (ICommandBars cmdBars = explorer.GetCommandBars())
{
IPictureDisp pict = cmdBars.GetImageMso(id, Images.ImageSize.Width, Images.ImageSize.Height);
var img = GetBitmapFromHBitmap2(new IntPtr(pict.Handle));
Images.Images.Add(img);
foreach (string id in icons)
{
Images.Images.Add(cmdBars.GetMso(id).GetImage(Images.ImageSize));
}
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Acacia.Utils
{
public static class ImageUtils
{
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
public static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap)
{
Bitmap bmp = Bitmap.FromHbitmap(nativeHBitmap);
if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32)
return bmp;
// Special handling is required to convert a bitmap with alpha channel, FromHBitmap doesn't
// set the correct pixel format
Rectangle bmBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(bmBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
Bitmap bmp2 = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
BitmapData bmpData2 = bmp2.LockBits(bmBounds, ImageLockMode.WriteOnly, bmp2.PixelFormat);
try
{
for (int y = 0; y < bmp.Height; ++y)
{
IntPtr target = bmpData2.Scan0 + bmpData2.Stride * y;
IntPtr source = bmpData.Scan0 + bmpData.Stride * y;
CopyMemory(target, source, (uint)Math.Abs(bmpData2.Stride));
}
}
finally
{
bmp2.UnlockBits(bmpData2);
bmp.UnlockBits(bmpData);
}
return bmp2;
}
}
}

View File

@ -134,11 +134,14 @@ namespace Acacia.ZPush
if (GlobalOptions.INSTANCE.LocalFolders_Hide)
{
// Hide the folders that are not custom folders
using (ComRelease com = new ComRelease())
using (IFolder root = store.GetRootFolder())
{
foreach(IFolder sub in store.GetRootFolder().GetSubFolders())
foreach(IFolder sub in root.GetSubFolders())
{
sub.AttrHidden = !IsCustomFolder(sub);
using (sub)
{
sub.AttrHidden = !IsCustomFolder(sub);
}
}
}
}