C#。Excel Addin。Can';t重新定位浮动自定义任务窗格
创建自定义任务窗格()并将其DockPosition设置为floating时,我想指定窗口的Top和Left属性。由于Office COM API不能直接实现这一点,因此人们建议更改CommandBar相应属性的值:C#。Excel Addin。Can';t重新定位浮动自定义任务窗格,c#,excel,add-in,excel-addins,customtaskpane,C#,Excel,Add In,Excel Addins,Customtaskpane,创建自定义任务窗格()并将其DockPosition设置为floating时,我想指定窗口的Top和Left属性。由于Office COM API不能直接实现这一点,因此人们建议更改CommandBar相应属性的值: var application = (_Application)_nativeTaskPane.Application; application.CommandBars["Task Pane Title"].Top = top; application.CommandBars["T
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) _应用程序是Microsoft.Office.Interop.Excel。_应用程序
当然,我是在设置Visible=true之后才这样做的。更确切地说,甚至订阅了任务窗格的VisibleStateChange。然而,我对HRESULT E_失败感到意外
问题是我可以在调试时读取这些属性(顶部和左侧),但是设置它们会引发异常
看起来这个问题在互联网上至少出现过几次:
(一)
(二)[http://aritrasaha.wordpress.com/2009/05/19/programatically-position-office-2007-floating-custom-task-pane/]
(三)[http://www.visualstudiodev.com/visual-studio-tools-for-office/need-location-of-custom-task-pane-45822.shtml]
解决方法是使用Windows API。然而,有人能解释一下使用CommandBar方法会有什么问题吗?也许我可以“重新配置”smth,使这个顶部/左侧设置器能够正常工作。我认为,一旦自定义窗格设置为浮动,您就无法根据定义更改其顶部/左侧属性。你到底想要实现什么?是否要将窗格定位到特定位置?如果是,请在将
visible
属性设置为true之前执行此操作,它应该可以工作,MVP Cindy Meister对此错误给出了有趣的评论(她在回答此论坛问题之前测试了它是否可以工作)——
在文章中,她说使用错误的变量获取应用程序对象会导致错误,即:
Globals.MyAddIn.Application -> this will ultimately cause an exception
Globals.ThisAddin.Application -> this will ultimately work
我们假设两者都返回相同的应用程序对象
如果你觉得这很奇怪,那你就有好朋友了
我在问题中添加了一条注释,询问为什么用于访问应用程序对象的变量的名称会有任何区别——当然,它是使用的同一个应用程序对象
我怀疑这是一些可怕的内部反射,类似于其他内部施加的限制。但是,无辜的开发人员并没有受到这种非常奇怪的情况的保护。这是我在程序中使用的解决方案:
/// <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;
}
//
///将自定义窗格位置设置为未锁定状态。
///
///自定义任务窗格。
///新的X位置。
///新的Y位置。
私有无效设置CustomPanePositionWhenfloating(CustomTaskPane CustomTaskPane,int x,int y)
{
var oldDockPosition=customTaskPane.DockPosition;
var oldVisibleState=customTaskPane.Visible;
customTaskPane.DockPosition=Microsoft.Office.Core.MsoCTPDockPosition.MsoCTPDockPosition浮动;
customTaskPane.Visible=true;//任务窗格必须可见才能设置其位置
var window=FindWindowW(“MsoCommandBar”,customTaskPane.Title);//MLHIDE
if(window==null)返回;
移动窗口(窗口,x,y,customTaskPane.Width,customTaskPane.Height,true);
customTaskPane.Visible=oldVisibleState;
customTaskPane.DockPosition=旧DockPosition;
}
[DllImport(“user32.dll”,EntryPoint=“FindWindowW”)]
public static extern System.IntPtr FindWindowW([System.Runtime.InteropServices.InAttribute()][System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]字符串lpClassName,[System.Runtime.InteropServices.InAttribute()][System.Runtime.InteropServices.MarshalAsAttribute](System.Runtime.InteropServices.UnmanagedType.LPWStr)]字符串(lpWindowName);
[DllImport(“user32.dll”,EntryPoint=“MoveWindow”)]
[返回:System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
公共静态外部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);
///
///在未固定状态下设置自定义窗格大小。
///
///自定义任务窗格。
///新的宽度。
///新高度。
私有void设置CustomPaneSizeWhenFloating(CustomTaskPane CustomTaskPane,整型宽度,整型高度)
{
var oldDockPosition=customTaskPane.DockPosition;
customTaskPane.DockPosition=Microsoft.Office.Core.MsoCTPDockPosition.MsoCTPDockPosition浮动;
customTaskPane.Width=宽度;
customTaskPane.Height=高度;
customTaskPane.DockPosition=旧DockPosition;
}
请随意使用它…:-)
问候,,
Jörg您应该参考的命令栏是“任务窗格”,它是命令栏集合中的标准命令栏。您收到HRESULT消息是因为在CommandBars集合中找不到“任务窗格标题”CommandBar 此外,您提供的“变通”链接不适用于多个监视器。在我的机器上,只要将窗口移动到给定的坐标,它就会显示在显示器上,而我的office程序甚至没有显示