Solved

Buttons. Easy, very easy.

Posted on 2000-03-29
13
193 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
ID: 2666971
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
ID: 2667009
Uppsss!!

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

(Error C2039)
0
 

Author Comment

by:javigil1
ID: 2667018
..of the CWnd class, sorry!
0
 

Expert Comment

by:asavard
ID: 2667034
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
ID: 2667271
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
ID: 2667300
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 11

Accepted Solution

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

Thanks for being gracious about the points, RONSLOW.

..B ekiM
0
 
LVL 10

Expert Comment

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


0
 

Expert Comment

by:asavard
ID: 2669353
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
ID: 2669806
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
ID: 2672667
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
ID: 2673350
> 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
ID: 2678554
>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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
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.
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…

910 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

23 Experts available now in Live!

Get 1:1 Help Now