Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 522
  • Last Modified:

Changing the bitmap for a CStatic object at runtime

I have this "picure" control (CStatic) which I want to have one of two bitmaps (a lightswitch depicting "on" or "off").

At runtime I want to click on the picture and have the bitmap switch from "on" to "off".

I set up the OnClick event for the CStatic object and this is the code I am using to switch the bitmap:

Don't ask me why I am subclassing the dialog item.  I don't even know if this is necessary.  I have been going through several books trying to gather bits and pieces of how this works.

What happens right now is when I click on the CStatic object the bitmap disappears completely.

Anyway, here is the code for my OnClick event:

void CRoom04Dlg::OnStaticBit7()
{
      HINSTANCE appinstance = AfxGetInstanceHandle();
      CStatic m_static;
      m_static.SubclassDlgItem(IDC_STATIC_BIT7,this);
      m_static.SetBitmap(HBITMAP (LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));            
}
0
Tom Knowlton
Asked:
Tom Knowlton
  • 8
  • 6
  • 2
  • +2
1 Solution
 
WynCommented:
dont subclass
0
 
ZoppoCommented:
Since this is not a derived class (so there isn't some extra PreSubclassWindow implemented) I agree with Wyn:

use GetDlgItem() to get a pointer to the static control like this:

void CRoom04Dlg::OnStaticBit7()
{
 HINSTANCE appinstance = AfxGetInstanceHandle();
 CStatic pStatic;
 pStatic = (CStatic*)GetDlgItem(IDC_STATIC_BIT7);
 pStatic->SetBitmap(HBITMAP (LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));
}


ZOPPO
0
 
MichaelSCommented:
What's about standard window's message STM_SETIMAGE?
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
ZoppoCommented:
Hi MichaelS: since knowIton uses MFC I think it's a good idea to stay in MFC ... SetBitmap just calls ::SendMessage( m_hWnd, STM_SETIMAGE, ... )
0
 
Amor_Commented:
I can advise u to use a CBitmapButton Class. You can load in constructor till 4 images, and one of them is if button focused.
You should define a CBitmapButton  (but).
In constructor but.LoadBitmaps and in
OnInitDialog :
VERIFY(but.SubclassDlgItem(IDOK,this));
but.SizeToContent();

Hope this will work.
 
0
 
MichaelSCommented:
2 Zoppo, 100% agree.
0
 
WynCommented:
->since knowIton uses MFC I think it's a good idea to stay in MFC ... SetBitmap just calls ::SendMessage( m_hWnd, STM_SETIMAGE, ... )
===============================
1000% :)
0
 
Tom KnowltonWeb developerAuthor Commented:
Zoppo:  Your code didn't work.

Amor_:  I do not understand your idea or why it will be useful.  Can you take my function and rewrite it to demonstrate what you are talking about?

Tom
0
 
Tom KnowltonWeb developerAuthor Commented:
Zoppo:

In regards to your posted code:

HINSTANCE appinstance = AfxGetInstanceHandle();
 CStatic pStatic;

//Here, GetDlgItem is a member function of pStatic.  You don't need to cast it.
 pStatic = (CStatic*)GetDlgItem(IDC_STATIC_BIT7);



//Here, pStatic was not declared as a pointer, so you don't need to use -> to access member function SetBitmap.
 pStatic->SetBitmap(HBITMAP (LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));
0
 
ZoppoCommented:
sorry, forgot the * before the pStatic:

void CRoom04Dlg::OnStaticBit7()
{
 HINSTANCE appinstance = AfxGetInstanceHandle();
 CStatic *pStatic;
 pStatic = (CStatic*)GetDlgItem(IDC_STATIC_BIT7);
 Static->SetBitmap(HBITMAP (LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));
}

ZOPPO
0
 
Tom KnowltonWeb developerAuthor Commented:
Zoppo:

It worked...but WHY did it work?  Can you explain what difference declaring pStatic as a pointer makes?

Please explain your rational for each line of your function.  I want to learn why this code works, not just blindly use it.

The points are yours!

I will reject Amor_'s answer (sorry Amor_).  Zoppo, please repost your *corrected* code as an answer.

