mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
f40644e9e6
* started graph control git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3215 21ef857c-d57f-4fe0-8362-d861dc6d29cd
339 lines
8.8 KiB
C
339 lines
8.8 KiB
C
/*
|
|
* Process Hacker -
|
|
* graph control
|
|
*
|
|
* Copyright (C) 2010 wj32
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <phgui.h>
|
|
#include <graph.h>
|
|
|
|
typedef struct _PHP_GRAPH_CONTEXT
|
|
{
|
|
PH_GRAPH_DRAW_INFO DrawInfo;
|
|
} PHP_GRAPH_CONTEXT, *PPHP_GRAPH_CONTEXT;
|
|
|
|
LRESULT CALLBACK PhpGraphWndProc(
|
|
__in HWND hwnd,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
);
|
|
|
|
BOOLEAN PhGraphControlInitialization()
|
|
{
|
|
WNDCLASSEX c = { sizeof(c) };
|
|
|
|
c.style = 0;
|
|
c.lpfnWndProc = PhpGraphWndProc;
|
|
c.cbClsExtra = 0;
|
|
c.cbWndExtra = sizeof(PVOID);
|
|
c.hInstance = PhInstanceHandle;
|
|
c.hIcon = NULL;
|
|
c.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
c.hbrBackground = NULL;
|
|
c.lpszMenuName = NULL;
|
|
c.lpszClassName = PH_GRAPH_CLASSNAME;
|
|
c.hIconSm = NULL;
|
|
|
|
if (!RegisterClassEx(&c))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID PhDrawGraph(
|
|
__in HDC hdc,
|
|
__in PPH_GRAPH_DRAW_INFO DrawInfo
|
|
)
|
|
{
|
|
ULONG width;
|
|
ULONG height;
|
|
ULONG flags;
|
|
ULONG step;
|
|
RECT rect;
|
|
POINT points[4];
|
|
HPEN nullPen;
|
|
HPEN dcPen;
|
|
HBRUSH dcBrush;
|
|
|
|
width = DrawInfo->Width;
|
|
height = DrawInfo->Height;
|
|
flags = DrawInfo->Flags;
|
|
step = DrawInfo->Step;
|
|
|
|
nullPen = GetStockObject(NULL_PEN);
|
|
dcPen = GetStockObject(DC_PEN);
|
|
dcBrush = GetStockObject(DC_BRUSH);
|
|
|
|
// Fill in the background.
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = width;
|
|
rect.bottom = height;
|
|
SetDCBrushColor(hdc, DrawInfo->BackColor);
|
|
FillRect(hdc, &rect, dcBrush);
|
|
|
|
// Draw the data.
|
|
|
|
{
|
|
ULONG x = width - DrawInfo->Step;
|
|
ULONG index = 0;
|
|
|
|
SelectObject(hdc, dcBrush);
|
|
|
|
while (index < DrawInfo->LineDataCount - 1)
|
|
{
|
|
FLOAT f0; // 0..1
|
|
FLOAT f1;
|
|
ULONG h0; // height..0
|
|
ULONG h1;
|
|
|
|
// Draw line 1.
|
|
|
|
f0 = DrawInfo->LineData1[index];
|
|
f1 = DrawInfo->LineData1[index + 1];
|
|
h0 = (ULONG)((1 - f0) * height);
|
|
h1 = (ULONG)((1 - f1) * height);
|
|
|
|
// top-left, top-right, bottom-right, bottom-left
|
|
points[0].x = x;
|
|
points[0].y = h1;
|
|
points[1].x = x + step;
|
|
points[1].y = h0;
|
|
points[2].x = x + step;
|
|
points[2].y = height;
|
|
points[3].x = x;
|
|
points[3].y = height;
|
|
|
|
// Fill in the area below the line.
|
|
SelectObject(hdc, nullPen);
|
|
SetDCBrushColor(hdc, DrawInfo->LineBackColor1);
|
|
Polygon(hdc, points, 4);
|
|
|
|
// Draw the line.
|
|
|
|
SelectObject(hdc, dcPen);
|
|
SetDCPenColor(hdc, DrawInfo->LineColor1);
|
|
Polyline(hdc, points, 2);
|
|
|
|
// Draw line 2 (either stacked or overlayed).
|
|
if (flags & PH_GRAPH_USE_LINE_2)
|
|
{
|
|
if (flags & PH_GRAPH_OVERLAY_LINE_2)
|
|
{
|
|
f0 = DrawInfo->LineData2[index];
|
|
f1 = DrawInfo->LineData2[index + 1];
|
|
}
|
|
else
|
|
{
|
|
f0 += DrawInfo->LineData2[index];
|
|
f1 += DrawInfo->LineData2[index + 1];
|
|
|
|
if (f0 > 1) f0 = 1;
|
|
if (f1 > 1) f1 = 1;
|
|
}
|
|
|
|
h0 = (ULONG)((1 - f0) * height);
|
|
h1 = (ULONG)((1 - f1) * height);
|
|
|
|
if (flags & PH_GRAPH_OVERLAY_LINE_2)
|
|
{
|
|
points[0].y = h1;
|
|
points[1].y = h0;
|
|
|
|
SelectObject(hdc, nullPen);
|
|
SetDCBrushColor(hdc, DrawInfo->LineBackColor2);
|
|
Polygon(hdc, points, 4);
|
|
|
|
SelectObject(hdc, dcPen);
|
|
SetDCPenColor(hdc, DrawInfo->LineColor2);
|
|
Polyline(hdc, points, 2);
|
|
}
|
|
else
|
|
{
|
|
// Fix the bottom points so we don't fill in the line 1 area.
|
|
points[2].y = points[1].y; // p2.y = h0(line1)
|
|
points[3].y = points[0].y; // p3.y = h1(line1)
|
|
points[0].y = h1;
|
|
points[1].y = h0;
|
|
|
|
SelectObject(hdc, nullPen);
|
|
SetDCBrushColor(hdc, DrawInfo->LineBackColor2);
|
|
Polygon(hdc, points, 4);
|
|
|
|
SelectObject(hdc, dcPen);
|
|
SetDCPenColor(hdc, DrawInfo->LineColor2);
|
|
Polyline(hdc, points, 2);
|
|
}
|
|
}
|
|
|
|
if (x < 0)
|
|
break;
|
|
|
|
x -= step;
|
|
index++;
|
|
}
|
|
}
|
|
|
|
// Draw the grid.
|
|
if (flags & PH_GRAPH_USE_GRID)
|
|
{
|
|
ULONG x = width / DrawInfo->GridWidth;
|
|
ULONG y = height / DrawInfo->GridHeight;
|
|
ULONG i;
|
|
ULONG pos;
|
|
|
|
SetDCPenColor(hdc, DrawInfo->GridColor);
|
|
SelectObject(hdc, dcPen);
|
|
|
|
// Draw the vertical lines.
|
|
|
|
points[0].y = 0;
|
|
points[1].y = height;
|
|
|
|
for (i = 0; i <= x; i++)
|
|
{
|
|
pos = width - (i * DrawInfo->GridWidth + DrawInfo->GridStart);
|
|
points[0].x = pos;
|
|
points[1].x = pos;
|
|
Polyline(hdc, points, 2);
|
|
}
|
|
|
|
// Draw the horizontal lines.
|
|
|
|
points[0].x = 0;
|
|
points[1].x = width;
|
|
|
|
for (i = 0; i <= y; i++)
|
|
{
|
|
pos = i * DrawInfo->GridHeight - 1;
|
|
points[0].y = pos;
|
|
points[1].y = pos;
|
|
Polyline(hdc, points, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
HWND PhCreateGraphControl(
|
|
__in HWND ParentHandle,
|
|
__in INT_PTR Id
|
|
)
|
|
{
|
|
return CreateWindow(
|
|
PH_GRAPH_CLASSNAME,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
|
0,
|
|
0,
|
|
3,
|
|
3,
|
|
ParentHandle,
|
|
(HMENU)Id,
|
|
PhInstanceHandle,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
VOID PhpCreateGraphContext(
|
|
__out PPHP_GRAPH_CONTEXT *Context
|
|
)
|
|
{
|
|
PPHP_GRAPH_CONTEXT context;
|
|
|
|
context = PhAllocate(sizeof(PHP_GRAPH_CONTEXT));
|
|
|
|
context->DrawInfo.Width = 3;
|
|
context->DrawInfo.Height = 3;
|
|
context->DrawInfo.Flags = PH_GRAPH_USE_GRID;
|
|
context->DrawInfo.Step = 2;
|
|
context->DrawInfo.BackColor = RGB(0x00, 0x00, 0x00);
|
|
context->DrawInfo.LineDataCount = 0;
|
|
context->DrawInfo.LineData1 = NULL;
|
|
context->DrawInfo.LineData2 = NULL;
|
|
context->DrawInfo.LineColor1 = RGB(0x00, 0xff, 0x00);
|
|
context->DrawInfo.LineColor2 = RGB(0xff, 0x00, 0x00);
|
|
context->DrawInfo.LineBackColor1 = RGB(0x00, 0x77, 0x00);
|
|
context->DrawInfo.LineBackColor2 = RGB(0x77, 0x00, 0x00);
|
|
context->DrawInfo.GridColor = RGB(0x00, 0xaa, 0x00);
|
|
context->DrawInfo.GridWidth = 12;
|
|
context->DrawInfo.GridHeight = 12;
|
|
context->DrawInfo.GridStart = 0;
|
|
|
|
*Context = context;
|
|
}
|
|
|
|
VOID PhpDeleteGraphContext(
|
|
__inout PPHP_GRAPH_CONTEXT Context
|
|
)
|
|
{
|
|
PhFree(Context);
|
|
}
|
|
|
|
LRESULT CALLBACK PhpGraphWndProc(
|
|
__in HWND hwnd,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
)
|
|
{
|
|
PPHP_GRAPH_CONTEXT context;
|
|
|
|
context = (PPHP_GRAPH_CONTEXT)GetWindowLongPtr(hwnd, 0);
|
|
|
|
if (uMsg == WM_CREATE)
|
|
{
|
|
PhpCreateGraphContext(&context);
|
|
SetWindowLongPtr(hwnd, 0, (LONG_PTR)context);
|
|
}
|
|
|
|
if (!context)
|
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
PhpDeleteGraphContext(context);
|
|
SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL);
|
|
}
|
|
break;
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT paintStruct;
|
|
HDC hdc;
|
|
|
|
if (hdc = BeginPaint(hwnd, &paintStruct))
|
|
{
|
|
PhDrawGraph(hdc, &context->DrawInfo);
|
|
EndPaint(hwnd, &paintStruct);
|
|
}
|
|
}
|
|
break;
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
}
|