SplitButton GetImage Callback Not Working - vba

I have a custom ribbon in Visio that displays correctly, except when I click to expand a SplitButton. When I expand the SplitButton, it calls the GetImage callback for my ribbon, and loads the bmp file using LoadPicture, but does not actually display in Visio. The next time I expand the SplitButton everything is fine.
Is there something I need to do in the callback to prompt the ribbon to display correctly when using a SplitButton?
We currently use a class that implements IRibbonExtensibility with callbacks for GetImage and OnAction, and they work fine for normal buttons, but we get this behavior only with SplitButton usage.
This is what I see the first time I click the drop down:

It is not clear what code is used for the custom Ribbon UI.
The getImage callback should have the following signature:
C#: IPictureDisp GetImage(IRibbonControl control)
VBA: Sub GetImage(control As IRibbonControl, ByRef image)
C++: HRESULT GetImage([in] IRibbonControl *pControl, [out, retval] IPictureDisp ** ppdispImage)
Visual Basic: Function GetImage(control as IRibbonControl) as IPictureDisp
Make sure that you return the IPictureDisp instance which points to the image you loaded. See Chapter 11: Creating Dynamic Ribbon Customizations (2 of 2) for a sample code.

The issue came down to the use of the DoEvents statement, which was added to our stack trace code in our codebase. Every time we enter a routine we push the routine name onto a call stack and then pop it on exit, but this routine also had added the DoEvents statement to help break out of any loops during development.
It would seem that, since we add the ribbon via a Document Created/Opened event, executing DoEvents must be causing Visio to not correctly process the ribbon loading callbacks. Removing the DoEvents statement fixed the problem.

Related

Refreshing custom ribbon button which relies on a table to get the label and image

I have a custom ribbon and one of the buttons on it (image and label for the button) are supposed to change based on what happens in one of the forms (so, essentially, it's supposed to change when values in a table change and making changes in the form is the trigger for the change).
On the CLOSE button of the form I have the following code:
sbRefreshRibbon
MyRibbon.Invalidate
and here is what the procedure does, so the MyRibbon.Invalidate part is probably redundant:
Public Sub sbRefreshRibbon()
On Error GoTo RestartApp
MyRibbon.Invalidate
On Error GoTo 0
Exit Sub
RestartApp:
MsgBox "Please restart Application for Ribbon changes to take effect", _
vbCritical, "Ribbon Refresh Failed"
End Sub
In any case, sometimes, when clicking CLOSE I get the "Please restart Application for Ribbon changes to take effect" error. After restarting, all is well, the label is correct and so is the image
but, how can I make the label and image change without errors and restarts?
There is no need to call the Invalidate method of the IRibbonUI interface multiple times. You need to left a single call as soon as your form is closed.
Also you may consider using the InvalidateControl method of the IRibbonUI interface instead. It allows invalidating the cached value for a single control (not the whole custom UI) on the Ribbon user interface.

displaying loading gif on a form during vba sub execution

I am trying to put an animated loading gif on a form during a long subroutine execution (specifically, sub being fired on a form's button click event), and it turns out to be surprisingly difficult in MS Access.
I already have my gif animation put on the form, linked to ActiveX Web Browser control (call it loadingGif in example below). It turns out, that doing simply:
Private Sub someButton_Click()
loadingGif.Visible = True
'... hard stuff here ...
loadingGif.Visible = False
End Sub
fails because screen doesn't get refreshed during subroutine execution, and so the user never sees the loadingGif control. Is there any way to make it visible during single subroutine execution?
Also:
I know it is possible to create an animated modal pop-up form instead, but that's not the idea
I already also use Hourglass, but icon on a form seems much more appealing

Application fail to exit when a runtime created object is used

I'm using vb.net 2013, and I have configured Shutdown mode to "When last form is closed".
On my main form, I have a menu item which has this code to close the application:
Application.Exit
Everything is working fine, except one case:
When I open a specific form, where a Combobox is created on runtime and I've used Addhandler to subscribe to several events.
The combobox is created when pressing a button.
When I open this form and I don't create the combobox, everything is working ok. If the combobox is created, when I close this form and try to close the application using the menu item, nothing happens. The application is not closed and no error message is displayed. (the same situation occurs when I try to close the main form with "x" button)
On the form's (where I have the combobox) close event , I tried to put a line of code:
MyCombobox.dispose()
But the situation is the same.
What can I do? Thank you!
What I do from my little experience is
1.) remove the MyCombobox from its parent control (I'm think this is in your combobox close event).
2.) set the MyCombobox to Nothing
3.) Dispose() it.
MyCombobox = Nothing
MyCombobox.Dispose()
It would be useful to see some part of your code for the close event so we can help you check. More power to you!
Update based on OP's comment:
I have read the following from MSDN: https://msdn.microsoft.com/en-us/library/system.windows.forms.form.closing(v=vs.110).aspx
From this, it is important to note that:
The Form.Closed and Form.Closing events are not raised when the Application.Exit method is called to exit your application. If you have validation code in either of these events that must be executed, you should call the Form.Close method for each open form individually before calling the Exit method.

System.Threading.ThreadstateException

I'm developing an adding for office powerpoint application.
I'm trying to display a description of the object(Customized object) currently dropped on the powerpoint slide in design mode(Design mode of the powerpoint).
When i click on my addin the related object description will be displayed on a tabbed window as the first tabpage.
There is a button on the tab page, and when i click on it i need the description to get copied to windows clipboard.
I tried this using clipboardclass it throws the following exception,
System.Threading.ThreadstateException
{"Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."}
Code for clipboard:
Clipboard.Clear()
Clipboard.SetText(lblObjectID.Text)
I searched the net for a solution and got couple of answers like,
1. Put [STAThread] in the main function
2. Thread.CurrentThread.SetApartmentState(ApartmentState.STA) Immediately before your call to SetDataObject.
But I'm not sure where to put the 1st one and the 2nd option didn't work.
Can anyone help me please.
Thanks.
WinForms are STA by default. Are you creating another thread or using a BackgroundWorker? Run this code to determine what mode you're in:
MessageBox.Show(System.Threading.Thread.CurrentThread.GetApartmentState().ToString())
Edit:
But maybe you could also try using this command before calling the clipboard functions:
Application.OleRequired()

VB.NET: How to close and re-open a dialog in this case?

I'm developing a WinForms app in VB.NET, that handles sets of style data, and when the user clicks on another set's label, it prompts through a dialog "You are leaving this style preset to edit another one. keep changes on this one? [Yes] [No]"
But, I'm facing the problem that, when the user clicks either option, and the dialog closes, everything has to be refreshed, and loading the form again seems a good option.
I've tried putting a public sub on a module, that does this:
Public Sub CloseOpenStyleDlg()
KeepOrDiscardPrompt.Close()
StylesDlg.Close()
StylesDlg.ShowDialog()
End Sub
But as soon as that sub is called from the prompt, it crashes the application. (doesn't show an error in debug, simply crashes) How should I, from a given dialog, close the dialog, it's parent, and re-open it's parent? (which triggers all the Dialog_Load() code of the parent)
Thanks in advance! :)
You need to instantiate the dialog again. If I take your code for example:
Public Sub CloseOpenStyleDlg()
KeepOrDiscardPrompt.Close()
StylesDlg.Close()
StylesDlg = new StylesDlg()
StylesDlg.ShowDialog()
End Sub
When a form is closed, all resources created within the object are closed and the form is disposed.
If you want to reuse the Window instance use StylesDialog.Hide() function instead.