RLMETER.C
上传用户:carrie980
上传日期:2013-03-28
资源大小:1143k
文件大小:8k
源码类别:

视频捕捉/采集

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1992 - 1996 Microsoft Corporation.  All Rights Reserved.
  9.  *
  10.  **************************************************************************/
  11. /****************************************************************************
  12.  *
  13.  *   rlmeter.c: Audio recording level window
  14.  *
  15.  *   Vidcap32 Source code
  16.  *
  17.  ***************************************************************************/
  18. /*
  19.  * This window class acts as a 'VU Meter' showing the current and peak
  20.  * volume. Set the volume via the WMRL_SETLEVEL message (lParam is new level).
  21.  * The peak level will be tracked by the control by means of a 2-second timer.
  22.  */
  23. #include <windows.h>
  24. #include <windowsx.h>
  25. #include "rlmeter.h"
  26. #ifdef _WIN32
  27. #ifndef EXPORT
  28. #define EXPORT
  29. #endif
  30. #endif
  31. LONG FAR PASCAL EXPORT
  32. RLMeterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  33. /*
  34.  * generic window class to support a volume level display.
  35.  *
  36.  * The window has a white background, and draws a black filled
  37.  * rectangle to show the current volume level, and a red line at the
  38.  * peak. Every two seconds on a timer we lower the peak (we set the
  39.  * saved peak value to 0 so that at the next update we move the line to
  40.  * whatever is the current level.
  41.  *
  42.  * We store the pen and brush handles and the current and maximum levels
  43.  * as window words using SetWindowWord on win16 and SetWindowLong on win32.
  44.  */
  45. // window data layout
  46. #define WD_MAX      0                           // current max
  47. #define WD_PREVMAX  (WD_MAX + sizeof(UINT))     // currently drawn max
  48. #define WD_PREVLVL  (WD_PREVMAX + sizeof(UINT)) // currently drawn level
  49. #define WD_PEN      (WD_PREVLVL + sizeof(UINT)) // pen for max line
  50. #define WDBYTES     (WD_PEN + sizeof(UINT))     // window bytes to alloc
  51. #ifdef _WIN32
  52. #define SetWindowUINT     SetWindowLong
  53. #define GetWindowUINT     GetWindowLong
  54. #else
  55. #define SetWindowUINT     SetWindowWord
  56. #define GetWindowUINT     GetWindowWord
  57. #endif
  58. // call (if first instance) to register class
  59. BOOL
  60. RLMeter_Register(HINSTANCE hInstance)
  61. {
  62.     WNDCLASS cls;
  63.     cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  64.     cls.hIcon          = NULL;
  65.     cls.lpszMenuName   = NULL;
  66.     cls.lpszClassName  = RLMETERCLASS;
  67.     cls.hbrBackground  = GetStockObject(WHITE_BRUSH);
  68.     cls.hInstance      = hInstance;
  69.     cls.style          = CS_HREDRAW | CS_VREDRAW;
  70.     cls.lpfnWndProc    = RLMeterProc;
  71.     cls.cbClsExtra     = 0;
  72.     cls.cbWndExtra     = WDBYTES;
  73.     return RegisterClass(&cls);
  74. }
  75. LONG FAR PASCAL EXPORT
  76. RLMeterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  77. {
  78.     switch(message) {
  79.     case WM_CREATE:
  80.         // init current level and max to 0
  81.         SetWindowUINT(hwnd, WD_MAX, 0);
  82.         SetWindowUINT(hwnd, WD_PREVMAX, 0);
  83.         SetWindowUINT(hwnd, WD_PREVLVL, 0);
  84.         // create a red pen for the max line and store this
  85.         SetWindowUINT(hwnd, WD_PEN,
  86.                 (UINT) CreatePen(PS_SOLID, 2, RGB(255, 0, 0)));
  87.         break;
  88.     case WM_DESTROY:
  89.         // destroy the pen we created
  90.         {
  91.             HPEN hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
  92.             if (hpen) {
  93.                 DeleteObject(hpen);
  94.                 SetWindowUINT(hwnd, WD_PEN, 0);
  95.             }
  96.             // also kill the timer we created
  97.             KillTimer(hwnd, 0);
  98.         }
  99.         break;
  100.     case WM_PAINT:
  101.         /*
  102.          * paint the entire control
  103.          *
  104.          * nb we must paint exactly as it is currently drawn because we
  105.          * may be clipped to only part of the control. Thus we must draw
  106.          * the max at WD_PREVMAX as it is currently drawn, since WD_MAX
  107.          * may have been set to 0 and not yet drawn - in this case, with
  108.          * some unfortunate timing and clipping, we would have two max lines.
  109.          */
  110.         {
  111.             PAINTSTRUCT ps;
  112.             HDC hdc;
  113.             RECT rc, rcFill;
  114.             HPEN hpenOld, hpen;
  115.             hdc = BeginPaint(hwnd, &ps);
  116.             GetClientRect(hwnd, &rc);
  117.             // treat the level as a percentage and fill that much of the
  118.             // control with black (from left)
  119.             rcFill = rc;
  120.             rcFill.right = (rc.right * GetWindowUINT(hwnd, WD_PREVLVL)) / 100;
  121.             SetBkColor(hdc, RGB(0,0,0));
  122.             // easy way to fill without creating a brush
  123.             ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
  124.             // draw the max line
  125.             rcFill.right = (rc.right * GetWindowUINT(hwnd, WD_PREVLVL)) / 100;
  126.             hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
  127.             hpenOld = SelectObject(hdc, hpen);
  128.             MoveToEx(hdc, rcFill.right, rcFill.top, NULL);
  129.             LineTo(hdc, rcFill.right, rcFill.bottom);
  130.             SelectObject(hdc, hpenOld);
  131.             EndPaint(hwnd, &ps);
  132.         }
  133.         break;
  134.     case WMRL_SETLEVEL:
  135.         // set new level, and update the displayed level block and max line
  136.         {
  137.             RECT rc, rcFill;
  138.             UINT uMax, uPrevMax, uPrevLevel, uLevel;
  139.             HDC hdc;
  140.             // new level is lParam
  141.             uLevel = (UINT) lParam;
  142.             // fetch other parameters
  143.             uMax = GetWindowUINT(hwnd, WD_MAX);
  144.             uPrevMax = GetWindowUINT(hwnd, WD_PREVMAX);
  145.             uPrevLevel = GetWindowUINT(hwnd, WD_PREVLVL);
  146.             // decay the max level. This rate works best if we are called
  147.             // to update every 1/20th sec - in this case the decay will be
  148.             // 64% in a second.
  149.             if (uMax > 0) {
  150.                 uMax = (uMax * 2007) / 2048;     // = 0.98 * uMax
  151.             }
  152.             hdc = GetDC(hwnd);
  153.             GetClientRect(hwnd, &rc);
  154.             rcFill = rc;
  155.             // is the current level a new peak ?
  156.             if (uLevel > uMax) {
  157.                 uMax = uLevel;
  158.             }
  159.             SetWindowUINT(hwnd, WD_MAX, uMax);
  160.             // if the max has moved, erase the old line
  161.             if (uMax != uPrevMax) {
  162.                 // white out the line by filling a 2-pixel wide rect
  163.                 rcFill.right = ((rc.right * uPrevMax) / 100) + 1;
  164.                 rcFill.left = rcFill.right - 2;
  165.                 SetBkColor(hdc, RGB(255, 255, 255));
  166.                 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
  167.             }
  168.             // calculate the area to update
  169.             rcFill.right = (rc.right * uPrevLevel) / 100;
  170.             rcFill.left = (rc.right * uLevel) / 100;
  171.             // are we erasing (lowering level) or drawing more black?
  172.             if (rcFill.right > rcFill.left) {
  173.                 // level has dropped - so fill with white down to new level
  174.                 SetBkColor(hdc, RGB(255, 255, 255));
  175.             } else {
  176.                 // level has gone up so fill with black up to new level
  177.                 int t;
  178.                 t = rcFill.right;
  179.                 rcFill.right = rcFill.left;
  180.                 rcFill.left = t;
  181.                 SetBkColor(hdc, RGB(0, 0, 0));
  182.                 // fill a little extra to ensure no rounding gaps
  183.                 if (rcFill.left > 0) {
  184.                     rcFill.left -= 1;
  185.                 }
  186.             }
  187.             ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
  188.             SetWindowUINT(hwnd, WD_PREVLVL, uLevel);
  189.             // draw the new max line if needed
  190.             if (uMax != uPrevMax) {
  191.                 HPEN hpen, hpenOld;
  192.                 rcFill.right = (rc.right * uMax) /100;
  193.                 hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
  194.                 hpenOld = SelectObject(hdc, hpen);
  195.                 MoveToEx(hdc, rcFill.right, rcFill.top, NULL);
  196.                 LineTo(hdc, rcFill.right, rcFill.bottom);
  197.                 SelectObject(hdc, hpenOld);
  198.                 SetWindowUINT(hwnd, WD_PREVMAX, uMax);
  199.             }
  200.             ReleaseDC(hwnd, hdc);
  201.             return(0);
  202.         }
  203.     }
  204.     return DefWindowProc(hwnd, message, wParam, lParam);
  205. }