3
votes

I'm new to MFC (coming from C# and Java) and figuring things out.

Consider a dialog with three text boxes. I have subclassed CEdit to CMyEdit, and the three text boxes are hooked up to CMyEdit variables in the dialog class.

I want to allow the dialog class to "know" when any of the three text boxes has been clicked with the left mouse button. I have found examples of how to add an ON_WM_LBUTTONDOWN handler to my CMyEdit class. Works great, but the handler is in the CMyEdit class only. Suppose that whenever one of the text boxes is clicked, I want the dialog to disable the other two. How can I get the dialog notified of the left-click?

This is a completely contrived and simplified example. I don'nt actually have an app where I'm worried about left clicks in text boxes. But I think the fact that I can't figure out how to do it indicates a fundamental misunderstanding of how to deal with UI events in MFC.

Coming from the world of C#, where everything is done for me and I have direct access to any of the events I want (got focus, mouse double click, whatever) I'm very confused on why certain events are special and provide easy access. In the case of CEdit, I don't understand why got focus, kill focus, change, and several others are "directly" available to me with no problem, but other events, like mouse click, are not.

But back to my actual question: in the scenario described above, how can I get the dialog notified of the left mouse clicks on the text boxes? Do the text boxes need to raise events or send messages (or something else) to the dialog?

1

1 Answers

3
votes

Add a WM_LBUTTONUP handler to your message map

ie

BEGIN_MESSAGE_MAP(CYourDialog, CDialog)
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

It is easiest to do this by adding an event handler to the window. This is most easily done through the resource editor. Go to the properties page then go to the messages section. Then add a function for WM_LBUTTONUP.

Finally you could fill in the function as follows.

void CYourDialog::OnLButtonUp(UINT nFlags, CPoint point)
{
    // Grab the 3 (or more) edit control
    CEdit* pEdit1   = (CEdit*)GetDlgItem( ID_YOUR_EDIT_CONTROL1 );
    CEdit* pEdit2   = (CEdit*)GetDlgItem( ID_YOUR_EDIT_CONTROL2 );
    CEdit* pEdit3   = (CEdit*)GetDlgItem( ID_YOUR_EDIT_CONTROL3 );

    // Grab the edit control window rects in screen coords.
    CRect edit1Rect;
    CRect edit2Rect;
    CRect edit3Rect;
    pEdit1->GetWindowRect( &edit1Rect );
    pEdit2->GetWindowRect( &edit2Rect );
    pEdit3->GetWindowRect( &edit3Rect );

    // Convert to client coordinates relative to their parent (ie this) window.
    ScreenToClient( edit1Rect );
    ScreenToClient( edit2Rect );
    ScreenToClient( edit3Rect );

    // Test if the point passed in to this function is in the control's rectangle.
    const BOOL bEnable1 = edit1Rect.PtInRect( point );
    const BOOL bEnable2 = edit2Rect.PtInRect( point );
    const BOOL bEnable3 = edit3Rect.PtInRect( point );

    // Enable the window that was clicked on and disable the others.
    pEdit1->EnableWindow( bEnable1 );
    pEdit2->EnableWindow( bEnable2 );
    pEdit3->EnableWindow( bEnable3 );

    // Set keyboard focus to the relevant control
    if      ( bEnable1 )
    {
        pEdit1->SetFocus();
    }
    else if ( bEnable1 )
    {
        pEdit2->SetFocus();
    }
    else if ( bEnable1 )
    {
        pEdit3->SetFocus();
    }

    CDialog::OnLButtonUp(nFlags, point);
}

This will, essentially, hit test and if the hit test is in an edit window it will enable it, disable the others and give it keyboard focus.