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_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||||
BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
||||||
LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
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 ( \
|
#define wantedICCClasses ( \
|
||||||
ICC_PROGRESS_CLASS | /* progress bars */ \
|
ICC_PROGRESS_CLASS | /* progress bars */ \
|
||||||
|
@ -115,6 +117,11 @@ DWORD initCommonControls(char **errmsg)
|
||||||
fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
|
fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
|
||||||
LOAD("DefSubclassProc");
|
LOAD("DefSubclassProc");
|
||||||
fv_DefSubclassProc = (LRESULT (*WINAPI)(HWND, UINT, WPARAM, LPARAM)) f;
|
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) {
|
if ((*ficc)(&icc) == FALSE) {
|
||||||
*errmsg = "error initializing Common Controls (comctl32.dll)";
|
*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_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
|
||||||
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
|
||||||
extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);
|
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
|
// control_windows.c
|
||||||
extern HWND newControl(LPWSTR, DWORD, DWORD);
|
extern HWND newControl(LPWSTR, DWORD, DWORD);
|
||||||
|
@ -112,4 +114,9 @@ extern void repaintArea(HWND);
|
||||||
extern DWORD makeAreaWindowClass(char **);
|
extern DWORD makeAreaWindowClass(char **);
|
||||||
extern HWND newArea(void *);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue