Added the beginning of ImageList, including the Windows implementation.

This commit is contained in:
Pietro Gagliardi 2014-08-16 14:02:00 -04:00
parent 3ac3a72471
commit 8702763137
5 changed files with 174 additions and 0 deletions

View File

@ -9,6 +9,8 @@ static HMODULE comctl32;
BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
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);
#define wantedICCClasses ( \
ICC_PROGRESS_CLASS | /* progress bars */ \
@ -115,6 +117,11 @@ DWORD initCommonControls(char **errmsg)
fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
LOAD("DefSubclassProc");
fv_DefSubclassProc = (LRESULT (*WINAPI)(HWND, UINT, WPARAM, LPARAM)) f;
LOAD("ImageList_Create");
fv_ImageList_Create = (HIMAGELIST (*WINAPI)(int, int, UINT, int, int)) f;
LOAD("ImageList_Add");
fv_ImageList_Add = (int (*WINAPI)(HIMAGELIST, HBITMAP, HBITMAP)) f;
if ((*ficc)(&icc) == FALSE) {
*errmsg = "error initializing Common Controls (comctl32.dll)";

29
redo/imagelist.go Normal file
View File

@ -0,0 +1,29 @@
// 16 august 2014
package ui
import (
"image"
)
// ImageList is a list of images that can be used in the rows of a Table or Tree.
// ImageList maintains a copy of each image added.
// Images in an ImageList will be automatically scaled to the needed size.
type ImageList interface {
// Append inserts an image into the ImageList.
Append(i *image.RGBA)
// Len returns the number of images in the ImageList.
Len() ImageIndex
imageListApply
}
// NewImageList creates a new ImageList.
// The ImageList is initially empty.
func NewImageList() ImageList {
return newImageList()
}
// ImageIndex is a special type used to denote an entry in a Table or Tree's ImageList.
type ImageIndex int

86
redo/imagelist_windows.c Normal file
View File

@ -0,0 +1,86 @@
// 16 august 2014
#include "winapi_windows.h"
#include "_cgo_export.h"
HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
{
BITMAPINFO bi;
VOID *ppvBits;
HBITMAP bitmap;
ZeroMemory(&bi, sizeof (BITMAPINFO));
bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bi.bmiHeader.biWidth = (LONG) dx;
bi.bmiHeader.biHeight = -((LONG) dy); // negative height to force top-down drawing;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = (DWORD) (dx * dy * 4);
bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
if (bitmap == NULL)
xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
dotoARGB(i, (void *) ppvBits);
return bitmap;
}
HIMAGELIST newImageList(int width, int height)
{
HIMAGELIST il;
// TODO does this strip alpha?
// sinni800 in irc.freenode.net/#go-nuts suggests our use of *image.RGBA makes this not so much of an issue
il = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
if (il == NULL)
xpanic("error creating image list", GetLastError());
return il;
}
void addImage(HIMAGELIST il, HBITMAP bitmap, int origwid, int oright, int width, int height)
{
BOOL wasScaled = FALSE;
HDC scaledDC, origDC;
HBITMAP scaled;
HBITMAP prevscaled, prevorig;
// first we need to scale the bitmap
if (origwid == width && oright == height) {
scaled = bitmap;
goto noscale;
}
wasScaled = TRUE;
scaledDC = GetDC(NULL);
if (scaledDC == NULL)
xpanic("error getting screen DC for scaled ImageList bitmap", GetLastError());
scaled = CreateCompatibleBitmap(scaledDC, width, height);
if (scaled == NULL)
xpanic("error creating scaled ImageList bitmap", GetLastError());
prevscaled = SelectObject(scaledDC, scaled);
if (prevscaled == NULL)
xpanic("error selecting scaled ImageList bitmap into screen DC", GetLastError());
origDC = GetDC(NULL);
if (origDC == NULL)
xpanic("error getting screen DC for original ImageList bitmap", GetLastError());
prevorig = SelectObject(origDC, bitmap);
if (prevorig == NULL)
xpanic("error selecting original ImageList bitmap into screen DC", GetLastError());
if (StretchBlt(scaledDC, 0, 0, width, height,
origDC, 0, 0, origwid, oright,
SRCCOPY) == 0)
xpanic("error scaling ImageList bitmap down", GetLastError());
if (SelectObject(origDC, prevorig) != bitmap)
xpanic("error selecting previous bitmap into original image's screen DC", GetLastError());
if (DeleteDC(origDC) == 0)
xpanic("error deleting original image's screen DC", GetLastError());
if (SelectObject(scaledDC, prevscaled) != scaled)
xpanic("error selecting previous bitmap into scaled image's screen DC", GetLastError());
if (DeleteDC(scaledDC) == 0)
xpanic("error deleting scaled image's screen DC", GetLastError());
noscale:
if ((*fv_ImageList_Add)(il, scaled, NULL) == -1)
xpanic("error adding ImageList image to image list", GetLastError());
if (wasScaled) // clean up
if (DeleteObject(scaled) == 0)
xpanic("error deleting scaled bitmap", GetLastError());
}

45
redo/imagelist_windows.go Normal file
View File

@ -0,0 +1,45 @@
// 16 august 2014
package ui
import (
"image"
"unsafe"
)
// #include "winapi_windows.h"
import "C"
type imagelist struct {
list []C.HBITMAP
width []int
height []int
}
func newImageList() ImageList {
return new(imagelist)
}
func (i *imagelist) Append(img *image.RGBA) {
i.list = append(i.list, C.unscaledBitmap(unsafe.Pointer(img), C.intptr_t(img.Rect.Dx()), C.intptr_t(img.Rect.Dy())))
i.width = append(i.width, img.Rect.Dx())
i.height = append(i.height, img.Rect.Dy())
}
func (i *imagelist) Len() ImageIndex {
return ImageIndex(len(i.list))
}
type imageListApply interface {
apply()
}
func (i *imagelist) apply() {
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, i.list[index], C.int(i.width[index]), C.int(i.height[index]), width, height)
}
// TODO do stuff
}

View File

@ -44,6 +44,8 @@ extern DWORD initCommonControls(char **);
extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
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);
// control_windows.c
extern HWND newControl(LPWSTR, DWORD, DWORD);
@ -112,4 +114,9 @@ extern void repaintArea(HWND);
extern DWORD makeAreaWindowClass(char **);
extern HWND newArea(void *);
// imagelist_windows.c
extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
extern HIMAGELIST newImageList(int, int);
extern void addImage(HIMAGELIST, HBITMAP, int, int, int, int);
#endif