Solved

CComboBox and OnChar

Posted on 2007-12-05
4
856 Views
Last Modified: 2008-03-19
I have defined a class which inherits from CComboBox and have declared the message map for the OnChar method so I can do some processing each time a character is pressed.

The problem is that message doesn't seem to be picked up as the method is never called.
Has anyone any ideas why?

class CMyComboBox : public CComboBox

{

public:

	DECLARE_DYNAMIC(CMyComboBox)

	CMyComboBox(TItem* item = NULL);

	virtual ~CMyComboBox();

	

	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);	

protected:

        TItem *m_Item;

	DECLARE_MESSAGE_MAP()
 

};
 
 

IMPLEMENT_DYNAMIC(CSRAutoCompletionComboBox,CComboBox)
 

CSRAutoCompletionComboBox::CSRAutoCompletionComboBox(TItem* item)

: CComboBox()

{

	m_Item = item;

}
 

/*virtual*/ CSRAutoCompletionComboBox::~CSRAutoCompletionComboBox()

{

}
 

BEGIN_MESSAGE_MAP(CSRAutoCompletionComboBox, CSRComboBox)

	ON_WM_CHAR()

END_MESSAGE_MAP()
 

void CSRAutoCompletionComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

	if(!fAutoComplete)

		CSRComboBox::OnChar(nChar, nRepCnt, nFlags);

}

Open in new window

0
Comment
Question by:krispin
  • 2
4 Comments
 
LVL 31

Expert Comment

by:Zoppo
ID: 20410903
Hi krispin,

probably there's no WM_CHAR message produced from default message processing for a ComboBox for WM_KEYDOWN/WM_KEYUP - you could add a message handler for WM_KEYDOWN instead ...

Hope that helps,

ZOPPO
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20411040
The dialog will catch all key messages. Your overloaded class needs a handler for the WM_GETDLGCODE message, where the dialog asks whether the control wants to handle messages itself:

BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)

    ON_WM_GETDLGCODE( )

END_MESSAGE_MAP()

UINT CMyComboBox::OnGetDlgCode( )
{  
    return DLGC_WANTALLKEYS;
}

In the class header you need to specify the following member function:

    afx_msg UINT OnGetDlgCode( );

Regards, Alex


0
 

Author Comment

by:krispin
ID: 20421058
Thanks for you responses.
Unfortunately neither of these approaches worked.
Like with OnChar(), when a key is pressed, the OnGetDlgCode() method does not get called.

I'm wondering if the message is getting lost somewhere along the way. Let me explain more about what I am trying to do.
I have my combo box as explained, but this is embedded within a List Control (using Report View) which has rows and columns. I have created a class which inherits from List Control so that I can create editable columns (as MFC only provides the ability to edit the first column with the "Edit Lables" property).

So, when a line in the List Control is double clicked, I have a method which checks which column this is, and checks what type of control it should be (at the moment, only Combo Boxes). So, a Combo Box is inserted in the appropriate position.

It is my combo box class that is instantiated and put into position. The idea then that each time I press a key, this combo box will do some sort of processing (for example, if I press tab, the List Control should be notified to remove this combo box from the list). But, as I have stated, the message does not seem to reach the combo box. Is it possible that the message is being sent to the list control instead of the active combo box, or somewhere else for that matter (The List Control is sitting in an MDI child window)?

On a somewhat interesting sidenote;
I tried implementing the PreTranslateMessage method in my combobox class as in my code snippet. When I did this, when I pressed a key, I could do some processing on the key press. So obviously, somewhere after translate and dispatch the message must get sent somewhere else.

This approach will actually work fine for what I need, but I consider this to be a bit messy and would much rather use the message map approach than this. If anyone has any ideas, I'm all ears. Thanks.
BOOL CMyComboBox::PreTranslateMessage(MSG* pMsg)

{

	if(pMsg->message == WM_KEYDOWN)

	{

		//Do Something

	}

}

Open in new window

0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 350 total points
ID: 20421360
>>>> Like with OnChar(), when a key is pressed, the
>>>> OnGetDlgCode() method does not get called.
The OnGetDlgCode will be called only once and the dialog saves the information.

>>>> I have my combo box as explained, but this is embedded
>>>> within a List Control (using Report View) which has rows and columns.
That is the problem, the dialog doesn't know from the combobox cause it was created on the fly or the parent was the reportview control. You would need to put a dummy combobox into the dialog form (make it invisible). Then, let the wizard create a member for the combobox. Change the type of the combobox member from CComboBox to CMyComboBox in the the dialog class header. That way, the combobox was sub-classed with the initial call of the DoDataExchange. 'Subclassing' is a mechanism that makes that messages directed to class CComboBox now were directed to class CMyComboBox. If you do so, the OnGetDlgCode would be called for that combobox member.

