summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2015-02-17 21:35:03 -0500
committerPietro Gagliardi <[email protected]>2015-02-17 21:35:03 -0500
commit3099edb9c973d709f48b28ddceff0c67bcf0923c (patch)
tree6b5edcc788a5bbf921f01d3aa45731a85c4b112c
parent749d1d75a67728f2315ced3e3faf13af1ce7ae34 (diff)
Next part of Table code: HBITMAP generation code migration.
-rw-r--r--image_windows.c35
-rw-r--r--imagelist_windows.c268
-rw-r--r--winapi_windows.h8
3 files changed, 38 insertions, 273 deletions
diff --git a/image_windows.c b/image_windows.c
new file mode 100644
index 0000000..7e57bff
--- /dev/null
+++ b/image_windows.c
@@ -0,0 +1,35 @@
+// 16 august 2014
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+// TODO rename to images_windows.c?
+
+HBITMAP toBitmap(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 in toBitmap()", GetLastError());
+ // image lists use non-premultiplied RGBA - see http://stackoverflow.com/a/25578789/3408572
+ // the TRUE here does the conversion
+ dotoARGB(i, (void *) ppvBits, TRUE);
+ return bitmap;
+}
+
+void freeBitmap(void *bitmap)
+{
+ if (DeleteObject((HBITMAP) bitmap) == 0)
+ xpanic("error deleting bitmap in freeBitmap()", GetLastError());
+}
diff --git a/imagelist_windows.c b/imagelist_windows.c
deleted file mode 100644
index 14d33a9..0000000
--- a/imagelist_windows.c
+++ /dev/null
@@ -1,268 +0,0 @@
-// 16 august 2014
-
-#include "winapi_windows.h"
-#include "_cgo_export.h"
-
-// TODO top left pixel of checkbox state 0 not drawn?
-
-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());
- // image lists use non-premultiplied RGBA - see http://stackoverflow.com/a/25578789/3408572
- // the TRUE here does the conversion
- dotoARGB(i, (void *) ppvBits, TRUE);
- return bitmap;
-}
-
-HIMAGELIST newImageList(int width, int height)
-{
- HIMAGELIST il;
-
- // this handles alpha properly; see https://web.archive.org/web/20100512144953/http://msdn.microsoft.com/en-us/library/ms997646.aspx#xptheming_topic13 and http://stackoverflow.com/a/2640897/3408572
- 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, HWND hwnd, HBITMAP bitmap, int origwid, int oright, int width, int height)
-{
- BOOL wasScaled = FALSE;
- HDC winDC, 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;
- winDC = GetDC(hwnd);
- if (winDC == NULL)
- xpanic("error getting DC for window", GetLastError());
- origDC = CreateCompatibleDC(winDC);
- if (origDC == NULL)
- xpanic("error getting DC for original ImageList bitmap", GetLastError());
- prevorig = SelectObject(origDC, bitmap);
- if (prevorig == NULL)
- xpanic("error selecting original ImageList bitmap into DC", GetLastError());
- scaledDC = CreateCompatibleDC(origDC);
- if (scaledDC == NULL)
- xpanic("error getting DC for scaled ImageList bitmap", GetLastError());
- scaled = CreateCompatibleBitmap(origDC, 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 DC", GetLastError());
- if (SetStretchBltMode(scaledDC, COLORONCOLOR) == 0)
- xpanic("error setting scaling mode", 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 DC", GetLastError());
- if (DeleteDC(origDC) == 0)
- xpanic("error deleting original image's DC", GetLastError());
- if (SelectObject(scaledDC, prevscaled) != scaled)
- xpanic("error selecting previous bitmap into scaled image's DC", GetLastError());
- if (DeleteDC(scaledDC) == 0)
- xpanic("error deleting scaled image's DC", GetLastError());
- if (ReleaseDC(hwnd, winDC) == 0)
- xpanic("error deleting window 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());
-}
-
-void applyImageList(HWND hwnd, UINT uMsg, WPARAM wParam, HIMAGELIST il, HIMAGELIST old)
-{
- 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)
-{
- 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 void dfcImage(HDC dc, RECT *r, int cbState, HTHEME theme)
-{
- if (DrawFrameControl(dc, r, DFC_BUTTON, dfcState(cbState)) == 0)
- xpanic("error drawing checkbox image", GetLastError());
-}
-
-static void dfcSize(HDC dc, int *width, int *height, HTHEME theme)
-{
- // 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);
-}
-
-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, HTHEME theme)
-{
- SIZE s;
- HRESULT res;
-
- res = GetThemePartSize(theme, dc, BP_CHECKBOX, themestates[cbState], NULL, TS_DRAW, &s);
- if (res != S_OK)
- xpanichresult("error getting theme part size", res);
- return s;
-}
-
-static void themeImage(HDC dc, RECT *r, int cbState, HTHEME theme)
-{
- HRESULT res;
-
- res = DrawThemeBackground(theme, dc, BP_CHECKBOX, themestates[cbState], r, NULL);
- if (res != S_OK)
- xpanichresult("error drawing checkbox image", res);
-}
-
-static void themeSize(HDC dc, int *width, int *height, HTHEME theme)
-{
- SIZE size;
- int cbState;
-
- size = getStateSize(dc, 0, theme);
- for (cbState = 1; cbState < checkboxnStates; cbState++) {
- SIZE against;
-
- against = getStateSize(dc, cbState, theme);
- if (size.cx != against.cx || size.cy != against.cy)
- xpanic("size mismatch in checkbox states", GetLastError());
- }
- *width = (int) size.cx;
- *height = (int) size.cy;
-}
-
-static HBITMAP makeCheckboxImageListEntry(HDC dc, int width, int height, int cbState, void (*drawfunc)(HDC, RECT *, int, HTHEME), HTHEME theme)
-{
- 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());
- (*drawfunc)(drawDC, &r, cbState, theme);
- 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;
-}
-
-static HIMAGELIST newCheckboxImageList(HWND hwnddc, void (*sizefunc)(HDC, int *, int *, HTHEME), void (*drawfunc)(HDC, RECT *, int, HTHEME), HTHEME theme)
-{
- int width, height;
- int cbState;
- HDC dc;
- HIMAGELIST il;
-
- dc = GetDC(hwnddc);
- if (dc == NULL)
- xpanic("error getting DC for making the checkbox image list", GetLastError());
- (*sizefunc)(dc, &width, &height, theme);
- il = (*fv_ImageList_Create)(width, height, ILC_COLOR32, 20, 20); // should be reasonable
- if (il == NULL)
- xpanic("error creating checkbox image list", GetLastError());
- for (cbState = 0; cbState < checkboxnStates; cbState++) {
- HBITMAP bitmap;
-
- bitmap = makeCheckboxImageListEntry(dc, width, height, cbState, drawfunc, theme);
- if ((*fv_ImageList_Add)(il, 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());
- return il;
-}
-
-HIMAGELIST makeCheckboxImageList(HWND hwnddc, HTHEME *theme)
-{
- if (*theme != NULL) {
- HRESULT res;
-
- res = CloseThemeData(*theme);
- if (res != S_OK)
- xpanichresult("error closing theme", res);
- *theme = NULL;
- }
- // ignore error; if it can't be done, we can fall back to DrawFrameControl()
- if (*theme == NULL) // try to open the theme
- *theme = OpenThemeData(hwnddc, L"button");
- if (*theme != NULL) // use the theme
- return newCheckboxImageList(hwnddc, themeSize, themeImage, *theme);
- // couldn't open; fall back
- return newCheckboxImageList(hwnddc, dfcSize, dfcImage, *theme);
-}
diff --git a/winapi_windows.h b/winapi_windows.h
index d751aca..0f34d17 100644
--- a/winapi_windows.h
+++ b/winapi_windows.h
@@ -128,11 +128,9 @@ extern HWND newAreaTextField(HWND, void *);
extern void areaOpenTextField(HWND, HWND, int, int, int, int);
extern void areaMarkTextFieldDone(HWND);
-// imagelist_windows.c
-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, HIMAGELIST);
+// image_windows.c
+extern HBITMAP toBitmap(void *, intptr_t, intptr_t);
+extern void freeBitmap(void *);
// dialog_windows.c
extern void openFile(HWND, void *);