Question

I'm writing a WTL Aero wizard and I'd like to gray out the window's Close button (its first step will require no user interaction and can not be canceled, so disabling the button is perfectly appropriate).

Putting the following code:

CMenuHandle pMenu = GetSystemMenu(FALSE);
pMenu.EnableMenuItem(SC_CLOSE, FALSE);

in OnInitDialog does not work, as the procedure is called before the window itself is displayed on the screen (the ATLASSERT(::IsMenu(m_hMenu)); assertion in EnableMenuItem is tripped at runtime).

Is there an elegant way to disable the Close button? (I'm a WTL beginner, and I'd like the solution to be as clean as possible).

This is a minimal version of the wizard's page code:

#include "stdafx.h"

class MainPage : public CAeroWizardPageImpl<MainPage> {
public:
    BEGIN_MSG_MAP(MainPage)
        MESSAGE_HANDLER_EX(WM_INITDIALOG, OnInitDialog)
        CHAIN_MSG_MAP(__super)
    END_MSG_MAP()

    enum {
        IDD = IDR_MAINFRAME
    };

    MainPage() : CAeroWizardPageImpl<MainPage>(IDR_MAINFRAME) {
        /* Set the wizard's title */
        m_headerTitle.LoadString(IDS_INSTALLHEADER);
        SetHeaderTitle(m_headerTitle);
    }
private:
    CString m_headerTitle;
    LRESULT OnInitDialog(UINT message, WPARAM wParam, LPARAM lParam) {
        UNREFERENCED_PARAMETER(message);
        UNREFERENCED_PARAMETER(wParam);
        UNREFERENCED_PARAMETER(lParam);

        /* Disable the wizard buttons and center the window */
        ShowWizardButtons(0, 0);
        EnableWizardButtons(PSWIZB_BACK, 0);
        CenterWindow();
        return TRUE;
    }
};
Was it helpful?

Solution

The close [X] button is a part of Common Controls wizard property sheet class. You are not supposed to alter its presentation and behavior. What you can do is to handle PSN_QUERYCANCEL notification and prevent wizard from closing. With WTL it is easy, however you need to know that that there are two versions of notifications handlers available.

If _WTL_NEW_PAGE_NOTIFY_HANDLERS is defined, typically in stdafx.h, then you do it like this:

class MainPage :
    public CAeroWizardPageImpl<MainPage>
{
// ...
    INT OnQueryCancel()
    {
        return 1; // Zero to Allow Wizard Close
    }
};

Otherwise, older syntax is in use:

class MainPage :
    public CAeroWizardPageImpl<MainPage>
{
// ...
    BOOL OnQueryCancel()
    {
        return FALSE; // Allow Wizard Close?
    }
};

Along with preventing cancellation/close you are free to indicate this by showing a message box suggesting use to wait until the pending operation is completed, or otherwise display a notification (e.g. flash a static control etc.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top