diff options
| author | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-07-08 21:03:41 +0200 |
|---|---|---|
| committer | Jonas Kümmerlin <jonas@kuemmerlin.eu> | 2020-07-08 21:03:41 +0200 |
| commit | c8a5d9cc2dedf3a8573659fa70b14f86e899bac4 (patch) | |
| tree | 396a26f622c5064734c44197b2dc8d39008e7410 | |
| parent | 960f0cef228a64ea598c4531d0a7d159dfb7ed0d (diff) | |
progress bar
| -rw-r--r-- | Makefile.mingw | 7 | ||||
| -rw-r--r-- | Makefile.mingw-amd64 | 7 | ||||
| -rw-r--r-- | Makefile.vc6 | 5 | ||||
| -rw-r--r-- | Makefile.vc6-ansi | 5 | ||||
| -rw-r--r-- | alf/alf.h | 38 | ||||
| -rw-r--r-- | alf/alfprogress.cpp | 476 | ||||
| -rw-r--r-- | widgetfactory.cpp | 115 |
7 files changed, 645 insertions, 8 deletions
diff --git a/Makefile.mingw b/Makefile.mingw index e61640a..e2157ca 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory.exe out/alf/alf.c out/widgetfactory-c.exe -out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alficon.o out/alflabel.o out/alflayout.o out/alfmessagedlg.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alfspinbox.o out/alftoplevel.o +out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alficon.o out/alflabel.o out/alflayout.o out/alfmessagedlg.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alfprogress.o out/alfspinbox.o out/alftoplevel.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -56,6 +56,9 @@ out/alfnotebook.o: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayout. out/alfpanel.o: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< +out/alfprogress.o: alf/alfprogress.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CXXFLAGS) -c -o $@ $< + out/alfspinbox.o: alf/alfspinbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< @@ -65,7 +68,7 @@ out/alftoplevel.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout. out/widgetfactory.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfspinbox.cpp alf/alftoplevel.cpp +out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfprogress.cpp alf/alfspinbox.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.mingw-amd64 b/Makefile.mingw-amd64 index 5a87ede..5ecf4dc 100644 --- a/Makefile.mingw-amd64 +++ b/Makefile.mingw-amd64 @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory64.exe out/alf/alf64.c out/widgetfactory64-c.exe -out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alficon.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfmessagedlg.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alfspinbox.amd64.o out/alftoplevel.amd64.o +out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alficon.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfmessagedlg.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alfprogress.amd64.o out/alfspinbox.amd64.o out/alftoplevel.amd64.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.amd64.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -56,6 +56,9 @@ out/alfnotebook.amd64.o: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alfl out/alfpanel.amd64.o: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< +out/alfprogress.amd64.o: alf/alfprogress.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CXXFLAGS) -c -o $@ $< + out/alfspinbox.amd64.o: alf/alfspinbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< @@ -65,7 +68,7 @@ out/alftoplevel.amd64.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alfl out/widgetfactory.amd64.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfspinbox.cpp alf/alftoplevel.cpp +out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alfprogress.cpp alf/alfspinbox.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.vc6 b/Makefile.vc6 index 03a30cf..a41f66e 100644 --- a/Makefile.vc6 +++ b/Makefile.vc6 @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link unicows.lib kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfspinbox.obj out/alftoplevel.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfprogress.obj out/alfspinbox.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -52,6 +52,9 @@ out/alfnotebook.obj: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayou out/alfpanel.obj: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfpanel.cpp +out/alfprogress.obj: alf/alfprogress.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfprogress.cpp + out/alfspinbox.obj: alf/alfspinbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfspinbox.cpp diff --git a/Makefile.vc6-ansi b/Makefile.vc6-ansi index 759b494..1a1ec7a 100644 --- a/Makefile.vc6-ansi +++ b/Makefile.vc6-ansi @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link /entry:_entry /opt:nowin98 /fixed:no kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfspinbox.obj out/alftoplevel.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alfprogress.obj out/alfspinbox.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -52,6 +52,9 @@ out/alfnotebook.obj: alf/alfnotebook.cpp alf/alfcompat.h alf/alf.h alf/alflayou out/alfpanel.obj: alf/alfpanel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfpanel.cpp +out/alfprogress.obj: alf/alfprogress.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfprogress.cpp + out/alfspinbox.obj: alf/alfspinbox.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfspinbox.cpp @@ -685,6 +685,44 @@ ALF_SpinBox_EditControl(HWND spinbox); HWND ALF_SpinBox_UpDownControl(HWND spinbox); +// progress +enum ALFProgressState { + ALF_PROGRESS_STATE_NORMAL = 1, //==PBST_NORMAL + ALF_PROGRESS_STATE_ERROR = 2, //==PBST_ERROR FIXME! only supported in native commctl v6 progress bar on Vista+ + ALF_PROGRESS_STATE_PAUSED = 3, //==PBST_PAUSED FIXME! only supported in native commctl v6 progress bar on Vista+ + ALF_PROGRESS_STATE_INDETERMINATE = 4, + ALF_PROGRESS_STATE_HIDDEN = 5 // TODO: define semantics and implement +}; + +HWND +ALF_AddNativeProgressBar(HWND parent, WORD id, int x, int y); + +HWND +ALF_AddProgressGauge(HWND parent, WORD id, int x, int y); + +// creates a native progress bar on commctlv6 (XP+), a selfmade progress gauge otherwise +HWND +ALF_AddProgressBar(HWND parent, WORD id, int x, int y); + +void +ALF_Progress_Range(HWND progress, int *pMin, int *pMax); + +void +ALF_Progress_SetRange(HWND progress, int min, int max); + +int +ALF_Progress_Value(HWND progress); + +void +ALF_Progress_SetValue(HWND progress, int value); + +enum ALFProgressState +ALF_Progress_State(HWND progress); + +void +ALF_Progress_SetState(HWND progress, enum ALFProgressState state); + + #ifdef __cplusplus } // extern C #endif diff --git a/alf/alfprogress.cpp b/alf/alfprogress.cpp new file mode 100644 index 0000000..3a5c4fc --- /dev/null +++ b/alf/alfprogress.cpp @@ -0,0 +1,476 @@ +#include "alfpriv.h" + +#define ALF_PROGRESS_MARQUEE_WIDTH 5 +#define ALF_PROGRESS_MARQUEE_TIMER_ID 42 + +// need special messages for gauge on Win32s because Win32s only keeps the +// low word of WPARAM where we occasionally need to pass 32bit LONGs +#define ALF_WM_PROGRESS_SETRANGE (ALF_WM__BASE + 201) +#define ALF_WM_PROGRESS_SETPOS (ALF_WM__BASE + 202) + +typedef struct { + int min; + int max; + int pos; + int marquee; + HFONT font; +} ALFProgressGaugePriv; + +static void +ALF_ProgressGauge_Init(ALFProgressGaugePriv *priv) +{ + priv->min = 0; + priv->max = 100; + priv->pos = 0; + priv->marquee = 0; +} + +static LRESULT +ALF_ProgressGauge_GetRange(ALFProgressGaugePriv *priv, HWND hwnd, WPARAM retminormax, PBRANGE *pRange) +{ + (void)hwnd; + + if (pRange) { + pRange->iLow = priv->min; + pRange->iHigh = priv->max; + } + + if (retminormax) + return priv->min; + else + return priv->max; +} + +static LRESULT +ALF_ProgressGauge_SetRange(ALFProgressGaugePriv *priv, HWND hwnd, int min, int max) +{ + priv->min = min; + priv->max = max; + + if (max < min) + priv->max = min; + + if (priv->pos < min) + priv->pos = min; + + if (priv->pos > max) + priv->pos = max; + + InvalidateRect(hwnd, NULL, TRUE); + return 1; +} + +static LRESULT +ALF_ProgressGauge_GetPos(ALFProgressGaugePriv *priv, HWND hwnd) +{ + (void)hwnd; + + return (LRESULT)priv->pos; +} + +static LRESULT +ALF_ProgressGauge_SetPos(ALFProgressGaugePriv *priv, HWND hwnd, int pos) +{ + priv->pos = pos; + + if (priv->pos < priv->min) + priv->pos = priv->min; + + if (priv->pos > priv->max) + priv->pos = priv->max; + + InvalidateRect(hwnd, NULL, TRUE); + return 1; +} + +static LRESULT +ALF_ProgressGauge_Size(ALFProgressGaugePriv *priv, HWND hwnd, WPARAM wparam, LPARAM lparam) +{ + (void)priv; + + InvalidateRect(hwnd, NULL, TRUE); + + return DefWindowProc(hwnd, WM_SIZE, wparam, lparam); +} + +static void +ALF_ProgressGauge_DoPaint(ALFProgressGaugePriv *priv, HWND hwnd, HDC dc, RECT *rcClip) +{ + (void)rcClip; + + RECT rc; + GetClientRect(hwnd, &rc); + OffsetRect(&rc, -rc.left, -rc.top); + + DrawEdge(dc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST); + + FrameRect(dc, &rc, GetSysColorBrush(COLOR_BTNFACE)); + InflateRect(&rc, -1, -1); + + TCHAR textbuf[64]; // FIXME! make this variable length? + ZeroMemory(textbuf, sizeof(textbuf)); + + int len = GetWindowText(hwnd, textbuf, sizeof(textbuf)/sizeof(textbuf[0])); + + HFONT oldfont = SelectFont(dc, (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0)); + + TEXTMETRIC tm; + ZeroMemory(&tm, sizeof(tm)); + + GetTextMetrics(dc, &tm); + + int refx = rc.left + (rc.right - rc.left) / 2; + int refy = rc.top + (rc.bottom - rc.top + tm.tmAscent - tm.tmDescent) / 2; + + SetTextAlign(dc, TA_CENTER | TA_BASELINE); + + COLORREF clrHilight = GetSysColor(COLOR_HIGHLIGHT); + COLORREF clrHilightText = GetSysColor(COLOR_HIGHLIGHTTEXT); + COLORREF clrBtnFace = GetSysColor(COLOR_BTNFACE); + COLORREF clrBtnText = GetSysColor(COLOR_BTNTEXT); + + if (GetWindowLong(hwnd, GWL_STYLE) & PBS_MARQUEE) { + RECT rcMarquee = { rc.left + priv->marquee, + rc.top, + rc.left + priv->marquee + ALF_PROGRESS_MARQUEE_WIDTH, + rc.bottom }; + if (rcMarquee.left < rc.left) + rcMarquee.left = rc.left; + if (rcMarquee.right > rc.right) + rcMarquee.right = rc.right; + + RECT rcMarqueeWrap = { rc.left, + rc.top, + rc.left + priv->marquee + ALF_PROGRESS_MARQUEE_WIDTH - rc.right + rc.left, + rc.bottom }; + if (rcMarqueeWrap.right < rcMarqueeWrap.left) + rcMarqueeWrap.right = rcMarqueeWrap.left; + + RECT rcLeftSpace = { rcMarqueeWrap.right, rc.top, rcMarquee.left, rc.bottom }; + RECT rcRightSpace = { rcMarquee.right, rc.top, rc.right, rc.bottom }; + + SetBkColor(dc, clrHilight); + SetTextColor(dc, clrHilightText); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcMarquee, textbuf, (UINT)len, NULL); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcMarqueeWrap, textbuf, (UINT)len, NULL); + + SetBkColor(dc, clrBtnFace); + SetTextColor(dc, clrBtnText); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcLeftSpace, textbuf, (UINT)len, NULL); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcRightSpace, textbuf, (UINT)len, NULL); + } else { + int barwidth = MulDiv(priv->pos - priv->min, rc.right - rc.left, priv->max - priv->min); + + // XXX: make the painting pixel-compatible to the original progress bar + // IMHO this seems to be some kind of off-by-one error in the microsoft code + if (barwidth >= rc.right - rc.left) + barwidth -= 1; + + RECT rcLeft = { rc.left, rc.top, rc.left + barwidth, rc.bottom }; + RECT rcRight = { rc.left + barwidth, rc.top, rc.right, rc.bottom }; + + SetBkColor(dc, clrHilight); + SetTextColor(dc, clrHilightText); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcLeft, textbuf, (UINT)len, NULL); + + SetBkColor(dc, clrBtnFace); + SetTextColor(dc, clrBtnText); + ExtTextOut(dc, refx, refy, ETO_OPAQUE|ETO_CLIPPED, &rcRight, textbuf, (UINT)len, NULL); + } + + SelectFont(dc, oldfont); +} + +static LRESULT +ALF_ProgressGauge_Paint(ALFProgressGaugePriv *priv, HWND hwnd) +{ + PAINTSTRUCT ps; + HDC dc = BeginPaint(hwnd, &ps); + + ALF_ProgressGauge_DoPaint(priv, hwnd, dc, &ps.rcPaint); + + EndPaint(hwnd, &ps); + return 0; +} + +static LRESULT +ALF_ProgressGauge_PrintClient(ALFProgressGaugePriv *priv, HWND hwnd, HDC dc) +{ + RECT rc; + GetClientRect(hwnd, &rc); + OffsetRect(&rc, -rc.left, -rc.top); + + ALF_ProgressGauge_DoPaint(priv, hwnd, dc, &rc); + return 0; +} + +static LRESULT +ALF_ProgressGauge_Timer(ALFProgressGaugePriv *priv, HWND hwnd, WPARAM id, LPARAM lparam) +{ + if (id == ALF_PROGRESS_MARQUEE_TIMER_ID) { + if (GetWindowLong(hwnd, GWL_STYLE) & PBS_MARQUEE) { + RECT rcClient; + GetClientRect(hwnd, &rcClient); + + priv->marquee += 1; + if (priv->marquee >= rcClient.right - rcClient.left - 4) { + priv->marquee = 0; + } + + InvalidateRect(hwnd, NULL, TRUE); + } else { + KillTimer(hwnd, id); + } + + return 0; + } else { + return DefWindowProc(hwnd, WM_TIMER, id, lparam); + } +} + +static LRESULT +ALF_ProgressGauge_SetMarquee(ALFProgressGaugePriv *priv, HWND hwnd, WPARAM onoff, UINT milliseconds) +{ + if (GetWindowLong(hwnd, GWL_STYLE) & PBS_MARQUEE) { + if (onoff) { + priv->pos = priv->min; + priv->marquee = -2; + InvalidateRect(hwnd, NULL, TRUE); + + if (milliseconds == 0) + milliseconds = 30; + + SetTimer(hwnd, ALF_PROGRESS_MARQUEE_TIMER_ID, milliseconds, NULL); + } else { + KillTimer(hwnd, ALF_PROGRESS_MARQUEE_TIMER_ID); + } + } + + return 0; +} + +static LRESULT +ALF_ProgressGauge_StyleChanged(ALFProgressGaugePriv *priv, HWND hwnd, WPARAM wparam, LPARAM lparam) +{ + (void)priv; + InvalidateRect(hwnd, NULL, TRUE); + return DefWindowProc(hwnd, WM_STYLECHANGED, wparam, lparam); +} + +static LRESULT +ALF_ProgressGauge_SetFont(ALFProgressGaugePriv *priv, HWND hwnd, HFONT font) +{ + priv->font = font; + InvalidateRect(hwnd, NULL, TRUE); + return 0; +} + +static LRESULT +ALF_ProgressGauge_GetFont(ALFProgressGaugePriv *priv, HWND hwnd) +{ + (void)hwnd; + return (LRESULT)priv->font; +} + +static LRESULT +ALF_ProgressGauge_SetText(ALFProgressGaugePriv *priv, HWND hwnd, const TCHAR *text) +{ + (void)priv; + + InvalidateRect(hwnd, NULL, TRUE); + return DefWindowProc(hwnd, WM_SETTEXT, 0, (LPARAM)text); +} + +static LRESULT +ALF_ProgressGauge_CalcSize(ALFProgressGaugePriv *priv, HWND hwnd, SIZE *pSize) +{ + if (GetWindowTextLength(hwnd) > 0) { + HDC dc = GetDC(hwnd); + HFONT oldfont = SelectFont(dc, priv->font); + + TEXTMETRIC tm; + ZeroMemory(&tm, sizeof(tm)); + GetTextMetrics(dc, &tm); + + int cy = tm.tmHeight + 8; + if (pSize->cy < cy) + pSize->cy = cy; + + SelectFont(dc, oldfont); + ReleaseDC(hwnd, dc); + } + + return 0; +} + +static LRESULT WINAPI +ALF_ProgressGauge_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + ALFProgressGaugePriv *priv = (ALFProgressGaugePriv *)GetWindowLongPtr(hwnd, 0); + + if (!priv) { + if (msg == WM_CREATE) { + priv = ALF_New(ALFProgressGaugePriv, 1); + ALF_ProgressGauge_Init(priv); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)priv); + } else { + return DefWindowProc(hwnd, msg, wparam, lparam); + } + } + + switch (msg) { + case WM_DESTROY: + SetWindowLongPtr(hwnd, 0, 0); + ALF_Free(priv); + break; + case PBM_GETPOS: + return ALF_ProgressGauge_GetPos(priv, hwnd); + case PBM_SETPOS: + return ALF_ProgressGauge_SetPos(priv, hwnd, (int)wparam); + case ALF_WM_PROGRESS_SETPOS: + return ALF_ProgressGauge_SetPos(priv, hwnd, (int)lparam); + case PBM_GETRANGE: + return ALF_ProgressGauge_GetRange(priv, hwnd, wparam, (PBRANGE *)lparam); + case PBM_SETRANGE32: + return ALF_ProgressGauge_SetRange(priv, hwnd, (int)wparam, (int)lparam); + case ALF_WM_PROGRESS_SETRANGE: + return ALF_ProgressGauge_SetRange(priv, hwnd, ((PBRANGE *)lparam)->iLow, ((PBRANGE *)lparam)->iHigh); + case WM_PAINT: + return ALF_ProgressGauge_Paint(priv, hwnd); + case WM_ERASEBKGND: + return TRUE; + case WM_PRINTCLIENT: + return ALF_ProgressGauge_PrintClient(priv, hwnd, (HDC)wparam); + case WM_TIMER: + return ALF_ProgressGauge_Timer(priv, hwnd, wparam, lparam); + case PBM_SETMARQUEE: + return ALF_ProgressGauge_SetMarquee(priv, hwnd, wparam, (UINT)lparam); + case WM_STYLECHANGED: + return ALF_ProgressGauge_StyleChanged(priv, hwnd, wparam, lparam); + case WM_SIZE: + return ALF_ProgressGauge_Size(priv, hwnd, wparam, lparam); + case WM_SETFONT: + return ALF_ProgressGauge_SetFont(priv, hwnd, (HFONT)wparam); + case WM_GETFONT: + return ALF_ProgressGauge_GetFont(priv, hwnd); + case WM_SETTEXT: + return ALF_ProgressGauge_SetText(priv, hwnd, (const TCHAR *)lparam); + case ALF_WM_QUERYSIZE: + return ALF_ProgressGauge_CalcSize(priv, hwnd, (SIZE *)lparam); + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +HWND +ALF_AddNativeProgressBar(HWND parent, WORD id, int x, int y) +{ + HWND hwnd = CreateWindowEx(0, + PROGRESS_CLASS, + NULL, + WS_CHILD | WS_VISIBLE | PBS_SMOOTH, + 0, 0, 10, 10, + parent, + (HMENU)(ULONG_PTR)id, + ALF_HINSTANCE, + NULL); + + ALF_AddControl(parent, x, y, hwnd, 12000, 1125, ALF_LAYOUT_TRANSPARENTBG); + + return hwnd; +} + +HWND +ALF_AddProgressGauge(HWND parent, WORD id, int x, int y) +{ + HWND hwnd = ALF_CreateControlWindow(0, + TEXT(""), + WS_CHILD | WS_VISIBLE, + 0, 0, 10, 10, + parent, + (HMENU)(ULONG_PTR)id, + ALF_ProgressGauge_WindowProc, + NULL); + + ALF_AddControl(parent, x, y, hwnd, 12000, 1125, ALF_LAYOUT_SIZE_QUERY | ALF_LAYOUT_INHERITFONT); + + return hwnd; +} + +HWND +ALF_AddProgressBar(HWND parent, WORD id, int x, int y) +{ + if (ALF_Compat_IsComCtlV6()) + return ALF_AddNativeProgressBar(parent, id, x, y); + else + return ALF_AddProgressGauge(parent, id, x, y); +} + +void +ALF_Progress_Range(HWND progress, int *pMin, int *pMax) +{ + PBRANGE r = { 0, 0 }; + SendMessage(progress, PBM_GETRANGE, 0, (LPARAM)&r); + + if (pMin) *pMin = r.iLow; + if (pMax) *pMax = r.iHigh; +} + +void +ALF_Progress_SetRange(HWND progress, int min, int max) +{ + PBRANGE r = { min, max }; + if (!SendMessage(progress, ALF_WM_PROGRESS_SETRANGE, 0, (LPARAM)&r)) { + SendMessage(progress, PBM_SETRANGE32, (WPARAM)min, (LPARAM)max); + } +} + +int +ALF_Progress_Value(HWND progress) +{ + return (int)SendMessage(progress, PBM_GETPOS, 0, 0); +} + +void +ALF_Progress_SetValue(HWND progress, int value) +{ + if (!SendMessage(progress, ALF_WM_PROGRESS_SETPOS, 0, (LPARAM)value)) + SendMessage(progress, PBM_SETPOS, (WPARAM)value, 0); +} + +enum ALFProgressState +ALF_Progress_State(HWND progress) +{ + LRESULT state = SendMessage(progress, /*PBM_GETSTATE*/(WM_USER + 17), 0, 0); + BOOL marquee = GetWindowLong(progress, GWL_STYLE) & PBS_MARQUEE; + + if (marquee) { + return ALF_PROGRESS_STATE_INDETERMINATE; + } else if (state == 0) { + // state not supported by this progress bar + return ALF_PROGRESS_STATE_NORMAL; + } else { + // enum values have been chosen to be equal to PBST_* + return (enum ALFProgressState)state; + } +} + +void +ALF_Progress_SetState(HWND progress, enum ALFProgressState state) +{ + switch (state) { + case ALF_PROGRESS_STATE_INDETERMINATE: + SetWindowLong(progress, GWL_STYLE, GetWindowLong(progress, GWL_STYLE) | PBS_MARQUEE); + SendMessage(progress, WM_USER+16/*PBM_SETSTATE*/, 1/*PBST_NORMAL*/, 0); + SendMessage(progress, PBM_SETMARQUEE, TRUE, 0); + break; + default: + if (GetWindowLong(progress, GWL_STYLE) & PBS_MARQUEE) { + SendMessage(progress, PBM_SETMARQUEE, FALSE, 0); + SetWindowLong(progress, GWL_STYLE, GetWindowLong(progress, GWL_STYLE) & ~PBS_MARQUEE); + } + // enum values have been chosen to equal to PBST_* + SendMessage(progress, WM_USER+16/*PBM_SETSTATE*/, (WPARAM)state, 0); + break; + } +} diff --git a/widgetfactory.cpp b/widgetfactory.cpp index b2c3396..12c08d9 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -11,6 +11,7 @@ enum { PANE_GROUPBOX, PANE_ICONVIEW, PANE_SPINBOX, + PANE_PROGRESS, PANE__MAX }; @@ -22,7 +23,8 @@ static const TCHAR *g_paneLabels[PANE__MAX] = { TEXT("Checkbox"), //PANE_CHECKBOX, TEXT("GroupBox"), //PANE_GROUPBOX, TEXT("Icon View"), //PANE_ICONVIEW, - TEXT("Spin Box") //PANE_SPINBOX + TEXT("Spin Box"), //PANE_SPINBOX + TEXT("Progress") //PANE_PROGRESS }; enum { @@ -34,6 +36,14 @@ enum { ID_HELLO, ID_SPINBOX, ID_SPINBOXOUT, + ID_PROGRESS_SPINBOX, + ID_PROGRESS_BAR, + ID_PROGRESS_GAUGE, + ID_PROGRESS_NATIVE_BAR, + ID_PROGRESS_NORMAL, + ID_PROGRESS_PAUSED, + ID_PROGRESS_ERROR, + ID_PROGRESS_INDETERMINATE, IDM_FILE, IDM_FILE_CLOSE, IDM_HELP, @@ -868,6 +878,105 @@ spinboxPanelInit(HWND panel) ALF_Panel_SetVTable(panel, &spinboxPanelVtbl, priv); } +/* progress panel */ + +static LRESULT +progressPanelCommand(void *closure, HWND panel, WORD notificationcode, WORD sourceid, HWND control) +{ + (void)closure; + + if (notificationcode == EN_CHANGE && sourceid == ID_PROGRESS_SPINBOX) { + ALF_Progress_SetValue(ALF_ControlHwndById(panel, ID_PROGRESS_BAR), (int)ALF_SpinBox_Pos(control)); + ALF_Progress_SetValue(ALF_ControlHwndById(panel, ID_PROGRESS_NATIVE_BAR), (int)ALF_SpinBox_Pos(control)); + ALF_Progress_SetValue(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), (int)ALF_SpinBox_Pos(control)); + + TCHAR buf[4]; + wsprintf(buf, TEXT("%d"), (int)ALF_SpinBox_Pos(control)); + ALF_SetText(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), buf); + + return 1; + } + + if (notificationcode == BN_CLICKED) { + if (sourceid == ID_PROGRESS_NORMAL) { + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_BAR), ALF_PROGRESS_STATE_NORMAL); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_NATIVE_BAR), ALF_PROGRESS_STATE_NORMAL); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), ALF_PROGRESS_STATE_NORMAL); + } + if (sourceid == ID_PROGRESS_PAUSED) { + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_BAR), ALF_PROGRESS_STATE_PAUSED); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_NATIVE_BAR), ALF_PROGRESS_STATE_PAUSED); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), ALF_PROGRESS_STATE_PAUSED); + } + if (sourceid == ID_PROGRESS_ERROR) { + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_BAR), ALF_PROGRESS_STATE_ERROR); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_NATIVE_BAR), ALF_PROGRESS_STATE_ERROR); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), ALF_PROGRESS_STATE_ERROR); + } + if (sourceid == ID_PROGRESS_INDETERMINATE) { + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_BAR), ALF_PROGRESS_STATE_INDETERMINATE); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_NATIVE_BAR), ALF_PROGRESS_STATE_INDETERMINATE); + ALF_Progress_SetState(ALF_ControlHwndById(panel, ID_PROGRESS_GAUGE), ALF_PROGRESS_STATE_INDETERMINATE); + } + + return 1; + } + + return 0; +} + +static void +progressPanelAttach(void *closure, HWND panel) +{ + (void)closure; + + HWND bar = ALF_AddProgressBar(panel, ID_PROGRESS_BAR, 1, 1); + ALF_Progress_SetRange(bar, -50, 50); + HWND native = ALF_AddNativeProgressBar(panel, ID_PROGRESS_NATIVE_BAR, 1, 3); + ALF_Progress_SetRange(native, -50, 50); + HWND gauge = ALF_AddProgressGauge(panel, ID_PROGRESS_GAUGE, 1, 5); + ALF_Progress_SetRange(gauge, -50, 50); + ALF_AddNumericSpinBox(panel, ID_PROGRESS_SPINBOX, 1, 7, 12, -50, 50); + + ALF_AddNativeButton(panel, ID_PROGRESS_NORMAL, 1, 9, TEXT("Normal")); + ALF_AddNativeButton(panel, ID_PROGRESS_PAUSED, 1, 11, TEXT("Paused")); + ALF_AddNativeButton(panel, ID_PROGRESS_ERROR, 1, 13, TEXT("Error")); + ALF_AddNativeButton(panel, ID_PROGRESS_INDETERMINATE, 1, 15, TEXT("Indeterminate")); + + ALF_Layout_SetRowMinSize(panel, 0, 825); + ALF_Layout_SetRowMinSize(panel, 2, 825); + ALF_Layout_SetRowMinSize(panel, 4, 825); + ALF_Layout_SetRowMinSize(panel, 6, 825); + ALF_Layout_SetRowMinSize(panel, 8, 825); + ALF_Layout_SetRowMinSize(panel, 10, 825); + ALF_Layout_SetRowMinSize(panel, 12, 825); + ALF_Layout_SetRowMinSize(panel, 14, 825); + ALF_Layout_SetRowMinSize(panel, 16, 825); + ALF_Layout_SetColumnMinSize(panel, 0, 825); + ALF_Layout_SetColumnMinSize(panel, 2, 525); + ALF_Layout_SetColumnMinSize(panel, 4, 825); + ALF_Layout_SetRowExpandNumerator(panel, 16, 1); + ALF_Layout_SetColumnExpandNumerator(panel, 1, 1); + ALF_Layout_SetColumnExpandNumerator(panel, 3, 1); +} + +static ALFPanelVTable progressPanelVtbl = { + progressPanelAttach, + commonPanelDestroy, + commonPanelMessage, + progressPanelCommand, + NULL, + commonPanelPaint, + NULL +}; + +static void +progressPanelInit(HWND panel) +{ + CommonPanelPriv *priv = ALF_New(CommonPanelPriv, 1); + ALF_Panel_SetVTable(panel, &progressPanelVtbl, priv); +} + void (*g_paneInitTable[PANE__MAX])(HWND) = { buttonPanelInit, //PANE_BUTTONS labelPanelInit, //PANE_LABEL, @@ -876,7 +985,8 @@ void (*g_paneInitTable[PANE__MAX])(HWND) = { checkboxPanelInit, //PANE_CHECKBOX, groupboxPanelInit, //PANE_GROUPBOX, iconviewPanelInit, //PANE_ICONVIEW, - spinboxPanelInit //PANE_SPINBOX + spinboxPanelInit, //PANE_SPINBOX + progressPanelInit //PANE_PROGRESS }; static void @@ -1156,6 +1266,7 @@ WinMain addPaneToNotebook(hwndNtbk, PANE_GROUPBOX); addPaneToNotebook(hwndNtbk, PANE_ICONVIEW); addPaneToNotebook(hwndNtbk, PANE_SPINBOX); + addPaneToNotebook(hwndNtbk, PANE_PROGRESS); ALF_AddNativeButton(win, ID_HELLO, 1, 3, TEXT("&Hello World!")); ALF_AddNativeButton(win, (WORD)-1, 3, 3, TEXT("Goodbye, World")); |
