Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Update 9/9/11: Here is a minimal example project that will reproduce the issue for me (VS 2008 solution): http://wfurl.com/09061bf

I have an ArcMap 10 add-in with a ComboBox class that I place on a toolbar. When I attempt to display a MessageBox after the user submits a value by typing in the ComboBox and pressing Enter, the ComboBox steals the keyboard focus from the MessageBox, so when the user tries to dismiss the MessageBox by pressing Enter again, the ComboBox's OnEnter event handler runs again instead of the MessageBox being closed.

Without any checks against this, you might end up with numerous MessageBox instances on top of one another with no way to dismiss them except by clicking OK on each one.

Attempts to work around this behavior have failed and include:

  1. Disabling the ComboBox before showing the MessageBox and re-enabling it afterwards. The enabled state doesn't change until after the MessageBox is closed and the focus issue still occurs. Employing Application.DoEvents has no effect.
  2. Setting a class-level boolean that tells the OnEnter handler to simply return when true (Set to True just before showing the MessageBox and False afterward.) The focus issue remains, meaning it takes 3 Enter keystrokes to dismiss the MessageBox, but at least the OnEnter code doesn't run again.
  3. Setting the MessageBox's parent window to the ArcMap application using the IWin32Window overload (actually this is necessary to get the MessageBox to show in the middle of the ArcMap window instead of on top of the ComboBox).
  4. Explicitly setting the MessageBox's MessageBoxOptions property to 0x1000 (MB_SYSTEMMODAL) or 0x2000 (MB_TASKMODAL)
  5. Using IApplication.StatusBar.set_Message() instead of MessageBox. The ComboBox's HintText message, even if not specified, or set to an empty string, instantly overrides anything I write in the set_Message main pane (0), so this method is essentially useless with Addin ComboBoxes.

Anyone have any other ideas as to what else I can try, or must I once again look at a WinAPI solution to deal with the ArcGIS framework's shortcomings?

share|improve this question
    
What happens if you open a form, rather than a combo box? Or you could just change the HintText to your message. –  Patrick Sep 6 '11 at 21:45
    
Unfortunately there is no HintText property on the ComboBox, the only place it can be set (as far as I can tell) is in the Config.esriaddinx XML file. Using a Form has the same problem -- just get a bunch of Form instances instead of MessageBox instances. –  blah238 Sep 6 '11 at 22:07
1  
Yeah, when you make a combobox on a toolbar that is not in an add-in, you need to be sure to use ICompletionNotify.SetComplete, which gets passed with IToolControl.Onfocus. Unfortunately, I don't see anything analogous to ICompletionNotify that gets passed to add-in comboboxes. –  Kirk Kuykendall Sep 9 '11 at 22:01
1  
It gets worse.. the toolbar and combobox are not standard Windows controls but a third party libray, from the window class it looks like CodeJock CommandBars for C++. Even getting the window handle is problematic, not to mention controlling the combobox via API calls, which result mostly in non-standard windows messages. Other than using the good old tool control, the only option I see is to intercept windows messages from this control and check for Enter key yourself... –  Petr Krebs Sep 12 '11 at 11:50
1  
Have you tried spawning the MessageBox on a different thread? Or does this box need to be executed inline with the ComboBox code? –  baens Sep 13 '11 at 16:12

1 Answer 1

up vote 4 down vote accepted
+100

In your code that you gave as an example. In my testing this worked for me.

new Thread(() =>
{
   MessageBox.Show(String.Format("The value '{0}' is not an integer!", currentValue));
}).Start();

Edit To incorporate the great comments, and as Petr pointed out that this way may be dangerous here is the other way of doing this as well:

SynchronizationContext.Current.Post(_ => MessageBox.Show("Message"), null);

Thanks to Kirk and Petr for this!

share|improve this answer
    
As it does for me too, nicely done! –  blah238 Sep 13 '11 at 17:59
2  
This will work for message boxes (sort of - they are not modal, the user can still interact with ArcMap window while the message box is open), but be warned that many scenarios, like opening a new form, need to be performed from the main thread. –  Petr Krebs Sep 13 '11 at 19:34
3  
@petr I wonder this SynchronizationContext.Post trick might work to overcome this. –  Kirk Kuykendall Sep 13 '11 at 19:52
2  
@Kirk, good one, I just tested this, calling SynchronizationContext.Current.Post(_ => MessageBox.Show("Message"), null); and works great - it does execute the delegate on the main UI thread, so the message box behaves correctly as a modal window. Should work for more complex UI related tasks as well. –  Petr Krebs Sep 13 '11 at 20:20
1  
@Kirk & Peter, you are right, it doesn't behave modally when put on its own thread. The Post trick works great. I'd rep you all if I could, high fives all around :) –  blah238 Sep 13 '11 at 22:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.