如何使已经有选中项的ComboBox在点击下拉箭头时,仍然默认从列表开始处显示,而不是跳到选中项的位置

背景知识:

(1)ComboBox实际是一个Edit控件和一个ListBox控件的组合,列表实际是ListBox,那么要实现上述目标,最主要的一点就是得获取到ListBox的句柄.

(2)WM_CTLCOLOR消息及其处理函数OnCtlColor

The framework calls this member function when a child control is about to be drawn. Most controls send this message to their parent (usually a dialog box) to prepare the pDC for drawing the control using the correct colors.

To change the text color, call the SetTextColor member function with the desired red, green, and blue (RGB) values.

(3)CListBox有一个消息叫做LB_SETTOPINDEX,截获这个消息,通过设置wparam为0可以使列表置顶

(4)通过实现一个类的WindowProc,可以截获改类的消息,并自行处理

 

实现步骤:

(1)从CListBox派生一个子类CMyListBox

(2)实现CListBox的虚函数WindowProc

LRESULT CMyListBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class
    if (message == LB_SETTOPINDEX)
    {
        wParam = 0;//wParam要传递给父类去处理,wParam在本消息中就是Topindex的位置
    }
    return CListBox::WindowProc(message, wParam, lParam);
}

(3)从CComboBox派生一个子类CMyComboBox,并增加两个成员变量,一个为CEdit类型,一个为CMyListBox类型

(4)为CMyComboBox实现WM_CTLCOLOR消息

HBRUSH CMyComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{

    if (nCtlColor == CTLCOLOR_EDIT)
    {
        if (m_edit.GetSafeHwnd() == NULL)
        {
            m_edit.SubclassWindow(pWnd->GetSafeHwnd());

//This method dynamically subclasses a window and attach it to this CWnd object
        }
    }
    else if (nCtlColor == CTLCOLOR_LISTBOX)
    {
        if (m_listbox.GetSafeHwnd() == NULL)
        {
            m_listbox.SubclassWindow(pWnd->GetSafeHwnd());
        }
    }

    HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
   
    // TODO: Change any attributes of the DC here
   
    // TODO: Return a different brush if the default is not desired

    return hbr;
}

(5)为CMyComboBox实现WM_DESTORY消息

void CMyComboBox::OnDestroy()
{
    if (m_edit.GetSafeHwnd() != NULL)
        m_edit.UnsubclassWindow();
    if (m_listbox.GetSafeHwnd() != NULL)
        m_listbox.UnsubclassWindow();

    CComboBox::OnDestroy();
   
    // TODO: Add your message handler code here
   
}

(6)在程序初始化的时候,如在OnInitdialog中给CMyListBox对象发消息

::SendMessage(m_combobox.m_listbox.m_hWnd,LB_SETTOPINDEX,0,0);

并且

    m_combobox.ShowDropDown();
    m_combobox.ShowDropDown(FALSE);

(原因为:"Note that for subclassing to occur, the dialog box must be painted at leastonce. ")

 

 

参考知识:

SUMMARY
While it is simple to directly subclass a combo box control, it is not simple t...

While it is simple to directly subclass a combo box control, it is notsimple to subclass the edit or list box inside a combo box. The problem isthat it is difficult to get the HWNDs of the child controls in a portablemanner.

One safe way to subclass the internal edit and list box controls is tosubclass them in the WM_CTLCOLORXXX messages. Because Win32 sends separateWM_CTLCOLOREDIT and WM_CTLCOLORLISTBOX messages, these messages are safeand easy ways to get the HWNDs of the child controls of the combo box.

Below is a CSuperComboBox class, which is an MFC implementation of thismethod. Because MFC routes all the WM_CTLCOLOR messages to OnCtlColor, thesubclassing takes place there.

MORE INFORMATION
Use ClassWizard to derive a class from CComboBox and add message handlers for W...

Use ClassWizard to derive a class from CComboBox and add message handlersfor WM_CTLCOLOR and WM_DESTROY. Then manually edit the header file to addthe data members, m_edit and m_listbox. Finally, copy the code from themessage handlers below:

Sample code

   // SuperComboBox.h : header file

   class CSuperComboBox : public CComboBox

   {

   public:

      CEdit      m_edit;

      CListBox   m_listbox;

   protected:

      afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

      afx_msg void OnDestroy();

   ...

   };



   // SuperComboBox.cpp : implementation file

   HBRUSH CSuperComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

   {

      if (nCtlColor == CTLCOLOR_EDIT)

      {

         //[ASCII 160][ASCII 160][ASCII 160]Edit control

         if (m_edit.GetSafeHwnd() == NULL)

            m_edit.SubclassWindow(pWnd->GetSafeHwnd());

      }

      else if (nCtlColor == CTLCOLOR_LISTBOX)

      {

         //ListBox control

         if (m_listbox.GetSafeHwnd() == NULL)

            m_listbox.SubclassWindow(pWnd->GetSafeHwnd());

      }

      HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);

      return hbr;

   }



   void CSuperComboBox::OnDestroy()

   {

      if (m_edit.GetSafeHwnd() != NULL)

         m_edit.UnsubclassWindow();

      if (m_listbox.GetSafeHwnd() != NULL)

         m_listbox.UnsubclassWindow();

      CComboBox::OnDestroy();

   }

				

Note that for subclassing to occur, the dialog box must be painted at leastonce. There are cases when the dialog box doesn't paint at all (forexample, closing the dialog box before it is displayed, hidden dialogboxes). This method may not be suitable when access to the subclassedwindows are needed in these cases.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值