Added cleanup of Windows image lists.

This commit is contained in:
Pietro Gagliardi 2014-08-25 16:53:47 -04:00
parent 107e66715b
commit e25831c609
6 changed files with 33 additions and 16 deletions

View File

@ -11,6 +11,7 @@ BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
HIMAGELIST (*WINAPI fv_ImageList_Create)(int, int, UINT, int, int);
int (*WINAPI fv_ImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
BOOL (*WINAPI fv_ImageList_Destroy)(HIMAGELIST);
#define wantedICCClasses ( \
ICC_PROGRESS_CLASS | /* progress bars */ \
@ -121,7 +122,8 @@ DWORD initCommonControls(char **errmsg)
fv_ImageList_Create = (HIMAGELIST (*WINAPI)(int, int, UINT, int, int)) f;
LOAD("ImageList_Add");
fv_ImageList_Add = (int (*WINAPI)(HIMAGELIST, HBITMAP, HBITMAP)) f;
LOAD("ImageList_Destroy");
fv_ImageList_Destroy = (BOOL (*WINAPI)(HIMAGELIST)) f;
if ((*ficc)(&icc) == FALSE) {
*errmsg = "error initializing Common Controls (comctl32.dll)";

View File

@ -94,11 +94,13 @@ noscale:
xpanic("error deleting scaled bitmap", GetLastError());
}
void applyImageList(HWND hwnd, UINT uMsg, WPARAM wParam, HIMAGELIST il)
void applyImageList(HWND hwnd, UINT uMsg, WPARAM wParam, HIMAGELIST il, HIMAGELIST old)
{
if (SendMessageW(hwnd, uMsg, wParam, (LPARAM) il) == (LRESULT) NULL)
;//TODO xpanic("error setting image list", GetLastError());
// TODO free old one here if any
if (SendMessageW(hwnd, uMsg, wParam, (LPARAM) il) != (LRESULT) old)
xpanic("error setting image list", GetLastError());
if (old != NULL && (*fv_ImageList_Destroy)(old) == 0)
xpanic("error freeing old checkbox image list", GetLastError());
}
static UINT dfcState(int cbstate)

View File

@ -31,15 +31,15 @@ func (i *imagelist) Len() ImageIndex {
}
type imageListApply interface {
apply(C.HWND, C.UINT, C.WPARAM)
apply(C.HWND, C.UINT)
}
func (i *imagelist) apply(hwnd C.HWND, uMsg C.UINT, wParam C.WPARAM) {
func (i *imagelist) apply(hwnd C.HWND, uMsg C.UINT) {
width := C.GetSystemMetrics(C.SM_CXSMICON)
height := C.GetSystemMetrics(C.SM_CYSMICON)
il := C.newImageList(width, height)
for index := range i.list {
C.addImage(il, hwnd, i.list[index], C.int(i.width[index]), C.int(i.height[index]), width, height)
}
C.applyImageList(hwnd, uMsg, wParam, il)
C.SendMessageW(hwnd, uMsg, 0, C.LPARAM(uintptr(unsafe.Pointer(il))))
}

View File

@ -27,19 +27,27 @@ static void handle(HWND hwnd, WPARAM wParam, LPARAM lParam, void (*handler)(void
struct tableData {
void *gotable;
HIMAGELIST imagelist;
HTHEME theme;
HIMAGELIST checkboxImageList;
};
static void tableLoadImageList(HWND hwnd, struct tableData *t, HIMAGELIST new)
{
HIMAGELIST old;
old = t->imagelist;
t->imagelist = new;
applyImageList(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, t->imagelist, old);
}
static void tableSetCheckboxImageList(HWND hwnd, struct tableData *t)
{
HIMAGELIST old;
old = t->checkboxImageList;
t->checkboxImageList = makeCheckboxImageList(hwnd, &t->theme);
if (SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM) (t->checkboxImageList)) == (LRESULT) NULL)
;//TODO xpanic("error setting image list", GetLastError());
// TODO free old one here if any
applyImageList(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, t->checkboxImageList, old);
// thanks to Jonathan Potter (http://stackoverflow.com/questions/25354448/why-do-my-owner-data-list-view-state-images-come-up-as-blank-on-windows-xp)
if (SendMessageW(hwnd, LVM_SETCALLBACKMASK, LVIS_STATEIMAGEMASK, 0) == FALSE)
xpanic("error marking state image list as application-managed", GetLastError());
@ -86,7 +94,10 @@ static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
tablePushed(t->gotable, -1, -1); // in case button held as drag out
// and let the list view do its thing
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
case msgTableMakeInitialImageList:
case msgLoadImageList:
tableLoadImageList(hwnd, t, (HIMAGELIST) lParam);
return 0;
case msgTableMakeInitialCheckboxImageList:
tableSetCheckboxImageList(hwnd, t);
return 0;
case WM_THEMECHANGED:

View File

@ -40,7 +40,7 @@ func finishNewTable(b *tablebase, ty reflect.Type) Table {
// LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added
C.tableAddExtendedStyles(t._hwnd, C.LVS_EX_FULLROWSELECT | C.LVS_EX_SUBITEMIMAGES)
// this must come after the subclass because it uses one of our private messages
C.SendMessageW(t._hwnd, C.msgTableMakeInitialImageList, 0, 0)
C.SendMessageW(t._hwnd, C.msgTableMakeInitialCheckboxImageList, 0, 0)
for i := 0; i < ty.NumField(); i++ {
C.tableAppendColumn(t._hwnd, C.int(i), toUTF16(ty.Field(i).Name))
}
@ -62,7 +62,7 @@ func (t *table) Unlock() {
}
func (t *table) LoadImageList(il ImageList) {
il.apply(t._hwnd, C.LVM_SETIMAGELIST, C.LVSIL_SMALL)
il.apply(t._hwnd, C.msgLoadImageList)
}
func (t *table) Selected() int {

View File

@ -38,7 +38,8 @@ enum {
msgEndModal,
msgAreaKeyDown,
msgAreaKeyUp,
msgTableMakeInitialImageList,
msgLoadImageList,
msgTableMakeInitialCheckboxImageList,
};
// uitask_windows.c
@ -55,6 +56,7 @@ extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
extern HIMAGELIST (*WINAPI fv_ImageList_Create)(int, int, UINT, int, int);
extern int (*WINAPI fv_ImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
extern BOOL (*WINAPI fv_ImageList_Destroy)(HIMAGELIST);
// control_windows.c
extern HWND newControl(LPWSTR, DWORD, DWORD);
@ -137,7 +139,7 @@ extern void areaMarkTextFieldDone(HWND);
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
extern HIMAGELIST newImageList(int, int);
extern void addImage(HIMAGELIST, HWND, HBITMAP, int, int, int, int);
extern void applyImageList(HWND, UINT, WPARAM, HIMAGELIST);
extern void applyImageList(HWND, UINT, WPARAM, HIMAGELIST, HIMAGELIST);
enum {
checkboxStateChecked = 1 << 0,
checkboxStateHot = 1 << 1,