Click here to Skip to main content
Licence CPOL
First Posted 8 Jul 2007
Views 54,837
Bookmarked 30 times

Workaround for flicker/flashing when programmatically activating MDI child forms

By | 8 Jul 2007 | Article
This short class demonstrates how to activate an MDI child form without the fireworks that you see if you just set the ActiveMdiChild property of the MDI parent form.

Introduction

This article shows how to activate an MDI child form maximized, without the fireworks that erupt when you activate an MDI child form using the Active() or Select() methods of the child form.

Background

If you've used MDI in WinForms or Win32, you've probably come across this very annoying issue, where MDI child forms that are activated through code, paint themselves in the restored window state they always have when they are non-active, just before they are activated and maximized (this happens only when the current MDI child form is maximized).

Because this issue was so annoying, and resulted in a very unprofessional 'look and feel', I became determined to find a workaround. The one I found to work best involves no subclassing or message handling. I discovered this when I noticed that if I activate the next MDI child form via Ctrl+F6 or the MDI system menu, there was none of the usual fireworks that I was seeing when a child form is activated by calling its Activate() method.

That lead me to the WM_MDINEXT Windows message which, at first glance, seemed only useful for activating the next MDI child form in the sequence. However, it can be used to activate any MDI child form by passing the handle of the next or previous MDI child in the Z-order along with a flag telling it whether to activate the next or previous MDI child in the Z-order.

Using the code

The following sample MDI parent Form class implements the workaround via a method that can be called and passed the MDI child form to be activated:

//  
//  MyMDIParent.cs
//

using System;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MyNamespace
{
   public partial class MyMDIParent : Form
   {
      public MyMDIParent()
      {
         InitializeComponent();
      }

      public void ActivateMdiChild( Form childToActivate )
      {
         if( this.ActiveMdiChild != childToActivate )
         {
            MdiClient mdiClient = GetMDIClient();
            int count = this.MdiChildren.Length;
            Control form = null;  // next or previous MDIChild form

            int pos = mdiClient.Controls.IndexOf( childToActivate );
            if( pos < 0 )
               throw new InvalidOperationException( "MDIChild form not found" );
            if( pos == 0 )
               form = mdiClient.Controls[1];  // get next and activate previous

            else
               form = mdiClient.Controls[pos - 1];  // get previous and activate next


            // flag indicating whether to activate previous or next MDIChild
            IntPtr direction = new IntPtr( pos == 0 ? 1 : 0 );
            
            // bada bing, bada boom
            SendMessage( mdiClient.Handle, WM_MDINEXT, form.Handle, direction );
         }
      }

      public MdiClient GetMDIClient()
      {
         foreach( Control c in this.Controls )
         {
            if( c is MdiClient )
               return (MdiClient) c;
         }
         throw new InvalidOperationException( "No MDIClient !!!" );
      }

      [System.Security.SuppressUnmanagedCodeSecurity]
      [DllImport( "user32.dll", CharSet = CharSet.Auto )]
      public static extern IntPtr SendMessage( IntPtr hWnd, int msg, 
                                  IntPtr wParam, IntPtr lParam );

      public const int WM_MDINEXT = 0x224;
   }
}

Points of interest

This solution works fine for me, when I need to activate a child window via code, but I haven't looked at how to get the MDI child form menu entries inserted into the menu by the framework, to use it. Any insight or advice on that would be welcome.

History

  • Initial submission - 7/09/07.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

tonyt



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralThank you Pinmemberajhuddy10:34 28 Oct '09  
GeneralMy vote of 1 PinmemberJon Burchel10:50 31 Aug '09  
General[My vote of 1] CRAP PinmemberJon Burchel10:50 31 Aug '09  
Questionchanging vs form look PinmemberMember 461164418:44 5 Mar '09  
GeneralSimilar Problem Pinmemberjohannesnestler22:13 7 May '08  
GeneralRe: Similar Problem Pinmembers.t.a.v.o3:48 8 Dec '08  
GeneralRe: Similar Problem Pinmemberjohannesnestler22:51 8 Dec '08  
QuestionRe: Similar Problem PinmemberMember 461164418:47 5 Mar '09  
AnswerRe: Similar Problem Pinmemberjohannesnestler5:25 6 Mar '09  
GeneralRe: Similar Problem Pinmemberjasonhh20:05 14 Apr '09  
QuestionI have a question please Pinmembersdev8:13 5 Oct '07  
GeneralFW: "A flicker issue in MDI applications" PinmemberMarcus Deecke11:54 17 Aug '07  
GeneralVery good - looking forward to the MDI menu working PinmemberMartin Berriman1:34 26 Jul '07  
GeneralRe: Very good - looking forward to the MDI menu working [modified] Pinmembertonyt14:37 18 Aug '07  
Generalstill MDI Questions PinmemberSHartmann14:59 22 Aug '07  
GeneralRe: Very good - looking forward to the MDI menu working Pinmemberjefrubio8:01 19 Feb '09  
GeneralRe: Very good - looking forward to the MDI menu working Pinmembersprice860:20 29 May '12  
Generalconverted to VB and adjusted Pinmemberdmbf1b510:27 17 Jul '07  
Hi,
 
I believe I have this working now in VB.   For some reason, specifying a 1 or 0 for the direction (last parameter of SendMessage) didn't seem to work - it always did the same thing, regardless of direction.   So I made a small adjustment, and it appears to work great now.
 
Here's the pertinent VB code in case anyone is interested.   BTW, if anyone sees a problem with this code, I'd appreciate it if you reply to this!
 
Thanks for putting me on the right track!
David
 
      Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
                                                                                                                  ByRef lParam As Integer) As Integer
      Const WM_MDINEXT As Integer = &H224
 
Then, in the procedure to actually do the work (note that moMDIClient I get the same way as this article, but maintain it for the life of the mdiparent form instead of getting it every time):
 
                        Dim iPos As Integer = moMDIClient.Controls.IndexOf(oFrm)
                        Dim frmTemp As Form
                        Dim iLastIdx As Integer = moMDIClient.Controls.Count - 1
                        If iPos = iLastIdx Then
                              frmTemp = moMDIClient.Controls(0)
                        Else
                              frmTemp = moMDIClient.Controls(iPos + 1)
                        End If
                        SendMessage(moMDIClient.Handle, WM_MDINEXT, frmTemp.Handle, 0)

GeneralRe: converted to VB and adjusted PinmemberJason Newland23:52 16 Feb '09  
GeneralRe: converted to VB and adjusted [modified] PinmemberJordan Deyton3:38 15 Jul '09  
Questionhow to SendMessage in VB.net? Pinmemberdmbf1b55:21 17 Jul '07  
AnswerRe: how to SendMessage in VB.net? PinmemberCalifBreton8:33 17 Jul '07  
GeneralNever seen any fireworks.... PinmemberKellyLeahy6:21 9 Jul '07  
GeneralRe: Never seen any fireworks.... Pinmembertonyt7:26 9 Jul '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120529.1 | Last Updated 9 Jul 2007
Article Copyright 2007 by tonyt
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid