2 * windows.c: Windows front end for my puzzle collection.
17 HBITMAP bitmap
, prevbm
;
25 void fatal(char *fmt
, ...)
31 vsprintf(buf
, fmt
, ap
);
34 MessageBox(NULL
, buf
, "Fatal error", MB_ICONEXCLAMATION
| MB_OK
);
39 void frontend_default_colour(frontend
*fe
, float *output
)
41 DWORD c
= GetSysColor(COLOR_MENU
); /* ick */
43 output
[0] = (float)(GetRValue(c
) / 255.0);
44 output
[1] = (float)(GetGValue(c
) / 255.0);
45 output
[2] = (float)(GetBValue(c
) / 255.0);
48 void draw_rect(frontend
*fe
, int x
, int y
, int w
, int h
, int colour
)
50 if (w
== 1 && h
== 1) {
52 * Rectangle() appears to get uppity if asked to draw a 1x1
53 * rectangle, presumably on the grounds that that's beneath
54 * its dignity and you ought to be using SetPixel instead.
57 SetPixel(fe
->hdc_bm
, x
, y
, fe
->colours
[colour
]);
59 HBRUSH oldbrush
= SelectObject(fe
->hdc_bm
, fe
->brushes
[colour
]);
60 HPEN oldpen
= SelectObject(fe
->hdc_bm
, fe
->pens
[colour
]);
61 Rectangle(fe
->hdc_bm
, x
, y
, x
+w
, y
+h
);
62 SelectObject(fe
->hdc_bm
, oldbrush
);
63 SelectObject(fe
->hdc_bm
, oldpen
);
67 void draw_line(frontend
*fe
, int x1
, int y1
, int x2
, int y2
, int colour
)
69 HPEN oldpen
= SelectObject(fe
->hdc_bm
, fe
->pens
[colour
]);
70 MoveToEx(fe
->hdc_bm
, x1
, y1
, NULL
);
71 LineTo(fe
->hdc_bm
, x2
, y2
);
72 SetPixel(fe
->hdc_bm
, x2
, y2
, fe
->colours
[colour
]);
73 SelectObject(fe
->hdc_bm
, oldpen
);
76 void draw_polygon(frontend
*fe
, int *coords
, int npoints
,
79 POINT
*pts
= snewn(npoints
+1, POINT
);
82 for (i
= 0; i
<= npoints
; i
++) {
83 int j
= (i
< npoints ? i
: 0);
84 pts
[i
].x
= coords
[j
*2];
85 pts
[i
].y
= coords
[j
*2+1];
89 HBRUSH oldbrush
= SelectObject(fe
->hdc_bm
, fe
->brushes
[colour
]);
90 HPEN oldpen
= SelectObject(fe
->hdc_bm
, fe
->pens
[colour
]);
91 Polygon(fe
->hdc_bm
, pts
, npoints
);
92 SelectObject(fe
->hdc_bm
, oldbrush
);
93 SelectObject(fe
->hdc_bm
, oldpen
);
95 HPEN oldpen
= SelectObject(fe
->hdc_bm
, fe
->pens
[colour
]);
96 Polyline(fe
->hdc_bm
, pts
, npoints
+1);
97 SelectObject(fe
->hdc_bm
, oldpen
);
103 void start_draw(frontend
*fe
)
106 hdc_win
= GetDC(fe
->hwnd
);
107 fe
->hdc_bm
= CreateCompatibleDC(hdc_win
);
108 fe
->prevbm
= SelectObject(fe
->hdc_bm
, fe
->bitmap
);
109 ReleaseDC(fe
->hwnd
, hdc_win
);
112 void draw_update(frontend
*fe
, int x
, int y
, int w
, int h
)
121 InvalidateRect(fe
->hwnd
, &r
, FALSE
);
124 void end_draw(frontend
*fe
)
126 SelectObject(fe
->hdc_bm
, fe
->prevbm
);
127 DeleteDC(fe
->hdc_bm
);
130 void deactivate_timer(frontend
*fe
)
132 KillTimer(fe
->hwnd
, fe
->timer
);
136 void activate_timer(frontend
*fe
)
138 fe
->timer
= SetTimer(fe
->hwnd
, fe
->timer
, 20, NULL
);
141 static frontend
*new_window(HINSTANCE inst
)
149 fe
->me
= midend_new(fe
);
150 midend_new_game(fe
->me
, NULL
);
151 midend_size(fe
->me
, &x
, &y
);
159 colours
= midend_colours(fe
->me
, &ncolours
);
161 fe
->colours
= snewn(ncolours
, COLORREF
);
162 fe
->brushes
= snewn(ncolours
, HBRUSH
);
163 fe
->pens
= snewn(ncolours
, HPEN
);
165 for (i
= 0; i
< ncolours
; i
++) {
166 fe
->colours
[i
] = RGB(255 * colours
[i
*3+0],
167 255 * colours
[i
*3+1],
168 255 * colours
[i
*3+2]);
169 fe
->brushes
[i
] = CreateSolidBrush(fe
->colours
[i
]);
171 MessageBox(fe
->hwnd
, "ooh", "eck", MB_OK
);
172 fe
->pens
[i
] = CreatePen(PS_SOLID
, 1, fe
->colours
[i
]);
179 AdjustWindowRectEx(&r
, WS_OVERLAPPEDWINDOW
&~
180 (WS_THICKFRAME
| WS_MAXIMIZEBOX
| WS_OVERLAPPED
),
183 fe
->hwnd
= CreateWindowEx(0, "puzzle", "puzzle",
184 WS_OVERLAPPEDWINDOW
&~
185 (WS_THICKFRAME
| WS_MAXIMIZEBOX
),
186 CW_USEDEFAULT
, CW_USEDEFAULT
,
187 r
.right
- r
.left
, r
.bottom
- r
.top
,
188 NULL
, NULL
, inst
, NULL
);
190 hdc
= GetDC(fe
->hwnd
);
191 fe
->bitmap
= CreateCompatibleBitmap(hdc
, x
, y
);
192 ReleaseDC(fe
->hwnd
, hdc
);
194 SetWindowLong(fe
->hwnd
, GWL_USERDATA
, (LONG
)fe
);
196 ShowWindow(fe
->hwnd
, SW_NORMAL
);
197 SetForegroundWindow(fe
->hwnd
);
199 midend_redraw(fe
->me
);
204 static LRESULT CALLBACK
WndProc(HWND hwnd
, UINT message
,
205 WPARAM wParam
, LPARAM lParam
)
207 frontend
*fe
= (frontend
*)GetWindowLong(hwnd
, GWL_USERDATA
);
222 hdc
= BeginPaint(hwnd
, &p
);
223 hdc2
= CreateCompatibleDC(hdc
);
224 prevbm
= SelectObject(hdc2
, fe
->bitmap
);
226 p
.rcPaint
.left
, p
.rcPaint
.top
,
227 p
.rcPaint
.right
- p
.rcPaint
.left
,
228 p
.rcPaint
.bottom
- p
.rcPaint
.top
,
230 p
.rcPaint
.left
, p
.rcPaint
.top
,
232 SelectObject(hdc2
, prevbm
);
242 case VK_LEFT
: key
= CURSOR_LEFT
; break;
243 case VK_RIGHT
: key
= CURSOR_RIGHT
; break;
244 case VK_UP
: key
= CURSOR_UP
; break;
245 case VK_DOWN
: key
= CURSOR_DOWN
; break;
249 if (!midend_process_key(fe
->me
, -1, -1, key
))
257 if (!midend_process_key(fe
->me
, LOWORD(lParam
), HIWORD(lParam
),
258 (message
== WM_LBUTTONDOWN ? LEFT_BUTTON
:
259 message
== WM_RBUTTONDOWN ? RIGHT_BUTTON
:
265 if (!midend_process_key(fe
->me
, -1, -1, (unsigned char)wParam
))
270 midend_timer(fe
->me
, (float)0.02);
274 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
277 int WINAPI
WinMain(HINSTANCE inst
, HINSTANCE prev
, LPSTR cmdline
, int show
)
287 wndclass
.lpfnWndProc
= WndProc
;
288 wndclass
.cbClsExtra
= 0;
289 wndclass
.cbWndExtra
= 0;
290 wndclass
.hInstance
= inst
;
291 wndclass
.hIcon
= LoadIcon(inst
, IDI_APPLICATION
);
292 wndclass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
293 wndclass
.hbrBackground
= NULL
;
294 wndclass
.lpszMenuName
= NULL
;
295 wndclass
.lpszClassName
= "puzzle";
297 RegisterClass(&wndclass
);
302 while (GetMessage(&msg
, NULL
, 0, 0)) {
303 TranslateMessage(&msg
);
304 DispatchMessage(&msg
);