libui/windows/events.cpp

152 lines
4.2 KiB
C++

// 20 may 2015
#include "uipriv_windows.hpp"
struct handler {
BOOL (*commandHandler)(uiControl *, HWND, WORD, LRESULT *);
BOOL (*notifyHandler)(uiControl *, HWND, NMHDR *, LRESULT *);
BOOL (*hscrollHandler)(uiControl *, HWND, WORD, LRESULT *);
uiControl *c;
// just to ensure handlers[new HWND] initializes properly
// TODO gcc can't handle a struct keyword here? or is that a MSVC extension?
handler()
{
this->commandHandler = NULL;
this->notifyHandler = NULL;
this->hscrollHandler = NULL;
this->c = NULL;
}
};
static std::map<HWND, struct handler> handlers;
void uiWindowsRegisterWM_COMMANDHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c)
{
if (handlers[hwnd].commandHandler != NULL)
uiprivImplBug("already registered a WM_COMMAND handler to window handle %p", hwnd);
handlers[hwnd].commandHandler = handler;
handlers[hwnd].c = c;
}
void uiWindowsRegisterWM_NOTIFYHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, NMHDR *, LRESULT *), uiControl *c)
{
if (handlers[hwnd].notifyHandler != NULL)
uiprivImplBug("already registered a WM_NOTIFY handler to window handle %p", hwnd);
handlers[hwnd].notifyHandler = handler;
handlers[hwnd].c = c;
}
void uiWindowsRegisterWM_HSCROLLHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c)
{
if (handlers[hwnd].hscrollHandler != NULL)
uiprivImplBug("already registered a WM_HSCROLL handler to window handle %p", hwnd);
handlers[hwnd].hscrollHandler = handler;
handlers[hwnd].c = c;
}
void uiWindowsUnregisterWM_COMMANDHandler(HWND hwnd)
{
if (handlers[hwnd].commandHandler == NULL)
uiprivImplBug("window handle %p not registered to receive WM_COMMAND events", hwnd);
handlers[hwnd].commandHandler = NULL;
}
void uiWindowsUnregisterWM_NOTIFYHandler(HWND hwnd)
{
if (handlers[hwnd].notifyHandler == NULL)
uiprivImplBug("window handle %p not registered to receive WM_NOTIFY events", hwnd);
handlers[hwnd].notifyHandler = NULL;
}
void uiWindowsUnregisterWM_HSCROLLHandler(HWND hwnd)
{
if (handlers[hwnd].hscrollHandler == NULL)
uiprivImplBug("window handle %p not registered to receive WM_HSCROLL events", hwnd);
handlers[hwnd].hscrollHandler = NULL;
}
template<typename T>
static BOOL shouldRun(HWND hwnd, T method)
{
// not from a window
if (hwnd == NULL)
return FALSE;
// don't bounce back if to the utility window, in which case act as if the message was ignored
if (IsChild(utilWindow, hwnd) != 0)
return FALSE;
// registered?
return method != NULL;
}
BOOL runWM_COMMAND(WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
HWND hwnd;
WORD arg3;
BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *);
uiControl *c;
hwnd = (HWND) lParam;
arg3 = HIWORD(wParam);
handler = handlers[hwnd].commandHandler;
c = handlers[hwnd].c;
if (shouldRun(hwnd, handler))
return (*handler)(c, hwnd, arg3, lResult);
return FALSE;
}
BOOL runWM_NOTIFY(WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
HWND hwnd;
NMHDR *arg3;
BOOL (*handler)(uiControl *, HWND, NMHDR *, LRESULT *);
uiControl *c;
arg3 = (NMHDR *) lParam;
hwnd = arg3->hwndFrom;
handler = handlers[hwnd].notifyHandler;
c = handlers[hwnd].c;
if (shouldRun(hwnd, handler))
return (*handler)(c, hwnd, arg3, lResult);
return FALSE;
}
BOOL runWM_HSCROLL(WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
HWND hwnd;
WORD arg3;
BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *);
uiControl *c;
hwnd = (HWND) lParam;
arg3 = LOWORD(wParam);
handler = handlers[hwnd].hscrollHandler;
c = handlers[hwnd].c;
if (shouldRun(hwnd, handler))
return (*handler)(c, hwnd, arg3, lResult);
return FALSE;
}
static std::map<HWND, bool> wininichanges;
void uiWindowsRegisterReceiveWM_WININICHANGE(HWND hwnd)
{
if (wininichanges[hwnd])
uiprivImplBug("window handle %p already subscribed to receive WM_WINICHANGEs", hwnd);
wininichanges[hwnd] = true;
}
void uiWindowsUnregisterReceiveWM_WININICHANGE(HWND hwnd)
{
if (!wininichanges[hwnd])
uiprivImplBug("window handle %p not registered to receive WM_WININICHANGEs", hwnd);
wininichanges[hwnd] = false;
}
void issueWM_WININICHANGE(WPARAM wParam, LPARAM lParam)
{
struct wininichange *ch;
for (const auto &iter : wininichanges)
SendMessageW(iter.first, WM_WININICHANGE, wParam, lParam);
}