1. 程式人生 > >為ListBox控制元件新增水平滾動條

為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這個訊息,它可以用來獲得列表項的字元長度。獲得列表項的畫素長度也許也能夠通過字元長度來換算。