#include "alfpriv.h" #include static LONG _alf_initLock = 0; static LONG _alf_initCounter = 0; void ALF_UpdateFonts(HWND win) { SendMessage(win, ALF_WM_UPDATEFONTS, 0, 0); } void ALF_InvalidateLayout(HWND hwnd) { SendMessage(hwnd, ALF_WM_INVALIDATELAYOUT, 0, 0); } void ALF_AddWidget(HWND win, int x, int y, HWND widget, int minWidth, int minHeight, DWORD flags) { ALFAddWidgetParams params; ZeroMemory(¶ms, sizeof(params)); params.hwnd = widget; params.x = x; params.y = y; params.width = minWidth; params.height = minHeight; params.flags = flags; SendMessage(win, ALF_WM_ADDWIDGET, 0, (LPARAM)¶ms); } void ALF_Initialize(void) { // acquire init lock while (InterlockedExchange(&_alf_initLock, 1)) { Sleep(0); } // we have the lock! if (!_alf_initCounter++) { InitCommonControls(); ALF_LoadCompatFunctions(); ALF_RegisterWindowClass(); ALF_RegisterControlClass(); ALF_Compat_BufferedPaintInit(); } // release init lock InterlockedExchange(&_alf_initLock, 0); } void ALF_UnInitialize(void) { // acquire init lock while (InterlockedExchange(&_alf_initLock, 1)) { Sleep(0); } // we have the lock! if (!--_alf_initCounter) { ALF_Compat_BufferedPaintUnInit(); UnregisterClass(_alf_windowClass, ALF_HINSTANCE); UnregisterClass(_alf_controlClass, ALF_HINSTANCE); ALF_UnloadCompatFunctions(); } // release init lock InterlockedExchange(&_alf_initLock, 0); } void * ALF_Alloc(SIZE_T nmemb, SIZE_T size) { if (size && nmemb > (SIZE_T)-1 / size) RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, nmemb * size); } void * ALF_ReAlloc(void *ptr, SIZE_T nmemb, SIZE_T size) { if (size && nmemb > (SIZE_T)-1 / size) RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); if (ptr) return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS, ptr, nmemb * size); else return ALF_Alloc(nmemb, size); } void ALF_Free(const void *p) { HeapFree(GetProcessHeap(), 0, (void*)p); } void ALF_DestroyWindow(HWND win) { DestroyWindow(win); } int ALF_ShowModal(HWND win) { MSG msg; ALF_SetModalResult(win, 0); // TODO: disable parent window ShowWindow(win, SW_SHOW); while (GetMessage(&msg, NULL, 0, 0) > 0) { // TODO: call application message hooks // TODO: call preprocess message hook if (!IsDialogMessage(win, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } int mr = ALF_GetModalResult(win); if (mr) return mr; } return 0; } void ALF_SetModalResult(HWND win, int result) { SendMessage(win, ALF_WM_SETMODALRESULT, (WPARAM)result, 0); } int ALF_GetModalResult(HWND win) { return (int)SendMessage(win, ALF_WM_GETMODALRESULT, 0, 0); } int ALF_CentipointsToPixels(int cptValue, int dpi) { return MulDiv(cptValue, dpi, 7200); } int ALF_GetDpi(HWND window) { return (int)SendMessage(window, ALF_WM_GETDPI, 0, 0); } void ALF_ResizeWindow(HWND win, int cptWidth, int cptHeight) { int dpi = ALF_GetDpi(win); int pxwidth = ALF_CentipointsToPixels(cptWidth, dpi); int pxheight = ALF_CentipointsToPixels(cptHeight, dpi); ALF_ResizeWindowPx(win, pxwidth, pxheight); } void ALF_ResizeWindowPx(HWND win, int pxwidth, int pxheight) { MINMAXINFO tmp = { { 0, 0 }, { pxwidth, pxheight }, { 0, 0 }, { pxwidth, pxheight }, { pxwidth, pxheight } }; SendMessage(win, WM_GETMINMAXINFO, 0, (LPARAM)&tmp); if (tmp.ptMinTrackSize.x > pxwidth) pxwidth = tmp.ptMinTrackSize.x; if (tmp.ptMinTrackSize.y > pxheight) pxheight = tmp.ptMinTrackSize.y; SetWindowPos(win, NULL, 0, 0, pxwidth, pxheight, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER); } struct ALF_WidgetHwndById_Closure { HWND result; WORD needle; }; static BOOL CALLBACK ALF_WidgetHwndById_EnumChildProc(HWND hwnd, LPARAM lParam) { struct ALF_WidgetHwndById_Closure *closure = (struct ALF_WidgetHwndById_Closure*)lParam; if ((WORD)GetWindowLongPtr(hwnd, GWLP_ID) == closure->needle) { closure->result = hwnd; return FALSE; } return TRUE; } HWND ALF_WidgetHwndById(HWND win, WORD id) { struct ALF_WidgetHwndById_Closure closure = { 0, id }; EnumChildWindows(win, ALF_WidgetHwndById_EnumChildProc, (LPARAM)&closure); return closure.result; } void ALF_SetText(HWND hwnd, const TCHAR *text) { SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)text); } void ALF_SetWidgetText(HWND parent, WORD id, const TCHAR *text) { HWND h = ALF_WidgetHwndById(parent, id); if (h) ALF_SetText(h, text); } TCHAR * // free with ALF_Free ALF_Text(HWND hwnd) { int len = GetWindowTextLength(hwnd); if (len > 0) { TCHAR *buf = ALF_New(TCHAR, (SIZE_T)len+1); if (GetWindowText(hwnd, buf, len+1)) { return buf; } else { ALF_Free(buf); } } return ALF_New(TCHAR, 1); } TCHAR * // free with ALF_Free ALF_WidgetText(HWND parent, WORD id) { HWND h = ALF_WidgetHwndById(parent, id); if (h) return ALF_Text(h); return NULL; } DWORD ALF_WidgetLayoutFlags(HWND parent, HWND widget) { return (DWORD)SendMessage(parent, ALF_WM_LYT_GETWDGTFLAGS, (WPARAM)widget, 0); } BOOL ALF_SetWidgetLayoutFlags(HWND parent, HWND widget, DWORD flags) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETWDGTFLAGS, (WPARAM)widget, (LPARAM)flags); } BOOL ALF_WidgetLayoutPosition(HWND parent, HWND widget, int *pX, int *pY) { POINT p = { 0, 0 }; LRESULT r = SendMessage(parent, ALF_WM_LYT_GETWIDGETPOS, (WPARAM)widget, (LPARAM)&p); *pX = p.x; *pY = p.y; return (BOOL)r; } BOOL ALF_SetWidgetLayoutPosition(HWND parent, HWND widget, int x, int y) { POINT p = { x, y }; return (BOOL)SendMessage(parent, ALF_WM_LYT_SETWIDGETPOS, (WPARAM)widget, (LPARAM)&p); } BOOL ALF_WidgetLayoutSpan(HWND parent, HWND widget, int *pXspan, int *pYspan) { POINT p = { 0, 0 }; LRESULT r = SendMessage(parent, ALF_WM_LYT_GETWDGTSPAN, (WPARAM)widget, (LPARAM)&p); *pXspan = p.x; *pYspan = p.y; return (BOOL)r; } BOOL ALF_SetWidgetLayoutSpan(HWND parent, HWND widget, int xspan, int yspan) { POINT p = { xspan, yspan }; return (BOOL)SendMessage(parent, ALF_WM_LYT_SETWDGTSPAN, (WPARAM)widget, (LPARAM)&p); } BOOL ALF_WidgetLayoutMinSize(HWND parent, HWND widget, int *pWidth, int *pHeight) { SIZE s = { 0, 0 }; LRESULT r = SendMessage(parent, ALF_WM_LYT_GETWIDGTSIZE, (WPARAM)widget, (LPARAM)&s); *pWidth = s.cx; *pHeight = s.cy; return (BOOL)r; } BOOL ALF_SetWidgetLayoutMinSize(HWND parent, HWND widget, int width, int height) { SIZE s = { width, height }; return (BOOL)SendMessage(parent, ALF_WM_LYT_SETWIDGTSIZE, (WPARAM)widget, (LPARAM)&s); } HWND ALF_WidgetAtLayoutPosition(HWND parent, int x, int y) { int xy[2] = { x, y }; return (HWND)SendMessage(parent, ALF_WM_GETWIDGETATPOS, 0, (LPARAM)&xy); } int ALF_LayoutRowMinSize(HWND parent, int rowno) { return (int)SendMessage(parent, ALF_WM_LYT_GETROWSIZE, (WPARAM)rowno, 0); } BOOL ALF_LayoutSetRowMinSize(HWND parent, int rowno, int rowsize) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETROWSIZE, (WPARAM)rowno, (LPARAM)rowsize); } int ALF_LayoutColumnMinSize(HWND parent, int colno) { return (int)SendMessage(parent, ALF_WM_LYT_GETCOLSIZE, (WPARAM)colno, 0); } BOOL ALF_LayoutSetColumnMinSize(HWND parent, int colno, int colsize) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETCOLSIZE, (WPARAM)colno, (LPARAM)colsize); } DWORD ALF_LayoutRowFlags(HWND parent, int rowno) { return (DWORD)SendMessage(parent, ALF_WM_LYT_GETROWFLAGS, (WPARAM)rowno, 0); } BOOL ALF_LayoutSetRowFlags(HWND parent, int rowno, DWORD flags) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETROWFLAGS, (WPARAM)rowno, (LPARAM)flags); } DWORD ALF_LayoutColumnFlags(HWND parent, int colno) { return (DWORD)SendMessage(parent, ALF_WM_LYT_GETCOLFLAGS, (WPARAM)colno, 0); } BOOL ALF_LayoutSetColumnFlags(HWND parent, int colno, DWORD flags) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETCOLFLAGS, (WPARAM)colno, (LPARAM)flags); } int ALF_LayoutRowExpandNumerator(HWND parent, int rowno) { return (int)SendMessage(parent, ALF_WM_LYT_GETROWEXPAND, (WPARAM)rowno, 0); } BOOL ALF_LayoutSetRowExpandNumerator(HWND parent, int rowno, int expand) { return (BOOL)SendMessage(parent, ALF_WM_LYT_SETROWEXPAND, (WPARAM)rowno, (LPARAM)expand); } int ALF_LayoutColumnExpandNumerator(HWND parent, int colno) { return (int)SendMessage(parent, ALF_WM_LYT_GETCOLEXPAND, (WPARAM)colno, 0); } BOOL ALF_LayoutSetColumnExpandNumerator(HWND parent, int colno, int expand) { return (int)SendMessage(parent, ALF_WM_LYT_SETCOLEXPAND, (WPARAM)colno, (LPARAM)expand); } BOOL ALF_ShouldMessageBubble(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { (void)wparam; (void)lparam; if (!GetParent(hwnd)) return FALSE; return msg == ALF_WM_GETDPI || msg == WM_COMMAND || msg == WM_NOTIFY || msg == WM_MEASUREITEM || msg == WM_DRAWITEM || msg == WM_CTLCOLORBTN || msg == WM_CTLCOLOREDIT || msg == WM_CTLCOLORLISTBOX || msg == WM_CTLCOLORSCROLLBAR || msg == WM_CTLCOLORSTATIC || msg == WM_NEXTDLGCTL; } void ALF_FillRect(HDC dc, const RECT *rc, ALFColor color) { if (color == ALF_COLOR_TRANSPARENT) return; COLORREF gdicolor = ALF_ColorToGdi(color); COLORREF oldBkColor = SetBkColor(dc, gdicolor); ExtTextOut(dc, 0, 0, ETO_OPAQUE, rc, NULL, 0, NULL); SetBkColor(dc, oldBkColor); } COLORREF ALF_ColorToGdi(ALFColor color) { if (color == ALF_COLOR_TRANSPARENT) { return (COLORREF)-1; } else if (color & 0x80000000) { return GetSysColor((color & 0x7f000000) >> 24); } else { return (COLORREF)color; } } void ALF_InvalidateBackground(HWND win) { SendMessage(win, ALF_WM_BACKGROUNDCHANGE, 0, 0); } void ALF_SetBackgroundColor(HWND win, ALFColor color) { HWND parent = GetParent(win); if (parent) { ALF_RemoveWidgetLayoutFlag(parent, win, ALF_LAYOUT_INHERITBGCOLOR); } SendMessage(win, ALF_WM_SETBGCOLOR, 0, (LPARAM)color); } ALFColor ALF_BackgroundColor(HWND win) { return (ALFColor)SendMessage(win, ALF_WM_GETBGCOLOR, 0, 0); } ALFColor ALF_TextColor(HWND win) { return (ALFColor)SendMessage(win, ALF_WM_GETTEXTCOLOR, 0, 0); } void ALF_SetTextColor(HWND win, ALFColor color) { SendMessage(win, ALF_WM_SETTEXTCOLOR, 0, (LPARAM)color); } void ALF_SetFocus(HWND target) { if (GetWindowStyle(target) & WS_CHILD) SendMessage(GetParent(target), WM_NEXTDLGCTL, (WPARAM)target, TRUE); else SendMessage(target, WM_NEXTDLGCTL, (WPARAM)target, TRUE); }