Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ending a combo box edit by loosing focus ends the edit to accept the new value #11

Closed
GoogleCodeExporter opened this issue Mar 16, 2015 · 3 comments

Comments

@GoogleCodeExporter
Copy link

You can end a combo box edit by clicking away to loose focus on the
control. This ends up setting a new value for the cell, even if the user
never selected or typed in anything.

What steps will reproduce the problem?
1. Put a break point in CGridListCtrlEx::OnEndLabelEdit
2. Select a cell in the State column so that the combo box shows
3. Click somewhere else in the control so the edit looses focus
4. Notice the breakpoint in OnEndLabelEdit gets hit, even though you didn't
type in anything

What is the expected output? What do you see instead?
The problem is that CGridEditorComboBoxEdit sends the WM_KEYUP message with
VK_RETURN, even if the value was not modified. The solution is to send
VK_ESCAPE if the value was not modified.

I've copied the changes to the code below. I've just added a new member to
CGridEditorComboBoxEdit and use this to track if the value has actually
been changed.


*******************CGridColumnTraitCombo.h**********************:

class CGridEditorComboBox : public CComboBox
{
public:
    CGridEditorComboBox(int nRow, int nCol, int nMaxWidth);

    virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,
UINT nID);
    virtual void EndEdit(bool bSuccess);

protected:
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnNcDestroy();
    afx_msg void OnDestroy();
    afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg UINT OnGetDlgCode();
    afx_msg void OnDropDown();
    afx_msg void OnCloseUp();
    afx_msg void OnEditChange();    
    afx_msg void OnChangeSelection();   

    DECLARE_MESSAGE_MAP();

    CGridEditorComboBoxEdit m_Edit; //!< Subclassed edit control inside the
CComboBox
    bool    m_Completed;            //!< Ensure the editor only reacts to a single close event
    int     m_Row;                  //!< The index of the row being edited
    int     m_Col;                  //!< The index of the column being edited
    int     m_MaxWidth;             //!< Max width (in pixels) of the CComboBox when doing
dropdown
    bool    m_Modified;             //!< If the value has been modified (should process
EndEdit(true))
};

*******************CGridColumnTraitCombo.cpp**********************:

BEGIN_MESSAGE_MAP(CGridEditorComboBox, CComboBox)
    //{{AFX_MSG_MAP(CGridEditorComboBox)
    ON_WM_KILLFOCUS()
    ON_WM_GETDLGCODE()
    ON_WM_DESTROY()
    ON_WM_KEYUP()
    ON_WM_NCDESTROY()
    ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseUp)
    ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown)
    ON_CONTROL_REFLECT(CBN_EDITCHANGE, OnEditChange)
    ON_CONTROL_REFLECT(CBN_SELCHANGE, OnChangeSelection)
    ON_CONTROL_REFLECT(CBN_SELENDOK, OnChangeSelection)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()


//------------------------------------------------------------------------
//! CGridEditorComboBox - Constructor
//------------------------------------------------------------------------
CGridEditorComboBox::CGridEditorComboBox(int nRow, int nCol, int nMaxWidth)
    :m_Row(nRow)
    ,m_Col(nCol)
    ,m_Completed(false)
    ,m_MaxWidth(nMaxWidth)
    ,m_Modified(false)
{}

//------------------------------------------------------------------------
//! The cell value editor was closed and the entered should be saved.
//!
//! @param bSuccess Should the entered cell value be saved
//------------------------------------------------------------------------
void CGridEditorComboBox::EndEdit(bool bSuccess)
{
    // Avoid two messages if key-press is followed by kill-focus
    if (m_Completed)
        return;

    m_Completed = true;

    // Send Notification to parent of ListView ctrl
    CString str;
    GetWindowText(str);

    LV_DISPINFO dispinfo = {0};
    dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    dispinfo.hdr.idFrom = GetDlgCtrlID();
    dispinfo.hdr.code = LVN_ENDLABELEDIT;

    dispinfo.item.iItem = m_Row;
    dispinfo.item.iSubItem = m_Col;
    if (bSuccess && m_Modified)
    {
        dispinfo.item.mask = LVIF_TEXT | LVIF_PARAM;
        dispinfo.item.pszText = str.GetBuffer(0);
        dispinfo.item.cchTextMax = str.GetLength();
        dispinfo.item.lParam = GetItemData(GetCurSel());
    }
    ShowWindow(SW_HIDE);
    GetParent()->GetParent()->SendMessage( WM_NOTIFY,
GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo );
    PostMessage(WM_CLOSE);
}

//------------------------------------------------------------------------
//! CBN_EDITCHANGE message handler called when the edit control for the
CComboBox control
//! has been modified.
//------------------------------------------------------------------------
void CGridEditorComboBox::OnEditChange()
{
    m_Modified = true;
}


//------------------------------------------------------------------------
//! CBN_SELCHANGE, CBN_SELENDOK message handler called when the selection
in the CComboBox control
//! has been modified.
//------------------------------------------------------------------------
void CGridEditorComboBox::OnChangeSelection()
{
    m_Modified = true;
}

Original issue reported on code.google.com by garretf...@gmail.com on 30 Sep 2009 at 1:22

@GoogleCodeExporter
Copy link
Author

Oops. I accidentally described my initial solution which had a problem. The 
solution
is to detect in CGridEditorComboBox whether the value has been modified, and 
only do
the set the text in the LV_DISPINFO if the value was modified.

I added a member to CGridEditorComboBox, not to CGridEditorComboBoxEdit.

Original comment by garretf...@gmail.com on 30 Sep 2009 at 1:27

@GoogleCodeExporter
Copy link
Author

Just tested the LVS_EDITLABELS in a vanilla CListCtrl, and yes you are correct 
that 
if no changes are made, then a LVN_ENDLABELEDIT notification is sent with NULL 
string.

I will update the different editable column-traits, so the behavior is the same.

Original comment by sweaty1 on 30 Sep 2009 at 7:54

@GoogleCodeExporter
Copy link
Author

I have now implemented check for modifications in the CEdit, CComboBox and 
CDateTimeCtrl editor. When the editor closes and no modifications was detected, 
then 
the parent will see it as the editing was cancelled.

Original comment by sweaty1 on 30 Sep 2009 at 9:37

  • Changed state: Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant