diff --git a/redo/comctl32_windows.c b/redo/comctl32_windows.c index 9dd67c1..841aa80 100644 --- a/redo/comctl32_windows.c +++ b/redo/comctl32_windows.c @@ -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)"; diff --git a/redo/imagelist_windows.c b/redo/imagelist_windows.c index fab4425..08046e7 100644 --- a/redo/imagelist_windows.c +++ b/redo/imagelist_windows.c @@ -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) diff --git a/redo/imagelist_windows.go b/redo/imagelist_windows.go index 37924bd..7ab014b 100644 --- a/redo/imagelist_windows.go +++ b/redo/imagelist_windows.go @@ -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)))) } diff --git a/redo/table_windows.c b/redo/table_windows.c index af61d96..a71b8e0 100644 --- a/redo/table_windows.c +++ b/redo/table_windows.c @@ -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: diff --git a/redo/table_windows.go b/redo/table_windows.go index cb00279..281f0d4 100644 --- a/redo/table_windows.go +++ b/redo/table_windows.go @@ -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 { diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h index 4a1791c..477a2f0 100644 --- a/redo/winapi_windows.h +++ b/redo/winapi_windows.h @@ -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,