Solved

How to disable or hiding a button at run-time?

Posted on 2000-03-08
22
450 Views
Last Modified: 2010-04-02
As my MFC VC++5.0 application is starting I want to check for the exisitance of a Help file, say 'xyz.hlp', and then disable or hide a Help button on my main menu dialog box depending on the exisitance this help file.

My background in VC++ is very limited so your answer or further questions will need to be very explicit. That's why I'm offering so many points.
0
Comment
Question by:vivitron
  • 8
  • 6
  • 3
  • +4
22 Comments
 
LVL 4

Expert Comment

by:abancroft
ID: 2597075
MFC has a neat mechanism for updating the state (enabled, disabled, checked, pushed etc) of controls.

It's all based around the ON_UPDATE_COMMAND_UI() macro.

Normally, this is used to enable/disable toolbar buttons. But it was designed to be able to update the state of any control - including those on a dialog box.

I need some further info:
1. Is this a dialog based app?
2. Where is the 'Help' button: on a toolbar or is it a control on the main window or somewhere else?
0
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 2597147
In your dialog's OnInitDialog function, you can use this code to disable the help button (this assumes the ID of your help button is IDHELP, if not, replace IDHELP with your ID):

BOOL CMyDialog::OnInitDialog()
{
  CDialog::OnInitDialog();
  GetDlgItem(IDHELP)->ShowWindow(SW_HIDE);
}

If you want to later turn it on, pass SW_SHOWNORMAL to ShowWindow().
0
 

Author Comment

by:vivitron
ID: 2597169
Answers to Abancroft questions of 3-8-00 at 10:38AM:

1. Yes this is a dialog based app.

2. The 'Help' button is a control on the main menu dialog box. The event 'Class or object handle' property is of IDC_BUTTON_HELP.
0
 
LVL 4

Expert Comment

by:abancroft
ID: 2597172
Doh! That'll be MUCH easier.

You'll need to disable it as well, else the user will be able to tab to it:
  GetDlgItem(IDHELP)->EnableWindow(FALSE);
0
 
LVL 4

Expert Comment

by:abancroft
ID: 2597177
(I was replying to Thui's post)
0
 

Author Comment

by:vivitron
ID: 2597906
I inserted the statement 'GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_HIDE)' and it worked. The 'Help' control button was hidden on the main menu dialog box.  Answer me why using this same statement for a 'Help' control button on a different dialog box that has the same button ID does not work?
0
 
LVL 2

Expert Comment

by:xLs
ID: 2598295
if you mean the button on the caption (system menu) this is how you would do it

::OnInitDialog()
{

....

CMenu* mmenu = GetMenu();
CMenu* submenu = mmenu->GetSubMenu(FALSE);
submenu->EnableMenuItem(ID_HELP, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);

}

ID_HELP is whatever your message is called

if not, they boys above are right and you are wrong :)

cheers
0
 

Author Comment

by:vivitron
ID: 2605319
I don't know what xLs is talking about, "caption (system menu)"?  These are dialog boxs that were made for this application.

In the application a dialog box is normally called like:

some control( Config_Header_Data_Dlg.DoModal() == some button )

The some button property ID name is 'IDC_BUTTON_HELP'.

Please indicate how and where to place your proposed answer. Thank you.
0
 

Expert Comment

by:namrata
ID: 2610676
Hello vivitron,

I am also novice in VC++ 5.0 programming.
sorry, I couldnt understand why the same code is not working in for other dialog box. Did u write that code in that other dialog's cpp file?
Regards,
Namrata
0
 

Author Comment

by:vivitron
ID: 2617620
I did not write any of the code in this program, I'm just trying to make it operate as expected.  My background is in 'C' not 'C++' so that is why I ask for specific answers.

Thank for your concern,
Vivitron.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2619954
if you get the button id correct, the code given will work in any dialog.

Just make sure you put it in the OnInitDialog.

Also I'd try setting some breakpoints in debug mode and see if the code is even being called in your other dialog.

ALSO: Be careful the the GetDlgItem doesn't return a NULL value because there is no control with that id.  This wil cause all sorts of problems.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:vivitron
ID: 2620474
In the code there is only one location where I can find the OnInitDialog().  This file.h location also has other code as follows:

virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonDownload();
afx_msg void OnButtonConfigureWra();
afx_msg void OnButtonTransferFiles();
afx_msg void OnButtonViewEngUnits();
afx_msg void OnButtonHelp();
afx_msg void OnButtonSetClock();

Are these OnButton~~~() the same as OnInitDialog().  If they are, I tried placing every suggested code example at the beginning of these modules.  The suggestion from "thui" dated 3/8/2000 @ 10:59AM would work only at the OnInitDialog() for the first (main nenu) at program start.  Thui, and all other suggestions have failed on the dialog boxes.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2621516
OnInitDialog is called when the dialog is first dislayed (by the call to DoModal).  It only gets called once until the dialog is closed and DoModal returns.

The OnButtonXXXX are called when the user clicks on the corresponding button (there will be a message map in the .cpp file that associates control ids with the OnButtonXXXX functions).

The OnPaint, OnQueryDragIcon, OnSysCommand are usually there so that the dialog behave properly when minimized (if it is a dialog-based application).

If there is only one file.h like this, then you only have source code for one dialog.  You'd need to show us the code for these other dialogs you are talking about.  Perhaps they are in other exe files or in dlls that have their source somewhere else.
0
 
LVL 1

Expert Comment

by:Amor_
ID: 2623307
In order to disable button you should define pointer to CButton and in constructor link it to ID of the button:
 f.e. :
Btn = (CButton*)GetDlgItem(IDOK);
and to disable/enable:
PrevBtn->ModifyStyle( 0, WS_DISABLED);
PrevBtn->ModifyStyle( WS_DISABLED, 0);
************************
To disable MenuItem use this:
add in .h file in message map functions
this function:
afx_msg void OnUpdateHelp(CCmdUI*pCmdUI);

in .cpp file in Begin_Message_Map:
ON_UPDATE_COMMAND_UI(ID_Help,OnUpdateHelp)

and in the function OnUpdateHelp add:
  pCmdUI->Enable( true/false );
 




0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2623460
Amor: NO !!!

You cannot do this in the constructor, because the dialog window does not exist yet, so GetDlgItem will not work.

Base place for MFC CDialog is usually in OnInitDialog.  Otherwise, try OnCreate.  If neither exist, then you'll have to create one (I'd go for OnInitDialog).

These functions are only called once each and only after the dialog window is created (so GetDlgItem will work).

Even better and easier is to use DDX_Control to associat a CButton member var (say m_helpbutton) with the control.  Then you just say
  m_helpbutton.EnableWindow(FALSE);
  m_helpbutton.ShowWindow(SW_HIDE);
etc.

if in OnInitDialog, do this AFTER the call to the base class CDialog::OnInitDialog);
0
 
LVL 1

Expert Comment

by:Amor_
ID: 2623549
RONSLOW: Surely you are right.
         GetDlgItem don't works in constructor.
          Sorry for misleading.
 
0
 

Author Comment

by:vivitron
ID: 2624729
Is this an answer, RONSLOW says its not.

RONSLOW asked to see the code. Here's the code part everyone seems to be talking about in the .cpp file. Can you determine where and how to implement your Answers? Please show me.

BOOL CMdpsDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);

    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);

        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    SetIcon(m_hIcon, TRUE);   // Set big icon
    SetIcon(m_hIcon, FALSE);  // Set small icon

    ComputerSpeedDlg computer_speed_dlg;
    computer_speed_dlg.Create(IDD_COMPUTER_SPEED);
    computer_speed_dlg.ShowWindow(SW_SHOW);
    computer_speed_dlg.RedrawWindow();
    computer_speed_dlg.Determine_Computer_Speed();
    computer_speed_dlg.EndDialog(IDOK);

    MDPS_User_Info_Dlg user_info;

    do
    {
        user_info.DoModal();

        if (user_info.m_name.GetLength() < 3)
        {
            Display_Message("Enter a full first and last name!  The entered name has less than 3 letters.");
            continue;
        }

        if (user_info.m_squadron.GetLength() < 2)
        {
            Display_Message("Enter the full squadron name!  The entered name has less than 2 characters.");
            continue;
        }

        if (user_info.m_phone_number.GetLength() < 10)
        {
            Display_Message("Enter the area code plus the phone number.  For example, 301-324-2442.  The entered phone number is less than 10 numbers.");
            continue;
        }
        break;
    }
    while (1);

    global_operator_name = user_info.m_name;
    global_operator_phone_number = user_info.m_phone_number;
    global_operator_squadron = user_info.m_squadron;

    return TRUE;  // return TRUE  unless you set the focus to a control
}

