c#.Excel外接程序.不能重新定位浮动自定义任务窗格

本文关键字:定位 自定义 任务 Excel 程序 不能 新定位 | 更新日期: 2023-09-27 18:04:12

当创建自定义任务窗格(_CustomTaskPane MSDN)并将其DockPosition设置为浮动时,我想指定出现窗口的TopLeft属性。由于Office COM api不提供这样做的直接可能性,人们建议更改命令栏的相应属性的值:

var application = (_Application)_nativeTaskPane.Application;
application.CommandBars["Task Pane Title"].Top = top;
application.CommandBars["Task Pane Title"].Left = left;
在上面的代码中,我假设

1) _nativeTaskPane是我的实例实现_CustomTaskPane(实际上它是Microsoft.Office.Core.CustomTaskPane)

2) _Application是Microsoft.Office.Interop.Excel._Application

当然,我是在设置Visible = true之后做的。甚至订阅了任务窗格的VisibleStateChange来更确定。然而,我得到一个COMException与HRESULT E_FAILED.

我可以读取这些属性(Top &左),但是设置它们会抛出异常。

看起来这个问题在网上至少出现了几次:

1) http://www.add-in-express.com/forum/read.php?FID=1& TID = 5595

2) [http://aritrasaha.wordpress.com/2009/05/19/programatically -职位-办公室- 2007 -浮-自定义-任务- pane/]

3) [http://www.visualstudiodev.com/visual工作室-工具- office/need位置- -自定义任务窗格- 45822. - shtml]

解决方法是使用Windows API。然而,有人能解释使用命令栏方法有什么问题吗?也许我可以"重新配置"smth,使这个Top/Left-setters工作,没有例外。

c#.Excel外接程序.不能重新定位浮动自定义任务窗格

这是我在我的程序中使用的解决方案:

    /// <summary>
    /// Set a custom panes position in the undocked state.
    /// </summary>
    /// <param name="customTaskPane">The custom task pane.</param>
    /// <param name="x">The new X position.</param>
    /// <param name="y">The new Y position.</param>
    private void SetCustomPanePositionWhenFloating(CustomTaskPane customTaskPane, int x, int y)
    {
        var oldDockPosition = customTaskPane.DockPosition;
        var oldVisibleState = customTaskPane.Visible;
        customTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionFloating;
        customTaskPane.Visible = true; //The task pane must be visible to set its position
        var window = FindWindowW("MsoCommandBar", customTaskPane.Title); //MLHIDE
        if (window == null) return;
        WinApi.MoveWindow(window, x, y, customTaskPane.Width, customTaskPane.Height, true);
        customTaskPane.Visible = oldVisibleState;
        customTaskPane.DockPosition = oldDockPosition;
    }
    [DllImport("user32.dll", EntryPoint = "FindWindowW")]
    public static extern System.IntPtr FindWindowW([System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string lpClassName, [System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string lpWindowName);
    [DllImport("user32.dll", EntryPoint = "MoveWindow")]
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
    public static extern bool MoveWindow([System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, int X, int Y, int nWidth, int nHeight, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool bRepaint);

    /// <summary>
    /// Set a custom panes size in the undocked state.
    /// </summary>
    /// <param name="customTaskPane">The custom task pane.</param>
    /// <param name="width">The new width.</param>
    /// <param name="height">The new height.</param>
    private void SetCustomPaneSizeWhenFloating(CustomTaskPane customTaskPane, int width, int height)
    {
        var oldDockPosition = customTaskPane.DockPosition;
        customTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionFloating;
        customTaskPane.Width = width;
        customTaskPane.Height = height;
        customTaskPane.DockPosition = oldDockPosition;
    }

请随意使用…: -)

问候,Jorg

它应该工作,并且有MVP Cindy Meister关于此错误的有趣评论(她在回答此论坛问题之前测试了它的工作)- http://social.msdn.microsoft.com/Forums/vstudio/en-US/2df0e430-4d93-416e-89a0-56f8ad5dc988/seting-position-of-a-floating-custome-task-pane?prof=required

在其中,她说使用错误的变量来获取应用程序对象会导致错误,即:

Globals.MyAddIn.Application -> this will ultimately cause an exception   
Globals.ThisAddin.Application -> this will ultimately work

假设两者返回相同的Application对象。

如果你认为这很奇怪,那么你是一个很好的公司。

我在这个问题上加了一条注释,问为什么用于访问Application对象的变量名会有什么不同——肯定是使用同一个Application对象。

我怀疑这是一些可怕的内部,反射一样的限制强加给其他内部。但是,无辜的开发人员并没有受到这种非常奇怪的情况的保护。

我认为一旦自定义窗格被设置为floating,你就不能通过定义改变它的顶部/左侧属性。你到底想达到什么目标?您想将窗格放置在特定位置上吗?如果是,请在将visible属性设置为true之前执行

您应该引用的命令栏是"任务窗格",它是命令栏集合中的标准命令栏。您得到了HRESULT消息,因为在CommandBars集合中没有找到"任务窗格标题"命令栏。