#include "alfpriv.h" static void ALF_Layout_CalcSizes(ALFLayout *layout, HWND window); static void ALF_Layout_EnsureRowExists(ALFLayout *layout, int rowno); static void ALF_Layout_EnsureColumnExists(ALFLayout *layout, int colno); static BOOL ALF_Layout_GetWidgetPos(ALFLayout *layout, HWND window, HWND needle, POINT *p); static BOOL ALF_Layout_SetWidgetPos(ALFLayout *layout, HWND window, HWND needle, POINT *p); static BOOL ALF_Layout_GetWidgetSize(ALFLayout *layout, HWND window, HWND needle, SIZE *s); static BOOL ALF_Layout_SetWidgetSize(ALFLayout *layout, HWND window, HWND needle, SIZE *s); static DWORD ALF_Layout_GetWidgetFlags(ALFLayout *layout, HWND window, HWND needle); static BOOL ALF_Layout_SetWidgetFlags(ALFLayout *layout, HWND window, HWND needle, DWORD flags); static int ALF_Layout_GetColumnSize(ALFLayout *layout, HWND window, int colno); static BOOL ALF_Layout_SetColumnSize(ALFLayout *layout, HWND window, int colno, int size); static int ALF_Layout_GetColumnExpand(ALFLayout *layout, HWND window, int colno); static BOOL ALF_Layout_SetColumnExpand(ALFLayout *layout, HWND window, int colno, int expand); static DWORD ALF_Layout_GetColumnFlags(ALFLayout *layout, HWND window, int colno); static BOOL ALF_Layout_SetColumnFlags(ALFLayout *layout, HWND window, int colno, DWORD flags); static int ALF_Layout_GetRowSize(ALFLayout *layout, HWND window, int rowno); static BOOL ALF_Layout_SetRowSize(ALFLayout *layout, HWND window, int rowno, int size); static int ALF_Layout_GetRowExpand(ALFLayout *layout, HWND window, int rowno); static BOOL ALF_Layout_SetRowExpand(ALFLayout *layout, HWND window, int rowno, int expand); static DWORD ALF_Layout_GetRowFlags(ALFLayout *layout, HWND window, int rowno); static BOOL ALF_Layout_SetRowFlags(ALFLayout *layout, HWND window, int rowno, DWORD flags); static void ALF_Layout_HandleBackgroundChange(ALFLayout *layout, HWND window); void ALF_Layout_Init(ALFLayout *layout) { ZeroMemory(layout, sizeof(*layout)); ALF_ListInit(&layout->widgets); layout->nRows = 1; layout->rows = ALF_New(ALFLayoutRowOrColumn, (SIZE_T)layout->nRows); layout->nColumns = 1; layout->columns = ALF_New(ALFLayoutRowOrColumn, (SIZE_T)layout->nColumns); layout->dpi = 96; layout->bgcolor = ALF_COLOR_TRANSPARENT; } void ALF_Layout_Clear(ALFLayout *layout) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { ALF_Free(w); } ALF_ListInit(&layout->widgets); ALF_Free(layout->columns); ALF_Free(layout->rows); layout->columns = NULL; layout->rows = NULL; layout->nColumns = 0; layout->nRows = 0; } static void ALF_Layout_ForwardFontToWidget(ALFLayout *layout, HWND window, ALFWidgetPriv *widget, HFONT font, LPARAM redraw) { if (widget->flags & ALF_LAYOUT_INHERITFONT) { SendMessage(widget->hwnd, WM_SETFONT, (WPARAM)font, redraw); switch (widget->flags & ALF_LAYOUT_SIZETYPE_MASK) { case ALF_LAYOUT_SIZE_EDIT: case ALF_LAYOUT_SIZE_CHECKBOX: ALF_Layout_Invalidate(layout, window); break; default: // do nothing break; } } } static void ALF_Layout_ForwardFont(ALFLayout *layout, HWND window, HFONT font, LPARAM redraw) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, i) { ALF_Layout_ForwardFontToWidget(layout, window, i, font, redraw); } } static void ALF_Layout_ForwardBgColor(ALFLayout *layout, HWND window, WPARAM wparam, LPARAM lparam) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, i) { if (i->flags & ALF_LAYOUT_INHERITBGCOLOR) { SendMessage(i->hwnd, ALF_WM_SETBGCOLOR, wparam, lparam); } } } static void ALF_Layout_ForwardDpiChange(ALFLayout *layout, HWND window, WPARAM wparam, LPARAM lparam) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, i) { if (i->flags & ALF_LAYOUT_SENDDPICHANGE) { SendMessage(i->hwnd, ALF_WM_DPICHANGE, wparam, lparam); } if (i->flags & ALF_LAYOUT_SIZE_EDIT) { ALF_Layout_Invalidate(layout, window); } } } static void ALF_Layout_HandleBackgroundChange(ALFLayout *layout, HWND window) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, i) { if (i->flags & ALF_LAYOUT_TRANSPARENTBG) { InvalidateRect(i->hwnd, NULL, TRUE); } if (i->flags & ALF_LAYOUT_SENDBGCHANGE) { ALF_InvalidateBackground(i->hwnd); } } } void ALF_Layout_EnsureRowExists(ALFLayout *layout, int rowno) { while (rowno >= layout->nRows) { layout->nRows *= 2; layout->rows = ALF_ReNew(layout->rows, ALFLayoutRowOrColumn, (SIZE_T)layout->nRows); } } void ALF_Layout_EnsureColumnExists(ALFLayout *layout, int colno) { while (colno >= layout->nColumns) { layout->nColumns *= 2; layout->columns = ALF_ReNew(layout->columns, ALFLayoutRowOrColumn, (SIZE_T)layout->nColumns); } } static void ALF_Layout_CalcEditSize(HWND hwndWindow, ALFLayout *layout, HWND hwndEdit, SIZE *ps) { (void)hwndWindow; HDC hDc = GetDC(hwndEdit); HFONT font = (HFONT)SendMessage(hwndEdit, WM_GETFONT, 0, 0); HFONT oldfont = SelectFont(hDc, font); TEXTMETRIC tm; ZeroMemory(&tm, sizeof(tm)); if (GetTextMetrics(hDc, &tm)) { int cy = tm.tmHeight + 2*ALF_Compat_GetSystemMetricsForDpi( SM_CYEDGE, (UINT)layout->dpi) + 4 /* padding internal to the edit control */; if (ps->cy < cy) ps->cy = cy; } SelectFont(hDc, oldfont); ReleaseDC(hwndEdit, hDc); } static void ALF_Layout_CalcCheckboxSize(HWND hwndWindow, ALFLayout *layout, HWND hwndCheckbox, SIZE *ps) { (void)hwndWindow; int checkwidth = 12 * layout->dpi / 96 + 1; HDC hDC = GetDC(hwndCheckbox); HFONT font = (HFONT)SendMessage(hwndCheckbox, WM_GETFONT, 0, 0); HFONT oldfont = SelectFont(hDC, font); RECT r = { 0, 0, 10, 10 }; TCHAR *textbuf = ALF_Text(hwndCheckbox); DrawText(hDC, textbuf, -1, &r, DT_CALCRECT); ALF_Free(textbuf); // lol int cx = 0; GetCharWidth(hDC, '0', '0', &cx); cx += checkwidth + r.right - r.left; int cy = r.bottom - r.top; if (checkwidth > cy) cy = checkwidth; if (ps->cx < cx) ps->cx = cx; if (ps->cy < cy) ps->cy = cy; SelectFont(hDC, oldfont); ReleaseDC(hwndCheckbox, hDC); } static void ALF_Layout_CalcMinWidgetSize(ALFLayout *layout, ALFWidgetPriv *c, HWND window, SIZE *s) { if (c->flags & ALF_LAYOUT_SIZE_PX) { s->cx = c->width; s->cy = c->height; } else { s->cx = ALF_CentipointsToPixels(c->width, layout->dpi); s->cy = ALF_CentipointsToPixels(c->height, layout->dpi); } switch (c->flags & ALF_LAYOUT_SIZETYPE_MASK) { case ALF_LAYOUT_SIZE_FIXED: // already done break; case ALF_LAYOUT_SIZE_QUERY: SendMessage(c->hwnd, ALF_WM_QUERYSIZE, 0, (LPARAM)s); break; case ALF_LAYOUT_SIZE_EDIT: ALF_Layout_CalcEditSize(window, layout, c->hwnd, s); break; case ALF_LAYOUT_SIZE_CHECKBOX: ALF_Layout_CalcCheckboxSize(window, layout, c->hwnd, s); break; default: // FIXME! unimplemented break; } } void ALF_Layout_CalcSizes(ALFLayout* layout, HWND window) { if (layout->beginCalcSizes) { layout->beginCalcSizes(layout, window); } layout->biggestColumnNo = 0; layout->columnExpandDenominator = 0; for (int i = 0; i < layout->nColumns; ++i) { if (layout->columns[i].requestedFlags & ALF_LAYOUT_SIZE_PX) { layout->columns[i].calculatedMinWidth = layout->columns[i].requestedMinWidth; } else { layout->columns[i].calculatedMinWidth = ALF_CentipointsToPixels(layout->columns[i].requestedMinWidth, layout->dpi); } layout->columns[i].calculatedExpandNumerator = layout->columns[i].requestedExpandNumerator; layout->columnExpandDenominator += layout->columns[i].requestedExpandNumerator; if (layout->columns[i].requestedExpandNumerator >= layout->columns[layout->biggestColumnNo].requestedExpandNumerator) layout->biggestColumnNo = i; } layout->biggestRowNo = 0; layout->rowExpandDenominator = 0; for (int i = 0; i < layout->nRows; ++i) { if (layout->rows[i].requestedFlags & ALF_LAYOUT_SIZE_PX) { layout->rows[i].calculatedMinWidth = layout->rows[i].requestedMinWidth; } else { layout->rows[i].calculatedMinWidth = ALF_CentipointsToPixels(layout->rows[i].requestedMinWidth, layout->dpi); } layout->rows[i].calculatedExpandNumerator = layout->rows[i].requestedExpandNumerator; layout->rowExpandDenominator += layout->rows[i].requestedExpandNumerator; if (layout->rows[i].requestedExpandNumerator >= layout->rows[layout->biggestRowNo].requestedExpandNumerator) layout->biggestRowNo = i; } ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, c) { int col = c->x; // TODO: skip spanning cells int row = c->y; SIZE qs = { 0, 0 }; ALF_Layout_CalcMinWidgetSize(layout, c, window, &qs); if (col < 0 || row < 0) { if (layout->handleContainerWidgetSize) layout->handleContainerWidgetSize(layout, window, c->hwnd, &qs); } else { ALF_Layout_EnsureColumnExists(layout, col); ALF_Layout_EnsureRowExists(layout, row); if (qs.cx > layout->columns[col].calculatedMinWidth) layout->columns[col].calculatedMinWidth = qs.cx; if (qs.cy > layout->rows[row].calculatedMinWidth) layout->rows[row].calculatedMinWidth = qs.cy; } } // TODO: second pass for spanning cells // total minimum bookkeeping layout->totalMinWidth = 0; for (int i = 0; i < layout->nColumns; ++i) { layout->totalMinWidth += layout->columns[i].calculatedMinWidth; } layout->totalMinHeight = 0; for (int i = 0; i < layout->nRows; ++i) { layout->totalMinHeight += layout->rows[i].calculatedMinWidth; } // expando bookkeeping if no expand numerators specified if (layout->columnExpandDenominator == 0) { for (int i = 0; i < layout->nColumns; ++i) { if (layout->columns[i].calculatedMinWidth > 0) { layout->columnExpandDenominator += 1; layout->columns[i].calculatedExpandNumerator = 1; layout->biggestColumnNo = i; } } // all columns empty? expand first one then if (layout->columnExpandDenominator == 0) { layout->columnExpandDenominator = 1; layout->columns[0].calculatedExpandNumerator = 1; layout->biggestColumnNo = 0; } } if (layout->rowExpandDenominator == 0) { for (int i = 0; i < layout->nRows; ++i) { if (layout->rows[i].calculatedMinWidth > 0) { layout->rowExpandDenominator += 1; layout->rows[i].calculatedExpandNumerator = 1; layout->biggestRowNo = i; } } // all rows empty? expand first one then if (layout->rowExpandDenominator == 0) { layout->rowExpandDenominator = 1; layout->rows[0].calculatedExpandNumerator = 1; layout->biggestRowNo = 0; } } SIZE containerMinSize = { 0,0 }; if (layout->endCalcSizes) layout->endCalcSizes(layout, window, &containerMinSize); if (layout->totalMinWidth < containerMinSize.cx - layout->containerMargins.left - layout->containerMargins.right) layout->totalMinWidth = containerMinSize.cx - layout->containerMargins.left - layout->containerMargins.right; if (layout->totalMinHeight < containerMinSize.cy - layout->containerMargins.top - layout->containerMargins.bottom) layout->totalMinHeight = containerMinSize.cy - layout->containerMargins.top - layout->containerMargins.bottom; layout->layoutValididityFlags &= ~ALF_LAYOUT_NEED_RECALC; } void ALF_Layout_Apply(ALFLayout* layout, HWND window) { if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) ALF_Layout_CalcSizes(layout, window); GetClientRect(window, &layout->allocatedWidgetRect); layout->allocatedWidgetRect.left += layout->containerMargins.left; layout->allocatedWidgetRect.right -= layout->containerMargins.right; layout->allocatedWidgetRect.top += layout->containerMargins.top; layout->allocatedWidgetRect.bottom -= layout->containerMargins.bottom; // FIXME! can that happen? if (layout->allocatedWidgetRect.right < layout->allocatedWidgetRect.left) layout->allocatedWidgetRect.right = layout->allocatedWidgetRect.left; if (layout->allocatedWidgetRect.bottom < layout->allocatedWidgetRect.top) layout->allocatedWidgetRect.bottom = layout->allocatedWidgetRect.top; // distribute extra space int extraWidth = 0; int extraHeight = 0; if (layout->allocatedWidgetRect.right - layout->allocatedWidgetRect.left > layout->totalMinWidth) extraWidth = layout->allocatedWidgetRect.right - layout->allocatedWidgetRect.left - layout->totalMinWidth; if (layout->allocatedWidgetRect.bottom - layout->allocatedWidgetRect.top > layout->totalMinHeight) extraHeight = layout->allocatedWidgetRect.bottom - layout->allocatedWidgetRect.top - layout->totalMinHeight; int extraWidthLeft = extraWidth; for (int i = 0; i < layout->nColumns; ++i) { if (i == layout->biggestColumnNo) continue; int extraHere = MulDiv(extraWidth, layout->columns[i].calculatedExpandNumerator, layout->columnExpandDenominator); if (extraHere > extraWidthLeft) extraHere = extraWidthLeft; layout->columns[i].allocatedWidth = layout->columns[i].calculatedMinWidth + extraHere; extraWidthLeft -= extraHere; } layout->columns[layout->biggestColumnNo].allocatedWidth = layout->columns[layout->biggestColumnNo].calculatedMinWidth + extraWidthLeft; int extraHeightLeft = extraHeight; for (int i = 0; i < layout->nRows; ++i) { if (i == layout->biggestRowNo) continue; int extraHere = MulDiv(extraHeight, layout->rows[i].calculatedExpandNumerator, layout->rowExpandDenominator); if (extraHere > extraHeightLeft) extraHere = extraHeightLeft; layout->rows[i].allocatedWidth = layout->rows[i].calculatedMinWidth + extraHere; extraHeightLeft -= extraHere; } layout->rows[layout->biggestRowNo].allocatedWidth = layout->rows[layout->biggestRowNo].calculatedMinWidth + extraHeightLeft; // set row/column positions int x = layout->allocatedWidgetRect.left; for (int i = 0; i < layout->nColumns; ++i) { layout->columns[i].allocatedPosition = x; x += layout->columns[i].allocatedWidth; } int y = layout->allocatedWidgetRect.top; for (int i = 0; i < layout->nRows; ++i) { layout->rows[i].allocatedPosition = y; y += layout->rows[i].allocatedWidth; } // now apply positions to widgets HDWP hdwp = BeginDeferWindowPos(layout->nColumns * layout->nRows); ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, c) { int col = c->x; int row = c->y; if (col >= layout->nColumns || row >= layout->nRows) continue; // FIXME: wat? RECT r = { 0,0,0,0 }; if (row < 0 || col < 0) { if (layout->preApplyLayoutToContainerWidget) layout->preApplyLayoutToContainerWidget(layout, window, c->hwnd, &r); } else { r.left = layout->columns[col].allocatedPosition; r.right = r.left + layout->columns[col].allocatedWidth; r.top = layout->rows[row].allocatedPosition; r.bottom = r.top + layout->rows[row].allocatedWidth; } if (c->flags & ALF_LAYOUT_CUSTOMPOS) { hdwp = (HDWP)SendMessage(c->hwnd, ALF_WM_APPLYSIZE, (WPARAM)hdwp, (LPARAM)&r); } else { UINT flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER; // NT 3.51 and Win32s have so many invalidation bugs it's not even funny if (!ALF_Compat_IsMinWindowsVersion(4, 0)) flags |= SWP_NOCOPYBITS; // transparent background: invalidate if widget moved if (layout->bgcolor == ALF_COLOR_TRANSPARENT) { RECT oldR; GetWindowRect(c->hwnd, &oldR); MapWindowRect(NULL, window, &oldR); if (oldR.left != r.left || oldR.top != r.top) { if (c->flags & ALF_LAYOUT_SENDBGCHANGE) { ALF_InvalidateBackground(c->hwnd); } if (c->flags & ALF_LAYOUT_TRANSPARENTBG) { flags |= SWP_NOCOPYBITS; } } } hdwp = DeferWindowPos(hdwp, c->hwnd, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, flags); } } EndDeferWindowPos(hdwp); layout->layoutValididityFlags &= ~ALF_LAYOUT_NEED_REAPPLY; } void ALF_Layout_AddWidget(ALFLayout* layout, HWND window, const ALFAddWidgetParams* params) { ALFWidgetPriv *w = ALF_New(ALFWidgetPriv, 1); w->hwnd = params->hwnd; w->x = params->x; w->y = params->y; w->width = params->width; w->height = params->height; w->flags = params->flags; if (GetParent(w->hwnd) != window) SetParent(w->hwnd, window); if (w->flags & ALF_LAYOUT_INHERITFONT) { ALF_Layout_ForwardFontToWidget(layout, window, w, layout->font, 0); } if (w->flags & ALF_LAYOUT_INHERITBGCOLOR) { SendMessage(w->hwnd, ALF_WM_SETBGCOLOR, 0, (LPARAM)layout->bgcolor); } if (w->flags & ALF_LAYOUT_SENDDPICHANGE) { SendMessage(w->hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)layout->dpi); } ALF_ListInsert(layout->widgets.prev, &w->list); ALF_Layout_Invalidate(layout, window); } HWND ALF_Layout_WidgetAtPos(ALFLayout* layout, int x, int y) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->x == x && w->y == y) { return w->hwnd; } } return NULL; } void ALF_Layout_Invalidate(ALFLayout *layout, HWND window) { if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) return; layout->layoutValididityFlags |= ALF_LAYOUT_NEED_RECALC | ALF_LAYOUT_NEED_REAPPLY; HWND parent = GetParent(window); if (parent) { ALF_InvalidateLayout(parent); } PostMessage(window, ALF_WM_VALIDATELAYOUT, 0, 0); } BOOL ALF_Layout_Validate(ALFLayout *layout, HWND window) { BOOL ret = FALSE; if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) { ALF_Layout_CalcSizes(layout, window); ret = TRUE; } if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_REAPPLY) { ALF_Layout_Apply(layout, window); ret = TRUE; } return ret; } void ALF_Layout_GetMinSize(ALFLayout *layout, HWND window, SIZE *size) { if (layout->layoutValididityFlags & ALF_LAYOUT_NEED_RECALC) { ALF_Layout_CalcSizes(layout, window); } size->cx = layout->totalMinWidth + layout->containerMargins.left + layout->containerMargins.right; size->cy = layout->totalMinHeight + layout->containerMargins.top + layout->containerMargins.bottom; } BOOL ALF_Layout_GetWidgetPos(ALFLayout *layout, HWND window, HWND needle, POINT *p) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { p->x = w->x; p->y = w->y; return TRUE; } } return FALSE; } static BOOL ALF_Layout_SetWidgetPos(ALFLayout *layout, HWND window, HWND needle, POINT *p) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { w->x = p->x; w->y = p->y; ALF_Layout_Invalidate(layout, window); return TRUE; } } return FALSE; } static BOOL ALF_Layout_GetWidgetSize(ALFLayout *layout, HWND window, HWND needle, SIZE *s) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { s->cx = w->width; s->cy = w->height; return TRUE; } } return FALSE; } static BOOL ALF_Layout_SetWidgetSize(ALFLayout *layout, HWND window, HWND needle, SIZE *s) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { w->width = s->cx; w->height = s->cy; ALF_Layout_Invalidate(layout, window); return TRUE; } } return FALSE; } static DWORD ALF_Layout_GetWidgetFlags(ALFLayout *layout, HWND window, HWND needle) { (void)window; ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { return w->flags; } } return 0; } static BOOL ALF_Layout_SetWidgetFlags(ALFLayout *layout, HWND window, HWND needle, DWORD flags) { ALF_FOR_LIST(ALFWidgetPriv, list, &layout->widgets, w) { if (w->hwnd == needle) { w->flags = flags; if (flags & ALF_LAYOUT_INHERITFONT) ALF_Layout_ForwardFontToWidget(layout, window, w, layout->font, 0); if (flags & ALF_LAYOUT_INHERITBGCOLOR) SendMessage(w->hwnd, ALF_WM_SETBGCOLOR, 0, (LPARAM)layout->bgcolor); if (flags & ALF_LAYOUT_SENDDPICHANGE) SendMessage(w->hwnd, ALF_WM_DPICHANGE, 0, (LPARAM)layout->dpi); ALF_Layout_Invalidate(layout, window); return TRUE; } } return FALSE; } int ALF_Layout_GetColumnSize(ALFLayout *layout, HWND window, int colno) { (void)window; if (colno >= layout->nColumns) return 0; return layout->columns[colno].requestedMinWidth; } BOOL ALF_Layout_SetColumnSize(ALFLayout *layout, HWND window, int colno, int size) { ALF_Layout_EnsureColumnExists(layout, colno); layout->columns[colno].requestedMinWidth = size; ALF_Layout_Invalidate(layout, window); return TRUE; } int ALF_Layout_GetColumnExpand(ALFLayout *layout, HWND window, int colno) { (void)window; if (colno >= layout->nColumns) return 0; return layout->columns[colno].requestedExpandNumerator; } static BOOL ALF_Layout_SetColumnExpand(ALFLayout *layout, HWND window, int colno, int expand) { ALF_Layout_EnsureColumnExists(layout, colno); layout->columns[colno].requestedExpandNumerator = expand; ALF_Layout_Invalidate(layout, window); return TRUE; } static DWORD ALF_Layout_GetColumnFlags(ALFLayout *layout, HWND window, int colno) { (void)window; if (colno >= layout->nColumns) return 0; return layout->columns[colno].requestedFlags; } static BOOL ALF_Layout_SetColumnFlags(ALFLayout *layout, HWND window, int colno, DWORD flags) { ALF_Layout_EnsureColumnExists(layout, colno); layout->columns[colno].requestedFlags = flags; ALF_Layout_Invalidate(layout, window); return TRUE; } static int ALF_Layout_GetRowSize(ALFLayout *layout, HWND window, int rowno) { (void)window; if (rowno >= layout->nRows) return 0; return layout->rows[rowno].requestedMinWidth; } static BOOL ALF_Layout_SetRowSize(ALFLayout *layout, HWND window, int rowno, int size) { ALF_Layout_EnsureRowExists(layout, rowno); layout->rows[rowno].requestedMinWidth = size; ALF_Layout_Invalidate(layout, window); return TRUE; } static int ALF_Layout_GetRowExpand(ALFLayout *layout, HWND window, int rowno) { (void)window; if (rowno >= layout->nRows) return 0; return layout->rows[rowno].requestedExpandNumerator; } static BOOL ALF_Layout_SetRowExpand(ALFLayout *layout, HWND window, int rowno, int expand) { ALF_Layout_EnsureRowExists(layout, rowno); layout->rows[rowno].requestedExpandNumerator = expand; ALF_Layout_Invalidate(layout, window); return TRUE; } static DWORD ALF_Layout_GetRowFlags(ALFLayout *layout, HWND window, int rowno) { (void)window; if (rowno >= layout->nRows) return 0; return layout->rows[rowno].requestedFlags; } static BOOL ALF_Layout_SetRowFlags(ALFLayout *layout, HWND window, int rowno, DWORD flags) { ALF_Layout_EnsureRowExists(layout, rowno); layout->rows[rowno].requestedFlags = flags; ALF_Layout_Invalidate(layout, window); return TRUE; } BOOL ALF_Layout_HandleMessage(ALFLayout *layout, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT *pRet) { *pRet = 0; if (msg == ALF_WM_QUERYSIZE) { SIZE s = { 0, 0 }; ALF_Layout_GetMinSize(layout, hwnd, &s); if (((SIZE*)lparam)->cx < s.cx) ((SIZE*)lparam)->cx = s.cx; if (((SIZE*)lparam)->cy < s.cy) ((SIZE*)lparam)->cy = s.cy; return TRUE; } if (msg == ALF_WM_APPLYLAYOUT) { ALF_Layout_Apply(layout, hwnd); return TRUE; } if (msg == ALF_WM_ADDWIDGET) { ALF_Layout_AddWidget(layout, hwnd, (ALFAddWidgetParams *)lparam); return TRUE; } if (msg == ALF_WM_GETWIDGETATPOS) { *pRet = (LRESULT)ALF_Layout_WidgetAtPos(layout, ((int*)lparam)[0], ((int*)lparam)[1]); return TRUE; } if (msg == WM_SETFONT) { *pRet = 1; if (layout->font == (HFONT)wparam) return TRUE; layout->font = (HFONT)wparam; ALF_Layout_ForwardFont(layout, hwnd, (HFONT)wparam, lparam); return TRUE; } if (msg == WM_GETFONT) { *pRet = (LRESULT)layout->font; return TRUE; } if (msg == ALF_WM_SETBGCOLOR) { *pRet = 1; if (layout->bgcolor == (ALFColor)lparam) return TRUE; layout->bgcolor = (ALFColor)lparam; ALF_Layout_ForwardBgColor(layout, hwnd, wparam, lparam); ALF_Layout_HandleBackgroundChange(layout, hwnd); InvalidateRect(hwnd, NULL, TRUE); return TRUE; } if (msg == ALF_WM_GETBGCOLOR) { *pRet = (LRESULT)layout->bgcolor; return TRUE; } if (msg == ALF_WM_BACKGROUNDCHANGE) { if (layout->bgcolor != ALF_COLOR_TRANSPARENT) return TRUE; // solid bg -> nothing to do InvalidateRect(hwnd, NULL, TRUE); ALF_Layout_HandleBackgroundChange(layout, hwnd); return TRUE; } if (msg == ALF_WM_DPICHANGE) { int dpi = (int)lparam; if (dpi != layout->dpi) { layout->dpi = dpi; ALF_Layout_ForwardDpiChange(layout, hwnd, wparam, lparam); ALF_Layout_Invalidate(layout, hwnd); } return TRUE; } if (msg == ALF_WM_GETDPI) { *pRet = (LRESULT)layout->dpi; return TRUE; } if (msg == ALF_WM_INVALIDATELAYOUT) { ALF_Layout_Invalidate(layout, hwnd); return TRUE; } if (msg == ALF_WM_VALIDATELAYOUT) { ALF_Layout_Validate(layout, hwnd); return TRUE; } if (msg == ALF_WM_LYT_GETWIDGETPOS) { *pRet = (LRESULT)ALF_Layout_GetWidgetPos(layout, hwnd, (HWND)wparam, (POINT *)lparam); return TRUE; } if (msg == ALF_WM_LYT_SETWIDGETPOS) { *pRet = (LRESULT)ALF_Layout_SetWidgetPos(layout, hwnd, (HWND)wparam, (POINT *)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETWIDGTSIZE) { *pRet = (LRESULT)ALF_Layout_GetWidgetSize(layout, hwnd, (HWND)wparam, (SIZE *)lparam); return TRUE; } if (msg == ALF_WM_LYT_SETWIDGTSIZE) { *pRet = (LRESULT)ALF_Layout_SetWidgetSize(layout, hwnd, (HWND)wparam, (SIZE *)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETWDGTFLAGS) { *pRet = (LRESULT)ALF_Layout_GetWidgetFlags(layout, hwnd, (HWND)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETWDGTFLAGS) { *pRet = (LRESULT)ALF_Layout_SetWidgetFlags(layout, hwnd, (HWND)wparam, (DWORD)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETCOLSIZE) { *pRet = (LRESULT)ALF_Layout_GetColumnSize(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETCOLSIZE) { *pRet = (LRESULT)ALF_Layout_SetColumnSize(layout, hwnd, (int)wparam, (int)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETCOLEXPAND) { *pRet = (LRESULT)ALF_Layout_GetColumnExpand(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETCOLEXPAND) { *pRet = (LRESULT)ALF_Layout_SetColumnExpand(layout, hwnd, (int)wparam, (int)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETCOLFLAGS) { *pRet = (LRESULT)ALF_Layout_GetColumnFlags(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETCOLFLAGS) { *pRet = (LRESULT)ALF_Layout_SetColumnFlags(layout, hwnd, (int)wparam, (DWORD)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETROWSIZE) { *pRet = (LRESULT)ALF_Layout_GetRowSize(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETROWSIZE) { *pRet = (LRESULT)ALF_Layout_SetRowSize(layout, hwnd, (int)wparam, (int)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETROWEXPAND) { *pRet = (LRESULT)ALF_Layout_GetRowExpand(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETROWEXPAND) { *pRet = (LRESULT)ALF_Layout_SetRowExpand(layout, hwnd, (int)wparam, (int)lparam); return TRUE; } if (msg == ALF_WM_LYT_GETROWFLAGS) { *pRet = (LRESULT)ALF_Layout_GetRowFlags(layout, hwnd, (int)wparam); return TRUE; } if (msg == ALF_WM_LYT_SETROWFLAGS) { *pRet = (LRESULT)ALF_Layout_SetRowFlags(layout, hwnd, (int)wparam, (DWORD)lparam); return TRUE; } return FALSE; }