Handling combo closing up in WindowProc!

Ah hello.

I have a custom combo box that, when dropped down, hides the default windows listbox part of the control, then displays my own custom one.  This all works, but I am having problems...

I have a class derived from CComboBox that handles the CBN_CLOSEUP and CBN_DROPDOWN via ON_CONTROL_REFLECT macros:  I can hide and show my custom list control respectively in these handler functions.  However, I am now instance subclassing an existing plain old CComboBox control: to do that I need to provide a special window procedure, which I do via SetWindowLong/GWL_WNDPROC.  This is the function I have so far:

      WNDPROC wndProcOld = NULL;
      VERIFY ( wndProcOld = ( WNDPROC ) GetProp ( hWnd, _T("OldWndProc") ) );
      if ( !wndProcOld ) return 0;

      LRESULT lRes = 0;

      if ( msg == CB_SHOWDROPDOWN )
            // Show custom list control: this works fine
            return 0;
      if ( msg == CBN_CLOSEUP )
            // Hide custom list control.  This does not work!
            return 0;
      lRes = ::CallWindowProc ( wndProcOld, hWnd, msg, wp, lp );

      return lRes;

Clearly, I get the old window procedure that I have set in the combo box's property table, using it if necessary.  I find that whereas I receive the CB_SHOWDROPDOWN every time the combo is dropped down, I don't receive the CBN_CLOSEUP message.  In fact, I only ever receieve this message once - strangely enough when the combo is first dropped down.  As a consequence, I am finding it hard to know when to close my custom list.

How can I handle the combo being closed?

LVL 19
Who is Participating?
AndyAinscowFreelance programmer / ConsultantCommented:
Something (possibly) interesting in the help files:

An application sends a CB_SHOWDROPDOWN message to show or hide the list  box of a combo box that has the CBS_DROPDOWN or CBS_DROPDOWNLIST style.  
To send this message, call the SendMessage  function as follows.        Copy Code lResult = SendMessage(     // returns BOOL in lResult    (HWND) hWndControl,     // handle to destination control    (UINT) CB_SHOWDROPDOWN,     // message ID    (WPARAM) wParam,     // = (WPARAM) (BOOL) wParam;   (LPARAM) lParam     // = 0; not used, must be zero);
Parameters  wParam Specifies whether the drop-down list box is to be shown or hidden. A value  of TRUE shows the list box; a value of FALSE hides it.  lParam This parameter is not used.
AndyAinscowFreelance programmer / ConsultantCommented:
Is the following correct?

When your list is shown it has the focus - right?
So when the custom list loses the focus then it should be hidden (eg. user clicks elsewhere on the dialog, user has selected an entry)

(I suspect the CBN_CLOSEUP is not being generated as you aren't using the listbox part of the combo, or do I misunderstand what you are doing.  Why you get it the very first time I am not certain.)
mrwad99Author Commented:
Hi Andy, I hope you are well.

I am still having major problems with this.  To answer your question, yes, that is correct: when the combo is dropped down, I display my own special window, which is, in essence, the skinned list control.  (see the article http://tinyurl.com/c4ug77 on codeproject).  I have uploaded a simple project to demonstrate this (http://www.yousendit.com/download/U0d5Wmdpd0lHa09Ga1E9PQ); you might even find it useful for your own code one day.  Click the skin windows button, then drop down the combo.  All of the code handling the combo is at the top of Skinner.cpp in the custom window procedure.  I am aware you might be busy, so provide the link for anyone else that may be interested.

Let me know if you take a look and have any ideas please.

AndyAinscowFreelance programmer / ConsultantCommented:
OK, I've downloaded and had a quick compile and run.

Before skinning I can drop and close the combo without problems.  After skinning I can only drop it and close it once, the second attempt just results in only the frame being shown when dropped (no list contents), when closing the frame just shrinks a little.  That makes me think your cleanup from the first drop/close is buggy, which might result in the bad behaviour on later drops/closes.
mrwad99Author Commented:
Thanks Andy.  After much playing, I needed to handle the CB_SHOWDROPDOWN as you suggested.  It turns out that the dialog was sending this message as you described, which was what was causing the standard list to be hidden.  When I started handling this, it all worked fine.

A summary of how to deal with this, for future searches is:

If receive CBN_DROPDOWN, WM_LBUTTONDOWN, then show the custom list.

If receive CB_SHOWDROPDOWN with a WPARAM of TRUE, then show the custom list.

If receive a WM_WINDOWPOSCHANGING, A CBN_CLOSEUP, or a CB_SHOWDROPDOWN with a WPARAM of FALSE, then hide the list.

The caveat to the latter is that a CBN_CLOSEUP will be sent the very first time the list is dropped, so the best thing to do is ignore it just the first time.

Thanks again :o)
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.