Solved

Problems with combobox

Posted on 2000-04-14
13
377 Views
Last Modified: 2013-11-20
I have the following code for the "change text" event in a combobox:

void CFhgDlg::OnEditchangeSc()
{

      CEnsemble* elementt;
      CString str;
      EnableApply();

      int tab=m_CTab.GetCurSel();
      int NoOfSC=m_SC.GetCurSel();  
      UpdateData(false);
      elementt=lista1.SearchList(tab);
      m_SC.GetWindowText(str);  
      elementt->ListOfSC[NoOfSC].SC_Label=str;      
}

The last line:
elementt->ListOfSC[NoOfSC].SC_Label=str;
...produces an assertion error.
Well, I can change one character of the name of the selected item, but when I try to change the second one, I get the assertion error.

I have exactly the same code with a text field, and I dont get any error at all, so I think my problem has something to do with the combobox itself. Can somebody help me?      
0
Comment
Question by:javigil1
  • 6
  • 4
  • 3
13 Comments
 
LVL 30

Expert Comment

by:Zoppo
ID: 2715157
how is this 'CEnsemble' declared?
where exactly does the assertion occur?
0
 

Author Comment

by:javigil1
ID: 2715189
class CEnsemble: public CObject
{
protected:
      CString Name;
      CEnsemble *nextNode;
    int number;
public:
      int NoOfSCs;
      DWORD Identifier;
      CEnsemble(CString);                        //Constructor
      void WriteName (CString);                  //Escribe el campo Name
    CString ReadName ();                        //Lee el campo Name
      void WriteNameR (CString);                  //Escribe en el registro
      CString ReadNameR ();                        //Lee en el registro
    CEnsemble* GetNextPtr();            //get pointer to the next node
      void SetNextPtr (CEnsemble*);      //set next node pointer
      void SetNumber (int);
      int GetNumber();
      SC ListOfSC[20];
};


Well, I have located the problem, but I dont see the solution yet.
In the line       
int NoOfSC=m_SC.GetCurSel();  

....I get NoOfSC=-1
when I make the second change in the string, and this provokes the assertion error.
But I dont know why do i get such a value.

0
 

Author Comment

by:javigil1
ID: 2715228
More detailed explanation of my problem:
Suppose you have a combobox with 3 values:
     Hello1
     Hello2
       Hello3

I implement the OnEditChangeSc method as described above.

I try to change the first element from Hello1 to Hello11. No problem.
Now I try to change Hello11 to Hello111: I get a problem because the
..GetCurSel() method of the combobox returns -1.

But:
I try to change the first element from Hello1 to Hello11. No problem.
Now I change the selected item to Hello2, for instance, and back to Hello11,
which has already been changed. Now I try to change from Hello11 to Hello111.
No problem!
So, if I do something between the changes, I can so many changes as I need,
otherwise, I get the error at the second change, because .GetCurSel is unable
to find the selected item.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2715257
Hi javigil1,

I think selection of combobox's list box is removed if combobox's edit box contains text which isn't in the combobox, so changing text 'Hello1' to 'Hello11' removes selection and next GetCurSel() returns -1, which indicates that no item is selected. So you have three possibilities: 1. Add the new string to the combobox or 2. replace the old string with the new one or 3. store the selected string when first change occurs and re-use for further changes.

hope that helps,

ZOPPO
0
 

Author Comment

by:javigil1
ID: 2715305
Well, Im trying to do what you say. All the possible items are stored in a vector. I update the vector, the clear the combobox and build it again with the new values:

void CFhgDlg::OnEditchangeSc()
{
      CEnsemble* elementt;
      CString str;
      EnableApply();

      int tab=m_CTab.GetCurSel();
      int NoOfSC=m_SC.GetCurSel();
      m_SC.GetWindowText(str);  
      elementt=lista1.SearchList(tab);

      elementt->ListOfSC[NoOfSC].SC_Label=str;      

      m_SC.ResetContent();

      for (int i=0; i<elementt->NoOfSCs; i++){
            m_SC.AddString(elementt->ListOfSC[i].SC_Label);
      }
      m_SC.SetCurSel(NoOfSC);

      UpdateData(true);
}

....but it doesnt work. Any ideas?
0
 

Author Comment

by:javigil1
ID: 2715307
Adjusted points from 75 to 100
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 30

Expert Comment

by:Zoppo
ID: 2715335
I don't think you need to delete whole combo box, just something like this:

void CFhgDlg::OnEditchangeSc()
{
 ...
 int tab=m_CTab.GetCurSel();
 int NoOfSC=m_SC.GetCurSel();
 m_SC.GetWindowText(str);    
 elementt=lista1.SearchList(tab);

 elementt->ListOfSC[NoOfSC].SC_Label=str;

 m_SC.DeleteString( NoOfSC );
 m_SC.InsertString( NoOfSC, str );
 m_SC.SetCurSel(NoOfSC);

 UpdateData(false);  // you shouldn't use true here, UpdateData( false ) is used to update controls depending on your member's data
}

