VSTO-Excel Custom Task Pane AutoResize based on Screen Resolution - excel

I have a problem with my VSTO addin for excel.
I tried creating custom task pane fot my addin. However, when I tried to deploy it on a screen with different resolution from the developer's monitor, the addin does not automatically fits the screen. Note: my clients have different screen resolution.
On my vsto project, i tried to create a custom user control, and attach it on the excel pane.
Please see my code below:
private void btnDownload_Click(object sender, RibbonControlEventArgs e)
{
taskPaneView = new ucCusipAddPanel();
if (myTaskPane == null)
{
myTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(taskPaneView, "My Custom Task Pane");
myTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight;
myTaskPane.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
myTaskPane.Visible = true;
myTaskPane.Width = 303;
}
else
{
myTaskPane.Visible = true;
taskPaneView.BringToFront();
taskPaneView.Focus();
}
}
ucCusipAddPanel is the name of my user control.
This is how invoke my custom taskpane upon ribbon button click. I already set the AutoSize property to true of my user control however still the problem exists.
How could I resolve this?
Thank you in advance.

You need to play with the AutoScaleMode of the myTaskPane object.
I think the correct solution is to use: myTaskPane.AutoScaleMode = AutoScaleMode.Dpi;
see MSDN

Related

VS 2012 Start UI Windows from VSPackage

i've started to work with the VS2012 extensibility possibilities. I did the first few Walkthroughs and now I'm trying get further on. What I'm trying is pretty easy I guess... I'm trying to build a simply vspackage which starts an UI window. Actually i do not find any howto or sample code.
Do you have some links with further information about doing something like that ?
Thanks for you help..
Iki
You can find initial information here.
Here is my code for menu item:
/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
/// where you can put all the initialization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
Debug.WriteLine ("Entering Initialize() of: {0}", this);
base.Initialize();
// Add our command handlers for menu (commands must exist in the .vsct file)
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if ( null != mcs )
{
// Create the command for the menu item.
CommandID menuCommandID = new CommandID(GuidList.guidPackageProject, (int)PkgCmdIDList.Impl);
OleMenuCommand menuItem = new OleMenuCommand(MenuItemCallback, menuCommandID);
mcs.AddCommand( menuItem );
}
}
/// <summary>
/// This function is the callback used to execute a command when the a menu item is clicked.
/// See the Initialize method to see how the menu item is associated to this function using
/// the OleMenuCommandService service and the MenuCommand class.
/// </summary>
private void MenuItemCallback(object sender, EventArgs e)
{
MyForm form = new MyForm();
form.ShowDialog(); // Here your form is opening
}
I have been searching for a solution to this recently as I also needed to start a WPF form from a VSPackage. I have got things working after a couple of hours searching various topics on this and some good ol' trial and error.
I had an existing WPF-Project in a separate solution, which had to be merged into a VSPackage. Here's the steps to get this working:
Create a new Solution of Project type 'Visual Studio Package'
Make sure you select the 'Tool Window' option in the VS Package
Wizard (see the image below)
Now that the Solution has been created, add the already existing
WPF-Project to it (Right-Click 'Solution', Add->Existing Project) NOTE: It might be wise to copy the WPF-project to the Solution folder prior to adding it to the Solution.
Make sure you create a reference to the WPF-Project from your
VSPackage-Project and (if necessary) edit the namespaces of the WPF-Project to meet those of the VSPackage-Project, or the other way around.
Your Solution will now look something like this:
Now, you need to edit MyToolWindow.cs:
// Original:
base.Content = new MyControl();
// Change to:
base.Content = new MainWindow();
Make the following changes to VSPackage1Package.cs (or whatever your *Package.cs file is called)
// Original
private void ShowToolWindow(object sender, EventArgs e)
{
// Get the instance number 0 of this tool window. This window is single instance so this instance
// is actually the only one.
// The last flag is set to true so that if the tool window does not exists it will be created.
ToolWindowPane window = this.FindToolWindow(typeof(MyToolWindow), 0, true);
if ((null == window) || (null == window.Frame))
{
throw new NotSupportedException(Resources.CanNotCreateWindow);
}
IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
}
// Change to:
private void ShowToolWindow(object sender, EventArgs e)
{
// Get the instance number 0 of this tool window. This window is single instance so this instance
// is actually the only one.
// The last flag is set to true so that if the tool window does not exists it will be created.
//ToolWindowPane window = this.FindToolWindow(typeof(MyToolWindow), 0, true);
//if ((null == window) || (null == window.Frame))
//{
// throw new NotSupportedException(Resources.CanNotCreateWindow);
//}
//IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
//Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
MainWindow mainwin = new MainWindow();
mainwin.Show();
}
If you get no build errors, you should be fine.
To test if your WPF-form opens, Press 'Start' to run the VSPackage in a new 'Experimental' Visual Studio instance. If everything went OK, you will find and should be able to run your WPF-from from the View->Other Windows menu.
If you don't see your VSPackage listed in the menu, close your 'Experimental' Visual Studio instance. Then Clean en Build your Solution and press 'Start' again. It should show up now.

