#include <string.h>
#include <assert.h>
#include <windows.h>
+#include <commctrl.h>
#include "widgets.h"
+#define WIN_STYLE WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME
+
struct wgt_window {
HWND handle;
struct wgt_rect rect;
HDC dc;
char cname[32];
struct wgt_widget *wlist;
+
+ int close_quit;
+ int (*cb_close)(struct wgt_window*);
};
struct wgt_widget {
static LRESULT WINAPI event_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
static struct wgt_widget *find_widget(struct wgt_window *win, HWND handle);
+
+void *wgt_window_handle(struct wgt_window *win)
+{
+ return win->handle;
+}
+
+void *wgt_widget_handle(struct wgt_widget *w)
+{
+ return w->handle;
+}
+
+unsigned int wgt_window_xid(struct wgt_window *win)
+{
+ return 0;
+}
+
+unsigned int wgt_widget_xid(struct wgt_widget *w)
+{
+ return 0;
+}
+
+
struct wgt_window *wgt_window(const char *title, int width, int height)
{
struct wgt_window *win;
DWORD err;
RECT rect;
- if(!(win = malloc(sizeof *win))) {
+ if(!(win = calloc(1, sizeof *win))) {
fprintf(stderr, "wgl_create_window: failed to allocate window structure\n");
return 0;
}
- win->wlist = 0;
+ win->close_quit = 1; /* by default quit when the window closes */
tlen = strlen(title);
if(tlen > sizeof win->cname - 10) {
return 0;
}
- if(!(win->handle = CreateWindow(win->cname, title, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, hinst, 0))) {
+ rect.left = rect.top = 0;
+ rect.right = width;
+ rect.bottom = height;
+ AdjustWindowRect(&rect, WIN_STYLE, FALSE);
+
+ if(!(win->handle = CreateWindow(win->cname, title, WIN_STYLE, CW_USEDEFAULT,
+ CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
+ 0, 0, hinst, 0))) {
fprintf(stderr, "wgt_create_window: failed to create window\n");
UnregisterClass(title, hinst);
return 0;
free(w);
}
- ReleaseDC(win->handle, win->dc);
- DestroyWindow(win->handle);
- UnregisterClass(win->cname, GetModuleHandle(0));
+ if(win->handle) {
+ ReleaseDC(win->handle, win->dc);
+ DestroyWindow(win->handle);
+ UnregisterClass(win->cname, GetModuleHandle(0));
+ }
+}
+void wgt_free_window(struct wgt_window *win)
+{
+ wgt_destroy_window(win);
free(win);
}
free(w->itemlist);
}
+void wgt_resize_window(struct wgt_window *win, int width, int height)
+{
+ RECT rect;
+
+ win->rect.width = width;
+ win->rect.height = height;
+
+ rect.left = win->rect.x;
+ rect.top = win->rect.y;
+ rect.right = rect.left + width;
+ rect.bottom = rect.top + height;
+ if(AdjustWindowRect(&rect, WIN_STYLE, FALSE)) {
+ width = rect.right - rect.left;
+ height = rect.bottom - rect.top;
+ }
+ MoveWindow(win->handle, win->rect.x, win->rect.y, width, height, TRUE);
+}
+
+void wgt_quit_on_close(struct wgt_window *win, int quit)
+{
+ win->close_quit = quit;
+}
+
+void wgt_close_action(struct wgt_window *win, int (*func)(struct wgt_window*))
+{
+ win->cb_close = func;
+}
+
void wgt_enable_widget(struct wgt_widget *w)
{
w->disabled = 0;
return &w->rect;
}
+void wgt_move_widget(struct wgt_widget *w, int x, int y)
+{
+ MoveWindow(w->handle, x, y, w->rect.width, w->rect.height, TRUE);
+ w->rect.x = x;
+ w->rect.y = y;
+}
+
+void wgt_resize_widget(struct wgt_widget *w, int width, int height)
+{
+ MoveWindow(w->handle, w->rect.x, w->rect.y, width, height, TRUE);
+ w->rect.width = width;
+ w->rect.height = height;
+}
+
int wgt_xpos_after(struct wgt_widget *w, int pad)
{
if(pad == WGT_AUTO) {
free(w);
return 0;
}
+ SendMessage(w->handle, BM_SETCHECK, on ? BST_CHECKED : BST_UNCHECKED, 0);
w->rect.x = x;
w->rect.y = y;
wgt_string_size(win, "00", &textsz);
max_width = width < 0 && width != WGT_AUTO ? -width : textsz.width;
+ /* first get the height of the editbox */
sum_height = SendMessage(cbwnd, CB_GETITEMHEIGHT, -1, 0);
sz->y = sum_height;
-
- for(i=0; i<num_items; i++) {
- wgt_string_size(win, items[i], &textsz);
- if(textsz.width > max_width) max_width = textsz.width;
- sum_height += SendMessage(cbwnd, CB_GETITEMHEIGHT, i, 0);
+ /* then add the height of the dropdown list items */
+ /* XXX I can't figure out why, but it's not sufficient to show all items
+ * without some more height, so let's double it...
+ */
+ sum_height *= 2;
+ sum_height += SendMessage(cbwnd, CB_GETITEMHEIGHT, 0, 0) * num_items;
+ sum_height += GetSystemMetrics(SM_CYEDGE) * 2;
+
+ if(width < 0) {
+ int sbar_width;
+ for(i=0; i<num_items; i++) {
+ wgt_string_size(win, items[i], &textsz);
+ if(textsz.width > max_width) max_width = textsz.width;
+ }
+ sbar_width = GetSystemMetrics(SM_CXVSCROLL);
+ width = max_width + sbar_width + GetSystemMetrics(SM_CXEDGE) * 2;
}
- if(width < 0) width = max_width * 3 / 2;
if(height < 0) height = sum_height;
sz->width = width;
SendMessage(w->handle, CB_SETCURSEL, sel, 0);
}
-
w->cb_modify = modfunc;
w->next = win->wlist;
win->wlist = w;
return w;
}
+struct wgt_widget *wgt_progbar(struct wgt_window *win, int x, int y, int width, int height, int p)
+{
+ struct wgt_widget *w;
+ INITCOMMONCONTROLSEX commctrl;
+
+ commctrl.dwSize = sizeof commctrl;
+ commctrl.dwICC = ICC_PROGRESS_CLASS;
+ InitCommonControlsEx(&commctrl);
+
+ if(!(w = calloc(1, sizeof *w))) {
+ fprintf(stderr, "wgt_progbar: failed to allocate widget structure\n");
+ return 0;
+ }
+ w->win = win;
+
+ if(height < 0) {
+ height = GetSystemMetrics(SM_CYVSCROLL);
+ }
+
+ if(!(w->handle = CreateWindow(PROGRESS_CLASS, 0, WS_CHILD | WS_VISIBLE, x, y,
+ width, height, win->handle, 0, GetModuleHandle(0), 0))) {
+ fprintf(stderr, "wgt_progbar: failed to create window\n");
+ free(w);
+ return 0;
+ }
+
+ /*
+ SendMessage(w->handle, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
+ SendMessage(w->handle, PBM_SETSTEP, 1, 0);
+ */
+ SendMessage(w->handle, PBM_SETPOS, p, 0);
+
+ w->rect.x = x;
+ w->rect.y = y;
+ w->rect.width = width;
+ w->rect.height = height;
+
+ w->next = win->wlist;
+ win->wlist = w;
+ return w;
+}
+
+void wgt_set_text(struct wgt_widget *w, const char *text)
+{
+ SendMessage(w->handle, WM_SETTEXT, 0, (long)text);
+
+ w->rect.width = wgt_string_size(w->win, text, 0);
+ MoveWindow(w->handle, w->rect.x, w->rect.y, w->rect.width, w->rect.height, TRUE);
+}
+
void wgt_checkbox_check(struct wgt_widget *w)
{
SendMessage(w->handle, BM_SETCHECK, BST_CHECKED, 0);
combosize(w->win, w->handle, items, num_items, w->rect.width, WGT_AUTO, &size);
MoveWindow(w->handle, w->rect.x, w->rect.y, w->rect.width, size.height, TRUE);
+
+ SendMessage(w->handle, CB_SETCURSEL, 0, 0);
return 0;
}
return w->itemlist[idx];
}
+void wgt_set_progress(struct wgt_widget *w, int p)
+{
+ SendMessage(w->handle, PBM_SETPOS, p, 0);
+}
+
static LRESULT WINAPI event_handler(HWND wnd, unsigned int msg, WPARAM wparam, LPARAM lparam)
{
int ncode;
switch(msg) {
case WM_CLOSE:
+ if(!win->cb_close || win->cb_close(win)) {
+ if(win) {
+ int quit = win->close_quit;
+ wgt_destroy_window(win);
+ memset(win, 0, sizeof *win);
+ win->close_quit = quit;
+ } else {
+ DestroyWindow(wnd);
+ }
+ }
+ break;
+
case WM_DESTROY:
- PostQuitMessage(0);
+ if(win && win->close_quit) {
+ PostQuitMessage(0);
+ }
break;
case WM_COMMAND: