如何在Outlook搜索文件夹上编程设置自定义图标?(即Outlook文件夹SetCustomIcon)

3
我正在尝试使用Folder.SetCustomIcon()方法在我编程创建的已保存搜索文件夹上放置自定义图标。虽然SetCustomIcon()文档很简洁,但可以在此处找到参考信息。
此外,它期望的对象在这里,而且示例也非常简单。
有谁知道如何为文件夹设置自定义图标吗?以下是我目前所拥有的代码:
searchFolders = inboxFolder.Store.GetSearchFolders();
foreach (Outlook.Folder folder in searchFolders)
{
    if (folder.Name == "Expiring Retention Policy Mail")
    {
        folder.ShowItemCount = Microsoft.Office.Interop.Outlook.OlShowItemCount.olShowTotalItemCount;
        folder.SetCustomIcon(new Bitmap(32, 32));   // <=-- this isn't working because it's expecting stdPicture which has very sparse information on how to convert to this type.
        Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder = folder;  
    }
}
2个回答

2
您只需要使用 PictureDispConverter 将图像/图标转换为 IPictureDisp。下面是 MSDN 的一个示例(链接)。这仅适用于Outlook 2010+。要在Outlook 2013中查看自定义文件夹图标,您需要查看文件夹列表 - 而不是邮件视图

从 MAPIFolder 设置自定义图标

private static void SetCustomIcon(Outlook.MAPIFolder folder)
{
    Icon icon = null;
    try
    {
        icon = Properties.Resources.myCustomIcon_16x16;
        stdole.StdPicture iconPictureDisp = PictureDispConverter.ToIPictureDisp(icon) as stdole.StdPicture;
        folder.SetCustomIcon(iconPictureDisp);
    }
    finally
    {
        icon.Dispose();
    }
}

PictureDispConverter(图标->IPictureDisp,图片->IPictureDisp

public static class PictureDispConverter
{
    //IPictureDisp GUID. 
    public static Guid iPictureDispGuid = typeof(stdole.IPictureDisp).GUID;

    // Converts an Icon into an IPictureDisp. 
    public static stdole.IPictureDisp ToIPictureDisp(Icon icon)
    {
        PICTDESC.Icon pictIcon = new PICTDESC.Icon(icon);
        return PictureDispConverter.OleCreatePictureIndirect(pictIcon, ref iPictureDispGuid, true);
    }

    // Converts an image into an IPictureDisp. 
    public static stdole.IPictureDisp ToIPictureDisp(Image image)
    {
        Bitmap bitmap = (image is Bitmap) ? (Bitmap)image : new Bitmap(image);
        PICTDESC.Bitmap pictBit = new PICTDESC.Bitmap(bitmap);
        return PictureDispConverter.OleCreatePictureIndirect(pictBit, ref iPictureDispGuid, true);
    }


    [DllImport("OleAut32.dll", EntryPoint = "OleCreatePictureIndirect", ExactSpelling = true,
    PreserveSig = false)]
    private static extern stdole.IPictureDisp OleCreatePictureIndirect(
    [MarshalAs(UnmanagedType.AsAny)] object picdesc, ref Guid iid, bool fOwn);

    private readonly static HandleCollector handleCollector =
    new HandleCollector("Icon handles", 1000);

    // WINFORMS COMMENT: 
    // PICTDESC is a union in native, so we'll just 
    // define different ones for the different types 
    // the "unused" fields are there to make it the right 
    // size, since the struct in native is as big as the biggest 
    // union. 
    private static class PICTDESC
    {
        //Picture Types 
        public const short PICTYPE_UNINITIALIZED = -1;
        public const short PICTYPE_NONE = 0;
        public const short PICTYPE_BITMAP = 1;
        public const short PICTYPE_METAFILE = 2;
        public const short PICTYPE_ICON = 3;
        public const short PICTYPE_ENHMETAFILE = 4;

        [StructLayout(LayoutKind.Sequential)]
        public class Icon
        {
            internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Icon));
            internal int picType = PICTDESC.PICTYPE_ICON;
            internal IntPtr hicon = IntPtr.Zero;
            internal int unused1 = 0;
            internal int unused2 = 0;

            internal Icon(System.Drawing.Icon icon)
            {
                this.hicon = icon.ToBitmap().GetHicon();
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public class Bitmap
        {
            internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Bitmap));
            internal int picType = PICTDESC.PICTYPE_BITMAP;
            internal IntPtr hbitmap = IntPtr.Zero;
            internal IntPtr hpal = IntPtr.Zero;
            internal int unused = 0;
            internal Bitmap(System.Drawing.Bitmap bitmap)
            {
                this.hbitmap = bitmap.GetHbitmap();
            }
        }
    }
} 

1
谢谢!就是这样。现在我的文件夹上显示了一个新的闪亮图标。 - Magnum
我知道这可能有点老了,但也许你知道如何处理使用图标的 DPI 问题?即使我将多尺寸(16、32、64)ico 文件设置为图标,在高 DPI 屏幕上,Outlook 365 仍会不正确地缩放它。 - Sergey Belikov

0

如果你想在VBA中实现它,这里有一个简单的版本。

Sub Change_mapiRootFolder_Icon()
Dim mapiRootFolder As Outlook.MAPIFolder, mapiCurrFolder As Outlook.MAPIFolder 
Dim stFullFolderPath As String, stCurrItemType As String, stIconPath As String, stCurrFolder As String
Dim i As Integer
Dim ipdMyPic As IPictureDisp

Set mapiCurrFolder = Application.ActiveExplorer.CurrentFolder
stCurrItemType = Application.ActiveExplorer.CurrentFolder.DefaultMessageClass

If stCurrItemType = "IPM.Note" Then  'mail Item types    https://msdn.microsoft.com/en-us/library/office/ff861573.aspx
    Set mapiRootFolder = mapiCurrFolder
    stFullFolderPath = mapiRootFolder.Name
    Do Until mapiRootFolder.Parent = "Mapi"
      Set mapiRootFolder = mapiRootFolder.Parent
      stFullFolderPath = mapiRootFolder.Name & "\" & stFullFolderPath
    Loop
    Debug.Print stFullFolderPath

    stIconPath = "U:\OUTLOOK\Icons\Sent\iconarchive_sent1.ico"
    stIconPath = "C:\Temp\iconarchive_sent1.bmp"
    Set ipdMyPic = LoadPicture(stIconPath)
    If Not (mapiCurrFolder Is Nothing) Then
        mapiCurrFolder.SetCustomIcon ipdMyPic
    End If

End If

End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接