Solved

Subclass APPLY button in CPropertySheet

Posted on 2001-07-04
16
732 Views
Last Modified: 2013-11-20
Hi all.

I've created property sheet using CPropertySheet. I want to add icons to the buttons on it (OK,Cancel,Apply,Help)
I am using a CButton derived class to do it. I've created 4 variables called m_BOK,m_BCancel,m_BApply,m_BHelp. In my OnInitDialog function, I subclass the variables with the ID of the property sheet buttons. When I call SetModified(), the Apply button get enabled and when I click on it, it loses it's icon and returns to a regular Apply button. I don't know how to overide it. I've tried to subclass it again after each button click, but it still don't work. What should I do ?
0
Comment
Question by:gilad_no
  • 9
  • 7
16 Comments
 

Author Comment

by:gilad_no
Comment Utility
------- Continue

When I've checked it using Spy++ I've noticed that after the WM_LBUTTONUP message, the button recieve a BM_SETSTYLE with BS_PUSHBUTTON style. I've tried to catch the BM_SETSTYLE message using PreTranslateMessage but I never get a call there !

What to do ?
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
There is a simple way to make a button display an image.  The most attractive results -- with the least effort -- come when you set the button's style to include the BS_ICON style and then use the CButton::SetIcon() function.  

Note: You could use the BS_BITMAP style and assign a bitmap to it, but then when the button is disabled, it looks kinda crappy (a grey rectangle the size of the bitmap is displayed).  Or you could subclass the button as a CBitmapButton, but then you need to create four bitmaps.

You might think there is a disadvantage to using an icon -- that the image can be only 32x32.  But here is a clever workaround and some bonus info for you:  When you load the icon, use LoadImage rather than LoadIcon.  

So, here is the complete solution:

1) In the resource editor, create a new icon (IDI_ICON1).  

2) Choose "New Device Image" from the Image menu

3) Click [Custom...] and make a custom icon that is, say 64 wide and 24 high (or whatever).

4) draw the image or paste it from elsewhere.  If you paste it, make sure to paint-bicket the background to be  the "mask color" so that when the button is disabled, it will look great.

=-=-=-=-=-=- coding it up -==-=-=-=-

5) In your CPropertySheet-derived object, use this:

BOOL CMySheet::OnInitDialog()
{
   BOOL bResult = CPropertySheet::OnInitDialog();
   CButton* pBtn= (CButton*)GetDlgItem(ID_APPLY_NOW);

   pBtn->ModifyStyle( 0, BS_ICON );

   HICON hIcn= (HICON)LoadImage(
        AfxGetApp()->m_hInstance,
        MAKEINTRESOURCE(IDI_ICON1),
        IMAGE_ICON,
        0,0, // use actual size
        LR_DEFAULTCOLOR
    );
   
    pBtn->SetIcon( hIcn );
 
    // pBtn->EnableWindow( FALSE); // some test code

    // repeat this for IDOK, IDHELP and IDCANCEL
    //(using different icons of course)
}

=-=-=-=-=-=-=-
I know this works for any standard dialog buttons, and I just now verified that it works for the buttons of a CPropertySheet.

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
Dan,

  Thanks for the answer, but this wasn't my question :)

  I have a class called CSXButton. I got it from www.codeproject.com and modified it a little to meet my needs. I've never had problems using it. I tried to use it with a CPropertySheet dialog. The problem as you know, is that I don't create the dialog resource of the sheet. I can only get a pointer to the button using GetDlgItem. I used subclassing with all the buttons. I can see an image on the buttons. But when I press the "Apply" button, it gets back to its regular style without the image. I've tried to trace it using Spy++ and I've noticed that it recieved a WM_SETSTYLE message with remove the BS_OWNERDRAW style from the button. I've tried to catch the message but I can't do it. I don't know why.
0
 

Author Comment

by:gilad_no
Comment Utility
Dan,

  I can't use regular CButton because I need an icon AND a text on the button. The class I use can handle both. The problem is that the button loses his BS_OWNERDRAW style. Why is that ?
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
You can show text in a CButton  --- just use the text tool when you draw the icon.  You can even doo fancy stuff luke a drop shadow, multiple lines, manually-tweeked lettering, etc.

I don't know anything about the CSXButton class.  But one possible problem is that the object itself is being destructied.  If you instaitate it in the OnInitDialog of the CPropertySheet, be sure that you make it a persistant object.  For instance, it could be a member variable oe a static variable.

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
Dan,

 I've tried to make the members static, but still, same problem. Here is a part of the OnInitDialog function:

m_BHelp.SubclassDlgItem(IDHELP,this);
m_BHelp.SetIcon(IDI_HELP,16,16);
m_BApply.SubclassDlgItem(ID_APPLY_NOW,this);
m_BApply.SetIcon(IDI_APPLY,16,16);