ZOPPO
0
 

Author Comment

by:javigil1
ID: 2715370
Yes, it should work (both your solution and my solution), but it doesnt...
The GetCurSel method keeps on getting
-1.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 2715414
I think best would be if you could email me your code ... zoppo@cdsgmbh.de

If you don't want me to see your code perhaps you can build a small, simple sample which has the same problem...

ZOPPO
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2715507
Are you trying to get a combo box that keeps a history of what you've typed in?

In that case, I can provide you with some source code.

Basically, I change PreTranslateMessage so that the enter key kills and set focus.

In the kill focus, I search for an existing item in the combo and if not found, add to the top of the list (deleting the last item when I have enough)

Would this help you?

0
 

Author Comment

by:javigil1
ID: 2715523
yes!!

javigil1@yahoo.com
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2715934
I'll post it here...
0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 100 total points
ID: 2716005
I'm going to submit this to codeguru .. but you can get it early !!

to use it, use DDX_Control to subclass a combo box in your dialog.

Call the appropriate methods in OnInitDialog to set the behaviour you want.

In your dialog class put the following lines in the appropriate places:

in the .h:

afx_msg LRESULT OnHistoryComboSelected(WPARAM wparam, LPARAM lparam);

in the .cpp:
ON_REGISTERED_MESSAGE(WM_HISTORYCOMBOSELECTED, OnHistoryComboSelected)

LRESULT CHistoryComboSampleDlg::OnHistoryComboSelected(WPARAM wparam, LPARAM lparam)
{
    // wparam is the id
    // lparam is pointer to the combo
    // use CHistoryComboBox* pHistoryCombo = reinterpret_cast<CHistoryComboBox*>(lparam);
    ....
}

Alternatively, derive from CHistroyComboBox and override OnSelect to do what you want.

(PS: let me know if there are any bugs etc)


HistoryComboBox.h:

#if !defined(_HISTORYCOMBOBOX_H_INCLUDED_)
#define _HISTORYCOMBOBOX_H_INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// HistoryComboBox.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CHistoryComboBox window

const UINT WM_HISTORYCOMBOSELECTED = ::RegisterWindowMessage("HISTORYCOMBOSELECTED");

class CHistoryComboBox : public CComboBox
{
// Construction
public:
    CHistoryComboBox();

// Attributes
public:
    // the text itself
    virtual CString GetText() const;
    virtual void SetText(CString strText);
    // the maximum number of entries in the combo
    virtual int MaxHistory() const;
    virtual void SetMaxHistory(int nMaxHistory);
    // what happens when you select from the combo
    virtual bool DropdownDoesSelect() const;
    virtual void MakeDropdownDoSelect(bool bDropdownDoesSelect=true);
    // what happens when the enter key is pressed
    virtual bool EnterStaysOnCombo() const;
    virtual void MakeEnterStayOnCombo(bool bEnterStaysOnCombo = true);
    virtual bool EnterActsLikeTab() const;
    virtual void MakeEnterActLikeTab(bool bEnterActsLikeTab = true);

// Operations
public:
    // response to a value being selected
    // default sends a WM_HISTORYCOMBOSELECTED
    // to the parent (dialog) with
    // wparam = id
    // lparam = pointer to this
    virtual void OnSelected();

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CHistoryComboBox)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CHistoryComboBox();

protected:
    virtual void LimitHistory();
    virtual void Select();

    // Generated message map functions
protected:
    //{{AFX_MSG(CHistoryComboBox)
    afx_msg void OnSetfocus();
    afx_msg void OnKillfocus();
    afx_msg void OnSelendok();
    afx_msg LRESULT OnHistoryComboSelendok(WPARAM wparam, LPARAM lparam);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
private:
    bool m_bDropdownDoesSelect;
    bool m_bEnterActsLikeTab;
    bool m_bEnterStaysOnCombo;
    int m_nMaxHistory;
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(_HISTORYCOMBOBOX_H_INCLUDED_)



HistoryComboBox.cpp:

// HistoryComboBox.cpp : implementation file
//

#include "stdafx.h"
#include "HistoryComboSample.h"
#include "HistoryComboBox.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CHistoryComboBox

static const UINT WM_HISTORYCOMBOSELENDOK = ::RegisterWindowMessage("HISTORYCOMBOSELENDOK");

CHistoryComboBox::CHistoryComboBox()
: m_nMaxHistory(0)
, m_bEnterActsLikeTab(false)
, m_bEnterStaysOnCombo(false)
, m_bDropdownDoesSelect(false)
{
}

CHistoryComboBox::~CHistoryComboBox()
{
}

int CHistoryComboBox::MaxHistory() const
{
    // the maximum number of entries
    return m_nMaxHistory;
}

void CHistoryComboBox::SetMaxHistory(int nMaxHistory)
{
    // set the maximum number of entries
    // <=0 means no limit
    m_nMaxHistory = nMaxHistory;
    LimitHistory();
}

