ListBox 每项前加 Icon(金山词霸索引控件)(上)

来源:互联网 发布:淘宝滥用商标关键字 编辑:程序博客网 时间:2024/04/30 15:47

终于搞完了英文戏剧,又有时间接着做项目了.昨天完成了一个类似于金山词霸索引的控件,界面如下图,觉得学到满多东西的,所以想到要写下来.

 listbox

要实现这样的一个功能,首先要想的是到底金山词霸用的是怎样的一个控件,ComboBox, ListBox, 还是ListView. 当我找了很多资料,研究了各控件的用法之后,我决定用ListBox, 最终还是可以实现到想要的功能.

相信大家都用过金山词霸吧,在输入框输入一个单词,它就会显示相应的索引. 要完成这个功能,其实很简单.首先,要在ListBox的每一项加一个位图,怎样在ListBox前面加位图呢,下面我把实现的重要步骤写下来:

 

1.       首先在你的Dialog项目中添加一个新类,例如CIconListBox. 接着在类里添加下面的函数

//重载DrawItem这个函数

void CIconListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

{

    // TODO: Add your code to draw the specified item

 

    CDC* pDC    = CDC::FromHandle(lpDrawItemStruct->hDC);

 

    if ((int)lpDrawItemStruct->itemID < 0)

    {

           if ((lpDrawItemStruct->itemAction & ODA_FOCUS) &&

                  (lpDrawItemStruct->itemState & ODS_FOCUS))

           {

                  pDC->DrawFocusRect(&lpDrawItemStruct->rcItem);

           }

           else if ((lpDrawItemStruct->itemAction & ODA_FOCUS) &&  

                  !(lpDrawItemStruct->itemState & ODS_FOCUS))

           {

                  pDC->DrawFocusRect(&lpDrawItemStruct->rcItem);

           }

           return;

    }

 

    CRect  rcItem(lpDrawItemStruct->rcItem); // To draw the focus rect.

    CRect  rClient(rcItem); // Rect to highlight the Item

    CRect  rText(rcItem); // Rect To display the Text

    CPoint Pt( rcItem.left , rcItem.top ); // Point To draw the Image

    if(m_pImageList)

    {

           rClient.left += 16;

           rText.left += 16;

           rText.top += 2;

    }

    else

    {

           rText.top += 2;

    }

 

    COLORREF crText;

    CString strText;

    int iImg = (int)lpDrawItemStruct->itemData;

    if ((lpDrawItemStruct->itemState & ODS_SELECTED) &&

            (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))

    {

           CBrush br(::GetSysColor(COLOR_HIGHLIGHT));

           pDC->FillRect(&rClient, &br);

    }

    else if (!(lpDrawItemStruct->itemState & ODS_SELECTED) &&

           (lpDrawItemStruct->itemAction & ODA_SELECT))

    {

           CBrush br(::GetSysColor(COLOR_WINDOW));

           pDC->FillRect(&rClient, &br);

    }

 

    if ((lpDrawItemStruct->itemAction & ODA_FOCUS) &&

           (lpDrawItemStruct->itemState & ODS_FOCUS))

    {

           pDC->DrawFocusRect(&rcItem);

    }

    else if ((lpDrawItemStruct->itemAction & ODA_FOCUS) &&  

           !(lpDrawItemStruct->itemState & ODS_FOCUS))

    {

           pDC->DrawFocusRect(&rcItem);

    }

 

    // To draw the Text set the background mode to Transparent.

    int iBkMode = pDC->SetBkMode(TRANSPARENT);

 

    if (lpDrawItemStruct->itemState & ODS_SELECTED)

           crText = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));

    else if (lpDrawItemStruct->itemState & ODS_DISABLED)

           crText = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));

    else

           crText = pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));

 

    GetText(lpDrawItemStruct->itemID, strText);

 

    UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;

    if (GetStyle() & LBS_USETABSTOPS)

           nFormat |= DT_EXPANDTABS;

    if(m_pImageList && (iImg != -1 ) )

           m_pImageList->Draw(pDC,iImg,Pt,ILD_NORMAL);

   

    //Draw the Text

    pDC->DrawText(strText, -1, &rText, nFormat | DT_CALCRECT);

    pDC->DrawText(strText, -1, &rText, nFormat);

 

    pDC->SetTextColor(crText);

    pDC->SetBkMode(iBkMode);

}

 

void CIconListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)

{

    // TODO: Add your code to determine the size of specified item

    lpMeasureItemStruct->itemHeight = 16;

}

//添加前面带位图的Item

int CIconListBox::AddString(LPCTSTR lpszItem, int iImg)

{

       int iRet = CListBox::AddString(lpszItem);

       if (iRet >= 0)

              SetItemData(iRet, iImg);

       return iRet;

}

//设置位图

void CIconListBox::SetItemImage(int iIndex, int iImg)

{

       SetItemData(iIndex, iImg);

       RedrawWindow();

}

在这个类添加一个protected类型的数据成员

       CImageList* m_pImageList;

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

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

以上完成后,在你的Dialog .cpp文件上添加这样一个函数

//初始化位图表

void CMyListBoxDlg::InitImageLists()

{

 

       CBitmap bmp;

       // normal tree images

//在这里设置可以将一幅大的位图分成小的(例如一幅位图的图案是ABCDE,你可以在

//一项前面输出A,下一项输出B),循环输出 如果不用到这个功能后面两个参数设1

       m_imgNormal.Create(

      16,  //截取位图的宽

       15,  //

       true,

       1,  //循环次数

       1);  

       ASSERT(m_imgNormal.m_hImageList);

       //load你要显示的位图

       bmp.LoadBitmap(IDB_BITMAP3);

       m_imgNormal.Add( &bmp, RGB(255,255,255));

       bmp.DeleteObject();

}

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

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

然后在你的Dialog .h文件上添加这样一个数据成员

protected:

       HICON m_hIcon;

       CImageList m_imgNormal;  //这里是要添加的

       void InitImageLists();

       CString Inputword;

       // Generated message map functions

       //{{AFX_MSG(CMyListBoxDlg)

       virtual BOOL OnInitDialog();

       afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

       afx_msg void OnPaint();

       afx_msg HCURSOR OnQueryDragIcon();

       afx_msg void OnEditchangeInputword();

       //}}AFX_MSG

       DECLARE_MESSAGE_MAP()

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

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

以上完成后,就可以在对话框上拖进一个ListBox控件,添加为数据成员,它的类型是control,基于ClistBox ,然后把CListBox改成你自己写的类,例如我们上面的CiconListBox.

接着我们就在你的Dialog.cpp文件的OnInitDialog() 添加代码:

 

InitImageLists();

for(int i = 0; i < 25 ; i++ )

{

m_list.AddString( "GWCB",0 ); //GWCB是要ItemText, 0ImageList的索引值

}

 

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

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

这样就完成了在ListBox每一项前面加位图了.后面要实现的是输入单词显示相应的单词索引,这个只是对字符串的处理,然后读索引文件(我是用XML格式的),比较简单,这里我就不多说了.有兴趣讨论或想要源代码的朋友可以联系我hongjian20_38@21cn.com 
原创粉丝点击