I recently wanted to emulate ListView-style deselection behavior for a ListBox, and wrote the following code which might be of use to somebody else.
What I mean by emulating the ListView-style deslection behavior is that clicking outside of the extent of the text of an item in report view will deselect the item. By default, a ListBox counts an item as having a width approximately equal to the ListBox's width for purposes of selection hit-tests.
You may wish to trap WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK as well.
This code is Unicode-compatible and requires tchar.h in addition to windowsx.h and windows.h. The alloca function requires memory.h; replace with any other method of allocating temporary storage if you so desire.
INT_PTR CALLBACK OnListBoxMessage(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
switch(uMsg) {
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
{
LONG_PTR Index;
Index = SendMessage(hWnd, LB_ITEMFROMPOINT, 0, lParam);
if(Index == LB_ERR)
break;
RECT ItemRect;
if(SendMessage(hWnd, LB_GETITEMRECT, (WPARAM)Index, (LPARAM)&ItemRect) == LB_ERR)
break;
size_t Size = (size_t)SendMessage(hWnd, LB_GETTEXTLEN, (WPARAM)Index, 0);
if(Size == (size_t)LB_ERR)
break;
LPTSTR Text = (LPTSTR)alloca(Size+1);
if(SendMessage(hWnd, LB_GETTEXT, (WPARAM)Index, (LPARAM)Text) == LB_ERR)
break;
HDC DC = GetDC(hWnd);
DrawText(DC, Text, -1, &ItemRect, DT_CALCRECT | DT_NOPREFIX);
OffsetRect(&ItemRect, 1, 0);
ReleaseDC(hWnd, DC);
if(GET_X_LPARAM(lParam) > ItemRect.right) {
SendMessage(hWnd, LB_SETCURSEL, (WPARAM)-1, 0);
return 0;
}
}
}
return CallWindowProc(OriginalListBoxProc, hWnd, uMsg, wParam, lParam);
}