集成了自动完成、tooltip提示和自动加宽listbox的ComboBox
2011年05月06日
头文件CComboCompletion.h: #if !defined(AFX_COMBOCOMPLETION_H__E1EBAD20_8F3B_48E5 _9D44_87410EF665A4__INCLUDED_) #define AFX_COMBOCOMPLETION_H__E1EBAD20_8F3B_48E5_9D44_874 10EF665A4__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ComboCompletion.h : header file // #define WM_SHOWDROP WM_USER + 101 ////////////////////////////////////////////////// /////////////////////////// // CComboCompletion window class CComboCompletion : public CComboBox { // Construction public: CComboCompletion(BOOL bEnableTool = TRUE, BOOL bEnabelResize = FALSE); // Attributes public: BOOL m_bEnableTool; BOOL m_bEnableResize; private: static CWnd m_tipWnd; // used to draw tooltip text static CFont m_font; static CMap m_mapWndProc; COMBOBOXINFO m_cbi; // is mouse in area static BOOL m_bEnter; // last tooltip_show_item of list static int m_nOriSel; BOOL m_bAutoComplete; // Operations public: void CreateTooltipWnd(); void DestroyTooltipWnd(); private: // specify the windowproc for edit and list void InstallEditAndListWndProc(); static LRESULT CALLBACK HookTooltipWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK HookEditboxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK HookListboxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // handler for paint tooltip window static void OnHandleTooltipPaint(); // handler for mouse move on listbox static void OnHandleListboxMousemove(CListBox *pList, CPoint pt); // handler for mouse hover on editbox static void OnHandleEditboxMousehover(CWnd *pWnd); // track mouse event static BOOL OnTrackMouseEvent(HWND hWnd, DWORD dwFlags); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CComboCompletion) public: virtual BOOL PreTranslateMessage(MSG* pMsg); protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL // Implementation public: virtual ~CComboCompletion(); // Generated message map functions protected: //{{AFX_MSG(CComboCompletion) afx_msg void OnDropdown(); afx_msg void OnEditupdate(); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); //}}AFX_MSG afx_msg HRESULT OnShowDropDown(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() }; ////////////////////////////////////////////////// /////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_COMBOCOMPLETION_H__E1EBAD20_8F3B_48E5 _9D44_87410EF665A4__INCLUDED_) 源文件CComboCompletion.cpp // ComboCompletion.cpp : implementation file // #include "stdafx.h" #include "DlgBase.h" #include "ComboCompletion.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ////////////////////////////////////////////////// /////////////////////////// // CComboCompletion CWnd CComboCompletion::m_tipWnd; CMap CComboCompletion::m_mapWndProc; CFont CComboCompletion::m_font; BOOL CComboCompletion::m_bEnter = FALSE; int CComboCompletion::m_nOriSel = LB_ERR; CComboCompletion::CComboCompletion(BOOL bEnableTool /*= TRUE*/, BOOL bEnabelResize /*= FALSE*/) { // use system default tool-tip font NONCLIENTMETRICS ncm; ZeroMemory(&ncm, sizeof(NONCLIENTMETRICS)); ncm.cbSize = sizeof(NONCLIENTMETRICS); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); if (m_font.m_hObject == NULL) { m_font.CreateFontIndirect(&ncm.lfStatusFont); } m_bEnableTool = bEnableTool; m_bEnableResize = bEnabelResize; CreateTooltipWnd(); } CComboCompletion::~CComboCompletion() { if (m_cbi.hwndItem) { m_mapWndProc.RemoveKey(m_cbi.hwndItem); } else if (m_cbi.hwndList) { m_mapWndProc.RemoveKey(m_cbi.hwndList); } // destroy tooltip window DestroyTooltipWnd(); m_mapWndProc.RemoveAll(); } BEGIN_MESSAGE_MAP(CComboCompletion, CComboBox) //{{AFX_MSG_MAP(CComboCompletion) ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown) ON_CONTROL_REFLECT(CBN_EDITUPDATE, OnEditupdate) ON_WM_CTLCOLOR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ////////////////////////////////////////////////// /////////////////////////// // CComboCompletion message handlers void CComboCompletion::CreateTooltipWnd() { if (!::IsWindow(m_tipWnd.m_hWnd)) { m_tipWnd.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(0), NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL); WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(m_tipWnd.m_hWnd, GWL_WNDPROC, (LONG)HookTooltipWndProc); m_mapWndProc.SetAt(m_tipWnd.m_hWnd, oldWndProc); } } void CComboCompletion::DestroyTooltipWnd() { // must first destroy window m_tipWnd.DestroyWindow(); // second,remove wndproc WNDPROC oldWndProc; HWND hWnd = m_tipWnd.m_hWnd; BOOL bRet = m_mapWndProc.Lookup(hWnd, oldWndProc); if (bRet == TRUE) { m_mapWndProc.RemoveKey(hWnd); } } void CComboCompletion::InstallEditAndListWndProc() { ZeroMemory(&m_cbi, sizeof(COMBOBOXINFO)); m_cbi.cbSize = sizeof(COMBOBOXINFO); ::GetComboBoxInfo(m_hWnd, &m_cbi); if (m_cbi.hwndItem) {// specify wndproc for editbox WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(m_cbi.hwndItem, GWL_WNDPROC, (LONG)HookEditboxWndProc); m_mapWndProc.SetAt(m_cbi.hwndItem, oldWndProc); } if (m_cbi.hwndList) {// specify wndproc for listbox WNDPROC oldWndProc = (WNDPROC)::SetWindowLong(m_cbi.hwndList, GWL_WNDPROC, (LONG)HookListboxWndProc); m_mapWndProc.SetAt(m_cbi.hwndList, oldWndProc); } } LRESULT CALLBACK CComboCompletion::HookTooltipWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_PAINT) { CComboCompletion::OnHandleTooltipPaint(); } else if (uMsg == WM_SHOWWINDOW && wParam == FALSE) { ReleaseCapture(); } // default handle other message WNDPROC oldWndProc; m_mapWndProc.Lookup(hWnd, oldWndProc); return ::CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); } LRESULT CALLBACK CComboCompletion::HookEditboxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CWnd *pWnd = CWnd::FromHandle(hWnd); if (uMsg == WM_MOUSEMOVE) { // note,mouse-leave msg must be send manual CPoint pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); CRect rect; pWnd->GetClientRect(&rect); if (!rect.PtInRect(pt)) { ::SendMessage(hWnd, WM_MOUSELEAVE, wParam, lParam); } // when mouse enter edit-box,start tracking mouse event if (!m_bEnter) { OnTrackMouseEvent(hWnd, TME_HOVER|TME_LEAVE); m_bEnter = TRUE; } } else if (uMsg == WM_MOUSEHOVER) { OnHandleEditboxMousehover(pWnd); } else if (uMsg == WM_MOUSELEAVE) { m_bEnter = FALSE; m_tipWnd.ShowWindow(SW_HIDE); } // default handle other message WNDPROC oldWndProc; m_mapWndProc.Lookup(hWnd, oldWndProc); return ::CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); } LRESULT CALLBACK CComboCompletion::HookListboxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CListBox *pList = (CListBox *)CWnd::FromHandle(hWnd); if (uMsg == WM_MOUSEMOVE) { CPoint pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); CRect rect; pList->GetClientRect(&rect); if (rect.PtInRect(pt)) { CComboCompletion::OnHandleListboxMousemove(pList, pt); } else { ::SendMessage(hWnd, WM_MOUSELEAVE, wParam, lParam); } // track mouse-leave msg if (m_bEnter == FALSE) { OnTrackMouseEvent(hWnd, TME_LEAVE); m_bEnter = TRUE; } } else if (uMsg == WM_MOUSELEAVE) { m_nOriSel = LB_ERR; m_bEnter = FALSE; m_tipWnd.ShowWindow(SW_HIDE); } else if (uMsg == WM_CAPTURECHANGED) {// note, because capture msg is handled by us,so it need not default handle return 1; } // default handle other message WNDPROC oldWndProc; m_mapWndProc.Lookup(hWnd, oldWndProc); return ::CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); } void CComboCompletion::OnHandleTooltipPaint() { // get dc CPaintDC dc(&m_tipWnd); // specify the rect CRect rect; m_tipWnd.GetClientRect(&rect); // draws a border around the specified rectangle CBrush border(RGB(0,0,0)); dc.FrameRect(&rect, &border); // fill the rectangle CBrush fill(GetSysColor(COLOR_INFOBK)); dc.FillRect(&rect, &fill); // specify the font CFont *pOldfont = dc.SelectObject(&m_font); // draw text CString strText; m_tipWnd.GetWindowText(strText); dc.SetBkMode(TRANSPARENT); dc.DrawText(strText, &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_NOPREFIX); // recover the default font dc.SelectObject(pOldfont); } BOOL CComboCompletion::OnTrackMouseEvent(HWND hWnd, DWORD dwFlags) { TRACKMOUSEEVENT track; ZeroMemory(&track, sizeof(TRACKMOUSEEVENT)); track.cbSize = sizeof(TRACKMOUSEEVENT); track.hwndTrack = hWnd; track.dwFlags = dwFlags; track.dwHoverTime = HOVER_DEFAULT; return _TrackMouseEvent(&track); } void CComboCompletion::OnHandleEditboxMousehover(CWnd *pWnd)// pWnd is the editbox pointer { // get rect of editbox CRect rcEdit; pWnd->GetClientRect(&rcEdit); CString strText; pWnd->GetWindowText(strText); // get tooltip dc CDC *pDc = m_tipWnd.GetDC(); CFont *pOldfont = pDc->SelectObject(&m_font); // use drawtext to calculate the actual rect of text CRect rcDraw = rcEdit; pDc->DrawText(strText, &rcDraw, DT_CALCRECT|DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_ NOPREFIX); // release tootip dc pDc->SelectObject(pOldfont); ::ReleaseDC(m_tipWnd.m_hWnd, pDc->m_hDC); if (rcDraw.Width() tooltip m_tipWnd.ShowWindow(SW_HIDE); } else {// if text is longer than edit, then show tooltip rcDraw.bottom = rcEdit.bottom; rcDraw.InflateRect(2, 2);// increase the width and height of draw rect pWnd->ClientToScreen(&rcDraw); m_tipWnd.SetWindowText(strText); ::SetCapture(pWnd->m_hWnd);// combobox has capture always m_tipWnd.SetWindowPos(&CWnd::wndTopMost, rcDraw.left, rcDraw.top, rcDraw.Width(), rcDraw.Height(), SWP_NOACTIVATE|SWP_SHOWWINDOW); } } void CComboCompletion::OnHandleListboxMousemove(CListBo x *pList, CPoint pt) { BOOL bOut = TRUE; int nSel = pList->ItemFromPoint(pt, bOut); if (nSel == m_nOriSel) return; if (nSel != LB_ERR && bOut == FALSE) { m_nOriSel = nSel; CString strText; pList->GetText(nSel, strText); CRect rcItem; pList->GetItemRect(nSel, &rcItem); CRect rcDraw = rcItem; CDC *pDc = m_tipWnd.GetDC(); CFont *pOldfont = pDc->SelectObject(&m_font); // re-calculate the acutal rect of text pDc->DrawText(strText, &rcDraw, DT_CALCRECT|DT_SINGLELINE|DT_CENTER|DT_VCENTER|DT_ NOPREFIX); CString strWidth; strWidth.Format("%d", rcDraw.Width()); OutputDebugString(strWidth); pDc->SelectObject(pOldfont); ::ReleaseDC(m_tipWnd.m_hWnd, pDc->m_hDC); if (rcDraw.Width() tooltip m_tipWnd.ShowWindow(SW_HIDE); } else { rcDraw.bottom = rcItem.bottom; rcDraw.InflateRect(2, 2);// increase the width and height of draw text pList->ClientToScreen(&rcDraw); m_tipWnd.ShowWindow(SW_HIDE); if (::GetCapture() != pList->m_hWnd) ::SetCapture(pList->m_hWnd); m_tipWnd.SetWindowText(strText); // note, in msdn, it say the SetWindowPos uses client coordinate,but in fact, it use screent coordinate m_tipWnd.SetWindowPos(&CWnd::wndTopMost, rcDraw.left, rcDraw.top, rcDraw.Width(), rcDraw.Height(), SWP_NOACTIVATE|SWP_SHOWWINDOW); } } } void CComboCompletion::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class if (m_bEnableTool == TRUE) { InstallEditAndListWndProc(); } CComboBox::PreSubclassWindow(); } // 以下为自动完成 BOOL CComboCompletion::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if (pMsg->message == WM_CHAR) { m_bAutoComplete = TRUE; int nVirKey = pMsg->wParam; switch (nVirKey) { case VK_RETURN: { // 关闭下拉框 ShowDropDown(FALSE); CString strLine; GetWindowText(strLine); // 回车即选中高亮项 SelectString(-1, strLine); // 给父窗口发送选项改变的消息 WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE); GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd); break; } case VK_DELETE: case VK_BACK: m_bAutoComplete = FALSE; break; default: break; } } return CComboBox::PreTranslateMessage(pMsg); } void CComboCompletion::OnDropdown() { // TODO: Add your control notification handler code here SetCursor(LoadCursor(NULL, IDC_ARROW)); } void CComboCompletion::OnEditupdate() { // TODO: Add your control notification handler code here CString strLine; GetWindowText(strLine); int iHiLightStart = strLine.GetLength(); if(strLine.GetLength() == 0) { ShowDropDown(FALSE); SetWindowText(_T("")); m_bAutoComplete = TRUE; return; } // 处理删除操作 if(!m_bAutoComplete) { m_bAutoComplete = TRUE; return; } // 开始匹配用户输入 int iSelectedRow = FindString(-1, strLine); if(iSelectedRow >= 0) { // ShowDropDown(TRUE); PostMessage(WM_SHOWDROP, 0, 0); // 匹配的选项被选中 PostMessage(CB_SETCURSEL, iSelectedRow, 0); // 给父窗口发送选项改变的消息,这样可以保证当输入完整的匹配的部门时,不用回车也触发部门改变消息 WPARAM wParam = MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE); GetParent()->PostMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd); } else { // ShowDropDown(FALSE); // SetWindowText(strLine); } // 高亮自动完成的部分 PostMessage(CB_SETEDITSEL, 0, MAKELPARAM(iHiLightStart, -1)); } HRESULT CComboCompletion::OnShowDropDown(WPARAM wParam, LPARAM lParam) { ShowDropDown(TRUE); return 0; } // 以下为自动加宽listbox HBRUSH CComboCompletion::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor); switch(nCtlColor) { case CTLCOLOR_EDIT: break; case CTLCOLOR_LISTBOX: if (m_bEnableResize == FALSE) { break; } int iItemNum=GetCount(); int iWidth=0; CString strItem; CClientDC dc(this); int iSaveDC=dc.SaveDC(); dc.SelectObject(GetFont()); int iVSWidth=::GetSystemMetrics(SM_CXVSCROLL); for(int i=0;i0) { CRect rc; pWnd->GetWindowRect(&rc); if(rc.Width()!=iWidth) { rc.right=rc.left+iWidth; pWnd->MoveWindow(&rc); } } break; } return hbr; } 以下为使用方法:
CDlgBaseDlg::CDlgBaseDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDlgBaseDlg::IDD, pParent), m_combo5(FALSE, TRUE)
发表评论
-
控件美化
2012-01-20 00:58 1242控件美化 2010年11月16日 2010-03-25 ... -
DataGridView概述
2012-01-20 00:58 1086DataGridView概述 2011年05月18日 通 ... -
comboBox下拉后鼠标移动到子项时出现对应的提示
2012-01-20 00:58 1757comboBox下拉后鼠标移动到子项时出现对应的提示 201 ... -
ComboBox的ToolTip显示
2012-01-20 00:57 967ComboBox的ToolTip显示 2010年06月17日 ... -
如何加强幼儿园安全管理
2012-01-19 08:46 887如何加强幼儿园安全管 ... -
3年后广东入园贵入园难基本解决 因地制宜制订各地幼儿园收费标准
2012-01-19 08:46 5143年后广东入园贵入园难基本解决 因地制宜制订各地幼儿园收费标准 ... -
园长联谊会发言稿
2012-01-19 08:46 607园长联谊会发言稿 2011年12月19日 园长联谊会发言 ... -
幼儿园园长以及教师的职责
2012-01-19 08:46 832幼儿园园长以及教师的职责 2010年07月25日 幼儿园 ... -
马湖乡中心幼稚园教师奖惩制度
2012-01-19 08:46 585马湖乡中心幼稚园教师奖惩制度 2011年06月17日 ... -
sdsadsadas
2012-01-17 01:15 538sdsadsadas 2010年11月22日 XV67 ... -
5230
2012-01-17 01:15 5315230 2010年10月03日 1、屏幕保护:一定要买 ... -
电脑天书(九)
2012-01-17 01:15 547电脑天书(九) 2011年04月 ... -
VISTA系统常识技巧集锦
2012-01-17 01:15 542VISTA系统常识技巧集锦 ... -
MAX三百问(珍藏版)上
2012-01-17 01:14 599MAX三百问(珍藏版)上 2011年06月13日 安装篇 ... -
yum install lamp
2012-01-15 19:55 656yum install lamp 2011年12月11日 ... -
Ubuntu下各网络服务器配置小结
2012-01-15 19:55 626Ubuntu下各网络服务器配置小结 2011年12月10日 ... -
LAMNP 编译安装参数(一)---Apache 安装编译参数
2012-01-15 19:55 558LAMNP 编译安装参数(一)---Apache 安装编译参数 ... -
惠普 康柏 510 笔记本电脑
2012-01-15 19:55 694惠普 康柏 510 笔记本电脑 2011年12月17日 ... -
俺的电脑配置
2012-01-15 19:55 546俺的电脑配置 2011年12月21日 电脑型号 微星 ... -
java 题集(二)-i'm thinking...-iteye技术网站
2012-01-11 12:09 580java 题集(二)-i'm thinking.. ...
相关推荐
微信小程序-ToolTip信息提示组件导入将ToolTip文件夹复制到pages文件夹内使用在需要使用ToolTip的页面对应的.wxml文件中添加: src="../ToolTip/toolTip.wxml"/> <!-- 引入toolTip模板 --> is=...
在listbox中显示每个Item的Tooltip
支持TOOLTIP的COMBOX,C#版本(该版本存在一定的问题,请下载资源中的其它相关资源)
这是一个vue的tooltip提示信息组件。它使用非常简便,同时它支持自定义样式,提示信息的位置,触发提示信息弹出的事件。提示出现隐藏的延迟时间等。
jQuery的一款tooltip提示插件,通过鼠标悬停显示提示时间,提示内容使用ajax动态显示。
JS弹出层对话框插件源码,包含弹出层对话框和Tooltip提示框,消息框等多种功能,兼容主流浏览器(注:不兼容IE9以下版本的IE浏览器)。内置4种颜色的皮肤,且可以自定义对话框样式,可设置对话框位置。Tooltip可以...
很实用的TOOLTIP提示框示例程序,鼠标移动到指定位置时会显示气泡提示框
数据窗口列的宽度不够时自动显示tooltip帮助住处界面
VC 简洁的tooltip提示类,包含static、Edit、Button等控件的文字提示。
jQuery图片tooltip提示是一款基于jquery css3实现的鼠标滑过缩略图tooltip提示显示大图特效。
直接扩展绑定数据源时的字段,以数据源中的某个字段作为TOOLTIP的显示内容
jQuery UI滑杆插件 可Tooltip提示是一款jQuery UI实现的,可以设置多种颜色,再加上CSS3上运用,可以让滑杆的游标变得有立体感,滑杆的Tooltip提示框也出现飞入飞出的动画效果。
jQuery UI滑杆插件 可Tooltip提示
jQuery Tooltip跟随鼠标提示条,处于四个角落时,自动变换位置
该工程实现了可以显示多行内容的ToolTip的ListBox,继承CWnd实现了一个自定义的ToolTip类,再继承CListBox实现了一个自定义的ListBox类
When you add a ToolTip control to a form, it is active by default. Therefore, you do not have to do anything to make it active. If you look at the source file for your form, you will see code that ...
jquery实现Tooltip提示(文字、链接、地图锚点),自带5种不同样式
可以应用各个地方的ToolTip控件, 相关使用方法:http://blog.csdn.net/tangjun0102/archive/2009/10/10/4650907.aspx
jquery Tooltip简易文本提示框插件
锁定界面和使用ToolTip创建提示,解锁界面的默认密码是1234,当鼠标移到确定按钮或这是第一个文本框时,出现提示。