Started a major overhaul of the control system on Windows. Events are now handled using registered handlers rather than having them be part of the singleHWND. This is needed for radio buttons. Right now, only WM_COMMAND has been modified as such.

This commit is contained in:
Pietro Gagliardi 2015-05-20 22:46:50 -04:00
parent 02c81c7b0d
commit 6a6ddc61f9
5 changed files with 90 additions and 14 deletions

View File

@ -9,6 +9,7 @@ osCFILES = \
windows/control.c \
windows/debug.c \
windows/entry.c \
windows/events.c \
windows/group.c \
windows/init.c \
windows/label.c \

View File

@ -4,7 +4,6 @@
struct singleHWND {
uiControl *c;
HWND hwnd;
BOOL (*onWM_COMMAND)(uiControl *, WORD, LRESULT *);
BOOL (*onWM_NOTIFY)(uiControl *, NMHDR *, LRESULT *);
BOOL (*onWM_HSCROLL)(uiControl *, WORD, LRESULT *);
void (*onDestroy)(void *);
@ -16,6 +15,7 @@ void osSingleDestroy(void *internal)
struct singleHWND *s = (struct singleHWND *) internal;
(*(s->onDestroy))(s->onDestroyData);
uiWindowsUnregisterWM_COMMANDHandler(s->hwnd);
if (DestroyWindow(s->hwnd) == 0)
logLastError("error destroying control in singleDestroy()");
uiFree(s);
@ -110,10 +110,6 @@ static LRESULT CALLBACK singleSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LRESULT lResult;
switch (uMsg) {
case msgCOMMAND:
if ((*(s->onWM_COMMAND))(s->c, HIWORD(wParam), &lResult) != FALSE)
return lResult;
break;
case msgNOTIFY:
if ((*(s->onWM_NOTIFY))(s->c, (NMHDR *) lParam, &lResult) != FALSE)
return lResult;
@ -145,7 +141,8 @@ void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p)
utilWindow, NULL, p->hInstance, p->lpParam);
if (s->hwnd == NULL)
logLastError("error creating control in uiWindowsMakeControl()");
s->onWM_COMMAND = p->onWM_COMMAND;
uiWindowsRegisterWM_COMMANDHandler(s->hwnd, p->onWM_COMMAND, uiControl(c));
s->onWM_NOTIFY = p->onWM_NOTIFY;
s->onWM_HSCROLL = p->onWM_HSCROLL;

79
redo/windows/events.c Normal file
View File

@ -0,0 +1,79 @@
// 20 may 2015
#include "uipriv_windows.h"
// TODO switch to uthash
struct commandHandler {
HWND hwnd;
BOOL (*handler)(uiControl *, WORD, LRESULT *);
uiControl *c;
};
struct notifyHandler {
HWND hwnd;
BOOL (*handler)(uiControl *, NMHDR *, LRESULT *);
uiControl *c;
};
struct hscrollHandler {
HWND hwnd;
BOOL (*handler)(uiControl *, WORD, LRESULT *);
uiControl *c;
};
struct ptrArray *commandHandlers = NULL;
struct ptrArray *notifyHandlers = NULL;
struct ptrArray *hscrollHandlers = NULL;
void uiWindowsRegisterWM_COMMANDHandler(HWND hwnd, BOOL (*handler)(uiControl *, WORD, LRESULT *), uiControl *c)
{
struct commandHandler *ch;
ch = uiNew(struct commandHandler);
ch->hwnd = hwnd;
ch->handler = handler;
ch->c = c;
if (commandHandlers == NULL)
commandHandlers = newPtrArray();
ptrArrayAppend(commandHandlers, ch);
}
void uiWindowsUnregisterWM_COMMANDHandler(HWND hwnd)
{
struct commandHandler *ch;
uintmax_t i;
for (i = 0; i < commandHandlers->len; i++) {
ch = ptrArrayIndex(commandHandlers, struct commandHandler *, i);
if (ch->hwnd == hwnd) {
ptrArrayDelete(commandHandlers, i);
uiFree(ch);
if (commandHandlers->len == 0) {
ptrArrayDestroy(commandHandlers);
commandHandlers = NULL;
}
return;
}
}
complain("window handle %p not registered with a WM_COMMAND handler in uiWindowsUnregisterWM_COMMANDHandler()", hwnd);
}
BOOL runWM_COMMAND(WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
HWND control;
struct commandHandler *ch;
uintmax_t i;
// bounce back to the control in question
// don't bounce back if to the utility window, in which case act as if the message was ignored
control = (HWND) lParam;
if (control != NULL && IsChild(utilWindow, control) == 0) {
for (i = 0; i < commandHandlers->len; i++) {
ch = ptrArrayIndex(commandHandlers, struct commandHandler *, i);
if (ch->hwnd == control)
return (*(ch->handler))(ch->c, HIWORD(wParam), lResult);
}
// not registered; fall out to return FALSE
}
return FALSE;
}

View File

@ -111,14 +111,7 @@ BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LR
switch (uMsg) {
case WM_COMMAND:
// bounce back to the control in question
// except if to the initial parent, in which case act as if the message was ignored
control = (HWND) lParam;
if (control != NULL && IsChild(utilWindow, control) == 0) {
*lResult = SendMessageW(control, msgCOMMAND, wParam, lParam);
return TRUE;
}
break;
return runWM_COMMAND(wParam, lParam, lResult);
case WM_NOTIFY:
// same as WM_COMMAND
control = nm->hwndFrom;

View File

@ -108,3 +108,9 @@ extern void uninitAlloc(void);
// tab.c
extern void tabEnterTabNavigation(HWND);
extern void tabLeaveTabNavigation(HWND);
// events.c
// TODO split the uiWindows ones to ui_windows.h
extern void uiWindowsRegisterWM_COMMANDHandler(HWND, BOOL (*)(uiControl *, WORD, LRESULT *), uiControl *);
extern void uiWindowsUnregisterWM_COMMANDHandler(HWND);
extern BOOL runWM_COMMAND(WPARAM, LPARAM, LRESULT *);