首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  界面/窗口  |  组合框   


自动过滤选择的组合框


原作者:lanzhengpeng2    源出处:CSDN    发布者:施昌权    发布类型:转载    发布日期:2008-10-15

              

经过两天的编码调试,完成了一个自动过滤选择的组合框,具有以下优点:
1。丝毫不妨碍组合框原有的功能
2。根据用户在编辑框里已经输入的单词,从组合框的列表选项过滤出匹配的项,并使用下拉列表显示出来以供用户选择。
3。不需要特别的设置。从View\ClassWizard\Member Variables里生成一个CComboBox,然后在源文件里把CComboBox替换成CACComboBox即可;或者让ClassWizard认识CACComboBox(删除MyApp.clw,选View\ClassWizard,按提示重新生成MyApp.clw,绝大多数时候能成功),从View\ClassWizard\Member Variables里直接生成一个CACComboBox。
4。你可以经过简单修改使之成为具有其他类似功能(自动填写??)的组合框。

由于时间仓促,没有写详细的注释。感兴趣的朋友请等几天后向我索要。联系方法:
linger0822@163.net

代码如下:

file://-----------------------------------------------------------------------------
// File: ACComboBox.h
//
// Desc:
//   根据用户在编辑框里已经输入的单词,从组合框的列表选项过滤出匹配的项,并使用下拉列表显示出来以供用户选择
//
// Copyright (c) 2001 EagleFly Studio.
//
// Original Author: Zhengpeng.Lan
// Author:
//
// Create Time:  2001/10/10
// Modify Time:  2001/10/11
//
file://-----------------------------------------------------------------------------
#if !defined(AFX_ACCOMBOBOX_H__81CBBD04_3955_4076_A688_74D3EA9730D9__INCLUDED_)
#define AFX_ACCOMBOBOX_H__81CBBD04_3955_4076_A688_74D3EA9730D9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "afxtempl.h"

// ACComboBox.h : header file
//
class CACComboBox;
/////////////////////////////////////////////////////////////////////////////
// CWndForACComboBox window
typedef struct
{
  int nid;
  CString strDepict;
}CInfoForACComboBox;

typedef CArray<CInfoForACComboBox,CInfoForACComboBox &>  CInfoForACComboBoxArray;

class CWndForACComboBox : public CWnd
{
  friend CACComboBox;
private:
// Construction
  LPCTSTR lpWndCls;
// Construction
public:
  CWndForACComboBox();

// Attributes
public:
  CComboBox * m_pComboBox;
  int   m_nMaxCount;
  CInfoForACComboBoxArray   m_aInfo;
  int   m_nMousePos;
  int   m_nBeginShow;

 inline void RemoveAll()
  {
   m_aInfo.RemoveAll();
   CWnd::SetScrollRange(SB_VERT,0,0);
  }
  inline void Add(CInfoForACComboBox &info)
  {
   m_aInfo.Add(info);
  }
  inline int GetSize()
  {
   return m_aInfo.GetSize();
  }
  inline void ShowList()
  {
   if(IsWindow(GetSafeHwnd()))
   {
    ShowWindow(SW_SHOWNOACTIVATE);
   }
  }
// Operations
public:

// Overrides
  // ClassWizard generated virtual function overrides
  file://{{AFX_VIRTUAL(CWndForACComboBox)
  public:
  virtual BOOL Create(CComboBox * pWnd);
  file://}}AFX_VIRTUAL

// Implementation
public:
  virtual ~CWndForACComboBox();

 // Generated message map functions
protected:
  file://{{AFX_MSG(CWndForACComboBox)
  afx_msg void OnDestroy();
  afx_msg void OnPaint();
  afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
  afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
  afx_msg void OnKillFocus(CWnd* pNewWnd);
  afx_msg void OnMouseMove(UINT nFlags, CPoint point);
  afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
  file://}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};


/////////////////////////////////////////////////////////////////////////////
// CACComboBox window

class CACComboBox : public CComboBox
{
private:
  CEdit*      m_pEdit;

// Construction
public:
  CACComboBox();

// Attributes
public:
  CWndForACComboBox  m_wndList;
  inline void WindowMove(void)
  {
   if(IsWindow(m_wndList.GetSafeHwnd()))
    m_wndList.Invalidate(FALSE);
  }
// Operations
public:
  virtual void HandleCompletion();

// Overrides
  // ClassWizard generated virtual function overrides
  file://{{AFX_VIRTUAL(CACComboBox)
  protected:
  virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
  virtual void PreSubclassWindow();
  file://}}AFX_VIRTUAL

// Implementation
public:
  virtual ~CACComboBox();