>>>> So, a Combo Box is inserted in the appropriate position.
For that case you would move the 'invisible' combobox to the appropriate cell, enable it and show it. You should overwrite the OnKillFocus handler of the combobox so that you can move it back and hide it when it is no more focussed.

You can do similar with an edit control, a button, an image, and more ...

Always have a 'template' which simply was 'activated' and moved to the appropriate cell. Look at the code I posted where I did the same with an edit control.

Regards, Alex



void DynupDlg::OnNMDblClickLstVec(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMLISTVIEW pListView = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

    int nItems    = m_lstDynRec.GetItemCount();

    int iItem     = pListView->iItem;

    int iSubItem  = pListView->iSubItem;

    // unfortunately pListView doesn't give a valid iItem if clicking on a sub item

    if (iItem >= -1 && iItem < nItems && iSubItem > 0)

    {   

        CRect rectGrid;

        // get windows rectangle of the list control

        m_lstDynRec.GetWindowRect(&rectGrid);

        // unfortunately pListView doesn't give a valid iItem if clicking on a sub item

        if (iItem == -1)

        {

            LVHITTESTINFO lvhti = { 0 };

            // we have to retrieve the 'item' line number 

            // by evaluating the current mouse position 

            GetCursorPos(&lvhti.pt);

            // convert to client coordinates

            lvhti.pt.x -= rectGrid.left;

            lvhti.pt.y -= rectGrid.top;

            if (m_lstDynRec.SubItemHitTest(&lvhti ) < 0)

                return;  // ignore clicks outside of grid

            iItem     = lvhti.iItem;

            iSubItem  = lvhti.iSubItem;

        }

        if (iItem < 0    || iItem    > nItems ||

            iSubItem < 1 || iSubItem > 10     ||

            iItem * 10 + iSubItem -1 >= Dynup::s_sizDynRec[m_idxField])

            return;
 

        int col = iSubItem - 1;

        // calculate rectangle for edit cell

        CRect rectDlg;

        GetWindowRect(&rectDlg);

        rectGrid -= rectDlg.TopLeft();  // relative to left-top of dialog

        CRect rectEdit;

        int off = GetSystemMetrics(SM_CYBORDER);

        int wid = rectGrid.Width() - 2 * off - GetSystemMetrics(SM_CXVSCROLL);

        int wdc = (wid * 94 + 500) / 1000;

        CHeaderCtrl* pHdr = m_lstDynRec.GetHeaderCtrl();

        if (pHdr == 0)

            return;

        CRect rectHdr;

        pHdr->GetClientRect(rectHdr);

        m_lstDynRec.GetItemRect(iItem, rectEdit, LVIR_LABEL);

        int wd1 = rectEdit.Width();

        int hgt = rectEdit.Height();

        rectEdit.top    += rectGrid.top - rectHdr.Height() - 2 * off;

        rectEdit.bottom  = rectEdit.top + hgt + 2 * off;

        rectEdit.left   += rectGrid.left + wd1 + col * wdc;

        rectEdit.right   = rectEdit.left + wdc;

        CString strDbl = m_lstDynRec.GetItemText(iItem, iSubItem);

        m_gridEdit.SetWindowText(strDbl);

        m_gridEdit.SetSel(0, -1);

        m_gridEdit.MoveWindow(rectEdit, TRUE);

        if (!m_gridEdit.IsWindowVisible() || !m_gridEdit.IsWindowEnabled())

        {

            m_gridEdit.ShowWindow(SW_SHOWNORMAL);

            m_gridEdit.EnableWindow(TRUE);

        }

        m_gridEdit.SetFocus();

        m_gridEdit.m_modified = false;

        m_gridEdit.m_d        = 0.;

        m_gridEdit.m_row      = iItem;

        m_gridEdit.m_col      = iSubItem;

        m_gridEdit.m_pGrid    = &m_lstDynRec;

        

   }

    *pResult = 1;

}

Open in new window

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
mixing C++ & C# in Vis Studio 2013 7 141
Template syntax for variable length arrays 9 71
c++ syntax question 9 44
Embarcadero C++ Builder XE10.1 Berlin red arrow Indicator 2 16
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

911 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

18 Experts available now in Live!

Get 1:1 Help Now