由於ClistCtrl一次也只能顯示一行文字,因此在進行顯示多行文字之前,需先讓CListCtrl的欄位可以隨著文字段數變動。這邊可以參考[CListCtrl]改變行高 。(參考文獻在上述連結內都有)
在顯示多行文字部分,則是透過改寫DrawItem()來讓文字可以斷行。
使用前,需先將CListCtrl的Owner Draw Fixed屬性打開(坊間流傳的SetExtendedStyle(LVS_OWNERDRAWFIXED)並無效果)。(PS.在這邊浪費了好幾個小時@@,果然跑不起來還是要先查設定@@)
在.h部分
afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
在.cpp部分
void CXListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
TCHAR lpBuffer[256];
LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM ;
lvi.iItem = lpDrawItemStruct->itemID ;
lvi.iSubItem = 0;
lvi.pszText = lpBuffer ;
lvi.cchTextMax = sizeof(lpBuffer);
VERIFY(GetItem(&lvi));
LV_COLUMN lvc, lvcprev ;
::ZeroMemory(&lvc, sizeof(lvc));
::ZeroMemory(&lvcprev, sizeof(lvcprev));
lvc.mask = LVCF_WIDTH | LVCF_FMT;
lvcprev.mask = LVCF_WIDTH | LVCF_FMT;
for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)
{
if ( nCol > 0 )
{
// Get Previous Column Width in order to move the next display item
GetColumn(nCol-1, &lvcprev) ;
lpDrawItemStruct->rcItem.left += lvcprev.cx ;
lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left ;
}
// Get the text
::ZeroMemory(&lvi, sizeof(lvi));
lvi.iItem = lpDrawItemStruct->itemID;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iSubItem = nCol;
lvi.pszText = lpBuffer;
lvi.cchTextMax = sizeof(lpBuffer);
VERIFY(GetItem(&lvi));
CDC* pDC;
pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
//--------------- Full selection - highlight -----------------------
if ( lpDrawItemStruct->itemState & ODS_SELECTED )
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, GetSysColor(COLOR_HIGHLIGHT)) ;
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) ;
}
else
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem, GetSysColor(COLOR_WINDOW)) ;
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) ;
}
//--------------- Full selection - highlight -----------------------
pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
UINT uFormat = DT_LEFT ;
::DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer),
&lpDrawItemStruct->rcItem, uFormat) ;
pDC->SelectStockObject(SYSTEM_FONT) ;
//Enable measureitem().
this->OnSetFont(NULL, NULL); //配合MeasureItem()用的
}
}
目前這個範例裡面還看不出是怎麼讓文字斷行的,但可確定的是,由於這個function會重新變更欄位的字體與背景顏色。因此當同時還有使用到OnNMCustomdrawLst()的話,OnNMCustomdrawLst()所繪製的顏色會被DrawItem()所覆蓋掉(因OnNMCustomdrawLst()比DrawItem()早執行),所以這邊要注意。
如有找到換行的方法,之後再補上。
PS.測試結果,DrawText似乎會在遇到newline時,就會把後面的文字自動輸出到下一行。
Problem:
1.在移動欄位title時,欄位內顯示之文字並不會像CListCtrl一樣,會加上"..."來代表有文字被遮蓋。
看來這邊是需要自行處理。(變更欄位大小時,畫面不會更新到其他地方)
2.上一次顯示文字之尾端總是會殘留在下一個欄位的開頭,這邊也需要另外再處理。
3.此範例所繪製的文字會貼齊於Cell的最左側邊界,會與CListCtrl顯示結果不同。
新找到的:Multi-line List Control
這篇提供的方法可以解決P.1、P.2、P3的問題。
差別在於,這篇提供的畫文字方法是CDC::DrawTextEx。這樣就可以讓CListCtrl自行去處理上述之問題,不然要手動處理的話,倒是挺麻煩的。如此一來,函式也變得比較乾淨了。
修改過後的函式如下:
void CXListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
LPDRAWITEMSTRUCT lpDrawHighLight = new DRAWITEMSTRUCT();
CString cstrSubitemText = "";
CRect rcSubItemRect;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //不用釋放
LV_ITEM lvi;
rcSubItemRect.SetRectEmpty();
LV_COLUMN lvc, lvcprev ;
::ZeroMemory(&lvc, sizeof(lvc));
::ZeroMemory(&lvcprev, sizeof(lvcprev));
lvc.mask = LVCF_WIDTH | LVCF_FMT;
lvcprev.mask = LVCF_WIDTH | LVCF_FMT;
//lpDrawItemStruct->rcItem為目前所要畫出文字的row的邊界。
for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)
{
// Get Previous Column Width in order to move the next display item
if ( nCol > 0 )
{
GetColumn(nCol-1, &lvcprev) ;
lpDrawItemStruct->rcItem.left += lvcprev.cx;
//lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left; //會影響到最後一個SubItem的顯示長度。
}
//--------------- Full selection - highlight -----------------------
//Let Drawed highlight like the CListCtrl do it.
::memcpy(lpDrawHighLight, lpDrawItemStruct, sizeof(DRAWITEMSTRUCT));
lpDrawHighLight->rcItem.left += this->GetStringWidth(" "); //保留開頭的空白。讓行為同CListCtrl。
if ( lpDrawItemStruct->itemState & ODS_SELECTED )
{
pDC->FillSolidRect(&lpDrawHighLight->rcItem, GetSysColor(COLOR_HIGHLIGHT)) ;
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) ;
}
else
{
pDC->FillSolidRect(&lpDrawHighLight->rcItem, GetSysColor(COLOR_WINDOW)) ;
pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) ;
}
//--------------- Full selection - highlight -----------------------
//-------------- Draw item -------------------------
pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
if ( !this->GetSubItemRect(lpDrawItemStruct->itemID, nCol, LVIR_BOUNDS, rcSubItemRect) ) {
continue; };
//::DrawText(lpDrawItemStruct->hDC, lpDisplayBuf, nShowWordsLen, &lpDrawText->rcItem, uFormat) ;
rcSubItemRect.left += this->GetStringWidth(" ");
rcSubItemRect.right -= this->GetStringWidth(" ");
cstrSubitemText = this->GetItemText(lpDrawItemStruct->itemID, nCol);
pDC->DrawTextEx(cstrSubitemText, rcSubItemRect, (DT_LEFT|DT_NOPREFIX|DT_TOP|DT_WORD_ELLIPSIS), NULL);
pDC->SelectStockObject(SYSTEM_FONT) ;
//-------------- Draw item -------------------------
//Enable measureitem().
this->OnSetFont(NULL, NULL);
} //End of for ( int nCol=0; GetColumn(nCol, &lvc); nCol++)
if ( lpDrawHighLight != NULL ) {
delete lpDrawHighLight;
lpDrawHighLight = NULL;
}
}
No comments:
Post a Comment