 // Generated message map functions
protected:
  file://{{AFX_MSG(CACComboBox)
  afx_msg void OnKillfocus();
  afx_msg void OnSelchange();
  file://}}AFX_MSG

 DECLARE_MESSAGE_MAP()
};

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

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

#endif // !defined(AFX_ACCOMBOBOX_H__81CBBD04_3955_4076_A688_74D3EA9730D9__INCLUDED_)


file://-----------------------------------------------------------------------------
// File: ACComboBox.cpp
//
// Desc:
//   根据用户在编辑框里已经输入的单词,从组合框的列表选项过滤出匹配的项,并使用下拉列表显示出来以供用户选择
//
// Copyright (c) 2001 EagleFly Studio.
//
// Original Author: Zhengpeng.Lan
// Author:
//
// Create Time:  2001/10/10
// Modify Time:  2001/10/11
//
file://-----------------------------------------------------------------------------

#include "stdafx.h"
#include "ACComboBox.h"

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

/////////////////////////////////////////////////////////////////////////////
// CACComboBox

CACComboBox::CACComboBox()
:CComboBox()
{
  m_pEdit = NULL;
}

CACComboBox::~CACComboBox()
{
  if(m_pEdit)
   delete m_pEdit;
}


BEGIN_MESSAGE_MAP(CACComboBox, CComboBox)
  file://{{AFX_MSG_MAP(CACComboBox)
  ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)
  ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelchange)
  file://}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CACComboBox message handlers
/////////////////////////////////////////////////////////////////////////////
// CWndForACComboBox

CWndForACComboBox::CWndForACComboBox()
:CWnd()
{
  lpWndCls = AfxRegisterWndClass(0);
  m_pComboBox = NULL;
  m_nMaxCount = 8;
  m_aInfo.SetSize(0,8);
  m_nMousePos = -1;
  m_nBeginShow = 0;
}

CWndForACComboBox::~CWndForACComboBox()
{

}


BEGIN_MESSAGE_MAP(CWndForACComboBox, CWnd)
  file://{{AFX_MSG_MAP(CWndForACComboBox)
  ON_WM_DESTROY()
  ON_WM_PAINT()
  ON_WM_KEYDOWN()
  ON_WM_LBUTTONUP()
  ON_WM_MOUSEWHEEL()
  ON_WM_KILLFOCUS()
  ON_WM_MOUSEMOVE()
  ON_WM_VSCROLL()
  file://}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CWndForACComboBox message handlers

BOOL CWndForACComboBox::Create(CComboBox * pWnd)
{
  ASSERT(pWnd);

 CRect rect;
  CWnd * pParentWnd = pWnd->GetParent();

 pWnd->GetWindowRect(&rect);
// pParentWnd->ScreenToClient(&rect);

 BOOL bRet = CWnd::CreateEx( WS_EX_TOPMOST | WS_EX_TOOLWINDOW,\
   lpWndCls, NULL, WS_POPUP | WS_VSCROLL, rect.left, rect.top, rect.Width(), rect.Height(),
   pParentWnd->GetSafeHwnd(), NULL, NULL);

 if(bRet)
   SetOwner(pParentWnd);

 m_pComboBox = pWnd;
  return bRet;
}

void CWndForACComboBox::OnDestroy()
{
  CWnd::OnDestroy();
 
  m_aInfo.RemoveAll(); 
}

