Solved

Buttons. Easy, very easy.

Posted on 2000-03-29
13
189 Views
Last Modified: 2013-11-20
How can I enable/disable a button? I mean, within a programm (not with the resource editor)  Which code do I have to use?
0
Comment
Question by:javigil1
  • 5
  • 4
  • 2
  • +1
13 Comments
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
In MFC, assuming your coding a member function of your CDialog-derived class where the button lives:

   CWnd* pWnd = GetDlgItem(IDC_YOURBUTTONID);

   // to disable
   pWnd->Enable(FALSE);

   // to enable
   pWnd->Enable(TRUE);

In Plain Windows SDK without MFC:

   HWND hw;
   hw = GetDlgItem(hwndDialog, IDC_YOURBUTTONID);

   // to disable
   EnableWindow(hw, FALSE);

   // to enable
   EnableWindow(hw, TRUE);

..B ekiM
0
 

Author Comment

by:javigil1
Comment Utility
Uppsss!!

The compiler says that "Enable" is not a component of the CWind class.

(Error C2039)
0
 

Author Comment

by:javigil1
Comment Utility
..of the CWnd class, sorry!
0
 

Expert Comment

by:asavard
Comment Utility
Try this (which is kinda like the same as mikeb answer)

CButton *pBtn = (CButton *)GetDlgItem(ID_BUTTON);

then, to enable :

pBtn->EnableWindow(TRUE);

and to this disable:
pBtn->EnableWindow(FALSE);

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
No need to cast to CButton*.

In fact (strictly speaking) it is not correct to do so, because GetDlgItem returns a pointer to a CWnd object, not a pointer to a CButton object.

However, as you are calling a CWnd function anyway, it won't hurt.

Genreally, I use ClassWizard / DDX_Control to associate member variables (eg a CButton member).

In that case, assuming that you associate CButton m_mybutton, then you'd simply say:

  m_mybutton.EnableWindow(true);

no need for GetDlgItem etc, as that is all done for you by MFC.

MIKE: You've basically provided the answer .. how about you submit again with the corrections.

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
The corrected code (in case Mike doesn't respond) should be

   CWnd* pWnd = GetDlgItem(IDC_YOURBUTTONID);
   // to disable
   pWnd->EnableWindow(FALSE);
   // to enable
   pWnd->EnableWindow(TRUE);

In Plain Windows SDK without MFC:

   HWND hw = ::GetDlgItem(hwndDialog, IDC_YOURBUTTONID);
   // to disable
   ::EnableWindow(hw, FALSE);
   // to enable
   ::EnableWindow(hw, TRUE);

And (my preference), use class wizard to associate a CButton member variable with the control, then you get:

   // to disable
   m_mybutton.EnableWindow(FALSE);
   // to enable
   m_mybutton.EnableWindow(TRUE);


0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 11

Accepted Solution

by:
mikeblas earned 75 total points
Comment Utility
Yep! Sorry--I meant CWnd::EnableWindow().

Thanks for being gracious about the points, RONSLOW.

..B ekiM
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
anytime, Mike .. your answer was correct (in spirit at least).  We all make typos and slip-ups :-)


0
 

Expert Comment

by:asavard
Comment Utility
RONSLOW,

Just asking, is it that bad to cast the pointer to the type the window really is?  I mean, isn't CEdit (and all others controls) a specialisation of CWnd?  I know you said "strictly speaking", just wondering if there are any implications to doing so, other than the fact GetDlgItem returns a CWnd pointer?  (Anyway i use member variables usually, but sometimes i use this method to reduce the number of them when control is only used in one function or so).

Bye!

Alex
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
In this case, you'll never have a problem casting to CButton* if you know that ID_SOMETHING refers to a window of class "BUTTON".

..B ekiM
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
asaward:

GetDlgItem will only return a pointer to a CTempWnd (directly derived from CWnd) UNLESS you have alreday subclassed the control yourself (eg. used DDX_Control).  It will NOT return a pointer to a CButton at all.

For most simple MFC control classes, you can get away with it because there are no virtual functions being called and no data members in those classes.  However, anything other than simple MFC-defined CWnd-derived simple control classes, you can get into trouble.

Strictly speaking what is going on there is bad code.  It is exactly equivalent to this:

class Base {
 ...
};
class Derived : public Base {
 ...
 void f();
};

Base base;
(Derived*) p = (Derived*)(&base);
p->f();

so you are calling a member function of class Derived on an object that is NOT of type class Derived.

If f() were a virtual function, or class Derived had memeber variables accessed in f(), then you'd be in big trouble.

Fortunately, as I said, the simple MFC control classes don't add any virtual functions or member variables.  However, some of the more complicated (like CCheckListBox), do.  But, if you were using these classes, you'd almost have to be subclassing anyway.

Unless you REALLY need a CButton-defined function, use CWnd* instead of CButton*. In your case, EnableWindow is a CWnd function, so make store the value returned by GetDlgItem as a CWnd*.

MIKE: The window class makes little difference (other than whether the control knows how to handle the specific message).  Few if any MFC classes check the window class.  What DOES make a difference is the class you cast the return of GetDlgItem to.  If you cast it to CButton* then you are safe (with the current implementation of MFC) .. indeed, you could happily write the code as

  CEdit* p = (CEdit*)GetDlgItem(ID_MYBUTTON);
  p->EnableWindow(TRUE);

and everything would still be fine.  If you called a CEdit defined function, the button would just not respond to the message.  But this cast is just bad code.  The CButton cast is only a little better, but not technically good code either.

To be techincaly correct, if you need to use anything other then CWnd-defined functions, then you should subclass the control .. whether by DDX_Control or directly.
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
> Few if any MFC classes check the window class.  

Actually, they all will end up sending window class-specific messages to the target window.  Since message IDs overlap, it's possible to send a message to a window and have that message do something unexpected when it reaches a window that's actually of a different type. There doesn't need to be an test for the actual window class name to have a problem.

 > indeed, you could happily write the code as

     CEdit* p = (CEdit*)GetDlgItem(ID_MYBUTTON);
     p->EnableWindow(TRUE);

 > and everything would still be fine.  

Sure. But, what if you code

   p->SetCurSel(35, 125);

or

   p->GetLine(strFoo);

?

On second thought, I guess it's not a problem. Now that I look at WINUSER.H, these messages seem to be defined to not overlap; I must be remembering Win16, where I thought they were of the form (WM_USER + x), and the values used for (x) overlapped for all the different styles.

I guess, again, the worst thing which'll happen is that your code just won't work.

..B ekiM
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
>Actually, they all will end up sending window class-specific messages to the
....

Quite true .. but only for WM_USER messages (some control use these internally i think).

>Sure. But, what if you code ...

I certainly wasn't for a moment suggesting that it was something you SHOULD do .. just an example of some bad code that happens to work.

The point I was making is that even if some code does work given the current definition/implementation of MFC etc, that doesn't make it good code.

Of course, good and bad code isn't a black and white issue .. especially when you have to work with / around the limitations of a framework such as MFC.  Sometime you have to do something not quite kosher .. or it is just simpler to do so (and sometimes simple and clear code is better than doing the 'right' thing).
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
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.
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…

763 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

7 Experts available now in Live!

Get 1:1 Help Now