We are developing a mixed c++ application were we host a usercontrol within an MFC CWinFormsView. This control contains UltraToolbars with PopupMenuTool dropdown menus.
We are experiencing problems with the dropdown menus remaining sticky on the screen when the mouse clicks outside the menu or the form is moved or closed. Furthermore, the Escape doesn't work for closing the menus or any other shortcut key assigned to a menu entry. We also have a WinNavigationBar that has the same problems when a dropdown for a location is opened.
Could you please advise?
Carlo
Its funny, I haven't seen anyone have this issue before, and now it has happened twice in the past 10 days (here is the other post: http://forums.infragistics.com/forums/p/2827/17955.aspx). It appears your are having the same problem. Here is the solution that worked before:
Add a call to Infragistics.Win.Utilities.ForceNativeMessageFilter() to the constructor of the UserControl. I say to add this call to the constructor and not to the start of the application because it doesn't hurt to call this method multiple times and calling it only applies to the thread it was called on. In a multi-threaded application, you would want to make sure the the fix is applied to user controls instantiated on all threads.
Thanks Mike, that worked great for the menus sticking on the screen. However the shortcut keys or the escape key for closing the menu still don't work. Do you have any suggestions for that?
Mike,
In my case all accelerator keys stop working. For instance if one of the menu items is find and I have assigned Ctrl + F to that menu item, Ctrl + F stops working. So in this case it would be the second path just not using the Alt Key but also the Ctrl key. Even a function key accelerator such as F5 from a menu for refresh stops working.
I'm not sure if anyone is doing this already, but there are some protected members that can be overridden on the toolbars manager that may help with this. They were added to help use a toolbars manager when it was hosted on a web page in Internet Explorer, and they may help in this situation too. Try overriding these members with the implementations described in each of their comments to see if it fixes the issue:
ActivateForm()ActiveControlOfActiveFormFormWindowStateIsControlOnActiveForm( Control control )IsFormActiveOnFloatingToolbarWindowShown( FloatingToolbarWindowBase floatingToolbarWindow )
Also, track the activation of the VB6 window and call these protected methods at the appropriate times:
OnFormActivated()OnFormDeactivate()
Here is a partial implementation that may help get you started. Also, you don't have to use a timer to track the form activation.
public class MyToolbarsManager : UltraToolbarsManager{ private bool isFormActive; private Timer timer;
protected override void Dispose( bool disposing ) { base.Dispose( disposing );
if ( this.timer != null ) { this.timer.Enabled = false; this.timer.Dispose(); this.timer = null; } }
protected override void OnEndInit() { base.OnEndInit();
this.timer = new Timer(); this.timer.Interval = 100; this.timer.Tick += new EventHandler( timer_Tick ); this.timer.Enabled = true; }
private void timer_Tick( object sender, EventArgs e ) { Control dockWithinContainer = this.DockWithinContainer;
if ( dockWithinContainer == null ) return;
bool isFormNowActive = IsControlOnActiveForm( dockWithinContainer );
if ( isFormNowActive != this.isFormActive ) { this.isFormActive = isFormNowActive;
if ( this.isFormActive ) this.OnFormActivated(); else this.OnFormDeactivate(); } }
protected override bool ActivateForm() { bool succeeded = base.ActivateForm();
if ( succeeded ) return true;
Control dockWithinContainer = this.DockWithinContainer;
if ( dockWithinContainer == null || dockWithinContainer.IsHandleCreated == false ) return false;
IntPtr parentHwnd = NativeWindowMethods.FindTopLevelWindow( dockWithinContainer.Handle );
if ( parentHwnd == IntPtr.Zero ) return false;
NativeWindowMethods.SetActiveWindow( parentHwnd ); return true; }
protected override Control ActiveControlOfActiveForm { get { Control control = base.ActiveControlOfActiveForm;
if ( control != null ) return control;
return Control.FromChildHandle( NativeWindowMethods.GetFocus() ); } }
protected override FormWindowState FormWindowState { get { FormWindowState windowState = base.FormWindowState;
if ( windowState != FormWindowState.Normal ) return windowState;
// TODO: Get the window state and return it return windowState; } }
protected override bool IsControlOnActiveForm( Control control ) { bool isOnActiveForm = base.IsControlOnActiveForm( control );
if ( isOnActiveForm ) return true;
IntPtr activeForm = NativeWindowMethods.GetForegroundWindow();
IntPtr controlHandle = control.Handle;
while ( controlHandle != IntPtr.Zero ) { if ( controlHandle == activeForm ) return true;
controlHandle = NativeWindowMethods.GetParent( controlHandle ); }
return false; }
protected override bool IsFormActive { get { bool isFormActive = base.IsFormActive;
if ( isFormActive ) return true;
IntPtr activeForm = NativeWindowMethods.GetForegroundWindow(); IntPtr form = NativeWindowMethods.FindTopLevelWindow( dockWithinContainer.Handle );
while ( activeForm != IntPtr.Zero ) { if ( activeForm == form ) return true;
activeForm = NativeWindowMethods.GetWindowLong( activeForm, NativeWindowMethods.GWL_HWNDPARENT ); }
return false; } }
protected override void OnFloatingToolbarWindowShown( FloatingToolbarWindowBase floatingToolbarWindow ) { base.OnFloatingToolbarWindowShown( floatingToolbarWindow );
if ( floatingToolbarWindow.Owner != null ) return;
if ( dockWithinContainer != null && dockWithinContainer.IsHandleCreated ) { try { IntPtr ownerHandle = NativeWindowMethods.FindTopLevelWindow( dockWithinContainer.Handle );
if ( ownerHandle != IntPtr.Zero ) { NativeWindowMethods.SetWindowLong( floatingToolbarWindow.Handle, NativeWindowMethods.GWL_HWNDPARENT, ownerHandle ); // TODO: If the owner is TopMost, make the floating toolbar window TopMost } } catch ( SecurityException ) { } } }}
[SuppressUnmanagedCodeSecurity]internal class NativeWindowMethods{ internal const int GWL_HWNDPARENT = -8;
[DllImport( "user32" )] internal static extern IntPtr GetFocus();
[DllImport( "user32" )] internal static extern IntPtr GetForegroundWindow();
[DllImport( "user32" )] internal static extern IntPtr GetParent( IntPtr childHwnd );
[DllImport( "user32" )] internal static extern IntPtr GetWindowLong( IntPtr hWnd, int nIndex );
[DllImport( "user32" )] internal static extern IntPtr SetActiveWindow( IntPtr hWnd );
[DllImport( "user32" )] internal static extern IntPtr SetWindowLong( IntPtr hWnd, int nIndex, IntPtr newLong );
internal static IntPtr FindTopLevelWindow( IntPtr childWindow ) { IntPtr control = childWindow;
while ( true ) { IntPtr nextControl = GetParent( control );
if ( nextControl == IntPtr.Zero ) break;
control = nextControl; }
return control; }}
Out of curiosity, has anyone tried this solution? If so, did it fix the problem? I'd also like to know just in case someone else has this problem in the future. Thanks for any input.
Mike I finally think I have found what causes the Infragistics Hotkeys to not register. If Microsoft Outlook is open when you launch the program with the hotkeys it seems to block the registration of those hotkeys. Close Outlook and launch the program and all is well.
This issue has been driving my users nuts for over a year and we think we've finally stumbled on the cause of the problem. Finally!
Now only if Infragistics can solve the rest of the riddle.
I can't see how that would affect the UltraToolbarsManager. Just to make sure of a few things, you are calling Utilities.ForceNativeMessageFilter and you are using the derived toolbars manager I posted above, correct? Specifically, is the ActiveControlOfActiveForm override returning something non-null when the shortcut is pressed?