Added the beginning of ImageList, including the Windows implementation.
This commit is contained in:
parent
3ac3a72471
commit
8702763137
|
@ -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)";
|
||||
|
|
|
@ -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
|
|
@ -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());
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue