C#。 Excel 插件。无法重新定位浮动自定义任务窗格

发布于 2024-11-27 22:42:26 字数 1396 浏览 1 评论 0 原文

创建自定义任务窗格 (_CustomTaskPane MSDN) 并设置其 DockPosition为浮动,我想指定出现的窗口的TopLeft属性。由于 Office COM API 不提供直接执行此操作的可能性,因此人们建议更改 CommandBar 相应属性的值:

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 。但是我收到了带有 HRESULT E_FAILED 的 COMException。

问题是我可以在调试时读取这些属性(顶部和左侧),但是设置它们会引发异常。

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

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

2) [http://aritrasaha.wordpress.com/2009/05/19/programatically-position-office-2007-floating-custom-task-pane/]

3) [http://www.visualstudiodev.com/visual-studio -tools-for-office/need-location-of-custom-task-pane-45822.shtml]

解决方法是使用 Windows API。但是,任何人都可以解释使用 CommandBar 方法可能会出现什么问题吗?也许我可以“重新配置”,让这个上/左二传手毫无例外地工作。

When creating a custom task pane (_CustomTaskPane MSDN) and setting its DockPosition to floating, I want to specify the Top and Left properties of the window appeared. As Office COM APIs do not provide direct possibility to do this, people advise to alter the values of corresponding properties of CommandBar:

var application = (_Application)_nativeTaskPane.Application;
application.CommandBars["Task Pane Title"].Top = top;
application.CommandBars["Task Pane Title"].Left = left;

In the code above I assume that

1) _nativeTaskPane is my instance implementing _CustomTaskPane (actually it is Microsoft.Office.Core.CustomTaskPane)

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

Of course, I'm doing it after setting Visible = true. Even subscribed to task pane's VisibleStateChange to be more sure. However I'm getting a COMException with the HRESULT E_FAILED.

The thing is I can read these properties (Top & Left) when debugging, however setting them throws exception.

Looks like the issue popped up in the internet at least several times:

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

2) [http://aritrasaha.wordpress.com/2009/05/19/programatically-position-office-2007-floating-custom-task-pane/]

3) [http://www.visualstudiodev.com/visual-studio-tools-for-office/need-location-of-custom-task-pane-45822.shtml]

The workaround is using Windows API. However, can anyone explain what can be wrong with using CommandBar-approach? Maybe I can "reconfigure" smth for this Top/Left-setters to work without exceptions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

嘴硬脾气大 2024-12-04 22:42:26

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

    /// <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;
    }

请随意使用它...:-)

问候,
约尔格

this is the solution I use in my programs:

    /// <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;
    }

Feel free to use it... :-)

Regards,
Jörg

离不开的别离 2024-12-04 22:42:26

它应该可以工作,并且 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 对象。

我怀疑这是由其他一些内部因素强加的一些可怕的内部的、类似于反射的限制。但无辜的开发者并没有受到保护,免受这种非常奇怪的情况的影响。

It should work and there is an interesting comment by MVP Cindy Meister regarding this error here (she tested that it works before answering this forum question) - http://social.msdn.microsoft.com/Forums/vstudio/en-US/2df0e430-4d93-416e-89a0-56f8ad5dc988/seting-position-of-a-floating-custome-task-pane?prof=required

In it, she says that using the wrong variable to get the application object causes the error ie:

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

Where we assume that both return the same Application object.

If you think that's bizarre, then you're in good company.

I've added a comment to the question that asks why would the name of the variable used to access the Application object make any difference - surely it's the same Application object being used.

I suspect it's some scary internal, reflection-like limitation imposed by some other internals. But that the innocent developer is not protected from this very odd scenario.

献世佛 2024-12-04 22:42:26

我认为一旦自定义窗格设置为浮动,您就无法根据定义更改其顶部/左侧属性。你到底想达到什么目的?您想将窗格放置在特定位置吗?如果是,请在将 visible 属性设置为 true 之前执行此操作

I think that once a custom pane is set to floating you can't change its top/left properties by definition. what exactly do you want to achieve? do you want to position the pane on specific position? if yes, do it before you set the visibleproperty to true

恬淡成诗 2024-12-04 22:42:26

您应该引用的命令栏是“任务窗格”,它是 CommandBars 集合中的标准 CommandBar。您收到 HRESULT 消息是因为在 CommandBars 集合中找不到“任务窗格标题”CommandBar。

The Commandbar you should be referencing is "Task Pane" which is a standard CommandBar in the CommandBars collection. You got the HRESULT message because the "Task Pane Title" CommandBar was not found in the CommandBars collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文