這邊找到的參考資料如下:
1.Report control - with category
2.Changing Row Height in an owner drawn Control
3.CListCtrl 行高问题最终解决方法
裡面提到的方式都是使用OnSetFont()以及MeasureItem()來搭配使用。
另一種就是直接在OnNMCustomdrawLst()裡面,進行文字繪製。
Expandable List Control to Accept Multilines
OnNMCustomdrawLst()使用方式可參考[CListCtrl]改變儲存格文字顏色。
由於使用OnNMCustomdrawLst()的方式比較複雜,所以底下就針對DrawItem()以及MeasureItem()兩個函式來說明。
在.h的部份:(SetFont()的部分稍後說明)
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) ;
afx_msg LRESULT OnSetFont(WPARAM wParam, LPARAM lParam);
afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
在message map部分:(無效的部份稍後說明)
BEGIN_MESSAGE_MAP(CXListCtrl, CListCtrl)
//Multi-line
ON_MESSAGE(WM_SETFONT, OnSetFont) //NOTE:無效
ON_WM_MEASUREITEM_REFLECT() //NOTE:無效
ON_WM_MEASUREITEM() //NOTE:無效
END_MESSAGE_MAP()
在.cpp裡面要加上下列4個函式:
1.OnMeasureItem()
void CXListCtrl::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
CListCtrl::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}
這邊為何要又呼叫一次CListCtrl::OnMeasureItem我就不曉得原因了,因上面參考連結是有這項。但程式卻都沒進入到此函式。所以不加應該也沒關係吧?!XD
2.MeasureItem()
void CXListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// Get the LOGFONT for the current font.
LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));
CFont* pFont = GetFont();
ASSERT_VALID(pFont);
if (pFont)
VERIFY(pFont->GetLogFont(&lf));
int nAdj(2) ; //Sample is 4
m_nLinesPerRow = max(m_nLinesPerRow, 1);
if (lf.lfHeight < 0)
lpMeasureItemStruct->itemHeight = ((-lf.lfHeight+nAdj) * (m_nLinesPerRow));
else
lpMeasureItemStruct->itemHeight = ((lf.lfHeight+nAdj) * (m_nLinesPerRow));
}
這邊實際上用來變更高度的是lpMeasureItemStruct->itemHeight,但由於抓到的並不是完整的文字高度,單行沒問題,三行以上就出錯了。所以在範例的部份,有加上平移值。這邊測試結果,如果平移值與顯示行數差值大於等於2時,最後一行文字就會被蓋掉。所以這個值還是要做動態的會比較好。
如有需要做到每行高度不同的話,後面乘上的顯示行數就需要針對顯示文字的行是做動態處理。
目前還沒想到好作法,之後再回來補充。
3.OnSetFont()
LRESULT CXListCtrl::OnSetFont(WPARAM wParam, LPARAM lParam)
{
CRect rc;
GetWindowRect(&rc);
WINDOWPOS wp;
wp.hwnd = this->m_hWnd;
wp.cx = rc.Width() ;
wp.cy = rc.Height() ;
wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
LRESULT lrReturn(Default());
SendMessage(WM_WINDOWPOSCHANGED, 0, reinterpret_cast<LPARAM> (&wp));
return lrReturn;
}
在範例裡,這個函式僅是用來觸發MeasureItem()更新動作的一個事件而已。觸發MeasureItem()的事件很獨特,就是讓畫面有所變動,然後系統就會送回重新繪製item的訊息,接下來就會進到MeasureItem()來重新繪製每個item的狀況。
此方法在範例中能成功,但我不管怎麼試,就是試不出來,也找不到原因。最後就在DrawItem()結束後,直接送出視窗訊息。
以上就是改變行高的作法
No comments:
Post a Comment