Ejemplo de grafica lineal en c

El siguiente código es un ejemplo de como crear una gráfica lineal como la del administrador de tareas de windows (taskmgr.exe). Para cambiar el tipo de gráfica haz clik sobre ella con el botón izquierdo del ratón.

#include <windows.h>
#include <math.h>

#define WIDTH 400
#define HEIGHT 125

HWND win = NULL;
DWORD timer = 0;
HDC specdc = 0, hdc = 0;
HBITMAP bmp = 0;
BYTE *pixels;
HPEN hPen;
unsigned int mode = 0, time = 0, pos = 0, v0, v1 = HEIGHT, grid = 0, a, b;

int sine_rand()
{
    static unsigned int values[10] = {0}, avg = 0;;
    int rn = (rand()%HEIGHT/2+sin(++time/31.416)*HEIGHT/2+HEIGHT/4);
    int index = time % 10;
    if (rn >= HEIGHT) rn = HEIGHT-1;
    else if (rn < 0) rn = 0;
    avg += rn - values[index];
    values[index] = rn;
    return avg / 10;
}

void CALLBACK Update(UINT id, UINT m, DWORD u , DWORD v, DWORD w)
{
    v0 = HEIGHT - 1 - sine_rand();

    if (mode == 0)
    {
        for (a = pos+1; a < HEIGHT * WIDTH; a += WIDTH)
            pixels[a] = 0, pixels[a+1] = 1;

        MoveToEx(specdc, pos, v1, NULL);
        LineTo(specdc, ++pos, v0);

        pos %= WIDTH;
    }
    else if (mode == 1)
    {
        BitBlt(specdc, 1, 0, WIDTH - 1, HEIGHT, specdc, 0, 0, SRCCOPY);
        for (a = 0; a < HEIGHT * WIDTH; a += WIDTH)
            pixels[a] = 0;

        MoveToEx(specdc, 1, v1, NULL);
        LineTo(specdc, 0, v0);
    }
    else //if (mode == 2)  windows taskmgr style
    {
        for (a = 0; a < HEIGHT * WIDTH; a += WIDTH)
        {
            memcpy(pixels + a, pixels + a + 1, WIDTH - 1);
            pixels[a + WIDTH - 1] = 0;
        }

        b = (grid++ % 11) ? 12*WIDTH : WIDTH;
        for (a = 0; a < HEIGHT * WIDTH; a += b)
            pixels[a+WIDTH-1] = 2;

        MoveToEx(specdc, WIDTH - 2, v1, NULL);
        LineTo(specdc, WIDTH - 1, v0);
    }
    v1 = v0;
    BitBlt(hdc, 0, 0, WIDTH, HEIGHT, specdc, 0, 0, SRCCOPY);
}

long FAR PASCAL WProc(HWND h, UINT m, WPARAM w, LPARAM l)
{
    switch (m)
    {
    case WM_PAINT:
    {
        RECT r;
        if (!GetUpdateRect(h, &r, 0)) return 0;
        PAINTSTRUCT p;
        HDC dc = BeginPaint(h, &p);
        if (!dc) return 0;
        BitBlt(dc, r.left, r.top, r.right-r.left, r.bottom-r.top,
               specdc, r.left, r.top, SRCCOPY);
        EndPaint(h, &p);
        return 0;
    }
    case WM_LBUTTONUP:
        mode = (mode + 1) % 3;
        memset(pixels, 0, WIDTH*HEIGHT);
        return 0;

    case WM_CREATE:
        win = h;
        hdc = GetDC(win);

        BYTE data[sizeof(BITMAPINFOHEADER) + 4*sizeof(RGBQUAD)] = {0};
        BITMAPINFO* bh = (BITMAPINFO*)data;
        RGBQUAD* pal = (RGBQUAD*)(data + sizeof(*bh));
        *bh = (BITMAPINFO){sizeof(*bh), WIDTH, HEIGHT, 1, 8, BI_RGB, 0,0,0,4,4};

        pal[0] = (RGBQUAD){0,0,0,0};
        pal[1] = (RGBQUAD){255,255,255,0};
        pal[2] = (RGBQUAD){0,100,0,0};
        pal[3] = (RGBQUAD){0,255,0,0};

        bmp = CreateDIBSection(0, bh, DIB_RGB_COLORS, (void**)&pixels, NULL, 0);
        specdc = CreateCompatibleDC(0);
        SelectObject(specdc, bmp);

        hPen = CreatePen(PS_SOLID, 1, RGB(0,255,0));
        SelectObject(specdc, hPen);

        timer = timeSetEvent(50, 20, (LPTIMECALLBACK)&Update, 0, TIME_PERIODIC);
        break;

    case WM_DESTROY:
        ReleaseDC(win, hdc);
        if (timer) timeKillEvent(timer);
        if (specdc) DeleteDC(specdc);
        if (bmp) DeleteObject(bmp);
        if (hPen) DeleteObject(hPen);
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(h, m, w, l);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev,LPSTR lpCmd, int nCmdShow)
{
    WNDCLASS wc = {0, WProc, 0, 0, hInst, 0, 0, 0, 0, "Spectrum"};

    if (!RegisterClass(&wc) || !CreateWindow("Spectrum","Ejemplo - DavidXL",
            WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 300, 200,
            WIDTH + 2 * GetSystemMetrics(SM_CXDLGFRAME), HEIGHT +
            GetSystemMetrics(SM_CYCAPTION) + 2*GetSystemMetrics(SM_CYDLGFRAME),
            NULL, NULL, hInst, NULL))
    {
        return 0; //Error
    }

    ShowWindow(win, SW_SHOWNORMAL);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

Comentarios