void CWndForACComboBox::OnPaint()
{
  CRect rect;
  CFont * pFont;
  LOGFONT logFont;

 if(m_pComboBox)
  {
   ASSERT(::IsWindow(m_pComboBox->GetSafeHwnd()));
 
   CWnd * pParentWnd = m_pComboBox->GetParent();
   m_pComboBox->GetWindowRect(&rect);
   pFont = pParentWnd->GetFont();
   ASSERT(pFont);
   pFont->GetLogFont(&logFont);

  if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;
   if(m_aInfo.GetSize() > m_nMaxCount)
   {
    logFont.lfWidth = m_nMaxCount * logFont.lfHeight;
   }
   else
   {
    logFont.lfWidth = m_aInfo.GetSize() * logFont.lfHeight;
   }
   if(logFont.lfWidth + rect.bottom > ::GetSystemMetrics(SM_CYSCREEN))
   {
    rect.bottom = rect.top;
    rect.top = rect.bottom - logFont.lfWidth - 2;
    if(rect.top < 0)
     rect.top = 0;
   }
   else
   {
    rect.top = rect.bottom;
    rect.bottom = rect.top + logFont.lfWidth + 2;
   }
   rect.right = rect.left + m_pComboBox->GetDroppedWidth();
//  pParentWnd->ScreenToClient(&rect);
   MoveWindow(&rect);
   if(rect.Height() < m_aInfo.GetSize() * logFont.lfHeight)
   {
    TRACE("%d   %d\r\n",rect.Height(),m_aInfo.GetSize() * logFont.lfHeight);
    SCROLLINFO info;

   info.cbSize = sizeof(info);
    info.fMask = SIF_PAGE;
    info.nPage = rect.Height() / logFont.lfHeight;
    CWnd::SetScrollRange(SB_VERT,0,m_aInfo.GetSize() - 1,FALSE);
    CWnd::ShowScrollBar(SB_VERT,TRUE);
    CWnd::SetScrollInfo(SB_VERT,&info);
   }
   else
   {
    CWnd::ShowScrollBar(SB_VERT,FALSE);
   }
  }
  CPaintDC dc(this); // device context for painting

 file://dc.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));
  dc.Rectangle(0,0,rect.Width(),rect.Height());
  logFont.lfWidth = 1;
  dc.SelectObject(pFont);
  int m_nBeginShow = CWnd::GetScrollPos(SB_VERT);
  for(int i=m_nBeginShow;i<m_aInfo.GetSize() && logFont.lfWidth < rect.Height() - 2;i++)
  {
   if(i == m_nMousePos)
   {
    dc.SetBkColor(RGB(0,0,128));
    dc.FillSolidRect(1,logFont.lfWidth,rect.Width() - 2,logFont.lfHeight,RGB(0,0,128));
    dc.SetTextColor(RGB(255,255,255));
   }
   else
   {
    dc.SetBkColor(RGB(255,255,255));
    dc.SetTextColor(RGB(0,0,0));
   }
   dc.TextOut(3,logFont.lfWidth,m_aInfo[i].strDepict);
   logFont.lfWidth += logFont.lfHeight;
  }
}

void CWndForACComboBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
  // TODO: Add your message handler code here and/or call default
 
  CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CWndForACComboBox::OnLButtonUp(UINT nFlags, CPoint point)
{
  CFont * pFont;
  LOGFONT logFont;

 if(m_pComboBox)
  {
   pFont = m_pComboBox->GetParent()->GetFont();
   pFont->GetLogFont(&logFont);
   if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;
   m_nMousePos = (point.y - 1) / logFont.lfHeight + CWnd::GetScrollPos(SB_VERT);
   if(m_nMousePos >= 0 && m_nMousePos < m_aInfo.GetSize())
    m_pComboBox->SetCurSel(m_aInfo[m_nMousePos].nid);
   ShowWindow(SW_HIDE);
  }
 
  CWnd::OnLButtonUp(nFlags, point);
}

BOOL CWndForACComboBox::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
  // TODO: Add your message handler code here and/or call default
 
  return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

void CWndForACComboBox::OnKillFocus(CWnd* pNewWnd)
{
  CWnd::OnKillFocus(pNewWnd);
 
  if(pNewWnd->GetSafeHwnd() != m_pComboBox->GetSafeHwnd() && pNewWnd->GetSafeHwnd() != GetSafeHwnd() && IsWindow(GetSafeHwnd()))
   ShowWindow(SW_HIDE);
}

void CWndForACComboBox::OnMouseMove(UINT nFlags, CPoint point)
{
  CFont * pFont;
  LOGFONT logFont;
  ::ShowCursor(TRUE);
  if(m_pComboBox)
  {
   pFont = m_pComboBox->GetParent()->GetFont();
   pFont->GetLogFont(&logFont);
   if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;
   logFont.lfWidth = point.y / logFont.lfHeight + CWnd::GetScrollPos(SB_VERT);
   if(logFont.lfWidth != m_nMousePos)
   {
    m_nMousePos = logFont.lfWidth;
    Invalidate();
   }
  }
 
  CWnd::OnMouseMove(nFlags, point);
}

