• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 769
  • Last Modified:

Subclass APPLY button in CPropertySheet

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
gilad_no
Asked:
gilad_no
  • 9
  • 7
1 Solution
 
gilad_noAuthor Commented:
------- 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
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
gilad_noAuthor Commented:
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
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
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
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
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
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
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
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
So how can I overide the SetModified function ? I've tried to overide OnApply but it didn't affect the button
0
 
DanRollinsCommented:


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
 
gilad_noAuthor Commented:
It doesn't work. But I used the idea of the icon and created an icon with text on it.

Thanks :)
0
 
DanRollinsCommented:
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
 
gilad_noAuthor Commented:
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

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 9
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now