RLMETER.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:
Windows编程
开发平台:
Visual C++
- /**************************************************************************
- *
- * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- * PURPOSE.
- *
- * Copyright (C) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
- *
- **************************************************************************/
- /****************************************************************************
- *
- * rlmeter.c: Audio recording level window
- *
- * Vidcap32 Source code
- *
- ***************************************************************************/
- /*
- * This window class acts as a 'VU Meter' showing the current and peak
- * volume. Set the volume via the WMRL_SETLEVEL message (lParam is new level).
- * The peak level will be tracked by the control by means of a 2-second timer.
- */
- #include <windows.h>
- #include <windowsx.h>
- #include "rlmeter.h"
- #ifdef _WIN32
- #ifndef EXPORT
- #define EXPORT
- #endif
- #endif
- LONG FAR PASCAL EXPORT
- RLMeterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
- /*
- * generic window class to support a volume level display.
- *
- * The window has a white background, and draws a black filled
- * rectangle to show the current volume level, and a red line at the
- * peak. Every two seconds on a timer we lower the peak (we set the
- * saved peak value to 0 so that at the next update we move the line to
- * whatever is the current level.
- *
- * We store the pen and brush handles and the current and maximum levels
- * as window words using SetWindowWord on win16 and SetWindowLong on win32.
- */
- // window data layout
- #define WD_MAX 0 // current max
- #define WD_PREVMAX (WD_MAX + sizeof(UINT)) // currently drawn max
- #define WD_PREVLVL (WD_PREVMAX + sizeof(UINT)) // currently drawn level
- #define WD_PEN (WD_PREVLVL + sizeof(UINT)) // pen for max line
- #define WDBYTES (WD_PEN + sizeof(UINT)) // window bytes to alloc
- #ifdef _WIN32
- #define SetWindowUINT SetWindowLong
- #define GetWindowUINT GetWindowLong
- #else
- #define SetWindowUINT SetWindowWord
- #define GetWindowUINT GetWindowWord
- #endif
- // call (if first instance) to register class
- BOOL
- RLMeter_Register(HINSTANCE hInstance)
- {
- WNDCLASS cls;
- cls.hCursor = LoadCursor(NULL,IDC_ARROW);
- cls.hIcon = NULL;
- cls.lpszMenuName = NULL;
- cls.lpszClassName = RLMETERCLASS;
- cls.hbrBackground = GetStockObject(WHITE_BRUSH);
- cls.hInstance = hInstance;
- cls.style = CS_HREDRAW | CS_VREDRAW;
- cls.lpfnWndProc = RLMeterProc;
- cls.cbClsExtra = 0;
- cls.cbWndExtra = WDBYTES;
- return RegisterClass(&cls);
- }
- LONG FAR PASCAL EXPORT
- RLMeterProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch(message) {
- case WM_CREATE:
- // init current level and max to 0
- SetWindowUINT(hwnd, WD_MAX, 0);
- SetWindowUINT(hwnd, WD_PREVMAX, 0);
- SetWindowUINT(hwnd, WD_PREVLVL, 0);
- // create a red pen for the max line and store this
- SetWindowUINT(hwnd, WD_PEN,
- (UINT) CreatePen(PS_SOLID, 2, RGB(255, 0, 0)));
- break;
- case WM_DESTROY:
- // destroy the pen we created
- {
- HPEN hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
- if (hpen) {
- DeleteObject(hpen);
- SetWindowUINT(hwnd, WD_PEN, 0);
- }
- // also kill the timer we created
- KillTimer(hwnd, 0);
- }
- break;
- case WM_PAINT:
- /*
- * paint the entire control
- *
- * nb we must paint exactly as it is currently drawn because we
- * may be clipped to only part of the control. Thus we must draw
- * the max at WD_PREVMAX as it is currently drawn, since WD_MAX
- * may have been set to 0 and not yet drawn - in this case, with
- * some unfortunate timing and clipping, we would have two max lines.
- */
- {
- PAINTSTRUCT ps;
- HDC hdc;
- RECT rc, rcFill;
- HPEN hpenOld, hpen;
- hdc = BeginPaint(hwnd, &ps);
- GetClientRect(hwnd, &rc);
- // treat the level as a percentage and fill that much of the
- // control with black (from left)
- rcFill = rc;
- rcFill.right = (rc.right * GetWindowUINT(hwnd, WD_PREVLVL)) / 100;
- SetBkColor(hdc, RGB(0,0,0));
- // easy way to fill without creating a brush
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
- // draw the max line
- rcFill.right = (rc.right * GetWindowUINT(hwnd, WD_PREVLVL)) / 100;
- hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
- hpenOld = SelectObject(hdc, hpen);
- MoveToEx(hdc, rcFill.right, rcFill.top, NULL);
- LineTo(hdc, rcFill.right, rcFill.bottom);
- SelectObject(hdc, hpenOld);
- EndPaint(hwnd, &ps);
- }
- break;
- case WMRL_SETLEVEL:
- // set new level, and update the displayed level block and max line
- {
- RECT rc, rcFill;
- UINT uMax, uPrevMax, uPrevLevel, uLevel;
- HDC hdc;
- // new level is lParam
- uLevel = (UINT) lParam;
- // fetch other parameters
- uMax = GetWindowUINT(hwnd, WD_MAX);
- uPrevMax = GetWindowUINT(hwnd, WD_PREVMAX);
- uPrevLevel = GetWindowUINT(hwnd, WD_PREVLVL);
- // decay the max level. This rate works best if we are called
- // to update every 1/20th sec - in this case the decay will be
- // 64% in a second.
- if (uMax > 0) {
- uMax = (uMax * 2007) / 2048; // = 0.98 * uMax
- }
- hdc = GetDC(hwnd);
- GetClientRect(hwnd, &rc);
- rcFill = rc;
- // is the current level a new peak ?
- if (uLevel > uMax) {
- uMax = uLevel;
- }
- SetWindowUINT(hwnd, WD_MAX, uMax);
- // if the max has moved, erase the old line
- if (uMax != uPrevMax) {
- // white out the line by filling a 2-pixel wide rect
- rcFill.right = ((rc.right * uPrevMax) / 100) + 1;
- rcFill.left = rcFill.right - 2;
- SetBkColor(hdc, RGB(255, 255, 255));
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
- }
- // calculate the area to update
- rcFill.right = (rc.right * uPrevLevel) / 100;
- rcFill.left = (rc.right * uLevel) / 100;
- // are we erasing (lowering level) or drawing more black?
- if (rcFill.right > rcFill.left) {
- // level has dropped - so fill with white down to new level
- SetBkColor(hdc, RGB(255, 255, 255));
- } else {
- // level has gone up so fill with black up to new level
- int t;
- t = rcFill.right;
- rcFill.right = rcFill.left;
- rcFill.left = t;
- SetBkColor(hdc, RGB(0, 0, 0));
- // fill a little extra to ensure no rounding gaps
- if (rcFill.left > 0) {
- rcFill.left -= 1;
- }
- }
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcFill, NULL, 0, NULL);
- SetWindowUINT(hwnd, WD_PREVLVL, uLevel);
- // draw the new max line if needed
- if (uMax != uPrevMax) {
- HPEN hpen, hpenOld;
- rcFill.right = (rc.right * uMax) /100;
- hpen = (HPEN) GetWindowUINT(hwnd, WD_PEN);
- hpenOld = SelectObject(hdc, hpen);
- MoveToEx(hdc, rcFill.right, rcFill.top, NULL);
- LineTo(hdc, rcFill.right, rcFill.bottom);
- SelectObject(hdc, hpenOld);
- SetWindowUINT(hwnd, WD_PREVMAX, uMax);
- }
- ReleaseDC(hwnd, hdc);
- return(0);
- }
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
- }