老规矩,先贴代码
//.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屏蔽掉了。这就是结果。。。