none
自作したOutlookアドインのツールヒントの無効化 RRS feed

  • 質問

  • いつもいつもお世話になっております。

    すごい勢いで質問してしまい申し訳ございません。

    OutlookのVSTOアドインで自作したリボンにマウスホバーすると、ツールヒントが表示されるのですが、

    ここの赤枠の箇所を、削除もしくは意図した文字に書き換えたいのですが、方法が分かりません。

    Excelの自作したアドインのみでは、ここの部分を非表示にすることはできないという記事を見つけたので(すべてのアドインで表示、非表示を切り替えなければならない)、Outlookのアドインでも同様に

    設定できないのではないかなと思います(自由に設定できるのは赤枠の上の部分までという認識)。

    なにか参考になる情報など教えていただけないでしょうか。

    宜しくお願いします。

    2019年8月9日 8:11

回答

  • 美味しい魚屋さんさん、こんにちは。フォーラムオペレーターのHarukaです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    既に見つけたように、その赤枠の箇所をカスタマイズすることはできません。
    Office リボンはこの機能を公開しておらず、今後は公開するニュースもありません。

    どうぞよろしくお願いします。


    MSDN/ TechNet Community Support Haruka

    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、
    ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年8月13日 8:30
    モデレータ

すべての返信

  • 美味しい魚屋さんさん、こんにちは。フォーラムオペレーターのHarukaです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    既に見つけたように、その赤枠の箇所をカスタマイズすることはできません。
    Office リボンはこの機能を公開しておらず、今後は公開するニュースもありません。

    どうぞよろしくお願いします。


    MSDN/ TechNet Community Support Haruka

    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、
    ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年8月13日 8:30
    モデレータ
  • カスタマイズできない件、承知いたしました。

    教えていただき有難うございます。

    2019年8月13日 10:04

  • <?xml version="1.0" encoding="UTF-8"?>
    <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
    xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui" 
              onLoad="Load" >
      <ribbon >
        <tabs >
          <tab idMso="TabAddIns">
            <group id="MyGroup1" label="ぐるーぷ" >
              <button label="ぼたん1" id="button1" 
                      getVisible="GetVisible"
                      getSupertip="GetSuperTip"
                      getScreentip="GetScreenTip" 
                      onAction="ButtonClick" />
    
              <button label="ぼたん2" id="button2"
                      getVisible="GetVisible"
                      getSupertip="GetSuperTip"
                      getScreentip="GetScreenTip"
                      onAction="ButtonClick" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    namespace OutlookAddIn1
    {
        using System;
        using System.IO;
        using System.Text;
        using Office = Microsoft.Office.Core;
        using Gekka.VSTO.Tools;
    
        [System.Runtime.InteropServices.ComVisible(true)]
        public partial class Ribbon1 : Office.IRibbonExtensibility
        {
            private RibbonTooltipTool tooltip = new RibbonTooltipTool();
    
            public Ribbon1()
            {
                tooltip.Showing += tooltip_Showing;
            }
    
            #region IRibbonExtensibility のメンバー
    
            public string GetCustomUI(string ribbonID)
            {
                if (ribbonID == "Microsoft.Outlook.Mail.Compose")
                {
                    return GetResourceText("OutlookAddIn1.RibbonMail.xml");
                }
                else if (ribbonID == "Microsoft.Outlook.Explorer")
                {
                    return GetResourceText("OutlookAddIn1.RibbonExplore.xml");
                }
    
                return string.Empty;
            }
    
            #endregion
    
            #region リボンのコールバック
            //ここでコールバック メソッドを作成します。コールバック メソッドの追加について詳しくは https://go.microsoft.com/fwlink/?LinkID=271226 をご覧ください
    
            private Office.IRibbonUI ribbon;
    
            public void Load(Office.IRibbonUI ribbonUI)
            {
                ribbon = ribbonUI;
            }
    
            public bool GetVisible(Office.IRibbonControl control)
            {
                this.tooltip.StartHook(control);
                return true;
            }
    
            public string GetScreenTip(Office.IRibbonControl control)
            {
                return this.tooltip.SCREENTIP_KEY + control.Id;
            }
    
            public string GetSuperTip(Office.IRibbonControl control)
            {
                return "";
            }
    
            public void ButtonClick(Office.IRibbonControl control)
            {
            }
    
            private void tooltip_Showing(object sender, RibbonTooltipTool.ShowEventArgs e)
            {
                if (e.ID == "button1")
                {
                    e.Cancel = false;
                    e.Model.ScreenTip = "あいうえお";
                    e.Model.SuperTip = "かきくけこ\r\nさしすせそ";
    
                    e.Model.HelpVisibility = System.Windows.Visibility.Visible;
    
                    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(16, 16);
                    using (var g = System.Drawing.Graphics.FromImage(bmp))
                    {
                        g.FillRectangle(System.Drawing.Brushes.Transparent, new System.Drawing.Rectangle(0, 0, 15, 15));
                        g.DrawRectangle(System.Drawing.Pens.Red, new System.Drawing.Rectangle(0, 0, 15, 15));
                        g.DrawLine(System.Drawing.Pens.Red, 0, 0, 15, 15);
                    }
                    e.Model.SetImge(bmp);
                    e.Model.Help = "ABCDEFG";
                    e.Model.HelpUri = new Uri("https://social.msdn.microsoft.com/Forums/ja-JP/home");
                }
                else if (e.ID == "button2")
                {
                    e.Cancel = false;
                    e.Model.ScreenTip = "ABC";
                    e.Model.SuperTip = "0123456789";
    
                    e.Model.HelpVisibility = System.Windows.Visibility.Collapsed;
                }
            }
            #endregion
    
            #region ヘルパー
    
            private static string GetResourceText(string resourceName)
            {
                System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
                string[] resourceNames = asm.GetManifestResourceNames();
                for (int i = 0; i < resourceNames.Length; ++i)
                {
                    if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
                        {
                            if (resourceReader != null)
                            {
                                return resourceReader.ReadToEnd();
                            }
                        }
                    }
                }
                return null;
            }
            #endregion
        }
    }
    
    namespace Gekka.VSTO.Tools
    {
        using System;
        using System.Windows.Automation;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Controls.Primitives;
        using System.ComponentModel;
        using System.Windows.Data;
    
        class RibbonTooltipTool
        {
            public readonly string SCREENTIP_KEY = "\x200B";
    
            private IntPtr hhook;
            private Win32.HOOKPROC hookproc;
            private IntPtr hwndNetUIToolWindow;
            private System.Threading.SynchronizationContext context;
    
            private System.Threading.Thread thread;
            private System.Windows.Window wpfw;
            private System.Windows.Threading.Dispatcher disp;
            private View popup;
    
            public bool StartHook(Microsoft.Office.Core.IRibbonControl control)
            {
                return this.StartHook(control.Context);
            }
    
            private bool StartHook(object obj)
            {
                if (this.hhook != IntPtr.Zero)
                {
                    return false;
                }
                var iow = obj as IOleWindow;
                if (iow == null)
                {
                    return false;
                }
    
                hookproc = new Win32.HOOKPROC(OnHook);
    
                IntPtr hwnd = iow.GetWindow();
                IntPtr hinstance = Win32.GetWindowLong(hwnd, -6);
                IntPtr pid;
                uint thread = Win32.GetWindowThreadProcessId(hwnd, out pid);
    
                this.hhook = Win32.SetWindowsHookEx(Win32.WH.WH_CBT, this.hookproc, hinstance, new UIntPtr(thread));
                var retval = this.hhook != IntPtr.Zero;
                if (retval)
                {
                    Init();
                }
                return retval;
            }
            public void Init()
            {
                context = System.Threading.SynchronizationContext.Current;
                if (context == null)
                {
                    context = new System.Threading.SynchronizationContext();
                    System.Threading.SynchronizationContext.SetSynchronizationContext(context);
                }
    
                if (thread == null)
                {
                    thread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                    {
                        disp = System.Windows.Threading.Dispatcher.CurrentDispatcher;
    
                        wpfw = new System.Windows.Window();
                        wpfw.Left = 0;
                        wpfw.Top = 0;
                        wpfw.Width = 0;
                        wpfw.Height = 0;
                        wpfw.WindowStyle = System.Windows.WindowStyle.None;
                        wpfw.ShowInTaskbar = false;
                        wpfw.Topmost = true;
                        wpfw.Visibility = System.Windows.Visibility.Hidden;
    
                        popup = new View();
    
                        var app = System.Windows.Application.Current;
                        if (app == null)
                        {
                            app = new System.Windows.Application();
                        }
                        app.Run(wpfw);
                    }));
                    thread.SetApartmentState(System.Threading.ApartmentState.STA);
                    thread.Start();
                }
            }
            private IntPtr OnHook(int nCode, IntPtr wParam, IntPtr lParam)
            {
                IntPtr hwnd = IntPtr.Zero;
                try
                {
                    System.Diagnostics.Debug.WriteLine(((Win32.HCBT)nCode).ToString());
                    if (nCode == (int)Win32.HCBT.HCBT_CREATEWND)
                    {
                        hwnd = wParam;
                        string className = Win32.GetClassName(hwnd);
                        System.Diagnostics.Debug.WriteLine("CREATE:" + hwnd.ToString() + className);
    
                        if (className == "Net UI Tool Window")
                        {
                            hwndNetUIToolWindow = hwnd;
                        }
                        else if (hwndNetUIToolWindow != IntPtr.Zero && className == "NetUIHWND")
                        {
                            IntPtr hwndTooltip = hwndNetUIToolWindow;
                            hwndNetUIToolWindow = IntPtr.Zero;
    
                            var pForm = System.Windows.Forms.Cursor.Position;
                            var p = new System.Windows.Point(pForm.X, pForm.Y);
                            AutomationElement elem = System.Windows.Automation.AutomationElement.FromPoint(p);
                            if (elem != null)
                            {
                                if (elem.Current.HelpText.StartsWith(SCREENTIP_KEY))
                                {
                                    string id = elem.Current.HelpText.Substring(SCREENTIP_KEY.Length);
                                    context.Post((o) =>
                                    {
                                        OnTipShow(hwndTooltip, id);
                                    }, null);
                                }
                            }
                        }
                        else
                        {
                            hwndNetUIToolWindow = IntPtr.Zero;
                        }
                    }
                    else
                    {
                        hwndNetUIToolWindow = IntPtr.Zero;
                    }
                }
                catch
                {
                }
                finally
                {
                }
                return Win32.CallNextHookEx(hhook, nCode, wParam, lParam);
    
            }
    
            private void OnTipShow(IntPtr hwnd, string id)
            {
                disp?.Invoke(async () =>
                {
                    ShowEventArgs e = new ShowEventArgs();
                    e.ID = id;
                    e.Cancel = true;
                    Showing?.Invoke(this, e);
                    if (e.Cancel || e.Model == null)
                    {
                        return;
                    }
    
                    while (!Win32.IsWindowVisible(hwnd))
                    {
                        System.Threading.Thread.Sleep(1);
                    }
    
                    var rect = Win32.GetWindowInfo(hwnd).rcWindow;
    
                    Win32.PostMessage(hwnd, (int)Win32.WM.WM_SIZE, IntPtr.Zero, new IntPtr(0x00010001));
    
                    wpfw.Topmost = false;
                    wpfw.Topmost = true;
    
                    popup.DataContext = e.Model;
                    popup.PlacementRectangle = new Rect(rect.Left, rect.Top, 0, 0);
                    popup.IsOpen = true;
                    while (Win32.IsWindowVisible(hwnd) || popup.IsMouseOverInternal)
                    {
                        await System.Threading.Tasks.Task.Delay(10);
                    }
                    popup.IsOpen = false;
                });
            }
    
            public event EventHandler<ShowEventArgs> Showing;
    
            public class ShowEventArgs : System.ComponentModel.CancelEventArgs
            {
                public string ID { get; set; }
                public Model Model { get; } = new Model();
            }
    
            class View : System.Windows.Controls.Primitives.Popup
            {
                public View()
                {
                    PlacementTarget = null;
                    StaysOpen = false;
                    Placement = PlacementMode.AbsolutePoint;
    
                    Border border = new Border() { BorderBrush = System.Windows.Media.Brushes.Gray, BorderThickness = new Thickness(1) };
                    {
                        Grid grid = new Grid();
                        {
                            grid.Background = System.Windows.Media.Brushes.White;
    
                            StackPanel stack = new StackPanel() { Margin = new System.Windows.Thickness(5, 5, 5, 5) };
                            {
                                var screentip = new TextBlock();
                                {
                                    screentip.FontWeight = FontWeights.Bold;
                                    screentip.Margin = new Thickness(0, 0, 0, 5);
                                    screentip.SetBinding(TextBlock.TextProperty, new System.Windows.Data.Binding(nameof(Model.ScreenTip)));
                                }
                                var supertip = new TextBlock();
                                {
                                    supertip.SetBinding(TextBlock.TextProperty, new System.Windows.Data.Binding(nameof(Model.SuperTip)));
                                    supertip.TextWrapping = TextWrapping.Wrap;
                                }
    
                                StackPanel stack2 = new StackPanel();
                                {
                                    Separator separator = new Separator();
                                    {
                                        separator.Margin = new Thickness(0, 3, 0, 3);
                                    }
                                    DockPanel dock = new DockPanel();
                                    {
                                        var icon = new Image();
                                        {
                                            icon.SetBinding(Image.SourceProperty, new Binding(nameof(Model.Image)));
                                        }
                                        var help = new TextBlock();
                                        {
                                            help.TextWrapping = TextWrapping.Wrap;
    
                                            System.Windows.Documents.Hyperlink link = new System.Windows.Documents.Hyperlink();
                                            {
                                                System.Windows.Documents.Run run = new System.Windows.Documents.Run();
                                                {
                                                    run.SetBinding(System.Windows.Documents.Run.TextProperty, new System.Windows.Data.Binding(nameof(Model.Help)) { Mode = BindingMode.OneWay });
                                                }
                                                link.Inlines.Add(run);
                                                link.Click += Link_Click;
    
                                            }
    
    
                                            help.Inlines.Add(link);
                                        }
    
                                        dock.Children.Add(icon);
                                        dock.Children.Add(help);
                                    }
                                    stack2.Children.Add(separator);
                                    stack2.Children.Add(dock);
                                    stack2.SetBinding(StackPanel.VisibilityProperty, new Binding(nameof(Model.HelpVisibility)));
                                }
                                stack.Children.Add(screentip);
                                stack.Children.Add(supertip);
                                stack.Children.Add(stack2);
                            }
    
                            grid.Children.Add(stack);
    
                            grid.MouseEnter += (s, e) => { this.IsMouseOverInternal = true; };
                            grid.MouseLeave += (s, e) => { this.IsMouseOverInternal = false; };
                        }
                        border.Child = grid;
                    }
                    this.Child = border;
    
                    this.DataContext = this.Model;
                }
    
                private void Link_Click(object sender, RoutedEventArgs e)
                {
                    System.Windows.Documents.Hyperlink link = (System.Windows.Documents.Hyperlink)sender;
                    var model = link.DataContext as Model;
    
                    if (model.HelpAction != null)
                    {
                        model.HelpAction();
                    }
                    else if (model.HelpUri != null)
                    {
                        System.Diagnostics.Process.Start(model.HelpUri.AbsoluteUri);
                    }
    
    
                }
    
                protected override void OnClosed(EventArgs e)
                {
                    this.IsMouseOverInternal = false;
                    base.OnClosed(e);
                }
                internal bool IsMouseOverInternal { get; private set; }
                public Model Model { get; } = new Model();
            }
    
            public class Model : System.ComponentModel.INotifyPropertyChanged
            {
                public event PropertyChangedEventHandler PropertyChanged;
                protected virtual void OnPropertyChanged(string name)
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
                }
                public string ScreenTip
                {
                    get { return _ScreenTip; }
                    set { _ScreenTip = value; OnPropertyChanged(nameof(ScreenTip)); }
                }
                private string _ScreenTip;
    
                public string SuperTip
                {
                    get { return _SuperTip; }
                    set { _SuperTip = value; OnPropertyChanged(nameof(SuperTip)); }
                }
                private string _SuperTip;
    
                public Visibility HelpVisibility
                {
                    get { return _HelpVisibility; }
                    set { _HelpVisibility = value; OnPropertyChanged(nameof(HelpVisibility)); }
                }
                private Visibility _HelpVisibility;
    
                public string Help
                {
                    get { return _Help; }
                    set { _Help = value; OnPropertyChanged(nameof(Help)); }
                }
                private string _Help;
    
                public Uri HelpUri { get; set; }
    
                public Action HelpAction { get; set; }
    
    
                public System.Windows.Media.ImageSource Image
                {
                    get { return _Image; }
                    set { _Image = value; OnPropertyChanged(nameof(Image)); }
                }
                private System.Windows.Media.ImageSource _Image;
    
                public void SetImge(System.Drawing.Bitmap bmp)
                {
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    ms.Position = 0;
                    var image = new System.Windows.Media.Imaging.BitmapImage();
                    {
                        image.BeginInit();
                        image.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
                        image.StreamSource = ms;
                        image.EndInit();
                    }
                    this.Image = image;
                }
    
                public object Tag { get; set; }
            }
        }
    }
    
    namespace Gekka.VSTO.Tools
    {
        using System;
        using System.Runtime.InteropServices;
        using System.Text;
    
        class Win32
        {
            [DllImport("user32.dll")]
            public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr ProcessId);
    
            [DllImport("user32.dll")]
            public static extern IntPtr SetWindowsHookEx(WH idHook, HOOKPROC lpfn, IntPtr hInstance, UIntPtr threadId);
    
            [DllImport("user32.dll")]
            public static extern bool UnhookWindowsHookEx(IntPtr hHook);
    
            [DllImport("user32.dll")]
            public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);
    
            public delegate IntPtr HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);
    
            public enum WH : int
            {
                WH_CBT = 5
    
            }
            public enum HCBT : int
            {
                HCBT_MOVESIZE = 0,
                HCBT_MINMAX = 1,
                HCBT_QS = 2,
                HCBT_CREATEWND = 3,
                HCBT_DESTROYWND = 4,
                HCBT_ACTIVATE = 5,
                HCBT_CLICKSKIPPED = 6,
                HCBT_KEYSKIPPED = 7,
                HCBT_SYSCOMMAND = 8,
                SHCBT_SETFOCUS = 9,
            }
    
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
            [StructLayout(LayoutKind.Sequential)]
            public struct WINDOWINFO
            {
                public uint cbSize;
                public RECT rcWindow;
                public RECT rcClient;
                public uint dwStyle;
                public uint dwExStyle;
                public uint dwWindowStatus;
                public uint cxWindowBorders;
                public uint cyWindowBorders;
                public ushort atomWindowType;
                public ushort wCreatorVersion;
            }
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);
    
            public static WINDOWINFO GetWindowInfo(IntPtr hwnd)
            {
                Win32.WINDOWINFO info = new Win32.WINDOWINFO();
                info.cbSize = (UInt32)(Marshal.SizeOf(typeof(Win32.WINDOWINFO)));
                GetWindowInfo(hwnd, ref info);
                return info;
            }
    
            [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
    
            [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
            static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
            public static string GetClassName(IntPtr hwnd)
            {
                StringBuilder sb = new StringBuilder(1000);
                GetClassName(hwnd, sb, 1000);
                return sb.ToString();
            }
    
            public enum WM
            {
                WM_CREATE = 0x1,
                WM_MOVE = 0x3,
                WM_SIZE = 0x5,
                WM_CLOSE = 0x10,
                WM_SHOWWINDOW = 0x18,
            }
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool IsWindowVisible(IntPtr hWnd);
        }
    
    
        [System.Runtime.InteropServices.ComImport]
        [System.Runtime.InteropServices.Guid("00000114-0000-0000-C000-000000000046")]
        [System.Runtime.InteropServices.InterfaceType(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
        interface IOleWindow
        {
            IntPtr GetWindow();
            void ContextSensitiveHelp([System.Runtime.InteropServices.In, System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fEnterMode);
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2019年8月14日 4:01
  • gekka様、本当にいつも有難うございます。
    理解して実装するのに時間がかかるとは思いますが、試してみます!
    2019年8月14日 5:17