C++MFC学习心得(四)——CListBox自绘控件碰到的一个小问题

来源:互联网 发布:4399赛尔号刷钻石软件 编辑:程序博客网 时间:2024/06/06 17:10

老规矩,先贴代码

//.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 100CMyApp 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屏蔽掉了。这就是结果。。。

原创粉丝点击