5.28.2010

Win32 Listbox Control 的操作

有時候要簡單的 log 來 show message,但是又不是 console mode ,這樣就要拉一個 ListBox 來作。

ListBox 的操作: MSDN - Listbox

首先 Win32 的 Control 就是預先寫好的小Dialog Window,所以要控制 Control Item ,只有用 SendMessage 的方式。

這種已經寫好的 Control (DialogWindow),每次要送message 過去,還要先從 ID 取得 hWnd 再送,有點麻煩,所以 Win32 提供一個直接對 ID 送 Message 的 function
SendDlgItemMessage
ListBox 的控制,用在 show log 的化,簡單的就是:
  1. 加入Item
  2. 移動 List
  3. 刪除 Item
三個都是用 SendDlgItemMesage 來完成的,三個function 的 Message ID 不一樣:
  1. 加入 Item : LB_ADDSTRING
  2. 移動List : LB_SETTOPINDEX
  3. 刪除 Item : LB_DELETESTRING
另外,ListBox 有一個 property - Sort,可以設定是否自動對 Item 排序,在作 Log 用時當然是不需要,但是 default 是 TRUE,要記得改。

ADDSTRING default 是作 "Append",所以剛好符合 log 的動作,從後面加上去。

ListBox 雖然有 scroll bar ,但是不會自己scroll 到最後,所以要用 LB_SETTOPINDEX 來指定第一個顯示的 item,好移動 scrollbar。
但是因為要讓最後一行對齊最後,所以反而要先用 LB_GETCOUNT 取得所有 item 的數量,自己減去 list 一面的 item 數好找到最後一頁的第一個 item 的 index...


以下就是簡單的 sample code,只有兩個 button - add, clear(all) 和一個 14 行的 list。
list 只保持 30 個 item,每按一下 add,就會加一行。
#include "stdafx.h"
#include <windows.h>
#include "ListBoxTest.h"


BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
static int i=0;
switch (uMsg)
{
case WM_INITDIALOG:

return TRUE;
case WM_CLOSE:
EndDialog(hWnd,0);
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDC_ADD :{
TCHAR outmsg[10];
swprintf(outmsg,_T("%d"),i++);

SendDlgItemMessage(hWnd,IDC_LIST1,LB_ADDSTRING,0,LPARAM(outmsg));
int cnt=SendDlgItemMessage(hWnd,IDC_LIST1,LB_GETCOUNT,0,0);
if(cnt>30)
SendDlgItemMessage(hWnd,IDC_LIST1,LB_DELETESTRING,0,0);
cnt=SendDlgItemMessage(hWnd,IDC_LIST1,LB_GETCOUNT,0,0);
if(cnt>=14)
SendDlgItemMessage(hWnd,IDC_LIST1,LB_SETTOPINDEX,cnt-14,0);
return TRUE;
}
case IDC_CLEAR:{
int cnt=SendDlgItemMessage(hWnd,IDC_LIST1,LB_GETCOUNT,0,0);
while(cnt-->0)
SendDlgItemMessage(hWnd,IDC_LIST1,LB_DELETESTRING,0,0);
return TRUE;
}
default:
return FALSE;
}
default:
return FALSE;
}
}


WTL 有包裝 ListBox,使用 WTL 的 example 是 http://realchecko.blogspot.com/2010/08/clistbox-listbox-control-in-wtl.html

3 則留言:

Tony's Blog 提到...
作者已經移除這則留言。
Tony's Blog 提到...

ListBox 中所 Show 的 ListItem 是使用 Stack Memory, ListItem 加到某種程度時有機會引發 Stack Overflow.

checko 提到...

這樣呀...真是糟糕 >_<