public bool IsCommandSupported(Guid commandGuid, uint commandId, out uint flags) { flags = 0; OLECMD[] cmd = new OLECMD[1]; cmd[0].cmdID = commandId; OLECMDTEXT commandText = new OLECMDTEXT(); int hr; GCHandle handle = GCHandle.Alloc(commandText, GCHandleType.Pinned); try { hr = target.QueryStatus(ref commandGuid, 1, cmd, handle.AddrOfPinnedObject()); } finally { handle.Free(); } if ((int)OleConstants.OLECMDERR_E_NOTSUPPORTED == hr) { return(false); } Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr); flags = cmd[0].cmdf; return(0 != (flags & (uint)OLECMDF.OLECMDF_SUPPORTED)); }
public void SetOleCmdText(IntPtr pCmdText, string text) { OLECMDTEXT CmdText = (OLECMDTEXT)Marshal.PtrToStructure(pCmdText, typeof(OLECMDTEXT)); char[] buffer = text.ToCharArray(); IntPtr pText = (IntPtr)((long)pCmdText + (long)Marshal.OffsetOf(typeof(OLECMDTEXT), "rgwz")); IntPtr pCwActual = (IntPtr)((long)pCmdText + (long)Marshal.OffsetOf(typeof(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 = (int)Math.Min(CmdText.cwBuf - 1, buffer.Length); Marshal.Copy(buffer, 0, pText, maxChars); // append a null Marshal.WriteInt16((IntPtr)((long)pText + (long)maxChars * 2), (Int16)0); // write out the length + null char Marshal.WriteInt32(pCwActual, maxChars + 1); }
public void SetOleCmdText(IntPtr pCmdText, string text) { // taken from https://social.msdn.microsoft.com/Forums/vstudio/en-US/e8c9418f-99a8-41d7-bb85-a7db15664abf/how-to-change-menu-controllers-text-dynamically?forum=vsx OLECMDTEXT CmdText = (OLECMDTEXT)Marshal.PtrToStructure(pCmdText, typeof(OLECMDTEXT)); char[] buffer = text.ToCharArray(); IntPtr pText = (IntPtr)((long)pCmdText + (long)Marshal.OffsetOf(typeof(OLECMDTEXT), "rgwz")); IntPtr pCwActual = (IntPtr)((long)pCmdText + (long)Marshal.OffsetOf(typeof(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 = (int)Math.Min(CmdText.cwBuf - 1, buffer.Length); Marshal.Copy(buffer, 0, pText, maxChars); // append a null Marshal.WriteInt16((IntPtr)((long)pText + (long)maxChars * 2), (Int16)0); // write out the length + null char Marshal.WriteInt32(pCwActual, maxChars + 1); }
// From https://github.com/tunnelvisionlabs/InheritanceMargin/blob/master/Tvl.VisualStudio.InheritanceMargin/CommandTranslation/CommandRouter.cs#L108 private static string GetCommandText(IntPtr structPtr) { if (structPtr == IntPtr.Zero) { return(string.Empty); } OLECMDTEXT olecmdtext = (OLECMDTEXT)Marshal.PtrToStructure(structPtr, typeof(OLECMDTEXT)); if (olecmdtext.cwActual == 0) { return(string.Empty); } IntPtr offset = Marshal.OffsetOf(typeof(OLECMDTEXT), "rgwz"); IntPtr ptr = (IntPtr)((long)structPtr + (long)offset); return(Marshal.PtrToStringUni(ptr, (int)olecmdtext.cwActual - 1)); }
// From https://github.com/tunnelvisionlabs/InheritanceMargin/blob/master/Tvl.VisualStudio.InheritanceMargin/CommandTranslation/CommandRouter.cs#L122 private static void SetCommandText(IntPtr pCmdTextInt, string text) { if (text != null) { OLECMDTEXT olecmdtext = (OLECMDTEXT)Marshal.PtrToStructure(pCmdTextInt, typeof(OLECMDTEXT)); if ((olecmdtext.cmdtextf & (uint)OLECMDTEXTF.OLECMDTEXTF_NAME) == 0) { return; } var source = text.ToCharArray(); var bufferOffset = Marshal.OffsetOf(typeof(OLECMDTEXT), "rgwz"); var lengthOffset = Marshal.OffsetOf(typeof(OLECMDTEXT), "cwActual"); var length = Math.Min(((int)olecmdtext.cwBuf) - 1, source.Length); // copy the new text var bufferAddress = (long)pCmdTextInt + (long)bufferOffset; Marshal.Copy(source, 0, (IntPtr)bufferAddress, length); // null terminator Marshal.WriteInt16(pCmdTextInt, (int)bufferOffset + length * 2, 0); // length including null terminator Marshal.WriteInt32(pCmdTextInt, (int)lengthOffset, length + 1); } }
public bool IsCommandSupported(Guid commandGuid, uint commandId, out uint flags) { flags = 0; OLECMD[] cmd = new OLECMD[1]; cmd[0].cmdID = commandId; OLECMDTEXT commandText = new OLECMDTEXT(); int hr; GCHandle handle = GCHandle.Alloc(commandText, GCHandleType.Pinned); try { hr = target.QueryStatus(ref commandGuid, 1, cmd, handle.AddrOfPinnedObject()); } finally { handle.Free(); } if ((int)OleConstants.OLECMDERR_E_NOTSUPPORTED == hr) { return false; } Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr); flags = cmd[0].cmdf; return (0 != (flags & (uint)OLECMDF.OLECMDF_SUPPORTED)); }
int IOleCommandTarget.QueryStatus(ref Guid guidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) { Debug.Assert(cCmds == 1, "Multiple commands"); Debug.Assert(prgCmds != null, "NULL argument"); if ((prgCmds == null)) { return(VSConstants.E_INVALIDARG); } // Filter out commands that are not defined by this package if (guidCmdGroup != GuidList.guidSccProviderCmdSet) { return((int)(Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED)); } OLECMDF cmdf = OLECMDF.OLECMDF_SUPPORTED; // All source control commands needs to be hidden and disabled when the provider is not active if (!sccService.Active) { cmdf = cmdf | OLECMDF.OLECMDF_INVISIBLE; cmdf = cmdf & ~(OLECMDF.OLECMDF_ENABLED); prgCmds[0].cmdf = (uint)cmdf; return(VSConstants.S_OK); } // Call hook to query additional commands first. var result = Blinkbox.Events.BlinkboxSccHooks.QueryCommandStatus(guidCmdGroup, prgCmds, cmdf, pCmdText); if (result != (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED) { // Handled in the hook return(result); } // Process our Commands switch (prgCmds[0].cmdID) { case CommandId.imnuGitSourceControlMenu: OLECMDTEXT cmdtxtStructure = (OLECMDTEXT)Marshal.PtrToStructure(pCmdText, typeof(OLECMDTEXT)); if (cmdtxtStructure.cmdtextf == (uint)OLECMDTEXTF.OLECMDTEXTF_NAME) { var branchName = sccService.CurrentBranchName; string menuText = string.IsNullOrEmpty(branchName) ? "Git" : "Git (" + branchName + ")"; SetOleCmdText(pCmdText, menuText); } break; case CommandId.icmdSccCommandGitBash: if (GitBash.Exists) { cmdf |= OLECMDF.OLECMDF_ENABLED; } break; case CommandId.icmdSccCommandGitExtension: var gitExtensionPath = GitSccOptions.Current.GitExtensionPath; if (!string.IsNullOrEmpty(gitExtensionPath) && File.Exists(gitExtensionPath) && GitSccOptions.Current.NotExpandGitExtensions) { cmdf |= OLECMDF.OLECMDF_ENABLED; } else { cmdf |= OLECMDF.OLECMDF_INVISIBLE; } break; case CommandId.icmdSccCommandGitTortoise: var tortoiseGitPath = GitSccOptions.Current.TortoiseGitPath; if (!string.IsNullOrEmpty(tortoiseGitPath) && File.Exists(tortoiseGitPath) && GitSccOptions.Current.NotExpandTortoiseGit) { cmdf |= OLECMDF.OLECMDF_ENABLED; } else { cmdf |= OLECMDF.OLECMDF_INVISIBLE; } break; case CommandId.icmdSccCommandUndo: case CommandId.icmdSccCommandCompare: if (GitBash.Exists && sccService.CanCompareSelectedFile) { cmdf |= OLECMDF.OLECMDF_ENABLED; } break; case CommandId.icmdSccCommandEditIgnore: if (sccService.IsSolutionGitControlled) { cmdf |= OLECMDF.OLECMDF_ENABLED; } break; case CommandId.icmdSccCommandHistory: case CommandId.icmdSccCommandPendingChanges: case CommandId.icmdPendingChangesAmend: case CommandId.icmdPendingChangesCommit: case CommandId.icmdPendingChangesCommitToBranch: if (GitBash.Exists && sccService.IsSolutionGitControlled) { cmdf |= OLECMDF.OLECMDF_ENABLED; } break; case CommandId.icmdSccCommandAbout: case CommandId.icmdSccCommandRefresh: //if (sccService.IsSolutionGitControlled) cmdf |= OLECMDF.OLECMDF_ENABLED; break; case CommandId.icmdSccCommandInit: if (!sccService.IsSolutionGitControlled) { cmdf |= OLECMDF.OLECMDF_ENABLED; } else { cmdf |= OLECMDF.OLECMDF_INVISIBLE; } break; default: var gitExtPath = GitSccOptions.Current.GitExtensionPath; var torGitPath = GitSccOptions.Current.TortoiseGitPath; if (prgCmds[0].cmdID >= CommandId.icmdGitExtCommand1 && prgCmds[0].cmdID < CommandId.icmdGitExtCommand1 + GitToolCommands.GitExtCommands.Count && !string.IsNullOrEmpty(gitExtPath) && File.Exists(gitExtPath) && !GitSccOptions.Current.NotExpandGitExtensions) { int idx = (int)prgCmds[0].cmdID - CommandId.icmdGitExtCommand1; SetOleCmdText(pCmdText, GitToolCommands.GitExtCommands[idx].Name); cmdf |= OLECMDF.OLECMDF_ENABLED; break; } else if (prgCmds[0].cmdID >= CommandId.icmdGitTorCommand1 && prgCmds[0].cmdID < CommandId.icmdGitTorCommand1 + GitToolCommands.GitTorCommands.Count && !string.IsNullOrEmpty(torGitPath) && File.Exists(torGitPath) && !GitSccOptions.Current.NotExpandTortoiseGit) { int idx = (int)prgCmds[0].cmdID - CommandId.icmdGitTorCommand1; SetOleCmdText(pCmdText, GitToolCommands.GitTorCommands[idx].Name); cmdf |= OLECMDF.OLECMDF_ENABLED; break; } else { return((int)(Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED)); } } prgCmds[0].cmdf = (uint)(cmdf); return(VSConstants.S_OK); }
void IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, ref OLECMDTEXT cmdText) { throw new NotImplementedException("The method or operation is not implemented."); }