/*
* windows.c: Windows front end for my puzzle collection.
- *
- * TODO:
- *
- * - Figure out what to do if a puzzle requests a size bigger than
- * the screen will take. In principle we could put scrollbars in
- * the window, although that would be pretty horrid. Another
- * option is to detect in advance that this will be a problem -
- * we can probably tell this using midend_size() before actually
- * generating the puzzle - and simply refuse to do it.
*/
#include <windows.h>
int ctlid;
};
+struct blitter {
+ HBITMAP bitmap;
+ frontend *fe;
+ int x, y, w, h;
+};
+
struct frontend {
midend_data *me;
HWND hwnd, statusbar, cfgbox;
}
}
+blitter *blitter_new(int w, int h)
+{
+ blitter *bl = snew(blitter);
+
+ memset(bl, 0, sizeof(blitter));
+ bl->w = w;
+ bl->h = h;
+ bl->bitmap = 0;
+
+ return bl;
+}
+
+void blitter_free(blitter *bl)
+{
+ if (bl->bitmap) DeleteObject(bl->bitmap);
+ sfree(bl);
+}
+
+static void blitter_mkbitmap(frontend *fe, blitter *bl)
+{
+ HDC hdc = GetDC(fe->hwnd);
+ bl->bitmap = CreateCompatibleBitmap(hdc, bl->w, bl->h);
+ ReleaseDC(fe->hwnd, hdc);
+}
+
+/* BitBlt(dstDC, dstX, dstY, dstW, dstH, srcDC, srcX, srcY, dType) */
+
+void blitter_save(frontend *fe, blitter *bl, int x, int y)
+{
+ HDC hdc_win, hdc_blit;
+ HBITMAP prev_blit;
+
+ if (!bl->bitmap) blitter_mkbitmap(fe, bl);
+
+ bl->x = x; bl->y = y;
+
+ hdc_win = GetDC(fe->hwnd);
+ hdc_blit = CreateCompatibleDC(hdc_win);
+ if (!hdc_blit) fatal("hdc_blit failed: 0x%x", GetLastError());
+
+ prev_blit = SelectObject(hdc_blit, bl->bitmap);
+ if (prev_blit == NULL || prev_blit == HGDI_ERROR)
+ fatal("SelectObject for hdc_main failed: 0x%x", GetLastError());
+
+ if (!BitBlt(hdc_blit, 0, 0, bl->w, bl->h,
+ fe->hdc_bm, x, y, SRCCOPY))
+ fatal("BitBlt failed: 0x%x", GetLastError());
+
+ SelectObject(hdc_blit, prev_blit);
+ DeleteDC(hdc_blit);
+ ReleaseDC(fe->hwnd, hdc_win);
+}
+
+void blitter_load(frontend *fe, blitter *bl, int x, int y)
+{
+ HDC hdc_win, hdc_blit;
+ HBITMAP prev_blit;
+
+ assert(bl->bitmap); /* we should always have saved before loading */
+
+ if (x == BLITTER_FROMSAVED) x = bl->x;
+ if (y == BLITTER_FROMSAVED) y = bl->y;
+
+ hdc_win = GetDC(fe->hwnd);
+ hdc_blit = CreateCompatibleDC(hdc_win);
+
+ prev_blit = SelectObject(hdc_blit, bl->bitmap);
+
+ BitBlt(fe->hdc_bm, x, y, bl->w, bl->h,
+ hdc_blit, 0, 0, SRCCOPY);
+
+ SelectObject(hdc_blit, prev_blit);
+ DeleteDC(hdc_blit);
+ ReleaseDC(fe->hwnd, hdc_win);
+}
+
void frontend_default_colour(frontend *fe, float *output)
{
DWORD c = GetSysColor(COLOR_MENU); /* ick */
SelectObject(fe->hdc_bm, oldpen);
}
+void draw_circle(frontend *fe, int cx, int cy, int radius,
+ int fill, int colour)
+{
+ if (fill) {
+ HBRUSH oldbrush = SelectObject(fe->hdc_bm, fe->brushes[colour]);
+ HPEN oldpen = SelectObject(fe->hdc_bm, fe->pens[colour]);
+ Ellipse(fe->hdc_bm, cx - radius, cy - radius,
+ cx + radius + 1, cy + radius + 1);
+ SelectObject(fe->hdc_bm, oldbrush);
+ SelectObject(fe->hdc_bm, oldpen);
+ } else {
+ HPEN oldpen = SelectObject(fe->hdc_bm, fe->pens[colour]);
+ MoveToEx(fe->hdc_bm, cx + radius, cy, NULL);
+ AngleArc(fe->hdc_bm, cx, cy, radius, 0.0F, 360.0F);
+ SelectObject(fe->hdc_bm, oldpen);
+ }
+}
+
void draw_polygon(frontend *fe, int *coords, int npoints,
int fill, int colour)
{
r.right - r.left, r.bottom - r.top,
NULL, NULL, inst, NULL);
- if (midend_wants_statusbar(fe->me))
+ if (midend_wants_statusbar(fe->me)) {
+ RECT sr;
fe->statusbar = CreateWindowEx(0, STATUSCLASSNAME, "ooh",
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, /* status bar does these */
fe->hwnd, NULL, inst, NULL);
- else
+ /*
+ * Now resize the window to take account of the status bar.
+ */
+ GetWindowRect(fe->statusbar, &sr);
+ GetWindowRect(fe->hwnd, &r);
+ SetWindowPos(fe->hwnd, NULL, 0, 0, r.right - r.left,
+ r.bottom - r.top + sr.bottom - sr.top,
+ SWP_NOMOVE | SWP_NOZORDER);
+ } else {
fe->statusbar = NULL;
+ }
{
HMENU bar = CreateMenu();