Confirm dialog window when closing a tab

I'm new to JavaFX. I want to create Listener which calls question dialog when user closes a tab into the TabPane. So far I managed to create tabs dynamically and add some custom configuration.
tabAvLabel = new Label(ss);
tabPane.getTabs().add(0, tab); // Place the new tab always first
tabPane.getSelectionModel().select(tab); // Always show the new tab
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); // Add close button to all new tabs
I don't know what event listener I need to use and how to define it. Would you show me how to implement this?
You can try onCloseRequest for Tab class
tab.setOnCloseRequest(new EventHandler<Event>()
{
#Override
public void handle(Event arg0)
{
//your code
}
});
Try this code :
tabAvLabel = new Label(ss);
tabPane.getTabs().add(0, tab); // Place the new tab always first
tabPane.getSelectionModel().select(tab); // Always show the new tab
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); // Add close button to all new tabs
tabPane.getOnClosed(), setOnClosed(new EventHandler<Event>(){
#Override void handle(Event e){
// What you have to do here
}
})
For more information, see http://docs.oracle.com/javafx/2/api/javafx/scene/control/Tab.html#onClosedProperty
I've hacked a similar support you have in jdk8 support into 2.2 (https://git.eclipse.org/c/efxclipse/org.eclipse.efxclipse.git/tree/bundles/runtime/org.eclipse.fx.e4.controls.fx2/src/org/eclipse/fx/e4/controls/fx2)
The answer of #VagrantAI can work. But you have to add the following codes on your 'OK' button click action function:
stage.fireEvent(
new WindowEvent(
stage,
WindowEvent.WINDOW_CLOSE_REQUEST
)
);
While the problem of this approach is the event is triggered when you click 'X' to close the window too. This should not be the purpose normally.
To solve this, add a flag (or static variable) in the class that loads the window. So every time the window is loaded, set the flag to false. When the window is closed, set the flag only when the 'OK' button is clicked. Then you can do your action regarding the value of this flag.

CommandBarButton on Context Menu doesn't work after ElementHost becomes visible

I have a CommandBarPopup on a the context menu in excel that contains three CommandBarButtons, one of those buttons opens a web page, the other two open a custom task pane.
If I make the custom task pane containing an element host which hosts a WPF user control visible then the any of the CommandBarButtons I have added will stop working.
Even if I close the custom task pane it will still not work.
If I do the same with a custom task pane container a web browser it seems to work fine.
Here is the code we are using
private void InitializeComponent()
{
this.elementHost1 = new System.Windows.Forms.Integration.ElementHost();
this.myView = new MyView();
this.SuspendLayout();
//
// elementHost1
//
this.elementHost1.Dock = System.Windows.Forms.DockStyle.Fill;
this.elementHost1.Location = new System.Drawing.Point(0, 0);
this.elementHost1.Name = "elementHost1";
this.elementHost1.Size = new System.Drawing.Size(780, 560);
this.elementHost1.TabIndex = 0;
this.elementHost1.Text = "elementHost1";
this.elementHost1.Child = this.myView;
//
// MyTaskPane
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.elementHost1);
this.Name = "MyTaskPane";
this.Size = new System.Drawing.Size(780, 560);
this.ResumeLayout(false);
}
So the answer was that the CommandBarButtons were being disposed once the variable scope ended which was surprising as I would have assumed they would be attached to the excel application object. Also looking at the excel commandbar, I could see the buttons there but clicking on them resulted in the click event not triggering.
Anyway I stored them in a class variable and it worked again.

