Hi people ...
I wanna add small bitmap image before text in lisbox item.
I've search trough forum but i only found one example for ownerdraw listbox for Aurora with
subclassing.Then i just look into Aurora examples and found one simpatic example for combobox
with small bitmaps before text in combox items called 'ComboboxEx_Example'.
This small program enable bitmaps on very easy way- is something like this posibile in IWBasic to?
Or maby someone already have some example with listbox bitmaps?
Any help will be ok...
thanks advance .... :)
Aurel
			
			
			
				Hi, I've created one for you :)
It uses the new subclassing API's from Windows XP: SetWindowSubclass, DefSubclassProc, RemoveWindowSubclass
$include "windowssdk.inc"
$include "commctrl.inc"
CONST LISTBOX_1 = 1000
DIALOG d1
CREATEDIALOG d1,0,0,300,202,0x80CB0080,0,"Caption",&d1_handler
CONTROL d1,@LISTBOX,"ListBox1",13,10,173,175,0x50A10140|LBS_OWNERDRAWFIXED,LISTBOX_1
$define SUBCLASS1_ID 12345 ' any number
HBITMAP g_image1 = LoadImage("D:\\download\\home.bmp", @IMGBITMAP)
DOMODAL d1
if (g_image1) then DeleteImage(g_image1, @IMGBITMAP)
SUB d1_handler
	SELECT @MESSAGE
		CASE @IDINITDIALOG
			SetWindowSubclass(d1.hwnd, &MySubclassProc, SUBCLASS1_ID, 0)
			CENTERWINDOW d1
			OnInitDialog()
		CASE @IDCLOSEWINDOW
			RemoveWindowSubclass(d1.hwnd, &MySubclassProc, SUBCLASS1_ID)
			CLOSEDIALOG d1,@IDOK
		CASE @IDCONTROL
			SELECT @CONTROLID
				CASE LISTBOX_1
				/* respond to control notifications here */
			ENDSELECT
	ENDSELECT
RETURN
ENDSUB
sub OnInitDialog()
	' add some string, saving its indexes
	int item_1_index = SendMessage(d1, LB_ADDSTRING, 0, "item 1", LISTBOX_1)
	int item_2_index = SendMessage(d1, LB_ADDSTRING, 0, "item 2", LISTBOX_1)
	' assign images
	SendMessage(d1, LB_SETITEMDATA, item_1_index, g_image1, LISTBOX_1)
	'SendMessage(d1, LB_SETITEMDATA, item_2_index, g_image2, LISTBOX_1)
endsub
sub MySubclassProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData)
	int imageWidth, imageHeight
	int itemWidth, itemHeight
	int TextPadding
	select (uMsg)
		case WM_DRAWITEM
			if( (*<DRAWITEMSTRUCT>lParam.CtlType = ODT_LISTBOX) _
			and	(*<DRAWITEMSTRUCT>lParam.CtlID = LISTBOX_1) _
			and (*<DRAWITEMSTRUCT>lParam.itemID >= 0))
				' set default text.padding.left
				TextPadding = 2
				' Erase item background
				FillRect(*<DRAWITEMSTRUCT>lParam.hDC, &*<DRAWITEMSTRUCT>lParam.rcItem, _
				GetSysColorBrush(IIF(*<DRAWITEMSTRUCT>lParam.itemState & ODS_SELECTED, _
					COLOR_HIGHLIGHT, COLOR_WINDOW)))
				' check if this item has assigned image
				if (*<DRAWITEMSTRUCT>lParam.itemData)
					' get the size of image
					GetBitmapSize *<DRAWITEMSTRUCT>lParam.itemData, imageWidth, imageHeight
					' get item width and height
					itemWidth = *<DRAWITEMSTRUCT>lParam.rcItem.right - *<DRAWITEMSTRUCT>lParam.rcItem.left
					itemHeight = *<DRAWITEMSTRUCT>lParam.rcItem.bottom - *<DRAWITEMSTRUCT>lParam.rcItem.top
					' put the image into device context, so we can Blt' it
					HDC hDevCtx = CreateCompatibleDC(*<DRAWITEMSTRUCT>lParam.hDC)
					HGDIOBJ imageOld = SelectObject(hDevCtx, *<DRAWITEMSTRUCT>lParam.itemData)
					' show the image ...
					int top = *<DRAWITEMSTRUCT>lParam.rcItem.top
					' ... centered vertically, if possible ...
					if (imageHeight < itemHeight) then top += ((itemHeight-imageHeight) / 2)
					' clip image
					imageWidth  = __min(imageWidth, itemWidth)
					imageHeight = __min(imageHeight,itemHeight)
					BitBlt(*<DRAWITEMSTRUCT>lParam.hDC, /*target device context: listbox*/_
						*<DRAWITEMSTRUCT>lParam.rcItem.left, /*target X: left aligned*/_
						top,         /*target Y*/_
						imageWidth,  /*target width*/_
						imageHeight, /*target height*/_
						hDevCtx,     /*source device context: image*/_
						0, 0,        /*source X,Y*/_
						SRCCOPY)
					' deselect the image from device context
					SelectObject(hDevCtx, imageOld)
					DeleteDC(hDevCtx)
					TextPadding = (imageWidth + 4 /*small space*/)
				endif
				' any text to draw?
				HWND hwndListbox = *<DRAWITEMSTRUCT>lParam.hwndItem
				' number of characters
				int cchText = _SendMessage(hwndListbox, LB_GETTEXTLEN, *<DRAWITEMSTRUCT>lParam.itemID, 0)
				if (cchText)
					' get the string
					pointer pText = new(TCHAR, cchText+1)
					_SendMessage(hwndListbox, LB_GETTEXT, *<DRAWITEMSTRUCT>lParam.itemID, pText)
					' setup text coordinates, equal to *<DRAWITEMSTRUCT>lParam.rcItem
					WINRECT rc
					CopyRect(&rc, &*<DRAWITEMSTRUCT>lParam.rcItem)
					' skip the image
					rc.left += TextPadding
					UINT bkMode = SetBkMode(*<DRAWITEMSTRUCT>lParam.hDC, TRANSPARENT)
					DrawText(*<DRAWITEMSTRUCT>lParam.hDC, pText, cchText, &rc, DT_SINGLELINE|DT_VCENTER)
					SetBkMode(*<DRAWITEMSTRUCT>lParam.hDC, bkMode)
					delete pText
				endif
				' do not forward this message to default handlers, we handled it
				return 0
			endif
	endselect
	return DefSubclassProc(hWnd, uMsg, wParam, lParam)
endsub
			
			
			
				WOW that looks very complex for me...
Thanks Sapero i will study this and compare with - one bcx code which i have.
Aurora seems that have same thing included internaly as i see in that combbox example.
			
			
			
				Aurel
What makes the Aurora example look so much easier is the combobox ability is a windows thing I believe.
Really has nothing to do with IWB vs Aurora.
Sapero can correct me if I'm wrong.
LarryMc
			
			
			
				A listbox control was originally designed to display text only. This applies also to combobox, because it uses a listbox as child/popup window.
ComboBoxEx is yet another control. It uses ownerdrawn combobox and is able to display images, including indentaton, so the internal listbox can display simple trees.
Do you mean ComboBoxEx_Example.src example?
			
			
			
				Yes Sapero this example, and yes you are right in some other languages technic to do this is very similiar.
thanks....
by the way i think that i use wrong control for what i need, i think that better option will be treeview control.
Aurel