/***********************************************************************/
void CMdpsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}

/***********************************************************************/
void CMdpsDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

HCURSOR CMdpsDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

/****************************************************/
void CMdpsDlg::OnButton~~~~~()
{
    ShowWindow(SW_HIDE);
    ~~~~~~
    module code
    ~~~~~~
    ShowWindow(SW_SHOW);
}

This void CMdpsDlg::OnButton~~~~~() is repeated for each button.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2625315
The coide you are showing makes the DIALOG disappear and reappear every time you push a button.

If that correct behaviour?  Seems a bit odd, unless it needs to disappear so that you can see/capture something underneath.

What you need to do is put lines into OnInitDialog just after the line CDialog::OnInitDialog(); like this

   GetDlgItem(IDC_xxxx)->ShowWindow(SW_HIDE);

For each button you want to make invisible in the main MdpsDlg.

To make buttons in the toerh dialogs disappear, you'll need to edit the code for them similarly.

Also, there is some strange code/behaviour there where it quickly creates a ComputerSpeedDialog, displays and kills it (user might just see a flash) .. very wierd.

Looks like this code needs a lot of work !!! (or at least some comments explaining why it is so odd).

0
 

Author Comment

by:vivitron
ID: 2628912
To RONSLOW in response to 3/16/00 @ 1:48PM answer,

In the CMdpsDlg::OnInitDialog() I did place
GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_HIDE);
right after the CDialog::OnInitDialog() statement and the HELP button on the main menu was hidden.  I used
GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_SHOWNORMAL);
to again show the button. This would only work for the main menu. In the void CMdpsDlg::OnButton~~~~() modules I placed the same
GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_HIDE);
statement after the ShowWindow(SW_HIDE); statement and before the the statement
if( Config_Header_Data_Dlg.DoModal() == some button ).
The HELP button for the dialog boxes displayed in these OnButton~~~~() would not hide.  This is where your expert help is needed. Are you saying these HELP buttons should also be hidden by the statement
GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_HIDE);?

There is code behind the ComputerSpeedDialog statements that calculate the speed of the computer and this progress bar is displayed for about 30 seconds.

The ShowWindow(SW_HIDE); and ShowWindow(SW_SHOW); are used to hide/show the main menu. This is what was wanted.

Thanks for your continued help,
vivitron.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2633083
You cannot hide the button of one dialog from another like this.  The code to hide the button needs to be in the other dialog.  This has been said before.

ie. if you want to get rid of a button in the Config_Header_Data_Dlg, then you need to add code to THAT DIALOG to do so.  Hiding the help button control on the MAIN menu won't help.

You need to edit each dialog in which the help button is to be disabled and (say) in the OnInitDialog for each of these, do a GetDlgItem(...)->ShowWindow(SH_HIDE or SW_SHOW) as appropriate.

NOTE: part of the reason why you cannot turn the help button on one of your other dialogs on and off from your main menu is that the other dialogs only exist while the DoModal is running.  
0
 

Author Comment

by:vivitron
ID: 2642531
I'll explain again!

I have done a global search in the *.cpp and *.h files and there are NO OTHER OnInitDialog() used with the OnButton~~~~() routines.  Is this why the statement GetDlgItem(IDC_BUTTON_HELP)->ShowWindow(SW_HIDE); at the beginning of EACH of the OnButton~~~~() routines DOES NOTHING?

If this is TRUE, then what must be written and where do I place these new OnInitDialog() routines?
0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 200 total points
ID: 2642549
The dialogs classes MUST be delcared somewhere.

if they don't already have OnInitDialog's then put them in (Use ClassWizard if you can - it does the word for you, otherwise manually add it, and make sure the you call the base class CDialog::OnInitDialog() in it).

Then put in the code to disable the appropriate buttons.
0

Featured Post

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

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

746 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

12 Experts available now in Live!

Get 1:1 Help Now