From 7155eff8bc159db4ea6facd111c15dd3297d902e Mon Sep 17 00:00:00 2001 From: Thomas Weidenmueller Date: Mon, 2 Aug 2004 22:19:50 +0000 Subject: [PATCH] Added support for PBS_MARQUEE style. --- dlls/comctl32/progress.c | 316 ++++++++++++++++++++++++++++++++++----- include/commctrl.h | 2 + 2 files changed, 280 insertions(+), 38 deletions(-) diff --git a/dlls/comctl32/progress.c b/dlls/comctl32/progress.c index 8b0e56410af..a63f42898a7 100644 --- a/dlls/comctl32/progress.c +++ b/dlls/comctl32/progress.c @@ -26,9 +26,6 @@ * Unless otherwise noted, we believe this code to be complete, as per * the specification mentioned above. * If you discover missing features, or bugs, please note them below. - * - * TODO - * --support PBS_MARQUE * */ @@ -52,6 +49,8 @@ typedef struct INT MinVal; /* Minimum progress value */ INT MaxVal; /* Maximum progress value */ INT Step; /* Step to use on PMB_STEPIT */ + INT MarqueePos; /* Marquee animation position */ + BOOL Marquee; /* Whether the marquee animation is enabled */ COLORREF ColorBar; /* Bar color */ COLORREF ColorBk; /* Background color */ HFONT Font; /* Handle to font (not unused) */ @@ -59,7 +58,9 @@ typedef struct /* Control configuration constants */ -#define LED_GAP 2 +#define LED_GAP 2 +#define MARQUEE_LEDS 5 +#define ID_MARQUEE_TIMER 1 /*********************************************************************** * PROGRESS_Invalidate @@ -156,51 +157,215 @@ static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc) { if (dwStyle & PBS_VERTICAL) { - INT old_top = rect.top; - rect.top = rightBar; - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top = old_top; - FillRect(hdc, &rect, hbrBk); + if (dwStyle & PBS_MARQUEE) + { + INT old_top, old_bottom, ledMStart, leds; + old_top = rect.top; + old_bottom = rect.bottom; + + leds = rect.bottom - rect.top; + ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; + + if(ledMStart > 0) + { + rect.top = max(rect.bottom - ledMStart, old_top); + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + } + if(infoPtr->MarqueePos > 0) + { + rect.top = max(old_bottom - infoPtr->MarqueePos, old_top); + FillRect(hdc, &rect, hbrBk); + rect.bottom = rect.top; + } + if(rect.top >= old_top) + { + rect.top = max(rect.bottom - MARQUEE_LEDS, old_top); + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + } + if(rect.top >= old_top) + { + rect.top = old_top; + FillRect(hdc, &rect, hbrBk); + } + } + else + { + INT old_top = rect.top; + rect.top = rightBar; + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + rect.top = old_top; + FillRect(hdc, &rect, hbrBk); + } } else { - INT old_right = rect.right; - rect.right = rightBar; - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right = old_right; - FillRect(hdc, &rect, hbrBk); + if (dwStyle & PBS_MARQUEE) + { + INT old_left, old_right, ledMStart, leds; + old_left = rect.left; + old_right = rect.right; + + leds = rect.right - rect.left; + ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; + rect.right = rect.left; + + if(ledMStart > 0) + { + rect.right = min(rect.left + ledMStart, old_right); + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + } + if(infoPtr->MarqueePos > 0) + { + rect.right = min(old_left + infoPtr->MarqueePos, old_right); + FillRect(hdc, &rect, hbrBk); + rect.left = rect.right; + } + if(rect.right < old_right) + { + rect.right = min(rect.left + MARQUEE_LEDS, old_right); + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + } + if(rect.right < old_right) + { + rect.right = old_right; + FillRect(hdc, &rect, hbrBk); + } + } + else + { + INT old_right = rect.right; + rect.right = rightBar; + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + rect.right = old_right; + FillRect(hdc, &rect, hbrBk); + } } } else { if (dwStyle & PBS_VERTICAL) { - while(rect.bottom > rightBar) { - rect.top = rect.bottom - ledWidth; - if (rect.top < rightMost) - rect.top = rightMost; - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top -= LED_GAP; - if (rect.top <= rightBar) break; - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; + if (dwStyle & PBS_MARQUEE) + { + INT i, old_top, old_bottom, ledMStart, leds; + old_top = rect.top; + old_bottom = rect.bottom; + + leds = ((rect.bottom - rect.top) + (ledWidth + LED_GAP) - 1) / (ledWidth + LED_GAP); + ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; + + while(ledMStart > 0) + { + rect.top = max(rect.bottom - ledWidth, old_top); + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + rect.top -= LED_GAP; + if (rect.top <= old_top) break; + FillRect(hdc, &rect, hbrBk); + rect.bottom = rect.top; + ledMStart--; + } + if(infoPtr->MarqueePos > 0) + { + rect.top = max(old_bottom - (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_top); + FillRect(hdc, &rect, hbrBk); + rect.bottom = rect.top; + } + for(i = 0; i < MARQUEE_LEDS && rect.top >= old_top; i++) + { + rect.top = max(rect.bottom - ledWidth, old_top); + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + rect.top -= LED_GAP; + if (rect.top <= old_top) break; + FillRect(hdc, &rect, hbrBk); + rect.bottom = rect.top; + } + if(rect.top >= old_top) + { + rect.top = old_top; + FillRect(hdc, &rect, hbrBk); + } + } + else + { + while(rect.bottom > rightBar) { + rect.top = rect.bottom - ledWidth; + if (rect.top < rightMost) + rect.top = rightMost; + FillRect(hdc, &rect, hbrBar); + rect.bottom = rect.top; + rect.top -= LED_GAP; + if (rect.top <= rightBar) break; + FillRect(hdc, &rect, hbrBk); + rect.bottom = rect.top; + } } rect.top = rightMost; FillRect(hdc, &rect, hbrBk); } else { - while(rect.left < rightBar) { - rect.right = rect.left + ledWidth; - if (rect.right > rightMost) - rect.right = rightMost; - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right += LED_GAP; - if (rect.right >= rightBar) break; - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; + if (dwStyle & PBS_MARQUEE) + { + INT i, old_right, old_left, ledMStart, leds; + old_left = rect.left; + old_right = rect.right; + + leds = ((rect.right - rect.left) + ledWidth - 1) / (ledWidth + LED_GAP); + ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; + rect.right = rect.left; + + while(ledMStart > 0) + { + rect.right = min(rect.left + ledWidth, old_right); + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + rect.right += LED_GAP; + if (rect.right > old_right) break; + FillRect(hdc, &rect, hbrBk); + rect.left = rect.right; + ledMStart--; + } + if(infoPtr->MarqueePos > 0) + { + rect.right = min(old_left + (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_right); + FillRect(hdc, &rect, hbrBk); + rect.left = rect.right; + } + for(i = 0; i < MARQUEE_LEDS && rect.right < old_right; i++) + { + rect.right = min(rect.left + ledWidth, old_right); + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + rect.right += LED_GAP; + if (rect.right > old_right) break; + FillRect(hdc, &rect, hbrBk); + rect.left = rect.right; + } + if(rect.right < old_right) + { + rect.right = old_right; + FillRect(hdc, &rect, hbrBk); + } + } + else + { + while(rect.left < rightBar) { + rect.right = rect.left + ledWidth; + if (rect.right > rightMost) + rect.right = rightMost; + FillRect(hdc, &rect, hbrBar); + rect.left = rect.right; + rect.right += LED_GAP; + if (rect.right >= rightBar) break; + FillRect(hdc, &rect, hbrBk); + rect.left = rect.right; + } + rect.right = rightMost; + FillRect(hdc, &rect, hbrBk); } - rect.right = rightMost; - FillRect(hdc, &rect, hbrBk); } } @@ -228,6 +393,63 @@ static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc) } +/*********************************************************************** + * PROGRESS_Timer + * Handle the marquee timer messages + */ +static LRESULT PROGRESS_Timer (PROGRESS_INFO *infoPtr, INT idTimer) +{ + if(idTimer == ID_MARQUEE_TIMER) + { + LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE); + RECT rect; + int ledWidth, leds; + + GetClientRect (infoPtr->Self, &rect); + InflateRect(&rect, -1, -1); + + if(!(style & PBS_SMOOTH)) + { + int width, height; + + if(style & PBS_VERTICAL) + { + width = rect.bottom - rect.top; + height = rect.right - rect.left; + } + else + { + height = rect.bottom - rect.top; + width = rect.right - rect.left; + } + ledWidth = MulDiv (height, 2, 3); + leds = (width + ledWidth - 1) / (ledWidth + LED_GAP); + } + else + { + ledWidth = 1; + if(style & PBS_VERTICAL) + { + leds = rect.bottom - rect.top; + } + else + { + leds = rect.right - rect.left; + } + } + + /* increment the marquee progress */ + if(++infoPtr->MarqueePos >= leds) + { + infoPtr->MarqueePos = 0; + } + + InvalidateRect(infoPtr->Self, &rect, TRUE); + } + return 0; +} + + /*********************************************************************** * PROGRESS_CoercePos * Makes sure the current position (CurVal) is within bounds. @@ -304,6 +526,8 @@ static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message, infoPtr->MaxVal = 100; infoPtr->CurVal = 0; infoPtr->Step = 10; + infoPtr->MarqueePos = 0; + infoPtr->Marquee = FALSE; infoPtr->ColorBar = CLR_DEFAULT; infoPtr->ColorBk = CLR_DEFAULT; infoPtr->Font = 0; @@ -326,6 +550,9 @@ static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message, case WM_PAINT: return PROGRESS_Paint (infoPtr, (HDC)wParam); + case WM_TIMER: + return PROGRESS_Timer (infoPtr, (INT)wParam); + case PBM_DELTAPOS: { INT oldVal; @@ -401,6 +628,19 @@ static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message, InvalidateRect(hwnd, NULL, TRUE); return 0; + case PBM_SETMARQUEE: + if(wParam != 0) + { + infoPtr->Marquee = TRUE; + SetTimer(infoPtr->Self, ID_MARQUEE_TIMER, (UINT)lParam, NULL); + } + else + { + infoPtr->Marquee = FALSE; + KillTimer(infoPtr->Self, ID_MARQUEE_TIMER); + } + return infoPtr->Marquee; + default: if ((message >= WM_USER) && (message < WM_APP)) ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam ); diff --git a/include/commctrl.h b/include/commctrl.h index 5622179d6da..278f4760012 100644 --- a/include/commctrl.h +++ b/include/commctrl.h @@ -456,10 +456,12 @@ static const WCHAR PROGRESS_CLASSW[] = { 'm','s','c','t','l','s','_', #define PBM_GETRANGE (WM_USER+7) #define PBM_GETPOS (WM_USER+8) #define PBM_SETBARCOLOR (WM_USER+9) +#define PBM_SETMARQUEE (WM_USER+10) #define PBM_SETBKCOLOR CCM_SETBKCOLOR #define PBS_SMOOTH 0x01 #define PBS_VERTICAL 0x04 +#define PBS_MARQUEE 0x08 typedef struct {