EXT.Net - Dynamic UserControlLoader with Property

I need a solution to the below scenario. I'm developing an application in ASP.Net with the help of EXT.Net Controls.
In my scenario, I'm creating dynamic tabs (EXT.Net) and loading an User Control dynamically with UserControlLoader component.
How can I pass a parameter to the UserControl dynamically? Below is my sample code.
[DirectMethod]
public void AddNewTab()
{
getTitle gt = new getTitle();
Ext.Net.Panel panel = new Ext.Net.Panel
{
Title = gt.Title(),
Closable = false,
Layout = "Fit",
Items = {
new UserControlLoader{
Path="ElementChooser.ascx"
}
}
};
TabPanel1.Add(panel);
panel.Render();
TabPanel1.SetLastTabAsActive();
}
Your help is highly appreciated.
It is a bit unclear what "pass a parameter to a User Control" means, but I think you need to handle the UserControlLoader's OnUserControlAdded and OnComponentAdded events.
The first one fires when a user control is added to a UserControlLoader.
The second one fires for each top level Ext.NET component from a user control.
These events helps to configure a user control and its components as needed.
Here is an example with the OnComponentAdded example.

Implementing a blocking modal view/dialog like in Windows Forms - is it possible?

In short:
I want to show a view or action sheet and only continue code execution after the user has dismissed the view / sheet. So: line one shows the view, line two reads some result variable.
In detail why I would need this:
I'm porting a Windows Forms application over to the iPad. The original implementation has a communication class which uses a web service to communicate with the server. It offers a couple of methods to get data. Conveniently it checks prior to each call if the user still has a valid connection or if he has to re-enter his password for security reasons.
If the password is required, the .NET class shows a modal dialog which blocks any further code executio and if the password was entered, retries the last call it has made before showing the dialog.
Now using CocoaTouch I'm facing a problem. I replaced the code that shows the dialog with a UIActionSheet. Works great but code execution continues immediately, whereas in Windows Forms it is blocked (the next line in Windows Forms after showing the dialogs is to read the entered password from the dialog) until the dialog has been closed.
I tried a Thread.Sleep() until the user dismisses the UIActionSheet but the Thread.Sleep() also blocks the main loop and my view won't even be drawn.
The alternative I currently see is to change all methods in the already working class and give them a return value: if password required, handle it, then retry.
But this means that all over my code I will have to add these checks because at any given moment the password might be needed. That's why it is nested in communication class in Windows Forms.
Any other ideas?
René
Yes, it is possible.
To do this, what you can do is to run the mainloop manually. I have not managed to stop the mainloop directly, so I instead run the mainloop for 0.5 seconds and wait until the user responds.
The following function shows how you could implement a modal query with the above approach:
int WaitForClick ()
{
int clicked = -1;
var x = new UIAlertView ("Title", "Message", null, "Cancel", "OK", "Perhaps");
x.Show ();
bool done = false;
x.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
clicked = buttonArgs.ButtonIndex;
};
while (clicked == -1){
NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
Console.WriteLine ("Waiting for another 0.5 seconds");
}
Console.WriteLine ("The user clicked {0}", clicked);
return clicked;
}
I think this approach using async/await is much better, and doesn't suffer from freezing the app when rotating the device, or when the autoscrolling interferes and leaves you stuck in the RunUntil loop forever without the ability to click a button (at least these problems are easy to reproduce on iOS7).
Modal UIAlertView
Task<int> ShowModalAletViewAsync (string title, string message, params string[] buttons)
{
var alertView = new UIAlertView (title, message, null, null, buttons);
alertView.Show ();
var tsc = new TaskCompletionSource<int> ();
alertView.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
tsc.TrySetResult(buttonArgs.ButtonIndex);
};
return tsc.Task;
}

Resources