diff --git a/redo/windows/control.c b/redo/windows/control.c index f5e2e75f..188e16d6 100644 --- a/redo/windows/control.c +++ b/redo/windows/control.c @@ -4,8 +4,6 @@ struct singleHWND { uiControl *c; HWND hwnd; - BOOL (*onWM_NOTIFY)(uiControl *, NMHDR *, LRESULT *); - BOOL (*onWM_HSCROLL)(uiControl *, WORD, LRESULT *); void (*onDestroy)(void *); void *onDestroyData; }; @@ -16,6 +14,8 @@ void osSingleDestroy(void *internal) (*(s->onDestroy))(s->onDestroyData); uiWindowsUnregisterWM_COMMANDHandler(s->hwnd); + uiWindowsUnregisterWM_NOTIFYHandler(s->hwnd); + uiWindowsUnregisterWM_HSCROLLHandler(s->hwnd); if (DestroyWindow(s->hwnd) == 0) logLastError("error destroying control in singleDestroy()"); uiFree(s); @@ -104,28 +104,6 @@ static int singleStartZOrder(uiControl *c, uiControlSysFuncParams *p) return 0; } -static LRESULT CALLBACK singleSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - struct singleHWND *s = (struct singleHWND *) dwRefData; - LRESULT lResult; - - switch (uMsg) { - case msgNOTIFY: - if ((*(s->onWM_NOTIFY))(s->c, (NMHDR *) lParam, &lResult) != FALSE) - return lResult; - break; - case msgHSCROLL: - if ((*(s->onWM_HSCROLL))(s->c, LOWORD(wParam), &lResult) != FALSE) - return lResult; - break; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, singleSubclassProc, uIdSubclass) == FALSE) - logLastError("error removing Windows control subclass in singleSubclassProc()"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p) { struct singleHWND *s; @@ -143,8 +121,8 @@ void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p) logLastError("error creating control in uiWindowsMakeControl()"); uiWindowsRegisterWM_COMMANDHandler(s->hwnd, p->onWM_COMMAND, uiControl(c)); - s->onWM_NOTIFY = p->onWM_NOTIFY; - s->onWM_HSCROLL = p->onWM_HSCROLL; + uiWindowsRegisterWM_NOTIFYHandler(s->hwnd, p->onWM_NOTIFY, uiControl(c)); + uiWindowsRegisterWM_HSCROLLHandler(s->hwnd, p->onWM_HSCROLL, uiControl(c)); s->onDestroy = p->onDestroy; s->onDestroyData = p->onDestroyData; @@ -152,10 +130,6 @@ void uiWindowsMakeControl(uiControl *c, uiWindowsMakeControlParams *p) if (p->useStandardControlFont) SendMessageW(s->hwnd, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE); - // this handles redirected notification messages - if (SetWindowSubclass(s->hwnd, singleSubclassProc, 0, (DWORD_PTR) s) == FALSE) - logLastError("error subclassing Windows control in uiWindowsMakeControl()"); - makeControl(uiControl(c), s); // PreferredSize() implemented by the individual controls diff --git a/redo/windows/events.c b/redo/windows/events.c index c71f0013..24e618ba 100644 --- a/redo/windows/events.c +++ b/redo/windows/events.c @@ -28,44 +28,59 @@ struct commandHandler *commandHandlers = NULL; struct notifyHandler *notifyHandlers = NULL; struct hscrollHandler *hscrollHandlers = NULL; -void uiWindowsRegisterWM_COMMANDHandler(HWND hwnd, BOOL (*handler)(uiControl *, WORD, LRESULT *), uiControl *c) -{ - struct commandHandler *ch; - - HASH_FIND_PTR(commandHandlers, &hwnd, ch); - if (ch != NULL) - complain("window handle %p already subscribed to receive WM_COMMANDs in uiWindowsRegisterWM_COMMANDHandler()", hwnd); - ch = uiNew(struct commandHandler); - ch->hwnd = hwnd; - ch->handler = handler; - ch->c = c; - HASH_ADD_PTR(commandHandlers, hwnd, ch); -} - -void uiWindowsUnregisterWM_COMMANDHandler(HWND hwnd) -{ - struct commandHandler *ch; - - HASH_FIND_PTR(commandHandlers, &hwnd, ch); - if (ch == NULL) - complain("window handle %p not registered with a WM_COMMAND handler in uiWindowsUnregisterWM_COMMANDHandler()", hwnd); - HASH_DEL(commandHandlers, ch); - uiFree(ch); -} - -BOOL runWM_COMMAND(WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - HWND control; - struct commandHandler *ch; - - // 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) { - HASH_FIND_PTR(commandHandlers, &control, ch); - if (ch != NULL) - return (*(ch->handler))(ch->c, HIWORD(wParam), lResult); - // not registered; fall out to return FALSE +#define REGFN(WM_MESSAGE, message, params) \ + void uiWindowsRegister ## WM_MESSAGE ## Handler(HWND hwnd, BOOL (*handler)params, uiControl *c) \ + { \ + struct message ## Handler *ch; \ + HASH_FIND_PTR(message ## Handlers, &hwnd, ch); \ + if (ch != NULL) \ + complain("window handle %p already subscribed with a %s handler in uiWindowsRegister%sHandler()", hwnd, #WM_MESSAGE, #WM_MESSAGE); \ + ch = uiNew(struct message ## Handler); \ + ch->hwnd = hwnd; \ + ch->handler = handler; \ + ch->c = c; \ + HASH_ADD_PTR(message ## Handlers, hwnd, ch); \ } - return FALSE; -} +REGFN(WM_COMMAND, command, (uiControl *, WORD, LRESULT *)) +REGFN(WM_NOTIFY, notify, (uiControl *, NMHDR *, LRESULT *)) +REGFN(WM_HSCROLL, hscroll, (uiControl *, WORD, LRESULT *)) + +#define UNREGFN(WM_MESSAGE, message) \ + void uiWindowsUnregister ## WM_MESSAGE ## Handler(HWND hwnd) \ + { \ + struct message ## Handler *ch; \ + HASH_FIND_PTR(message ## Handlers, &hwnd, ch); \ + if (ch == NULL) \ + complain("window handle %p not registered with a %s handler in uiWindowsUnregister%sHandler()", hwnd, #WM_MESSAGE, #WM_MESSAGE); \ + HASH_DEL(message ## Handlers, ch); \ + uiFree(ch); \ + } +UNREGFN(WM_COMMAND, command) +UNREGFN(WM_NOTIFY, notify) +UNREGFN(WM_HSCROLL, hscroll) + +#define RUNFN(WM_MESSAGE, message, gethwnd, arg2) \ + BOOL run ## WM_MESSAGE(WPARAM wParam, LPARAM lParam, LRESULT *lResult) \ + { \ + HWND control; \ + struct message ## Handler *ch;\ + /* 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 = gethwnd; \ + if (control != NULL && IsChild(utilWindow, control) == 0) { \ + HASH_FIND_PTR(message ## Handlers, &control, ch); \ + if (ch != NULL) \ + return (*(ch->handler))(ch->c, arg2, lResult); \ + /* not registered; fall out to return FALSE */ \ + } \ + return FALSE; \ + } +RUNFN(WM_COMMAND, command, + (HWND) lParam, + HIWORD(wParam)) +RUNFN(WM_NOTIFY, notify, + ((NMHDR *) lParam)->hwndFrom, + ((NMHDR *) lParam)) +RUNFN(WM_HSCROLL, hscroll, + (HWND) lParam, + LOWORD(wParam)) diff --git a/redo/windows/parent.c b/redo/windows/parent.c index 5a510b78..52db218a 100644 --- a/redo/windows/parent.c +++ b/redo/windows/parent.c @@ -113,21 +113,9 @@ BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LR case WM_COMMAND: return runWM_COMMAND(wParam, lParam, lResult); case WM_NOTIFY: - // same as WM_COMMAND - control = nm->hwndFrom; - if (control != NULL && IsChild(utilWindow, control) == 0) { - *lResult = SendMessageW(control, msgNOTIFY, wParam, lParam); - return TRUE; - } - break; + return runWM_NOTIFY(wParam, lParam, lResult); case WM_HSCROLL: - // same as WM_COMMAND - control = (HWND) lParam; - if (control != NULL && IsChild(utilWindow, control) == 0) { - *lResult = SendMessageW(control, msgHSCROLL, wParam, lParam); - return TRUE; - } - break; + return runWM_HSCROLL(wParam, lParam, lResult); case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: if (parentBrush != NULL) diff --git a/redo/windows/uipriv_windows.h b/redo/windows/uipriv_windows.h index 97de71b1..0c921f83 100644 --- a/redo/windows/uipriv_windows.h +++ b/redo/windows/uipriv_windows.h @@ -112,5 +112,11 @@ 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 uiWindowsRegisterWM_NOTIFYHandler(HWND, BOOL (*)(uiControl *, NMHDR *, LRESULT *), uiControl *); +extern void uiWindowsRegisterWM_HSCROLLHandler(HWND, BOOL (*)(uiControl *, WORD, LRESULT *), uiControl *); extern void uiWindowsUnregisterWM_COMMANDHandler(HWND); +extern void uiWindowsUnregisterWM_NOTIFYHandler(HWND); +extern void uiWindowsUnregisterWM_HSCROLLHandler(HWND); extern BOOL runWM_COMMAND(WPARAM, LPARAM, LRESULT *); +extern BOOL runWM_NOTIFY(WPARAM, LPARAM, LRESULT *); +extern BOOL runWM_HSCROLL(WPARAM, LPARAM, LRESULT *);