m_BHelp & m_BApply are both CSXButton type. CSXButton is a CButton derived class which can display text & images on a button. As you can see, I've tried to subclass them to the original button. But when I press the Apply button, it returns to the original button. It doesn't happen with the other buttons. The problem is only with the Apply button. Maybe you know if the Apply operation destroy the button ?
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Here is how to narrow down the range of possible problems:

// m_BHelp.SubclassDlgItem(IDHELP,this);
// m_BHelp.SetIcon(IDI_HELP,16,16);
// m_BApply.SubclassDlgItem(ID_APPLY_NOW,this);
// m_BApply.SetIcon(IDI_APPLY,16,16);
m_BApply.SubclassDlgItem(IDI_HELP,this);
m_BApply.SetIcon(IDI_HELP,16,16);

Or try...

// m_BHelp.SubclassDlgItem(IDHELP,this);
// m_BHelp.SetIcon(IDI_HELP,16,16);
// m_BApply.SubclassDlgItem(ID_APPLY_NOW,this);
// m_BApply.SetIcon(IDI_APPLY,16,16);
m_BHelp.SubclassDlgItem(ID_APPLY_NOW,this);
m_BHelp.SetIcon(ID_APPLY_NOW,16,16);

See if these switches yield the same behaviors and report your findings here.

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
I've tried both cases. Still the same problem. When I track it using Spy++, I've noticed that after I press the apply button, it recieved BM_SETSTYLE which reset the style of the button and remove the BS_OWNERDRAW style. What causes that ?
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Interesting.  It seems to take place when You call SetModified for a property page.  That fn sends a PSM_CHANGED or PSM_UNCHANGED message to the common control.  That causes the [Apply] btn to be disabled, so it can no longer be the default button.  I believe that it is in the transition that a BM_SETSTYLE is called which does not honor the previous style flags.

I can't see anyplace in MFC where this could be happening.  So, I would check the code for this ultra cool button control that you are using (CSXButton).  If it is not there, then it might be a bug in common controls.

The work-around would probably be to change the style back in you OnApply handler for each page.

But the best solution would be to get rid of CSXButton and just use standard Icon buttons, as I have suggested.

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
The problem is not with the SetModified. When I enter the page, I can see the button with the icon and it is disabled. When I call SetModified it becomes enable. Only when I click on it, it loses the icon and returns to be disabled.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
You are not looking at the complete sequence:

The act of clicking the [Apply] button causes your OnApply handler (or the default one) to be executed.  One thing *that* does is call SetModified(FALSE) with the assumption that once the changes have been applied, the [Apply] button should be disabled (it has no purpose because all of the changes have been applied).  

Likewise, calling SetModified(TRUE) results, eventually, in the [Apply] button becoming enabled.

In the acto fo enabling/disabling the [Apply] button,  something is setting the style flags for the button without honoring the OwnerDraw flag.

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
So how can I overide the SetModified function ? I've tried to overide OnApply but it didn't affect the button
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 75 total points
Comment Utility


BOOL CDlgPg1::OnApply()
{
   //return CPropertyPage::OnApply();
   //--- do something here (eg, save values to disk)
   //--- but return 0 so default "OnApply" won't happen
   return( FALSE );
}
0
 

Author Comment

by:gilad_no
Comment Utility
It doesn't work. But I used the idea of the icon and created an icon with text on it.

Thanks :)
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Great!  So you took my original suggestion and used it and it solved your problem.  So why have you given me a B?

As an expert here at EE, I am striving for a "4.0 grade point average."  When you accept my comment as a "Good" answer, it lowers my average.  Please answer these questions, to help me understand how to improve:

1) Did the comment I posted help you to solve your problem?

2) Obviously my comment was less than a perfect solution in your eyes.  What could I have added to make it 100% perfect?

3) Do you understand that it costs you no more to give an A than it does to give a B or a C, but that the expert recieves more points for the better grade?

4) Have you read the information at
http://www.experts-exchange.com/jsp/cmtyQuestAnswer.jsp#3
and do you understand it?

5) Is there anything I said that offended you in any way?

-- Dan
0
 

Author Comment

by:gilad_no
Comment Utility
I didn't ment to offend you by giving you a B grade. I am sorry for that. I am trying to be objective regarding grading answers. You did solved me question but not the way I wanted. I knew I could use a bitmap on a button but I dodn't want it because I want to use my class for it. It slightly more attractive. In the end, I did get a button with a picture, but I didn't solved my problem. I have some other buttons classes and I STILL don't know how to use them in CPropertySheet page.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 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

14 Experts available now in Live!

Get 1:1 Help Now