I have a CommandBarControl and on the click of this control, I want to get a number as user input.
private void oControlHandler_Click(object CommandBarControl, ref bool Handled, ref bool CancelDefault)
{
//get a number as user input
//do some work on input
}
How to get user input?
I am using VS 2013 and .NET framework 4.0.
You need to create a Windows Forms (or WPF) form with a control to enter the input, which can be a TextBox or some kind of NumericUpDown. Then, on the Click event you show the form modally (ShowDialog). Notice that your question is not related to Visual Studio add-ins.
Related
I work on an Outlook 2016 add-in (C# visual studio 2017 on Windows 10).
The add-in do its job perfectly when a new message is created and then sent from the "Write new message" window launched from the Outlook main menu (or toolbar) : the add-in displays its own ribbon with some radiobuttons to configure the message to be sent and that's all.
But when a new message window is created from the Windows contextual menu "Send to" on a file (to be sent as an attachement), the add-in is ignored : the radio buttons, even if they trigger their respective callbacks and so configure the underlying model, let the new message unchanged :-(
The main difference observed under debugger is :
from the outlook menu : the "ThisAddIn" class seems to retrieve a wrapper for the new message window and so the configuration is taken into account when the message is sent :-)
from the Windows contextual menu : only a "GetCustomUI" callback is triggered and so the message is sent unchanged when the "Send" button is clicked :-(
Any help (examples, documentation, howto, ...) appreciated ...
JF
Not all event handlers are triggered when users try to send files using the context menu Send To.
If the GetCustomUI is triggered when a user sends files from a folder (using a context menu) you can add a custom ribbon UI with your radio buttons to configure the message to be sent. I suppose that is all what your add-in does.
You just need to use Ribbon XML to create a custom UI and use the GetCustomUI function to return it back. Read more about that in the Walkthrough: Create a custom tab by using Ribbon XML article.
In the ribbon event handlers you need to make sure you get access to the item through the Context passed as an argument. For example, the onAction callback has the following signature:
C#: void OnAction(IRibbonControl control)
VBA: Sub OnAction(control As IRibbonControl)
C++: HRESULT OnAction([in] IRibbonControl *pControl)
Visual Basic: Sub OnAction(control As IRibbonControl)
The IRibbonControl interface instance provides the Context property which represents the active window containing the Ribbon user interface that triggers a callback procedure. So, you may cast it to the Inspector or Explorer for retrieving the actual mail item you have to deal with.
I am trying to automate button presses for a desktop application on Windows 7 - 10. I have been able to do this using AutoHotKey and PowerShell. However, I have had the following issues:
The controls I am trying to click do not have text that I can use to
isolate the control
The ClassNN name for the components is not
static
I have looked through the MSDN documentation for the System.Windows.Automation namespace, but the documentation doesn't provide actual examples or describe how to use the namespace.
Question
If I always have a window handle (HWND) and an Automation ID for a control, how do I invoke a button press on the control using AutoHotKey, PowerShell(3.0+), or C#?
You can do it with C# and System.Windows.Automation.
First of all get your control as an AutomationElement (let's call it thiselement).
Then you can invoke InvokePattern to perform click action.
InvokePattern ip;
ip = thiselement.GetCurrentPattern(InvokePattern.Pattern) as
InvokePattern;
ip.Invoke();
Suppose your window handle is 'handle' and automation id of the button is 'automationId' then you can do something like
AutomationElement parentWin = AutomationElement.FromHandle(handle);
Condition c1 = new PropertyCondition(AutomationElement.AutomationIdProperty,
automationId);
AutomationElement thiselement = parentWin.FindFirst(TreeScope.Descendants, c1);
once you get the button object,just invoke the InvokePattern .Please forgive the foramatting of text
I am writing an extension to Visual studio 2012 using VSPackage. I need to add a context menu entry to Test Explorer and on click of this menu item, I need to get the selected unit test(s). I tried to add an item using
((CommandBars)DTE.CommandBars)["Test Window Context Menu"].Controls.Add(Type: MsoControlType.msoControlButton);
and adding an event handler by subscribing to the event
DTE.Events.CommandBarEvents[command].Click
I succeeded in adding an item to Context menu but the Click event handler never gets fired. MSDN said, I needed to set the OnAction property of the command to a valid string value for the Click event handler to get fired. It didn't work either.
Then, I figured out I needed to add a command through the VSCT file in a VSPackage. However, I am not able to find the Test Window Context menu so that I can attach the command to it. Also, I need to get all the unit tests (TestCase objects) listed in the Test Explorer.
Any help is greatly appreciated!
Usually these are the files I look for Visual Studio shell GUIDs or command, context menu, group, etc IDs:
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\stdidcmd.h
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\vsshlids.h
Actually they are included in the top of your newly created .vsct file (<Extern href="vsshlids.h" />). I guess you've already checked them. I did a quick search, but what I found for "Test" is just a test ribbon and a test dialog. Probably now that you're looking for. It might be still useful for someone finding this post.
You might also want try it brute force style:
Search your Program Files (x86)\Visual Studio [VERSION] for regexp: ^#define.*TEST.*$
This shall give you the defines containing TEST.
Also you might want to consider asking Microsoft directly.
I wrote some exploratory code to loop over commands in that context menu. I also played around with registering a priority command target and seeing what group GUID and command ID I got. The GUID for that context menu appears to be {1e198c22-5980-4e7e-92f3-f73168d1fb63}. You can probably use that to add a command via the .vsct file without using the DTE.CommandBars to add it dynamically.
Here's my experiment code which lists the GUID and command ID of the commands currently in that context menu, in case it helps anyone.
var bars = ((Microsoft.VisualStudio.CommandBars.CommandBars)DTE.CommandBars);
var teContextMenu = bars["Test Window Context Menu"];
var ctls = teContextMenu.Controls;
foreach (var ctl in ctls)
{
var cmdCtl = ctl as Microsoft.VisualStudio.CommandBars.CommandBarControl;
string guid; int id;
DTE.Commands.CommandInfo(ctl, out guid, out id);
Debug.WriteLine($"{cmdCtl?.accName} {guid} {id}");
}
This article on command routing was helpful to me:
https://learn.microsoft.com/en-us/visualstudio/extensibility/internals/command-routing-algorithm
My experimental priority command target, where I set a breakpoint to see what GUID and command IDs were sent, is registered as follows. The TestCommandInterceptor class is a bare-bones implementation of IOleCommandTarget.
var cmdService = GetService(typeof(SVsRegisterPriorityCommandTarget)) as IVsRegisterPriorityCommandTarget;
var target = new TestCommandInterceptor();
cmdService.RegisterPriorityCommandTarget(0, target, out _testCmdInterceptorRegistrationCookie);
I would still like to know the answer to the second part of this question about how to determine the selected tests.
I've just built an MS Outlook Add In using Visual Studio and Office 2010. I've installed it ok on 4 machines, but one user is getting the following error -
Error found in Custom UI XML of "...."
...
...
Failed to find Office control by ID
Everyone is running Windows 7 and Outlook 2010 - not sure why this person is having a problem. Can anyone suggest how to diagnose this?
For those having similar issues, you don't have to remove any add-in.
What is happening is: Outlook will try to load all ribbons (found in your ribbon xml) into any window the user goes to. Then it'll complain about not finding ID x or y.
Just make sure your GetCustomUI method in Ribbon.cs does not load the entire ribbon XML at once but rather loads it per fragment.
If you're not sure what IDs you need to target, use a breakpoint in GetCustomUI then start Outlook, surf different views (main, new email, new appointment, calendar...etc) in order to gather the IDs for the views wherein you need to show you add-in.
In my case, I needed Microsoft.Outlook.Explorer, Microsoft.Outlook.Mail.Compose and Microsoft.Outlook.Appointment.
Therefore I changed my GetCustomUI to:
public string GetCustomUI(string ribbonID)
{
switch (ribbonID)
{
case "Microsoft.Outlook.Explorer":
return GetResourceText("MyAddin.RibbonsForOutlookExplorer.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("MyAddin.RibbonForOutlookMailCompose.xml");
case "Microsoft.Outlook.Appointment":
return GetResourceText("MyAddin.RibbonForOutlookAppointment.xml");
default:
return null;
}
}
Of course, I had to break down my Ribbon.xml into the three XML files mentioned above. The result: Outlook will ONLY load the fragment needed for a given screen (appointment, new email ...) and will not complain about "not finding an ID on screen X or Y".
Finally, for those who are not sure why some users get that error while others don't: it's because of "Show add-in user interface errors" option (in Options -> Advanced). If that is unchecked then Outlook will ignore the malformed ribbon XML errors. If it checked, users will get related errors about your add-in (if any exists) and also about other add-ins.
If it works for everyone except one user. As #Brijesh Mishra mentioned check if the user has got any other addin and if he is having own quick access tool bar customized.
If he has got any of this then, remove the other addins and try to install or reset the quick access tool bar customization.
For all of you that use a Designer-based VSTO plugin, and not the XML solution.
I searched all the web for this problem, but only found XML-based solutions.
There's nothing for Visual Designer on the web, because in this case you don't have to override the "GetCustomUI" method.
Ribbons designed by using the Visual Designer return a RibbonManager by default.
This RibbonManager object represents all Ribbon (Visual Designer) items in the project and is automatically handled in background through the active window inspector.
So you don't have to write any special code to handle different windows.
To configure it correctly you just have to:
Add one extra Visual Designer Ribbon for every window the user goes to
in the Ribbon Object go under "RibbonType", open the checkbox list an only activate the corresponding window, where the ribbon should appear.
If there is more than one window checked in the list, Outlook trys to insert the ribbon in all the marked windows. Even if the corresponding window is currently not opened. That's the reason, why the error "Failed to find control ID" appears.
the actual fix for me was to separate the ribbon XML files containing the customUI and redirecting to the correct one in the GetCustomUI method (implemented using Office.IRibbonExtensibility)
in example:
public string GetCustomUI(string RibbonID)
{
switch (RibbonID)
{
case "Microsoft.Outlook.Mail.Read":
return GetResourceText("namespace.type1.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("namespace.type2.xml");
default:
return null;
}
}
I used the VS 2010 SDK to create and show a custom ToolWindowPane with a WPF control as content. I create a new instance and show it each time a Tool menu item is clicked (the ProvideToolWindow attribute has MultiInstances = true).
When the user attaches the debugger (e.g., hits F5 while in C# project) my ToolWindowPane suddenly hides. I'd like to make sure my tool window is always visible while open, no matter what context the user is in. Is there a way I can enforce that?
I've tried using the ProvideToolWindowVisibility attribute but that automatically shows a new instance of my tool window rather than keeping a remaining one open.
For VS 2010 SDK Microsoft added a new flag __VSCREATETOOLWIN2.CTW_fDocumentLikeTool
You can use this way:
public override void OnToolWindowCreated()
{
IVsWindowFrame windowFrame = Frame as IVsWindowFrame;
object varFlags;
windowFrame.GetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, out varFlags);
int flags = (int)varFlags | (int)__VSCREATETOOLWIN2.CTW_fDocumentLikeTool;
windowFrame.SetProperty((int)__VSFPROPID.VSFPROPID_CreateToolWinFlags, flags);
}
This way Tool Window persist open at "Document Well" when you go Debugging
However I have to say this give us some problems when debugging projects, avoiding us to open code files while debugging, like if Visual Studio document management was 'block', there are not so much information for this new flag...
So we preferred to hook to EnvDTE.DebuggerEvents and show the ToolWindow if hide when a debugging session start...
(our ToolWindow has MultiInstances = false)
Implement QueryShowTool
public:
int QueryShowTool(Guid % rguidPersistenceSlot, System::UInt32 dwId, [Runtime::InteropServices::Out] int % pfShowTool);
Enables the VSPackage to control whether to show or hide the tool
window. The shell calls this method when the user switches views or
contexts, for example Design, Debugging, Full Screen.
See https://learn.microsoft.com/en-us/visualstudio/extensibility/opening-a-dynamic-tool-window?view=vs-2017