Solved

Subclass APPLY button in CPropertySheet

Posted on 2001-07-04
16
744 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 7
16 Comments
 

Author Comment

by:gilad_no
ID: 6253153
------- 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
ID: 6253869
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
ID: 6261756
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:gilad_no
ID: 6262085
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
ID: 6300847
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
ID: 6305822
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
ID: 6306420
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
ID: 6307379
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6309765
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
ID: 6311280
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
ID: 6313635
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
ID: 6316606
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
ID: 6352585


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
ID: 6352757
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
ID: 6360634
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
ID: 6362904
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

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

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

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…
In this post we will learn different types of Android Layout and some basics of an Android App.
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.
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

707 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