Start of refactoring of stuff into classes! It's spaghetti already~

This commit is contained in:
Pietro Gagliardi 2018-10-29 21:11:16 -04:00
parent c49151a4dc
commit 447dc24651
1 changed files with 232 additions and 140 deletions

View File

@ -34,6 +34,14 @@ void diehr(const char *func, HRESULT hr)
exit(EXIT_FAILURE);
}
// TODO if we merge this into libui proper, this will need to be deduplicated
static inline HRESULT lastErrorToHRESULT(DWORD lastError)
{
if (lastError == 0)
return E_FAIL;
return HRESULT_FROM_WIN32(lastError);
}
HINSTANCE hInstance;
HWND leftButtons[5];
HWND rightButtons[3];
@ -59,77 +67,87 @@ static struct {
{ L"New folder", FALSE },
};
// TODO check errors
void drawExplorerBackground(HTHEME theme, HDC dc, RECT *rcWindow, RECT *rcPaint)
{
COLORREF color;
TRIVERTEX vertices[4];
static GRADIENT_RECT gr[2] = {
{ 0, 1 },
{ 2, 3 },
class commandModuleStyleParams {
public:
virtual int partID_CMOD_MODULEBACKGROUND(void) const = 0;
virtual int partID_CMOD_TASKBUTTON(void) const = 0;
virtual int partID_CMOD_SPLITBUTTONLEFT(void) const = 0;
virtual int partID_CMOD_SPLITBUTTONRIGHT(void) const = 0;
virtual int partID_CMOD_MENUGLYPH(void) const = 0;
virtual int partID_CMOD_OVERFLOWGLYPH(void) const = 0;
virtual int stateID_CMODS_NORMAL(void) const = 0;
virtual int stateID_CMODS_HOT(void) const = 0;
virtual int stateID_CMODS_PRESSED(void) const = 0;
virtual int stateID_CMODS_KEYFOCUSED(void) const = 0;
virtual int stateID_CMODS_NEARHOT(void) const = 0;
virtual HRESULT backgroundGradientColors(HTHEME theme, COLORREF *colors) const = 0;
};
class commandModuleStyleParamsVista : public commandModuleStyleParams {
public:
virtual int partID_CMOD_MODULEBACKGROUND(void) const { return 1; }
virtual int partID_CMOD_TASKBUTTON(void) const { return 2; }
virtual int partID_CMOD_SPLITBUTTONLEFT(void) const { return 3; }
virtual int partID_CMOD_SPLITBUTTONRIGHT(void) const { return 4; }
virtual int partID_CMOD_MENUGLYPH(void) const { return 5; }
virtual int partID_CMOD_OVERFLOWGLYPH(void) const { return 6; }
virtual int stateID_CMODS_NORMAL(void) const { return 1; }
virtual int stateID_CMODS_HOT(void) const { return 2; }
virtual int stateID_CMODS_PRESSED(void) const { return 3; }
virtual int stateID_CMODS_KEYFOCUSED(void) const { return 4; }
virtual int stateID_CMODS_NEARHOT(void) const { return 5; }
virtual HRESULT backgroundGradientColors(HTHEME theme, COLORREF *colors) const
{
if (colors == NULL)
return E_POINTER;
#define argb(a, r, g, b) ((((COLORREF) ((BYTE) (a))) << 24) | RGB(r, g, b))
colors[0] = argb(255, 4, 80, 130);
colors[1] = argb(255, 17, 101, 132);
colors[2] = argb(255, 29, 121, 134);
#undef argb
return S_OK;
}
};
class commandModuleStyleParams7 : public commandModuleStyleParams {
virtual int partID_CMOD_MODULEBACKGROUND(void) const { return 1; }
virtual int partID_CMOD_TASKBUTTON(void) const { return 3; }
virtual int partID_CMOD_SPLITBUTTONLEFT(void) const { return 4; }
virtual int partID_CMOD_SPLITBUTTONRIGHT(void) const { return 5; }
virtual int partID_CMOD_MENUGLYPH(void) const { return 6; }
virtual int partID_CMOD_OVERFLOWGLYPH(void) const { return 7; }
virtual int stateID_CMODS_NORMAL(void) const { return 1; }
virtual int stateID_CMODS_HOT(void) const { return 2; }
virtual int stateID_CMODS_PRESSED(void) const { return 3; }
virtual int stateID_CMODS_KEYFOCUSED(void) const { return 4; }
/*TODO verify this*/virtual int stateID_CMODS_NEARHOT(void) const { return 5; }
virtual HRESULT backgroundGradientColors(HTHEME theme, COLORREF *colors) const
{
HRESULT hr;
// yes, Vista doesn't seem to have the colors in the theme, so get them from the UIFILE instead
vertices[0].x = rcWindow->left;
vertices[0].y = rcWindow->top;
vertices[0].Red = 4 << 8;
vertices[0].Green = 80 << 8;
vertices[0].Blue = 130 << 8;
vertices[0].Alpha = 255 << 8;
// TODO get constant names
if (colors == NULL)
return E_POINTER;
hr = GetThemeColor(theme,
2, 0,
3810, &color);
if (hr == S_OK) {
vertices[0].Red = ((COLOR16) GetRValue(color)) << 8;
vertices[0].Green = ((COLOR16) GetGValue(color)) << 8;
vertices[0].Blue = ((COLOR16) GetBValue(color)) << 8;
vertices[0].Alpha = ((COLOR16) LOBYTE(color >> 24)) << 8;
}
vertices[1].x = (rcWindow->right - rcWindow->left) / 2;
vertices[1].y = rcWindow->bottom;
vertices[1].Red = 17 << 8;
vertices[1].Green = 101 << 8;
vertices[1].Blue = 132 << 8;
vertices[1].Alpha = 255 << 8;
TMT_GRADIENTCOLOR1. color + 0);
if (hr != S_OK)
return hr;
hr = GetThemeColor(theme,
2, 0,
3811, &color);
if (hr == S_OK) {
vertices[1].Red = ((COLOR16) GetRValue(color)) << 8;
vertices[1].Green = ((COLOR16) GetGValue(color)) << 8;
vertices[1].Blue = ((COLOR16) GetBValue(color)) << 8;
vertices[1].Alpha = ((COLOR16) LOBYTE(color >> 24)) << 8;
}
vertices[2] = vertices[1];
vertices[2].y = rcWindow->top;
vertices[3].x = rcWindow->right;
vertices[3].y = rcWindow->bottom;
vertices[3].Red = 29 << 8;
vertices[3].Green = 121 << 8;
vertices[3].Blue = 134 << 8;
vertices[3].Alpha = 255 << 8;
hr = GetThemeColor(theme,
TMT_GRADIENTCOLOR2, color + 1);
if (hr != S_OK)
return hr;
return GetThemeColor(theme,
2, 0,
3812, &color);
if (hr == S_OK) {
vertices[3].Red = ((COLOR16) GetRValue(color)) << 8;
vertices[3].Green = ((COLOR16) GetGValue(color)) << 8;
vertices[3].Blue = ((COLOR16) GetBValue(color)) << 8;
vertices[3].Alpha = ((COLOR16) LOBYTE(color >> 24)) << 8;
TMT_GRADIENTCOLOR3, color + 2);
}
GradientFill(dc, vertices, 4, (PVOID) gr, 2, GRADIENT_FILL_RECT_H);
DrawThemeBackground(theme, dc,
1, 0,
rcWindow, rcPaint);
}
#define hasNonsplitArrow(button) ((button) == leftButtons[0] || (button) == leftButtons[1] || (button) == leftButtons[2])
};
// all coordinates are in client space
struct buttonMetrics {
@ -144,6 +162,64 @@ struct buttonMetrics {
SIZE arrowSize;
};
class commandModuleStyle {
public:
virtual HRESULT drawFolderBar(commandModuleStyleParams *p, HDC dc, RECT *rcWindow, RECT *rcPaint) const = 0;
virtual HRESULT buttonMetrics(commandModuleStyleParams *p, HWND button, HDC dc, struct buttonMetrics *m) const = 0;
};
class commandModuleStyleThemed : public commandModuleStyle {
HTHEME theme;
public:
commandModuleStyleThemed(theme) { this->theme = theme; }
virtual HRESULT drawFolderBar(commandModuleStyleParams *p, HDC dc, RECT *rcWindow, RECT *rcPaint) const
{
COLORREF colors[3];
TRIVERTEX vertices[4];
static GRADIENT_RECT gr[2] = {
{ 0, 1 },
{ 2, 3 },
};
HRESULT hr;
hr = p->backgroundGradientColors(this->theme, colors);
if (hr != S_OK)
return hr;
vertices[0].x = rcWindow->left;
vertices[0].y = rcWindow->top;
vertices[0].Red = ((COLOR16) GetRValue(colors[0])) << 8;
vertices[0].Green = ((COLOR16) GetGValue(colors[0])) << 8;
vertices[0].Blue = ((COLOR16) GetBValue(colors[0])) << 8;
vertices[0].Alpha = ((COLOR16) LOBYTE(colors[0] >> 24)) << 8;
vertices[1].x = (rcWindow->right - rcWindow->left) / 2;
vertices[1].y = rcWindow->bottom;
vertices[1].Red = ((COLOR16) GetRValue(colors[1])) << 8;
vertices[1].Green = ((COLOR16) GetGValue(colors[1])) << 8;
vertices[1].Blue = ((COLOR16) GetBValue(colors[1])) << 8;
vertices[1].Alpha = ((COLOR16) LOBYTE(colors[1] >> 24)) << 8;
vertices[2] = vertices[1];
vertices[2].y = rcWindow->top;
vertices[3].x = rcWindow->right;
vertices[3].y = rcWindow->bottom;
vertices[3].Red = ((COLOR16) GetRValue(colors[2])) << 8;
vertices[3].Green = ((COLOR16) GetGValue(colors[2])) << 8;
vertices[3].Blue = ((COLOR16) GetBValue(colors[2])) << 8;
vertices[3].Alpha = ((COLOR16) LOBYTE(colors[2] >> 24)) << 8;
if (GradientFill(dc, vertices, 4, (PVOID) gr, 2, GRADIENT_FILL_RECT_H) == FALSE)
return lastErrorToHRESULT(GetLastError());
return DrawThemeBackground(this->theme, dc,
p->partID_CMOD_MODULEBACKGROUND(), 0,
rcWindow, rcPaint);
}
#define hasNonsplitArrow(button) ((button) == leftButtons[0] || (button) == leftButtons[1] || (button) == leftButtons[2])
#define dlgUnitsToX(dlg, baseX) MulDiv((dlg), (baseX), 4)
#define dlgUnitsToY(dlg, baseY) MulDiv((dlg), (baseY), 8)
// TODO verify the parameter order
@ -151,21 +227,26 @@ struct buttonMetrics {
#define dipsToY(dip, dpiY) MulDiv((dip), (dpiY), 96)
// TODO check errors
// TODO the sizes are correct (according to UI Automation) but they don't visually match?
void buttonMetrics(HWND button, HDC dc, struct buttonMetrics *m)
// TODO for win7: the sizes are correct (according to UI Automation) but they don't visually match?
virtual HRESULT buttonMetrics(commandModuleStyleParams *p, HWND button, HDC dc, struct buttonMetrics *m) const
{
BOOL releaseDC;
TEXTMETRICW tm;
RECT r;
int minStdButtonHeight;
HRESULT hr;
releaseDC = FALSE;
if (dc == NULL) {
dc = GetDC(button);
if (dc == NULL)
return lastErrorToHRESULT(GetLastError());
releaseDC = TRUE;
}
ZeroMemory(&tm, sizeof (TEXTMETRICW));
// TODO get constant names
// TODO make textstyleTheme a member
GetThemeTextMetrics(textstyleTheme, dc,
4, 0,
&tm);
@ -190,31 +271,37 @@ void buttonMetrics(HWND button, HDC dc, struct buttonMetrics *m)
n = SendMessageW(button, WM_GETTEXTLENGTH, 0, 0);
buf = new WCHAR[n + 1];
GetWindowTextW(button, buf, n + 1);
GetThemeTextExtent(textstyleTheme, dc,
hr = GetThemeTextExtent(textstyleTheme, dc,
4, 0,
buf, n, DT_CENTER,
NULL, &r);
delete[] buf;
if (hr != S_OK)
goto fail;
m->textSize.cx = r.right - r.left;
m->textSize.cy = r.bottom - r.top;
delete[] buf;
m->fittingSize.cx += m->textSize.cx;
m->fittingSize.cy += m->textSize.cy;
// dui70.dll adds this to the width when "overhang" is enabled, and it seems to be enabled for our cases, but I can't tell what conditions it's enabled for...
// and yes, it seems to be using the raw lfHeight value here :/
// TODO find the right TMT constant
GetThemeFont(textstyleTheme, dc,
hr = GetThemeFont(textstyleTheme, dc,
4, 0,
TMT_FONT, &lf);
if (hr != S_OK)
goto fail;
m->fittingSize.cx += 2 * (abs(lf.lfHeight) / 6);
}
m->hasArrow = hasNonsplitArrow(button);
if (m->hasArrow) {
// TS_MIN returns 1x1 and TS_DRAW returns 0x0, so...
GetThemePartSize(theme, dc,
hr = GetThemePartSize(theme, dc,
6, 0,
NULL, TS_TRUE, &(m->arrowSize));
if (hr != S_OK)
goto fail;
m->fittingSize.cx += m->arrowSize.cx;
// TODO I don't think dui70.dll takes this into consideration...
if (m->fittingSize.cy < m->arrowSize.cy)
@ -230,9 +317,14 @@ void buttonMetrics(HWND button, HDC dc, struct buttonMetrics *m)
if (m->fittingSize.cy < minStdButtonHeight)
m->fittingSize.cy = minStdButtonHeight;
hr = S_OK;
fail:
if (releaseDC)
// TODO when migrating this to libui, this will need to be renamed to indicate we are intentionally ignoring errors
ReleaseDC(button, dc);
}
return hr;
};
};
struct buttonRects {
RECT clientRect;