Thanks,

Tom
0
 
Tom KnowltonWeb developerAuthor Commented:
Adjusted points from 10 to 20
0
 
Tom KnowltonWeb developerAuthor Commented:
Nevermind about reposting.  I forgot about "Accept comment as answer".

Thanks again.

Tom
0
 
Amor_Commented:
knowlton:
 Add Button to your dialog in size of your bitmap( by using Class Wizard or other way). In your Dialog Class add
variable CBitmapButton but.
In Dialog Constructor write next code:
but.LoadBitmaps(1,2,3,4) where num are
id of the bitmaps.
first bitmap is picture "off"
third bitmap is picture "on"
second bitmap is when button is down.
If you dont want use button,simple disable it.
In InitDialog add next:
VERIFY(but.SubclassDlgItem(ID_Button, this));
but.SizeToContent();
 
 
0
 
ZoppoCommented:
you're welcome          :)

have a nice day,

regards,

ZOPPO
0
 
Tom KnowltonWeb developerAuthor Commented:
Zoppo:

So you're not going to explain the code to me?  :(

Well, thanks anyway.

Tom
0
 
Tom KnowltonWeb developerAuthor Commented:
Amor_:

Your answer probably works fine, but it is more complex than it needs to be for what I am doing.

Thanks!

Tom
0
 
ZoppoCommented:
Hi knowIton,

here's a brief explanation:

void CRoom04Dlg::OnStaticBit7()
{
 HINSTANCE appinstance = AfxGetInstanceHandle();
 CStatic *pStatic;
 pStatic = (CStatic*)GetDlgItem(IDC_STATIC_BIT7);
 Static->SetBitmap(HBITMAP (LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));
}

GetDlgItem() returns a a pointer to a (temporary) CWnd object which represantates the control with given ID. We then cast this CWnd pointer to CStatic to make it possible to call a CStatic member function for this control.
--------------------------------------------------------------------------------------------
CAUTION: This pStatic pointer is not really a pointer to a CStatic object but a pointer to a generic CWnd object. Calling a member function of the CStatic pointer only works here because the function itself does simply send a message to the window (so no function call or member access of in the CStatic class occurs). You cannot use this method if you want i.e. call a function which directly accesses some data or function of the CStatic (or any other derived class), i.e. if you implement your own CStatic derived class with i.e. a virtual function which uses any member you've implemented, a call against an object returned by GetDlgItem() will crash. For such a case you'll have to subclass the control.
--------------------------------------------------------------------------------------------
The SetBitmap() then just sends the control the STM_SETIMAGE message which then is handled by the static control's window procedure.

further question?

ZOPPO
0
 
Tom KnowltonWeb developerAuthor Commented:
So WHY doesn't a normal CStatic variable work here?  That still is not quite clear.

If you took the same code above but used a normal CStatic variable, what would be the difference?  I mean, other than the fact it wouldn't work properly?

Thanks.
0
 
ZoppoCommented:
The problem with your code was simply that subclassing a window to a CWnd-derived object 'attaches' this window to the CWnd object in the same manner as CWnd::Attach() does. Then, the destructor of the CWnd-derived object causes the window to be destroyed (take a look at the CWnd-destructor at file wincore.cpp, about line 745). You could also have your problem solved by calling CWnd::UnsubclassWindow() or by using Attach()/Detach() instead of subclassing the control, but each of these solutions implicies overhead which is not needed, i.e. you never need to create a CWnd-derived object on the stack and call its constructor.

Here's the same code using Attach()/Detach() as example:

void CRoom04Dlg::OnStaticBit7()
{
 HINSTANCE appinstance = AfxGetInstanceHandle();
 CStatic m_static;
 m_static.Attach(GetDlgItem(IDC_STATIC_BIT7));
 m_static.SetBitmap(HBITMAP(LoadBitmap(appinstance,MAKEINTRESOURCE(IDB_BITMAP_ON))));
 m_static.Detach(); // have to do this to avoid the CStatic's dtor destroyes the control
}

ZOPPO
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 8
  • 6
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now