From 0eb4412ed481bd0f9de147667ab3fc32b2151a9d Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Fri, 10 Feb 2017 11:01:19 +0100
Subject: [PATCH] Cleaned up OutlookImageList
---
.../AcaciaZPushPlugin.csproj | 6 +
.../AcaciaZPushPlugin/Stubs/IAddIn.cs | 7 +-
.../AcaciaZPushPlugin/Stubs/ICommandBars.cs | 24 ++++
.../AcaciaZPushPlugin/Stubs/IExplorer.cs | 17 +++
.../AcaciaZPushPlugin/Stubs/IOutlookWindow.cs | 12 ++
.../Stubs/OutlookWrappers/AddInWrapper.cs | 96 +++++++++-------
.../OutlookWrappers/CommandBarsWrapper.cs | 59 ++++++++++
.../Stubs/OutlookWrappers/ExplorerWrapper.cs | 31 ++++++
.../Stubs/OutlookWrappers/OutlookWrapper.cs | 4 -
.../UI/Outlook/OutlookImageList.cs | 104 ++----------------
.../AcaciaZPushPlugin/Utils/ImageUtils.cs | 47 ++++++++
.../ZPush/ZPushLocalStore.cs | 9 +-
12 files changed, 272 insertions(+), 144 deletions(-)
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ICommandBars.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IExplorer.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IOutlookWindow.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/CommandBarsWrapper.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ExplorerWrapper.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/ImageUtils.cs
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
index ed0c59b..d0a457b 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
@@ -281,10 +281,15 @@
+
+
+
+
+
@@ -293,6 +298,7 @@
+
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
index 4a07b11..21ffdf2 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAddIn.cs
@@ -22,9 +22,14 @@ namespace Acacia.Stubs
IEnumerable> COMAddIns { get; }
string Version { get; }
- IWin32Window Window { get; }
+ #region UI
OutlookUI OutlookUI { get; }
+ IWin32Window Window { get; }
+ IExplorer GetActiveExplorer();
+
+ #endregion
+
#region Event handlers
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ICommandBars.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ICommandBars.cs
new file mode 100644
index 0000000..e6faa24
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ICommandBars.cs
@@ -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
+ {
+ ///
+ /// Returns the command with the specified id.
+ ///
+ /// The id.
+ /// The command, or null if it does not exist.
+ IMSOCommand GetMso(string id);
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IExplorer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IExplorer.cs
new file mode 100644
index 0000000..e4b4474
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IExplorer.cs
@@ -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
+ {
+ ///
+ /// Returns the command bars.
+ ///
+ /// The command bars. The caller is responsible for disposing.
+ ICommandBars GetCommandBars();
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IOutlookWindow.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IOutlookWindow.cs
new file mode 100644
index 0000000..3181e84
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IOutlookWindow.cs
@@ -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
+ {
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
index ebad830..2e75aed 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/AddInWrapper.cs
@@ -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 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)
{
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/CommandBarsWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/CommandBarsWrapper.cs
new file mode 100644
index 0000000..492ffd2
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/CommandBarsWrapper.cs
@@ -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;
+ }
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ExplorerWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ExplorerWrapper.cs
new file mode 100644
index 0000000..c02ca0f
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/ExplorerWrapper.cs
@@ -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);
+ }
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
index fe56318..c444b3d 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/OutlookWrapper.cs
@@ -44,10 +44,6 @@ namespace Acacia.Stubs.OutlookWrappers
this._item = item;
}
- ~OutlookWrapper()
- {
- }
-
protected override void DoRelease()
{
if (_props != null)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookImageList.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookImageList.cs
index 048d413..0f4afbc 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookImageList.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/Outlook/OutlookImageList.cs
@@ -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.
///
/// 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));
+ }
}
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/ImageUtils.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/ImageUtils.cs
new file mode 100644
index 0000000..6a7d5c5
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/ImageUtils.cs
@@ -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;
+ }
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushLocalStore.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushLocalStore.cs
index 643b266..8341a04 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushLocalStore.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushLocalStore.cs
@@ -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);
+ }
}
}
}