爲ListBox控件添加水平滾動條

Win32的標準控件之中,列表控件(ListBox)並沒有和列表視圖(ListView)一樣提供水平滾動條,所以如果列表項的長度超過列表的寬度的話,那麼超出的部分將無法顯示。在本文中我將以一個簡單的例子來說明如何使用SDK來解決這一問題,在這個例子中,我將爲一個列表控件添加100行如下格式的文本:

case WM_INITDIALOG:
{
 int i;
 TCHAR str[100];
 for(i = 0; i < 100; i++)
 {
  wsprintf(str, "This is a very very very very very long sentence - line %d", i + 1);
  SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)str);
 }
}
break;

當然,在添加水平滾動條之前,就是下圖這樣的效果:

下面爲這個列表控件來添加水平滾動條,首先需要在資源的設計中爲這個列表控件設置水平滾動條,然後就可以通過向列表控件發送一條LB_SETHORIZONTALEXTENT消息來向它添加水平滾動條了。在這條消息的附加參數中,wParam參數就是以像素爲單位的水平滾動條長度,lParam不使用。那麼,可以爲這個滾動條設置一個足夠的長度(假設爲500),有以下的代碼:

case WM_INITDIALOG:
{
 HDC hdc;
 int i;
 TCHAR str[100];
 for(i = 0; i < 100; i++)
 {
  wsprintf(str, "This is a very very very very very long sentence - line %d", i + 1);
  SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)str);
 }
 SendDlgItemMessage(hDlg, IDC_LIST, LB_SETHORIZONTALEXTENT, 500, 0);
 // 設置長度爲500像素的水平滾動條
}
break;

  這段代碼執行完畢後,效果如下圖:




  如你所見,我們已經成功地爲列表控件添加了水平滾動條。然而美中不足的是,500這一長度似乎太長,很不美觀。那麼我們所需要的,就是一種方法,我們能通過這種方法來將字符串的長度換算成爲一個適當的像素長度,這樣就可以使這個界面較爲美觀了。幸運的是,Win32 API之中的確有這麼一個函數:

BOOL GetTextExtentPoint32(
 HDC hdc, // 相關設備句柄
 LPCTSTR lpString, // 字符串
 int cbString, // 字符串的字符數(即長度)
 LPSIZE lpSize // 用來接收字符串的尺寸
);

  也許你會很納悶:這個函數爲什麼要和HDC扯上關係?其實原因很簡單:Windows是一個基於圖形的操作系統,所以所有的文本也是被Windows系統“畫”到界面上去的。那麼這樣一來,字符串的長度自然和所選用的字體和字體的大小發生關係,字符串的像素寬度也必須這麼計算了。我的代碼如下:

case WM_INITDIALOG:
{
 HDC hdc;
 SIZE s;
 int i;
 TCHAR str[100];
 hdc = GetDC(hDlg); // 獲得相關設備句柄
 for(i = 0; i < 100; i++)
 {
  wsprintf(str, "This is a very very very very very long sentence - line %d", i + 1);
  GetTextExtentPoint32(hdc, str, lstrlen(str), &s); // 獲取字符串的像素大小
  // 如果新的字符串寬度大於先前的水平滾動條寬度,則重新設置滾動條寬度
  if (s.cx > (LONG)SendDlgItemMessage(hDlg, IDC_LIST, LB_GETHORIZONTALEXTENT, 0, 0))
   SendDlgItemMessage(hDlg, IDC_LIST, LB_SETHORIZONTALEXTENT, (WPARAM)s.cx, 0);
   SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)str);
 }
 ReleaseDC(hDlg, hdc);
}
break;

看看效果吧:



  你可能還會問,爲什麼右邊的部分還有一點空白?對於這個問題,GetTextExtentPoint32的備註是這麼解釋的:“由於有的設備緊縮字符,因此一個字符串裏字符的範圍之和或許不等於字符串的範圍,計算的字符寬度考慮了由SetTextCharacterExtra設備的字符間隔。”

 在MSDN中的列表控件消息裏發現了LB_GETTEXTLEN這個消息,它可以用來獲得列表項的字符長度。獲得列表項的像素長度也許也能夠通過字符長度來換算。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章