Solved

Eliminating Flicker in a Property Sheet

Posted on 1998-08-15
12
786 Views
Last Modified: 2013-11-20
I've got a CPropertySheet derived class running in wizard mode which contains several property pages.  Each property page displays the same bitmap within a static control in the same location, similar to the familiar InstallShield wizard. When I change between pages, the control's frame and client area is erased (by MFC I assume) and the CPropertyPage derived class for the selected property page's OnPaint() function is called to fill in the bitmap.  This works fine, except the erasing causes noticable flicker.  How can I eliminate this ?

Thanks.
0
Comment
Question by:brosenb0
12 Comments
 
LVL 2

Expert Comment

by:warmcat
ID: 1320859
You could place the entire CPropertySheet derivation as a child on a dialog.  The CpropertySheet is placed, say, to the right of a bitmap which is a child of the dialog.  Just to be clear, this would remove the bitmap from the property pages and make it a sibling of the property sheet on an underlying substrate dialog.
0
 
LVL 8

Expert Comment

by:trestan
ID: 1320860
To avoid flickering, you should use a memory DC. You output the bitmap to the memory DC instead of directly to the screen. Then transfer this bitmap Memory DC to screen which is much faster. So that flickering can be avoided. Use CreateCompatibleDC to create the memory DC, use LoadBitmap or SelectObject to put the bitmap in the DC, and at last use Bitblt to put the bitmap to screen. Good luck.
0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320861
Sorry Trestan,
I'm already using a memory DC for painting the bitmap.  The problem seems to be caused by the static control erasing its background when the pages are changed.

Warmcat,
How do I move the property sheet to where ever I want in the dialog's client area? A property sheet is not a control as such and can't be manipulated in the resource editor.  In wizard mode the property sheet draws a sunken line between the pages and its buttons.  How do I tie this in with the parent dialog ?  Got any examples ?
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1320862
The problem is caused because each property sheet is destroyed/hidden and a new one created when you move to the next stage in the wizard.

Each time you move to the next stage in the wizard the you get a new static control (if you do GetDlgItem(ID_WHATEVER)->m_hWnd() on the static you will probably be able to see the hWnd change).

My suggestion to get around this:
Don't use a static control.  Instead override the WM_PAINT message for each property page that that should have the graphics placed placed on it.  Each WM_PAINT message will have to be essentially overridden the same way.  This is tricky but is do-able.  
Take at look at http://www.codeguru.com/propertysheet/index.shtml and in particular an article called "Placing A Bitmap In The PropertySheet Button area".  This code over-rides WM_PAINT for a property sheet.  You should be able to use the same idea for your propertypages.

0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320863
Answers2000,

That method may work, however, I will have to include the control's border in the bitmap & calculate the dest. RECT manually. Even if the control was removed, when the freshly selected property page erased its background upon a page change, wouldn't flicker still occur ?  Which is painted last - the sheet or the page ?  If the page is painted last, it would erase the painting done by the sheet.  Is there a way to subclass the static control to stop it erasing its background ?
0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320864
Sorry Answers200,
The property sheet still erases each page as they are changed.  With regard to Warmcat's suggestion, placing the sheet inside a dialog is ok for a tabbed property sheet, but no good in wizard mode.

What I might be able to do is remove the static control from each page and create a CStatic control on the sheet itself at runtime.  To do this I would have to leave the pages (at least one) the same size so that the sheet was large enough to accomodate the control.  Next I would have to resize each page before they were drawn so that they don't overwrite the CStatic control.  I found an article at www.codeguru.com that discussed placing a control directly on a property sheet at runtime, however, the method used was to extend the sheet, rather than shrink the pages.  This method worked in tabbed mode, however, with wizard mode this results in the divider bar between the buttons and the pages not being extended correctly and the sheet looks funny.  Does anyone know how to do this ?

Thanks.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 7

Expert Comment

by:psdavis
ID: 1320865
Absolutely, when resizing the pages in wizard mode, use the GetWindow( GW_CHILD ) and cycle through using the GW_HWNDNEXT parameter to move each and every window including the divider bar.  I have full source code to this at work and I'll send it over at 8:20 CST for you!

It is with a Wizard and it grows on page 2 and shrinks on page 3.  It should be exactly what you want.

Phillip
0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320866
Sounds good Phil.  Whack it through as an answer and we'll see how we go.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1320867
Apply the WS_CLIPCHILDREN style to the property page (the parent window of the static control).
0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320868
This just stopped the OnPaint() function from being called and the bitmap was not painted at all.
0
 
LVL 7

Accepted Solution

by:
psdavis earned 200 total points
ID: 1320869
// Here's the Offset button function that allows you to move everything including the bar and the buttons.

BOOL CMyPropertySheet::OffsetButtons( CPropertySheet* pSheet, CSize& sizOffset )
{
   CTabCtrl* pTabControl = pSheet->GetTabControl( );
   
   for( CWnd* pChild = pSheet->GetWindow( GW_CHILD ); pChild; pChild = pChild->GetNextWindow( GW_HWNDNEXT ))
   {
      if( pChild == pTabControl || pChild == this )
         continue;
     
      CRect rectWindow;
      pChild->GetWindowRect( &rectWindow );
      pSheet->ScreenToClient( &rectWindow );
      rectWindow.OffsetRect( sizOffset );
      pChild->MoveWindow( &rectWindow, TRUE );
   }
   
   return TRUE;
}

CMyPropertyPage::OnSetActive( )
{
.
short sWidth  = 550;
short sHeight = 120;
 
OffsetButtons( pScanWizard, CSize( sWidth, sHeight ));
   
CRect rectWindow;
GetWindowRect( &rectWindow );
pScanWizard->ScreenToClient( &rectWindow );
rectWindow += CRect( 0, 0, sWidth, sHeight );
MoveWindow( &rectWindow, TRUE );
   
pScanWizard->GetWindowRect( &rectWindow );
rectWindow.InflateRect( CSize( sWidth / 2, sHeight / 2 ));
pScanWizard->SetWindowPos( NULL, rectWindow.left, rectWindow.top, rectWindow.Width( ), rectWindow.Height( ), SWP_NOZORDER );

.
}

// and to move it back

CMyPropertySheet::OnKillActive( )
{
.
short sWidth  = 550;
short sHeight =  50;
   
CPropertySheet* pSheet = (CPropertySheet*) GetParent( );
OffsetButtons( pSheet, CSize( -sWidth, -sHeight ));
   
CRect rectWindow;
pSheet->GetWindowRect( &rectWindow );
rectWindow.DeflateRect( CSize( sWidth / 2, sHeight / 2 ));
pSheet->SetWindowPos( NULL, rectWindow.left, rectWindow.top, rectWindow.Width( ), rectWindow.Height( ), SWP_NOZORDER );
.
}

// Hope this helps you!

// Phillip
0
 
LVL 3

Author Comment

by:brosenb0
ID: 1320870
Thanks Phillip that was just what I was after.

Bruce.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Is it possible to combine several text files into one big one? (redhat v5 enterprise) 4 81
isEverywhere  challenge 19 71
FizzBuzz challenge 9 76
sumHeights  challenge 17 65
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
A company’s greatest vulnerability is their email. CEO fraud, ransomware and spear phishing attacks are the no1 threat to a company’s security. Cybercrime is responsible for the largest loss of money to companies today with losses projected to r…

930 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now