void CWndForACComboBox::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
  if(m_aInfo.GetSize() <= 0)
  {
   CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
   return ;
  }

 switch(nSBCode)
  {
// case SB_BOTTOM://Scroll to bottom.
// case SB_ENDSCROLL://End scroll.
  case SB_LINEDOWN://Scroll one line down.
   {
    RECT rc;
    LOGFONT logFont;
    CFont * pFont;

   GetClientRect(&rc);
    pFont = m_pComboBox->GetParent()->GetFont();
    pFont->GetLogFont(&logFont);
    ASSERT(logFont.lfHeight != 0);
    if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;
    rc.left = (rc.bottom - rc.top) / logFont.lfHeight;

   int nPos = GetScrollPos(SB_VERT) + 1;
    if(nPos + rc.left <= m_aInfo.GetSize())
    {
     SetScrollPos(SB_VERT,nPos);
     Invalidate();
    }
   }
   break;
  case SB_LINEUP://Scroll one line up.
   {
    int nPos = GetScrollPos(SB_VERT) - 1;
    if(nPos >= 0)
    {
     SetScrollPos(SB_VERT,nPos);
     Invalidate();
    }
   }
   break;
  case SB_PAGEDOWN://Scroll one page down.
   {
    RECT rc;
    LOGFONT logFont;
    CFont * pFont;

   GetClientRect(&rc);
    pFont = m_pComboBox->GetParent()->GetFont();
    pFont->GetLogFont(&logFont);
    ASSERT(logFont.lfHeight != 0);
    if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;

   rc.top = rc.bottom / logFont.lfHeight;
    int nPos = GetScrollPos(SB_VERT);
    if(nPos < m_aInfo.GetSize() - rc.top)
    {
     nPos += rc.top;
     if(nPos > m_aInfo.GetSize() - rc.top) nPos = m_aInfo.GetSize() - rc.top;
     SetScrollPos(SB_VERT,nPos);
     Invalidate();
    }
   }
   break;
  case SB_PAGEUP://Scroll one page up.
   {
    RECT rc;
    LOGFONT logFont;
    CFont * pFont;

   GetClientRect(&rc);
    pFont = m_pComboBox->GetParent()->GetFont();
    pFont->GetLogFont(&logFont);
    ASSERT(logFont.lfHeight != 0);
    if(logFont.lfHeight < 0) logFont.lfHeight = -logFont.lfHeight;

   rc.top = rc.bottom / logFont.lfHeight;
    int nPos = GetScrollPos(SB_VERT);
    if(nPos > 0)
    {
     nPos -= rc.top;
     if(nPos < 0) nPos = 0;
     SetScrollPos(SB_VERT,nPos);
     Invalidate();
    }
   }
   break;
// case SB_THUMBPOSITION://Scroll to the absolute position. The current position is provided in nPos.
  case SB_THUMBTRACK://Drag scroll box to specified position. The current position is provided in nPos.
   {
    SetScrollPos(SB_VERT,nPos);
    Invalidate();
   }
   break;
// case SB_TOP://Scroll to top  
  }
 
  CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CACComboBox::HandleCompletion()
{
  // Make sure we can 'talk' to the edit control
  if( m_pEdit == NULL ) 
  {
   m_pEdit = new CEdit();
   m_pEdit->SubclassWindow(GetDlgItem(1001)->GetSafeHwnd());
  }

 // Save the state of the edit control
  CString text,bestText;
  CInfoForACComboBox info;
  int n = GetCount();

 m_wndList.RemoveAll();
  m_pEdit->GetWindowText(text);
  CPoint ptCaret = m_pEdit->GetCaretPos();

// int start,end;
// m_pEdit->GetSel(start,end);

 // Perform actual completion
  int bestindex = -1;
  int bestfrom  = INT_MAX;
  int from;
  for ( int x = 0; x < n; x++ )
  {
   GetLBText(x,info.strDepict);
   info.nid = x;

  from = info.strDepict.Find(text);

  if(from != -1)
   {
    m_wndList.Add(info);
    if( from != -1 && from < bestfrom )
    {
     bestindex = x;
     bestText = info.strDepict;
     bestfrom = from;
    }
   }
  }

 if ( bestindex != -1)
  {
   // Restore the edit control
   m_pEdit->SetWindowText(bestText);
   m_pEdit->SetSel(text.GetLength(),bestText.GetLength());
   m_pEdit->SetCaretPos(ptCaret);
  }
  if(m_wndList.GetSize() != 0)
  {
   m_wndList.ShowList();
   m_wndList.Invalidate();
  }
  else
  {
   m_wndList.ShowWindow(SW_HIDE);
  }
}

BOOL CACComboBox::OnCommand(WPARAM wParam, LPARAM lParam)
{
  if(HIWORD(wParam) == EN_CHANGE)
  {
   HandleCompletion();
   return TRUE;
  }
  
  return CComboBox::OnCommand(wParam, lParam);
}

void CACComboBox::PreSubclassWindow()
{
  CComboBox::PreSubclassWindow();

 m_wndList.Create(this);
}

void CACComboBox::OnKillfocus()
{
  m_wndList.OnKillFocus(GetFocus());
}

void CACComboBox::OnSelchange()
{
  m_wndList.ShowWindow(SW_HIDE); 
}


关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号