bool CHistoryComboBox::EnterActsLikeTab() const
{
    // does the enter key act like the tab key?
    return m_bEnterActsLikeTab;
}

void CHistoryComboBox::MakeEnterActLikeTab(bool bEnterActsLikeTab)
{
    m_bEnterActsLikeTab = bEnterActsLikeTab;
}

bool CHistoryComboBox::EnterStaysOnCombo() const
{
    // does the enter key act stay in the combo (but enters a value)
    return m_bEnterStaysOnCombo;
}

void CHistoryComboBox::MakeEnterStayOnCombo(bool bEnterStaysOnCombo)
{
    m_bEnterStaysOnCombo = bEnterStaysOnCombo;
}

bool CHistoryComboBox::DropdownDoesSelect() const
{
    // does selecting from the dropdown do a select
    return m_bDropdownDoesSelect;
}

void CHistoryComboBox::MakeDropdownDoSelect(bool bDropdownDoesSelect)
{
    m_bDropdownDoesSelect = bDropdownDoesSelect;
}

CString CHistoryComboBox::GetText() const
{
    // return the current text
    CString strText;
    GetWindowText(strText);
    return strText;
}

void CHistoryComboBox::SetText(CString strText)
{
    // must have a control and a non empty string
    if (GetSafeHwnd() && ! strText.IsEmpty()) {
        // find existing strText (exact match)
        int isel = FindStringExact(-1,strText);
        // if not at the top
        if (isel != 0) {
            // delete old one, if any
            if (isel != CB_ERR) {
                DeleteString(isel);
            }
            // insert new one at the top
            InsertString(0, strText);
            // remove old ones from the end
            LimitHistory();
        }
        // set selection to top of history
        SetCurSel(0);
        // put the text in the edit box
        SetWindowText(strText);
    }
}

void CHistoryComboBox::Select()
{
    // get the value from the edit box
    CString strText = GetText();
    if (! strText.IsEmpty()) {
        // add it to the history
        SetText(strText);
        // call virtual for value selected
        OnSelected();
    }
    // act like we just arrived here
    OnSetfocus();
}

void CHistoryComboBox::OnSelected()
{
    CWnd* pParent = GetParent();
    if (pParent) {
        pParent->SendMessage(WM_HISTORYCOMBOSELECTED,GetDlgCtrlID(),reinterpret_cast<LPARAM>(this));
    }
}

void CHistoryComboBox::LimitHistory()
{
    // remove entries from the end of the list
    if (m_nMaxHistory > 0) {
        while (GetCount() > m_nMaxHistory) {
            DeleteString(GetCount()-1);
        }
    }
}

BEGIN_MESSAGE_MAP(CHistoryComboBox, CComboBox)
    //{{AFX_MSG_MAP(CHistoryComboBox)
    ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)
    ON_CONTROL_REFLECT(CBN_SETFOCUS, OnSetfocus)
    ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendok)
    ON_REGISTERED_MESSAGE(WM_HISTORYCOMBOSELENDOK, OnHistoryComboSelendok)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHistoryComboBox message handlers

void CHistoryComboBox::OnSetfocus()
{
    // select the text
    SetEditSel(0,-1);
}

void CHistoryComboBox::OnKillfocus()
{
    if (EnterActsLikeTab() || EnterStaysOnCombo()) {
        ; // do nothing as enter key does the work
    } else {
        Select();
    }
}

void CHistoryComboBox::OnSelendok()
{
    if (DropdownDoesSelect()) {
        // do a select soon...
        PostMessage(WM_HISTORYCOMBOSELENDOK);
    }
}

LRESULT CHistoryComboBox::OnHistoryComboSelendok(WPARAM /*wparam*/, LPARAM /*lparam*/)
{
    if (DropdownDoesSelect()) {
        // do a select
        Select();
    }
    return 0;
}

void CHistoryComboBox::PreSubclassWindow()
{
    // ensure that the history box isn't sorted alphabetically
    ModifyStyle(CBS_SORT,CBS_DROPDOWN);
    CComboBox::PreSubclassWindow();
}

BOOL CHistoryComboBox::PreTranslateMessage(MSG* pMsg)
{
    // any special treatment of the enter key?
    if (EnterActsLikeTab() || EnterStaysOnCombo()) {
        if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
            // if it acts like a tab, emulate the tab press
            if (EnterActsLikeTab()) {
                CWnd* pParent = GetParent();
                if (pParent) {
                    CWnd* pNextControl = pParent->GetNextDlgTabItem(this);
                    if (pNextControl && pNextControl != this) {
                        pNextControl->SetFocus();
                    }
                }
            }
            // just pretend we lost focus (but stay here)
            Select();
            return TRUE;
        }
    }
    // normal processing
    return CComboBox::PreTranslateMessage(pMsg);
}

0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
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.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

760 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

21 Experts available now in Live!

Get 1:1 Help Now