Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
9.1 KiB

  1. /*-----------------------------------------------------------------------
  2. **
  3. ** Progress.c
  4. **
  5. ** A "gas gauge" type control for showing application progress.
  6. **
  7. **
  8. ** BUGBUG: need to implement the block style per UI style guidelines
  9. **
  10. **-----------------------------------------------------------------------*/
  11. #include "ctlspriv.h"
  12. // BUGBUG raymondc - should Process control support __int64 on Win64?
  13. typedef struct {
  14. HWND hwnd;
  15. DWORD dwStyle;
  16. int iLow, iHigh;
  17. int iPos;
  18. int iStep;
  19. HFONT hfont;
  20. COLORREF _clrBk;
  21. COLORREF _clrBar;
  22. } PRO_DATA, NEAR *PPRO_DATA; // ppd
  23. LRESULT CALLBACK ProgressWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
  24. #pragma code_seg(CODESEG_INIT)
  25. BOOL FAR PASCAL InitProgressClass(HINSTANCE hInstance)
  26. {
  27. WNDCLASS wc;
  28. wc.lpfnWndProc = ProgressWndProc;
  29. wc.lpszClassName = s_szPROGRESS_CLASS;
  30. wc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
  31. wc.hInstance = hInstance; // use DLL instance if in DLL
  32. wc.hIcon = NULL;
  33. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  34. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  35. wc.lpszMenuName = NULL;
  36. wc.cbWndExtra = sizeof(PPRO_DATA); // store a pointer
  37. wc.cbClsExtra = 0;
  38. RegisterClass(&wc);
  39. return TRUE;
  40. }
  41. #pragma code_seg()
  42. int NEAR PASCAL UpdatePosition(PPRO_DATA ppd, int iNewPos, BOOL bAllowWrap)
  43. {
  44. int iPosOrg = ppd->iPos;
  45. UINT uRedraw = RDW_INVALIDATE | RDW_UPDATENOW;
  46. if (ppd->iLow == ppd->iHigh)
  47. iNewPos = ppd->iLow;
  48. if (iNewPos < ppd->iLow) {
  49. if (!bAllowWrap)
  50. iNewPos = ppd->iLow;
  51. else {
  52. iNewPos = ppd->iHigh - ((ppd->iLow - iNewPos) % (ppd->iHigh - ppd->iLow));
  53. // wrap, erase old stuff too
  54. uRedraw |= RDW_ERASE;
  55. }
  56. }
  57. else if (iNewPos > ppd->iHigh) {
  58. if (!bAllowWrap)
  59. iNewPos = ppd->iHigh;
  60. else {
  61. iNewPos = ppd->iLow + ((iNewPos - ppd->iHigh) % (ppd->iHigh - ppd->iLow));
  62. // wrap, erase old stuff too
  63. uRedraw |= RDW_ERASE;
  64. }
  65. }
  66. // if moving backwards, erase old version
  67. if (iNewPos < iPosOrg)
  68. uRedraw |= RDW_ERASE;
  69. if (iNewPos != ppd->iPos) {
  70. ppd->iPos = iNewPos;
  71. // paint, maybe erase if we wrapped
  72. RedrawWindow(ppd->hwnd, NULL, NULL, uRedraw);
  73. MyNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, ppd->hwnd, OBJID_CLIENT, 0);
  74. }
  75. return iPosOrg;
  76. }
  77. #define HIGHBG g_clrHighlight
  78. #define HIGHFG g_clrHighlightText
  79. #define LOWBG g_clrBtnFace
  80. #define LOWFG g_clrBtnText
  81. void NEAR PASCAL ProPaint(PPRO_DATA ppd, HDC hdcIn)
  82. {
  83. int x, dxSpace, dxBlock, nBlocks, i;
  84. HDC hdc;
  85. RECT rc, rcClient;
  86. PAINTSTRUCT ps;
  87. int iStart, iEnd;
  88. // RECT rcLeft, rcRight;
  89. // TCHAR ach[40];
  90. // int xText, yText, cText;
  91. // HFONT hFont;
  92. // DWORD dw;
  93. if (hdcIn == NULL)
  94. hdc = BeginPaint(ppd->hwnd, &ps);
  95. else
  96. hdc = hdcIn;
  97. GetClientRect(ppd->hwnd, &rcClient);
  98. // give 1 pixel around the bar
  99. InflateRect(&rcClient, -1, -1);
  100. rc = rcClient;
  101. if (ppd->dwStyle & PBS_VERTICAL) {
  102. iStart = rc.top;
  103. iEnd = rc.bottom;
  104. dxBlock = (rc.right - rc.left) * 2 / 3;
  105. } else {
  106. iStart = rc.left;
  107. iEnd = rc.right;
  108. dxBlock = (rc.bottom - rc.top) * 2 / 3;
  109. }
  110. x = MulDiv(iEnd - iStart, ppd->iPos - ppd->iLow, ppd->iHigh - ppd->iLow);
  111. dxSpace = 2;
  112. if (dxBlock == 0)
  113. dxBlock = 1; // avoid div by zero
  114. if (ppd->dwStyle & PBS_SMOOTH) {
  115. dxBlock = 1;
  116. dxSpace = 0;
  117. }
  118. nBlocks = (x + (dxBlock + dxSpace) - 1) / (dxBlock + dxSpace); // round up
  119. for (i = 0; i < nBlocks; i++) {
  120. if (ppd->dwStyle & PBS_VERTICAL) {
  121. rc.top = rc.bottom - dxBlock;
  122. // are we past the end?
  123. if (rc.bottom <= rcClient.top)
  124. break;
  125. if (rc.top <= rcClient.top)
  126. rc.top = rcClient.top + 1;
  127. } else {
  128. rc.right = rc.left + dxBlock;
  129. // are we past the end?
  130. if (rc.left >= rcClient.right)
  131. break;
  132. if (rc.right >= rcClient.right)
  133. rc.right = rcClient.right - 1;
  134. }
  135. if (ppd->_clrBar == CLR_DEFAULT)
  136. FillRectClr(hdc, &rc, g_clrHighlight);
  137. else
  138. FillRectClr(hdc, &rc, ppd->_clrBar);
  139. if (ppd->dwStyle & PBS_VERTICAL) {
  140. rc.bottom = rc.top - dxSpace;
  141. } else {
  142. rc.left = rc.right + dxSpace;
  143. }
  144. }
  145. if (hdcIn == NULL)
  146. EndPaint(ppd->hwnd, &ps);
  147. }
  148. LRESULT NEAR PASCAL Progress_OnCreate(HWND hWnd, LPCREATESTRUCT pcs)
  149. {
  150. PPRO_DATA ppd = (PPRO_DATA)LocalAlloc(LPTR, sizeof(*ppd));
  151. if (!ppd)
  152. return -1;
  153. // remove ugly double 3d edge
  154. SetWindowPtr(hWnd, 0, ppd);
  155. ppd->hwnd = hWnd;
  156. ppd->iHigh = 100; // default to 0-100
  157. ppd->iStep = 10; // default to step of 10
  158. ppd->dwStyle = pcs->style;
  159. ppd->_clrBk = CLR_DEFAULT;
  160. ppd->_clrBar = CLR_DEFAULT;
  161. #ifdef DEBUG
  162. if (GetAsyncKeyState(VK_SHIFT) < 0 &&
  163. GetAsyncKeyState(VK_CONTROL) < 0)
  164. ppd->dwStyle |= PBS_SMOOTH;
  165. if (GetAsyncKeyState(VK_SHIFT) < 0 &&
  166. GetAsyncKeyState(VK_MENU) < 0) {
  167. ppd->dwStyle |= PBS_VERTICAL;
  168. SetWindowPos(hWnd, NULL, 0, 0, 40, 100, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  169. }
  170. #endif
  171. // hack of the 3d client edge that WM_BORDER implies in dialogs
  172. // add the 1 pixel static edge that we really want
  173. SetWindowLong(hWnd, GWL_EXSTYLE, (pcs->dwExStyle & ~WS_EX_CLIENTEDGE) | WS_EX_STATICEDGE);
  174. if (!(pcs->dwExStyle & WS_EX_STATICEDGE))
  175. SetWindowPos(hWnd, NULL, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
  176. return 0;
  177. }
  178. LRESULT CALLBACK ProgressWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  179. {
  180. int x;
  181. HFONT hFont;
  182. PPRO_DATA ppd = (PPRO_DATA)GetWindowPtr(hWnd, 0);
  183. switch (wMsg)
  184. {
  185. case WM_CREATE:
  186. CCCreateWindow();
  187. return Progress_OnCreate(hWnd, (LPCREATESTRUCT)lParam);
  188. case WM_DESTROY:
  189. CCDestroyWindow();
  190. if (ppd)
  191. LocalFree((HLOCAL)ppd);
  192. break;
  193. case WM_SYSCOLORCHANGE:
  194. InitGlobalColors();
  195. InvalidateRect(hWnd, NULL, TRUE);
  196. break;
  197. case WM_SETFONT:
  198. hFont = ppd->hfont;
  199. ppd->hfont = (HFONT)wParam;
  200. return (LRESULT)(UINT_PTR)hFont;
  201. case WM_GETFONT:
  202. return (LRESULT)(UINT_PTR)ppd->hfont;
  203. case PBM_GETPOS:
  204. return ppd->iPos;
  205. case PBM_GETRANGE:
  206. if (lParam) {
  207. PPBRANGE ppb = (PPBRANGE)lParam;
  208. ppb->iLow = ppd->iLow;
  209. ppb->iHigh = ppd->iHigh;
  210. }
  211. return (wParam ? ppd->iLow : ppd->iHigh);
  212. case PBM_SETRANGE:
  213. // win95 compat
  214. wParam = LOWORD(lParam);
  215. lParam = HIWORD(lParam);
  216. // fall through
  217. case PBM_SETRANGE32:
  218. {
  219. LRESULT lret = MAKELONG(ppd->iLow, ppd->iHigh);
  220. // only repaint if something actually changed
  221. if ((int)wParam != ppd->iLow || (int)lParam != ppd->iHigh)
  222. {
  223. ppd->iHigh = (int)lParam;
  224. ppd->iLow = (int)wParam;
  225. // force an invalidation/erase but don't redraw yet
  226. RedrawWindow(ppd->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
  227. UpdatePosition(ppd, ppd->iPos, FALSE);
  228. }
  229. return lret;
  230. }
  231. case PBM_SETPOS:
  232. return (LRESULT)UpdatePosition(ppd, (int) wParam, FALSE);
  233. case PBM_SETSTEP:
  234. x = ppd->iStep;
  235. ppd->iStep = (int)wParam;
  236. return (LRESULT)x;
  237. case PBM_STEPIT:
  238. return (LRESULT)UpdatePosition(ppd, ppd->iStep + ppd->iPos, TRUE);
  239. case PBM_DELTAPOS:
  240. return (LRESULT)UpdatePosition(ppd, ppd->iPos + (int)wParam, FALSE);
  241. case PBM_SETBKCOLOR:
  242. {
  243. COLORREF clr = ppd->_clrBk;
  244. ppd->_clrBk = (COLORREF)lParam;
  245. InvalidateRect(hWnd, NULL, TRUE);
  246. return clr;
  247. }
  248. case PBM_SETBARCOLOR:
  249. {
  250. COLORREF clr = ppd->_clrBar;
  251. ppd->_clrBar = (COLORREF)lParam;
  252. InvalidateRect(hWnd, NULL, TRUE);
  253. return clr;
  254. }
  255. case WM_PRINTCLIENT:
  256. case WM_PAINT:
  257. ProPaint(ppd,(HDC)wParam);
  258. break;
  259. case WM_ERASEBKGND:
  260. if (ppd) {
  261. if (ppd->_clrBk != CLR_DEFAULT) {
  262. RECT rc;
  263. GetClientRect(hWnd, &rc);
  264. FillRectClr((HDC)wParam, &rc, ppd->_clrBk);
  265. return 1;
  266. }
  267. }
  268. goto DoDefault;
  269. case WM_GETOBJECT:
  270. if( lParam == OBJID_QUERYCLASSNAMEIDX )
  271. return MSAA_CLASSNAMEIDX_PROGRESS;
  272. goto DoDefault;
  273. DoDefault:
  274. default:
  275. return DefWindowProc(hWnd,wMsg,wParam,lParam);
  276. }
  277. return 0;
  278. }