Added code to prepare a state image list of checkboxes for adding checkbox columns to Table on Windows.
This commit is contained in:
parent
4a5218df5b
commit
38e7565c37
|
@ -3,6 +3,8 @@
|
||||||
#include "winapi_windows.h"
|
#include "winapi_windows.h"
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
// TODO eliminate duplicate code
|
||||||
|
|
||||||
HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
|
HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
|
||||||
{
|
{
|
||||||
BITMAPINFO bi;
|
BITMAPINFO bi;
|
||||||
|
@ -53,7 +55,7 @@ void addImage(HIMAGELIST il, HWND hwnd, HBITMAP bitmap, int origwid, int oright,
|
||||||
if (winDC == NULL)
|
if (winDC == NULL)
|
||||||
xpanic("error getting DC for window", GetLastError());
|
xpanic("error getting DC for window", GetLastError());
|
||||||
origDC = CreateCompatibleDC(winDC);
|
origDC = CreateCompatibleDC(winDC);
|
||||||
if (winDC == NULL)
|
if (origDC == NULL)
|
||||||
xpanic("error getting DC for original ImageList bitmap", GetLastError());
|
xpanic("error getting DC for original ImageList bitmap", GetLastError());
|
||||||
prevorig = SelectObject(origDC, bitmap);
|
prevorig = SelectObject(origDC, bitmap);
|
||||||
if (prevorig == NULL)
|
if (prevorig == NULL)
|
||||||
|
@ -81,7 +83,7 @@ void addImage(HIMAGELIST il, HWND hwnd, HBITMAP bitmap, int origwid, int oright,
|
||||||
xpanic("error selecting previous bitmap into scaled image's DC", GetLastError());
|
xpanic("error selecting previous bitmap into scaled image's DC", GetLastError());
|
||||||
if (DeleteDC(scaledDC) == 0)
|
if (DeleteDC(scaledDC) == 0)
|
||||||
xpanic("error deleting scaled image's DC", GetLastError());
|
xpanic("error deleting scaled image's DC", GetLastError());
|
||||||
if (DeleteDC(winDC) == 0)
|
if (ReleaseDC(hwnd, winDC) == 0)
|
||||||
xpanic("error deleting window DC", GetLastError());
|
xpanic("error deleting window DC", GetLastError());
|
||||||
|
|
||||||
noscale:
|
noscale:
|
||||||
|
@ -98,3 +100,217 @@ void applyImageList(HWND hwnd, UINT uMsg, WPARAM wParam, HIMAGELIST il)
|
||||||
;//TODO xpanic("error setting image list", GetLastError());
|
;//TODO xpanic("error setting image list", GetLastError());
|
||||||
// TODO free old one here if any
|
// TODO free old one here if any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT dfcState(int cbstate)
|
||||||
|
{
|
||||||
|
UINT ret;
|
||||||
|
|
||||||
|
ret = DFCS_BUTTONCHECK;
|
||||||
|
if ((cbstate & checkboxStateChecked) != 0)
|
||||||
|
ret |= DFCS_CHECKED;
|
||||||
|
if ((cbstate & checkboxStateHot) != 0)
|
||||||
|
ret |= DFCS_HOT;
|
||||||
|
if ((cbstate & checkboxStatePushed) != 0)
|
||||||
|
ret |= DFCS_PUSHED;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HBITMAP dfcImage(HDC dc, int width, int height, int cbState)
|
||||||
|
{
|
||||||
|
BITMAPINFO bi;
|
||||||
|
VOID *ppvBits;
|
||||||
|
HBITMAP bitmap;
|
||||||
|
RECT r;
|
||||||
|
HDC drawDC;
|
||||||
|
HBITMAP prevbitmap;
|
||||||
|
|
||||||
|
r.left = 0;
|
||||||
|
r.top = 0;
|
||||||
|
r.right = width;
|
||||||
|
r.bottom = height;
|
||||||
|
ZeroMemory(&bi, sizeof (BITMAPINFO));
|
||||||
|
bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
||||||
|
bi.bmiHeader.biWidth = (LONG) width;
|
||||||
|
bi.bmiHeader.biHeight = -((LONG) height); // negative height to force top-down drawing;
|
||||||
|
bi.bmiHeader.biPlanes = 1;
|
||||||
|
bi.bmiHeader.biBitCount = 32;
|
||||||
|
bi.bmiHeader.biCompression = BI_RGB;
|
||||||
|
bi.bmiHeader.biSizeImage = (DWORD) (width * height * 4);
|
||||||
|
bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
|
||||||
|
if (bitmap == NULL)
|
||||||
|
xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
|
||||||
|
|
||||||
|
drawDC = CreateCompatibleDC(dc);
|
||||||
|
if (drawDC == NULL)
|
||||||
|
xpanic("error getting DC for checkbox image list bitmap", GetLastError());
|
||||||
|
prevbitmap = SelectObject(drawDC, bitmap);
|
||||||
|
if (prevbitmap == NULL)
|
||||||
|
xpanic("error selecting checkbox image list bitmap into DC", GetLastError());
|
||||||
|
if (DrawFrameControl(drawDC, &r, DFC_BUTTON, dfcState(cbState)) == 0)
|
||||||
|
xpanic("error drawing checkbox image", GetLastError());
|
||||||
|
if (SelectObject(drawDC, prevbitmap) != bitmap)
|
||||||
|
xpanic("error selecting previous bitmap into checkbox image's DC", GetLastError());
|
||||||
|
if (DeleteDC(drawDC) == 0)
|
||||||
|
xpanic("error deleting checkbox image's DC", GetLastError());
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
HIMAGELIST checkboxImageList = NULL;
|
||||||
|
|
||||||
|
void makeCheckboxImageList_DFC(HWND hwnddc)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
int cbState;
|
||||||
|
HDC dc;
|
||||||
|
HIMAGELIST il;
|
||||||
|
|
||||||
|
// there's no real metric around
|
||||||
|
// let's use SM_CX/YSMICON and hope for the best
|
||||||
|
width = GetSystemMetrics(SM_CXSMICON);
|
||||||
|
height = GetSystemMetrics(SM_CYSMICON);
|
||||||
|
dc = GetDC(hwnddc);
|
||||||
|
if (dc == NULL)
|
||||||
|
xpanic("error getting DC for making the checkbox image list", GetLastError());
|
||||||
|
checkboxImageList = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
|
||||||
|
if (checkboxImageList == NULL)
|
||||||
|
xpanic("error creating checkbox image list", GetLastError());
|
||||||
|
for (cbState = 0; cbState < checkboxnStates; cbState++) {
|
||||||
|
HBITMAP bitmap;
|
||||||
|
|
||||||
|
bitmap = dfcImage(dc, width, height, cbState);
|
||||||
|
if ((*fv_ImageList_Add)(checkboxImageList, bitmap, NULL) == -1)
|
||||||
|
xpanic("error adding checkbox image to image list", GetLastError());
|
||||||
|
if (DeleteObject(bitmap) == 0)
|
||||||
|
xpanic("error deleting checkbox bitmap", GetLastError());
|
||||||
|
}
|
||||||
|
if (ReleaseDC(hwnddc, dc) == 0)
|
||||||
|
xpanic("error deleting checkbox image list DC", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
static HTHEME theme = NULL;
|
||||||
|
|
||||||
|
static void openTheme(HWND hwnd)
|
||||||
|
{
|
||||||
|
if (theme != NULL)
|
||||||
|
// TODO save HRESULT
|
||||||
|
if (CloseThemeData(theme) != S_OK)
|
||||||
|
xpanic("error closing theme", GetLastError());
|
||||||
|
// ignore error; if it can't be done, we can fall back to DrawFrameControl()
|
||||||
|
theme = OpenThemeData(hwnd, L"button");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int themestates[checkboxnStates] = {
|
||||||
|
CBS_UNCHECKEDNORMAL, // 0
|
||||||
|
CBS_CHECKEDNORMAL, // checked
|
||||||
|
CBS_UNCHECKEDHOT, // hot
|
||||||
|
CBS_CHECKEDHOT, // checked | hot
|
||||||
|
CBS_UNCHECKEDPRESSED, // pushed
|
||||||
|
CBS_CHECKEDPRESSED, // checked | pushed
|
||||||
|
CBS_UNCHECKEDPRESSED, // hot | pushed
|
||||||
|
CBS_CHECKEDPRESSED, // checked | hot | pushed
|
||||||
|
};
|
||||||
|
|
||||||
|
static SIZE getStateSize(HDC dc, int cbState)
|
||||||
|
{
|
||||||
|
SIZE s;
|
||||||
|
|
||||||
|
// TODO use HRESULT
|
||||||
|
if (GetThemePartSize(theme, dc, BP_CHECKBOX, themestates[cbState], NULL, TS_DRAW, &s) != S_OK)
|
||||||
|
xpanic("error getting theme part size", GetLastError());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HBITMAP drawThemeImage(HDC dc, int width, int height, int cbState)
|
||||||
|
{
|
||||||
|
BITMAPINFO bi;
|
||||||
|
VOID *ppvBits;
|
||||||
|
HBITMAP bitmap;
|
||||||
|
RECT r;
|
||||||
|
HDC drawDC;
|
||||||
|
HBITMAP prevbitmap;
|
||||||
|
|
||||||
|
r.left = 0;
|
||||||
|
r.top = 0;
|
||||||
|
r.right = width;
|
||||||
|
r.bottom = height;
|
||||||
|
ZeroMemory(&bi, sizeof (BITMAPINFO));
|
||||||
|
bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
||||||
|
bi.bmiHeader.biWidth = (LONG) width;
|
||||||
|
bi.bmiHeader.biHeight = -((LONG) height); // negative height to force top-down drawing;
|
||||||
|
bi.bmiHeader.biPlanes = 1;
|
||||||
|
bi.bmiHeader.biBitCount = 32;
|
||||||
|
bi.bmiHeader.biCompression = BI_RGB;
|
||||||
|
bi.bmiHeader.biSizeImage = (DWORD) (width * height * 4);
|
||||||
|
bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
|
||||||
|
if (bitmap == NULL)
|
||||||
|
xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
|
||||||
|
|
||||||
|
drawDC = CreateCompatibleDC(dc);
|
||||||
|
if (drawDC == NULL)
|
||||||
|
xpanic("error getting DC for checkbox image list bitmap", GetLastError());
|
||||||
|
prevbitmap = SelectObject(drawDC, bitmap);
|
||||||
|
if (prevbitmap == NULL)
|
||||||
|
xpanic("error selecting checkbox image list bitmap into DC", GetLastError());
|
||||||
|
// TODO get HRESULT
|
||||||
|
if (DrawThemeBackground(theme, drawDC, BP_CHECKBOX, themestates[cbState], &r, NULL) != S_OK)
|
||||||
|
xpanic("error drawing checkbox image", GetLastError());
|
||||||
|
if (SelectObject(drawDC, prevbitmap) != bitmap)
|
||||||
|
xpanic("error selecting previous bitmap into checkbox image's DC", GetLastError());
|
||||||
|
if (DeleteDC(drawDC) == 0)
|
||||||
|
xpanic("error deleting checkbox image's DC", GetLastError());
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void makeCheckboxImageList_theme(HWND hwnddc)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
int cbState;
|
||||||
|
SIZE size;
|
||||||
|
HDC dc;
|
||||||
|
|
||||||
|
// first, make sure that all things have the same size
|
||||||
|
dc = GetDC(hwnddc);
|
||||||
|
if (dc == NULL)
|
||||||
|
xpanic("error getting DC for making the checkbox image list", GetLastError());
|
||||||
|
size = getStateSize(dc, 0);
|
||||||
|
for (cbState = 1; cbState < checkboxnStates; cbState++) {
|
||||||
|
SIZE against;
|
||||||
|
|
||||||
|
against = getStateSize(dc, cbState);
|
||||||
|
if (size.cx != against.cx || size.cy != against.cy)
|
||||||
|
xpanic("size mismatch in checkbox states", GetLastError());
|
||||||
|
}
|
||||||
|
width = (int) size.cx;
|
||||||
|
height = (int) size.cy;
|
||||||
|
|
||||||
|
// NOW draw
|
||||||
|
checkboxImageList = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
|
||||||
|
if (checkboxImageList == NULL)
|
||||||
|
xpanic("error creating checkbox image list", GetLastError());
|
||||||
|
for (cbState = 0; cbState < checkboxnStates; cbState++) {
|
||||||
|
HBITMAP bitmap;
|
||||||
|
|
||||||
|
bitmap = drawThemeImage(dc, width, height, cbState);
|
||||||
|
if ((*fv_ImageList_Add)(checkboxImageList, bitmap, NULL) == -1)
|
||||||
|
xpanic("error adding checkbox image to image list", GetLastError());
|
||||||
|
if (DeleteObject(bitmap) == 0)
|
||||||
|
xpanic("error deleting checkbox bitmap", GetLastError());
|
||||||
|
}
|
||||||
|
if (ReleaseDC(hwnddc, dc) == 0)
|
||||||
|
xpanic("error deleting checkbox image list DC", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeCheckboxImageList(HWND hwnddc)
|
||||||
|
{
|
||||||
|
if (theme == NULL) // try to open the theme
|
||||||
|
openTheme(hwnddc);
|
||||||
|
if (theme != NULL) { // use the theme
|
||||||
|
makeCheckboxImageList_theme(hwnddc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// couldn't open; fall back
|
||||||
|
makeCheckboxImageList_DFC(hwnddc);
|
||||||
|
}
|
||||||
|
|
|
@ -41,5 +41,6 @@ func (i *imagelist) apply(hwnd C.HWND, uMsg C.UINT, wParam C.WPARAM) {
|
||||||
for index := range i.list {
|
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.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.applyImageList(hwnd, uMsg, wParam, il)
|
||||||
|
C.applyImageList(hwnd, uMsg, wParam, C.checkboxImageList)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,10 @@ static LRESULT CALLBACK msgwinproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l
|
||||||
if (sharedWndProc(hwnd, uMsg, wParam, lParam, &shared))
|
if (sharedWndProc(hwnd, uMsg, wParam, lParam, &shared))
|
||||||
return shared;
|
return shared;
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
|
case WM_CREATE:
|
||||||
|
// initial
|
||||||
|
makeCheckboxImageList(hwnd);
|
||||||
|
return 0;
|
||||||
case msgRequest:
|
case msgRequest:
|
||||||
doissue((void *) lParam);
|
doissue((void *) lParam);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
#include <vsstyle.h>
|
||||||
|
#include <vssym32.h>
|
||||||
|
|
||||||
// global messages unique to everything
|
// global messages unique to everything
|
||||||
enum {
|
enum {
|
||||||
|
@ -119,5 +121,13 @@ extern HBITMAP unscaledBitmap(void *, intptr_t, intptr_t);
|
||||||
extern HIMAGELIST newImageList(int, int);
|
extern HIMAGELIST newImageList(int, int);
|
||||||
extern void addImage(HIMAGELIST, HWND, HBITMAP, int, int, 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);
|
||||||
|
enum {
|
||||||
|
checkboxStateChecked = 1 << 0,
|
||||||
|
checkboxStateHot = 1 << 1,
|
||||||
|
checkboxStatePushed = 1 << 2,
|
||||||
|
checkboxnStates = 1 << 3,
|
||||||
|
};
|
||||||
|
extern HIMAGELIST checkboxImageList;
|
||||||
|
extern void makeCheckboxImageList(HWND);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue