gpt4 book ai didi

visual-studio-extensions - 如何更新 VS 包内 DynamicItemStart 按钮的内容

转载 作者:行者123 更新时间:2023-12-02 01:52:25 27 4
gpt4 key购买 nike

我正在做一个 VS 包,它在菜单中有一个 DynamicItemStart 按钮。我在 VS 启动时加载动态按钮的内容没有任何问题,但我试图在某些事件(例如打开项目)之后向其内容添加更多命令。我将新命令添加到此“占位符”按钮,但看不到 Visual Studio UI 已更新。我试过 UpdateUI 命令:

Microsoft.VisualStudio.Shell.ServiceProvider serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(((DTE)Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(DTE))) as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
IVsUIShell uiShell = serviceProvider.GetService(typeof(SVsUIShell)) as IVsUIShell;
uiShell.UpdateCommandUI(1);

我在 Button 的 BeforeQueryStatus 事件中调用此代码,但这不起作用。有没有人取得过类似的成就?

非常感谢任何提示。

编辑 1:这是我用来添加新命令的代码

private void InitMRUMenu(ref OleMenuCommandService mcs)
{
InitializeMRUList();
if (_connectionsList != null)
{
int i = 0;
foreach (var conn in _connectionsList)
{
var cmdID = new CommandID(GuidList.guidAdvancedVSCTSampleCmdSet, this.baseMRUID + i);
var mc = new OleMenuCommand(new EventHandler(OnMRUExec), cmdID);
mruList.Add(conn.DisplayName);
mc.BeforeQueryStatus += new EventHandler(OnMRUQueryStatus);
mcs.AddCommand(mc);
i++;
}
}
}

private void OnMRUQueryStatus(object sender, EventArgs e)
{
OleMenuCommand menuCommand = sender as OleMenuCommand;
if (null != menuCommand)
{
int MRUItemIndex = menuCommand.CommandID.ID - this.baseMRUID;
if (MRUItemIndex >= 0 && MRUItemIndex < this.mruList.Count)
{
menuCommand.Text = this.mruList[MRUItemIndex] as string;
}
}
}

private void OnMRUExec(object sender, EventArgs e)
{
//Do some actions
}

最佳答案

您需要在 IOleCommandTarget.QueryStatus 的实现中添加一些代码,像这样(在 C# 中):

int IOleCommandTarget.QueryStatus(ref Guid cmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
if (cmdGroup == yourCommandSet)
{
if (prgCmds[0].cmdID >= yourDynamicId && prgCmds[0].cmdID < (yourDynamicId + 16)) // suppose you want a maximum of 16 dynamic items
{
int index = (int)prgCmds[0].cmdID - yourDynamicId;

OLECMDTEXT.OLECMDTEXTF flags = OLECMDTEXT.GetFlags(pCmdText);
if (flags == OLECMDTEXT.OLECMDTEXTF.OLECMDTEXTF_NAME)
{
OLECMDTEXT.SetText(pCmdText, "yourText" + index);
}

prgCmds[0].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED); // for example
}
}
}

当然,关联IOleCommandTarget.Exec也必须修改以对应(使用相同的计算索引)。

OLECMDTEXT 是一个非常 hacky 的实用程序类,可以在互联网上的各个地方找到,这里是:

/// <devdoc>
/// Helper class for setting the text parameters to OLECMDTEXT structures.
/// </devdoc>
internal static class OLECMDTEXT
{
/// <summary>
/// Flags for the OLE command text
/// </summary>
public enum OLECMDTEXTF
{
/// <summary>No flag</summary>
OLECMDTEXTF_NONE = 0,
/// <summary>The name of the command is required.</summary>
OLECMDTEXTF_NAME = 1,
/// <summary>A description of the status is required.</summary>
OLECMDTEXTF_STATUS = 2
}

/// <summary>
/// Gets the flags of the OLECMDTEXT structure
/// </summary>
/// <param name="pCmdTextInt">The structure to read.</param>
/// <returns>The value of the flags.</returns>
public static OLECMDTEXTF GetFlags(IntPtr pCmdTextInt)
{
if (pCmdTextInt == IntPtr.Zero)
return OLECMDTEXTF.OLECMDTEXTF_NONE;

Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT pCmdText = (Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT)Marshal.PtrToStructure(pCmdTextInt, typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT));

if ((pCmdText.cmdtextf & (int)OLECMDTEXTF.OLECMDTEXTF_NAME) != 0)
return OLECMDTEXTF.OLECMDTEXTF_NAME;

if ((pCmdText.cmdtextf & (int)OLECMDTEXTF.OLECMDTEXTF_STATUS) != 0)
return OLECMDTEXTF.OLECMDTEXTF_STATUS;

return OLECMDTEXTF.OLECMDTEXTF_NONE;
}

/// <devdoc>
/// Accessing the text of this structure is very cumbersome. Instead, you may
/// use this method to access an integer pointer of the structure.
/// Passing integer versions of this structure is needed because there is no
/// way to tell the common language runtime that there is extra data at the end of the structure.
/// </devdoc>
public static string GetText(IntPtr pCmdTextInt)
{
Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT pCmdText = (Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT)Marshal.PtrToStructure(pCmdTextInt, typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT));

// Get the offset to the rgsz param.
IntPtr offset = Marshal.OffsetOf(typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT), "rgwz");

// Punt early if there is no text in the structure.
if (pCmdText.cwActual == 0)
return String.Empty;

char[] text = new char[pCmdText.cwActual - 1];
Marshal.Copy((IntPtr)((long)pCmdTextInt + (long)offset), text, 0, text.Length);
StringBuilder s = new StringBuilder(text.Length);
s.Append(text);
return s.ToString();
}

/// <include file='doc\NativeMethods.uex' path='docs/doc[@for="OLECMDTEXTF.SetText"]/*' />
/// <devdoc>
/// Accessing the text of this structure is very cumbersome. Instead, you may
/// use this method to access an integer pointer of the structure.
/// Passing integer versions of this structure is needed because there is no
/// way to tell the common language runtime that there is extra data at the end of the structure.
/// </devdoc>
/// <summary>
/// Sets the text inside the structure starting from an integer pointer.
/// </summary>
/// <param name="pCmdTextInt">The integer pointer to the position where to set the text.</param>
/// <param name="text">The text to set.</param>
public static void SetText(IntPtr pCmdTextInt, string text)
{
Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT pCmdText = (Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT)Marshal.PtrToStructure(pCmdTextInt, typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT));
char[] menuText = text.ToCharArray();

// Get the offset to the rgsz param. This is where we will stuff our text
IntPtr offset = Marshal.OffsetOf(typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT), "rgwz");
IntPtr offsetToCwActual = Marshal.OffsetOf(typeof(Microsoft.VisualStudio.OLE.Interop.OLECMDTEXT), "cwActual");

// The max chars we copy is our string, or one less than the buffer size,
// since we need a null at the end.
int maxChars = Math.Min((int)pCmdText.cwBuf - 1, menuText.Length);

Marshal.Copy(menuText, 0, (IntPtr)((long)pCmdTextInt + (long)offset), maxChars);

// append a null character
Marshal.WriteInt16((IntPtr)((long)pCmdTextInt + (long)offset + maxChars * 2), 0);

// write out the length +1 for the null char
Marshal.WriteInt32((IntPtr)((long)pCmdTextInt + (long)offsetToCwActual), maxChars + 1);
}
}

关于visual-studio-extensions - 如何更新 VS 包内 DynamicItemStart 按钮的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21963323/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com