progress.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

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