Solved

Eliminating Flicker in a Property Sheet

Posted on 1998-08-15
12
792 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
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
bobThere java chalenge 45 94
C++ BOOL WINAPI ReadFile fails on windows 10 when reading from USB cable 9 473
windows 10 how make picture as desktop background 2 65
Not needed 13 119
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
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.
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

829 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