C++MFC学习心得(四)——CListBox自绘控件碰到的一个小问题
2013-05-18 20:35
831 查看
老规矩,先贴代码
在这个程序里,是一个自绘CListBox的程序,但是,CListBox不响应SELCHANGE的消息,很纳闷,因为这是书上的原程序。
然后开始找吧,开始,以为消息映射没做好,改来改去,没什么结果。
下面,新建工程,CListBox,好的,有响应。
在下面,新建工程,自绘CListBox,没响应;推出,这是自绘的问题。。。然后找到前面,这里:
把第三行注释掉,好了。。。最后发现,原来是~和-的差别,最后得到,差别就是,结果最后一位差了1。即原来的表达式,算出来最后一位为0,。
查了一下,这一位是LBS_NOTIFY。征结找到了,为什么呢?
百科中是这样说的:
ON_LBN_SELCHANGE 列表框中的选择可能改变。如果选择被CListBox::SetCurSel成员函数改变,则通知不发送。此通知只适用于LBS_NOTIFY风格的列表框。无论何时用户按下箭头键,即使选择未改变,LBN_SELCHANGE通知消息都被发送给多选列表框。
看得我云里雾里,不知道他想说什么。没办法,我们还有一个文档叫做MSDN...
MSDN里是这么说的:
LBS_NOTIFY Parent window receives an input message whenever the user clicks or double-clicks a string.
LBS_NOTIFY 就是说,不管操作者单击或者双击某一项(不管这一项是不是之前选定的),父窗口会收到输入信息。如果没有这一位,就将SELCHANGE屏蔽掉了。这就是结果。。。
//.h
class CMyApp:public CWinApp { public: virtual BOOL InitInstance(); }; class CIconListBox:public CListBox { public: virtual BOOL PreCreateWindow(CREATESTRUCT &cs); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpmis); virtual void DrawItem(LPDRAWITEMSTRUCT lpdis); int AddIcon(HICON hIcon); void ProjectImage(CDC* pDC,LPRECT pRect,COLORREF clrBackColor); }; class CMainWnd:public CWnd { protected: int m_cxChar; int m_cyChar; CFont m_font; CRect m_rcImage; CButton m_wndGroupBox; CIconListBox m_wndIconListBox; CStatic m_wndLabel; public: CMainWnd(); protected: virtual void PostNcDestroy(); afx_msg int OnCreate(LPCREATESTRUCT lpcs); afx_msg void OnPaint(); afx_msg void OnSetFocus(CWnd* pWnd); afx_msg void OnDropFiles(HDROP hDropInfo); afx_msg void OnSelChange(); DECLARE_MESSAGE_MAP() };
//.cpp
#include<afxwin.h> #include"IconView.h" #define IDC_LISTBOX 100 CMyApp myApp; BOOL CMyApp::InitInstance() { m_pMainWnd = new CMainWnd; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } BEGIN_MESSAGE_MAP(CMainWnd,CWnd) ON_WM_CREATE() ON_WM_PAINT() ON_WM_SETFOCUS() ON_WM_DROPFILES() ON_LBN_SELCHANGE(IDC_LISTBOX,OnSelChange) END_MESSAGE_MAP() CMainWnd::CMainWnd() { CString strWndClass = AfxRegisterWndClass( 0, myApp.LoadCursor(IDC_ARROW), (HBRUSH)(COLOR_3DFACE +1), myApp.LoadIcon(IDI_WINLOGO)); CreateEx(0, strWndClass, _T("Icon View"), WS_OVERLAPPED|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL); CRect rect(0,0,m_cxChar * 84,m_cyChar * 21); CalcWindowRect(&rect); SetWindowPos(NULL,0,0,rect.Width(),rect.Height(),SWP_NOZORDER|SWP_NOMOVE|SWP_NOREDRAW); } int CMainWnd::OnCreate(LPCREATESTRUCT lpcs) { if(CWnd::OnCreate(lpcs) == -1) return -1; m_font.CreatePointFont(80,_T("MS Sans Serif")); CClientDC dc(this); CFont* pOldFont = dc.SelectObject(&m_font); TEXTMETRIC tm; dc.GetTextMetrics(&tm); m_cxChar = tm.tmAveCharWidth; m_cyChar = tm.tmHeight + tm.tmInternalLeading; dc.SelectObject(pOldFont); m_rcImage.SetRect(m_cxChar * 4, m_cyChar * 3, m_cxChar * 46, m_cyChar * 19); m_wndGroupBox.Create(_T("Detail"), BS_GROUPBOX|WS_VISIBLE|WS_CHILD, CRect(m_cxChar * 2,m_cyChar,m_cxChar* 48,m_cyChar * 20), this, UINT(-1)); m_wndLabel.Create(_T("Icons"), WS_CHILD|WS_VISIBLE|SS_LEFT, CRect(m_cxChar * 50,m_cyChar,m_cxChar* 82,m_cyChar * 2), this); m_wndIconListBox.Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_BORDER|LBS_NOTIFY|LBS_NOINTEGRALHEIGHT, CRect(m_cxChar* 50,m_cyChar* 2,m_cxChar*82,m_cyChar * 20), this, IDC_LISTBOX); m_wndGroupBox.SetFont(&m_font); m_wndLabel.SetFont(&m_font); DragAcceptFiles(); return 0; } void CMainWnd::PostNcDestroy() { delete this; } void CMainWnd::OnPaint() { CPaintDC dc(this); m_wndIconListBox.ProjectImage(&dc,m_rcImage,::GetSysColor(COLOR_3DFACE)); } void CMainWnd::OnSetFocus(CWnd* pWnd) { m_wndIconListBox.SetFocus(); } void CMainWnd::OnDropFiles(HDROP hDropInfo) { int nCount = ::DragQueryFile(hDropInfo,(UINT)-1,NULL,0); if(nCount == 1) { m_wndIconListBox.ResetContent(); char szFile[MAX_PATH]; ::DragQueryFile(hDropInfo,0,szFile,sizeof(szFile)); int nIcons = (int)::ExtractIcon(NULL,szFile,(UINT)-1); if(nIcons) { HICON hIcon; for(int i = 0;i<nIcons;i++) { hIcon = ::ExtractIcon(AfxGetInstanceHandle(),szFile,i); m_wndIconListBox.AddIcon(hIcon); } } CString strWndTitle = szFile; strWndTitle += _T(" - Icon View"); SetWindowText(strWndTitle); CClientDC dc(this); m_wndIconListBox.SetCurSel(0); m_wndIconListBox.ProjectImage(&dc,m_rcImage,::GetSysColor(COLOR_3DFACE)); } ::DragFinish(hDropInfo); } void CMainWnd::OnSelChange() { CClientDC dc(this); m_wndIconListBox.ProjectImage(&dc,m_rcImage,::GetSysColor(COLOR_3DFACE)); } BOOL CIconListBox::PreCreateWindow(CREATESTRUCT &cs) { if(!CListBox::PreCreateWindow(cs)) return FALSE; cs.style &=~(LBS_SORT|LBS_OWNERDRAWVARIABLE); cs.style |= LBS_OWNERDRAWFIXED; return TRUE; } void CIconListBox::MeasureItem(LPMEASUREITEMSTRUCT lpmis) { lpmis->itemHeight = 36; } void CIconListBox::DrawItem(LPDRAWITEMSTRUCT lpdis) { CDC dc; dc.Attach(lpdis->hDC); CRect rect = lpdis->rcItem; int nIndex = lpdis->itemID; CBrush* pBrush = new CBrush; pBrush->CreateSolidBrush(::GetSysColor((lpdis->itemState&ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW)); dc.FillRect(rect,pBrush); delete pBrush; if(lpdis->itemState & ODS_FOCUS) dc.DrawFocusRect(rect); if(nIndex!=(UINT)-1) dc.DrawIcon(rect.left + 4,rect.top + 2,(HICON)GetItemData(nIndex)); dc.Detach(); } int CIconListBox::AddIcon(HICON hIcon) { int nIndex = AddString(_T("")); if((nIndex != LB_ERR)&&(nIndex != LB_ERRSPACE)) SetItemData(nIndex,(DWORD)hIcon); return nIndex; } void CIconListBox::ProjectImage(CDC* pDC, LPRECT pRect, COLORREF clrBackColor) { CDC dcMem; dcMem.CreateCompatibleDC(pDC); CBitmap bitmap; bitmap.CreateCompatibleBitmap(pDC,32,32); CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap); CBrush* pBrush = new CBrush(clrBackColor); dcMem.FillRect(CRect(0,0,32,32),pBrush); delete pBrush; int nIndex = GetCurSel(); if(nIndex != LB_ERR) dcMem.DrawIcon(0,0,(HICON)GetItemData(nIndex)); pDC->StretchBlt(pRect->left,pRect->top,pRect->right - pRect->left,pRect->bottom - pRect->top, &dcMem,0,0,32,32,SRCCOPY); dcMem.SelectObject(pOldBitmap); }
在这个程序里,是一个自绘CListBox的程序,但是,CListBox不响应SELCHANGE的消息,很纳闷,因为这是书上的原程序。
然后开始找吧,开始,以为消息映射没做好,改来改去,没什么结果。
下面,新建工程,CListBox,好的,有响应。
在下面,新建工程,自绘CListBox,没响应;推出,这是自绘的问题。。。然后找到前面,这里:
BOOL CIconListBox::PreCreateWindow(CREATESTRUCT &cs) { if(!CListBox::PreCreateWindow(cs)) return FALSE; cs.style &=~(LBS_SORT|LBS_OWNERDRAWVARIABLE);//原来这里是cs.style &=-(LBS_SORT|LBS_OWNERDRAWVARIABLE);
cs.style |= LBS_OWNERDRAWFIXED; return TRUE; }
把第三行注释掉,好了。。。最后发现,原来是~和-的差别,最后得到,差别就是,结果最后一位差了1。即原来的表达式,算出来最后一位为0,。
查了一下,这一位是LBS_NOTIFY。征结找到了,为什么呢?
百科中是这样说的:
ON_LBN_SELCHANGE 列表框中的选择可能改变。如果选择被CListBox::SetCurSel成员函数改变,则通知不发送。此通知只适用于LBS_NOTIFY风格的列表框。无论何时用户按下箭头键,即使选择未改变,LBN_SELCHANGE通知消息都被发送给多选列表框。
看得我云里雾里,不知道他想说什么。没办法,我们还有一个文档叫做MSDN...
MSDN里是这么说的:
LBS_NOTIFY Parent window receives an input message whenever the user clicks or double-clicks a string.
LBS_NOTIFY 就是说,不管操作者单击或者双击某一项(不管这一项是不是之前选定的),父窗口会收到输入信息。如果没有这一位,就将SELCHANGE屏蔽掉了。这就是结果。。。
相关文章推荐
- 计算机科学与技术学习心得之计算机理论的一个核心问题--从数学谈起(转载)
- MFC入门学习之控件(2)创建一个对话框窗口并在运行时显示
- MFC学习之路(四)不够细心,一个小问题蛋疼了一天
- 计算机科学与技术学习心得之计算机理论的一个核心问题--计算数学基础(转载)
- 多线程学习中碰到的一个很有意思的问题
- VS2010 C++ MFC框架学习笔记3 - 控件Tab顺序设置及模态对话框
- C++ MFC学习心得(一)
- 计算机科学与技术学习心得之计算机理论的一个核心问题--续谈其他的一些计算数学(转载)
- (转)看完了第二遍C++Primer,学习心得与问题
- C++ MFC学习心得(二)
- VC++6.0&&VS2008&MFC&API学习问题总结(三)(多线程更新控件)
- 刚开始学习C++容易碰到的问题
- wf的学习中碰到了一个问题
- 控件的Group属性 一个菜鸟问题 MFC高手进来
- 一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(3) 最大子序列和问题
- 今日学习心得:如何做解决数据绑定控件嵌套问题
- 看完了第二遍C++Primer,学习心得与问题
- VS2010 C++ MFC框架学习笔记1 - 创建一个简单的加法计算器(1)
- Android学习心得(一)记录一个问题
- MFC中资源ID和具体控件之间的关系问题【学习笔记】