program Project1;
uses
Windows,
Messages;
const
EXWNDLONG_SIZE = 4 *4;
GWL_POINTS = 0;
GWL_MIN = 4;
GWL_MAX = 8;
GWL_STEPSIZE = 12;
GM_SETMINMAXVALUE = WM_USER;
GM_ADDPOINT = WM_USER + 1;
type
tPoints = array of Integer;
pPoints = ^tPoints;
function WndProc(Wnd : HWND; msg : Cardinal; wParam, lParam : Integer) : Integer; stdcall;
var PaintStuct : TPaintStruct;
i, len, y, Range, Min, Max : Integer;
Scale : Double;
Points : pPoints;
rt : TRect;
begin
case msg of
WM_CREATE :
begin
New(Points);
SetWindowLong(Wnd, GWL_POINTS, Integer(Points));
SetWindowLong(wnd, GWL_MIN, 0);
SetWindowLong(wnd, GWL_MAX, 64);
SetWindowLong(wnd, GWL_STEPSIZE, 8);
SetTimer(wnd, 0, 450, nil);
end; {WM_CREATE}
WM_DESTROY :
begin
Points := pPoints( GetWindowLong(Wnd, GWL_POINTS) );
SetLength(Points^, 0);
Dispose(Points);
PostQuitMessage(0);
end; {WM_DESTOY}
WM_PAINT :
begin
BeginPaint(Wnd, PaintStuct);
FillRect(PaintStuct.hdc, PaintStuct.rcPaint, GetStockObject(WHITE_BRUSH));
Points := pPoints( GetWindowLong(Wnd, GWL_POINTS) );
GetClientRect(wnd, rt);
Min := GetWindowLong(wnd, GWL_MIN);
Max := GetWindowLong(wnd, GWL_MAX);
Range := Abs(min) + abs(max);
Scale := rt.Bottom / Range;
y := trunc(rt.Bottom - Points^[0]*scale);
y := trunc(y + Min*scale);
MoveToEx(PaintStuct.hdc, rt.Right, y, nil);
//нет смысла перересовывать все, можно расчитать PaintStuct.rcPaint
for i := 1 to Length(Points^) - 1 do
begin
Dec(rt.Right, GetWindowLong(Wnd, GWL_STEPSIZE));
y := trunc(rt.Bottom - Points^*scale);
y := trunc(y + Min*scale);
LineTo(PaintStuct.hdc, rt.Right, y);
end;
Writeln;
EndPaint(Wnd, PaintStuct);
end; {WM_PAINT}
WM_TIMER :
begin
SendMessage(wnd, GM_ADDPOINT, Random(64), 0);// собственно нужно только это
//InvalidateRect(wnd, nil, false);
end; { WM_TIMER }
WM_SIZE :
begin
Points := pPoints( GetWindowLong(Wnd, GWL_POINTS) );
GetClientRect(wnd, rt);
SetLength(Points^, (rt.Right div GetWindowLong(Wnd, GWL_STEPSIZE)) + 1);
end; { WM_SIZE }
GM_ADDPOINT :
begin
Points := pPoints( GetWindowLong(Wnd, GWL_POINTS) );
for i := Length(Points^) - 1 downto 0 do Points^[i+1] := Points^;
//CopyMemory(@Points^[1], @Points^[0], Length(Points^) - 1);
Points^[0] := wParam;
i := GetWindowLong(wnd, GWL_STEPSIZE);
ScrollWindow(Wnd, -i, 0, nil, nil);
end { GM_ADDPOINT }
else
begin
Result := DefWindowProc(Wnd, msg, wParam, lParam);
end;
end
end;
var
wnd : HWND;
msg : TMsg;
wc : TWndClass;
begin
ZeroMemory(@wc, SizeOf(wc));
wc.style := CS_DBLCLKS or CS_OWNDC or CS_VREDRAW or CS_HREDRAW;
wc.lpfnWndProc := @WndProc;
wc.cbWndExtra := EXWNDLONG_SIZE;
wc.hInstance := hInstance;
wc.hIcon := LoadIcon(0, IDI_APPLICATION);
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.lpszClassName := 'GraphicWndClass';
if not Boolean(RegisterClass(wc)) then
begin
MessageBox(0, PChar('Class <' + wc.lpszClassName + '> is not register'), nil, MB_ICONERROR or MB_SYSTEMMODAL);
ExitProcess(0)
end;
wnd := CreateWindow('GraphicWndClass', 'Graphic', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0, 0, HInstance, nil);
if wnd = 0 then
begin
MessageBox(0, PChar('Window not created'), nil, MB_ICONERROR or MB_SYSTEMMODAL);
ExitProcess(0)
end;
ShowWindow(wnd, SW_SHOW);
while GetMessage(msg, 0, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end.
Хронологический график средствами WinAPI
Вообщем, стоит задача реализации графика на подобии графиков в диспетчере задач Windows. Подручными средствами пытался опеределить их принадлежность к common control-ам, ничего не получилось:(. Может кто сталкивался с такой задачей или кто-нить видел примерные решения ?
P.S. В С Builder и Delphi есть такая компонента как TPerformanceGraph, но проблема в том, что они собирают большие по размерам модули, так что их использование сразу отпадает!
Наверно можно найти подходящий исходник. Я как-то делал подобное, правда, сразу для нескольких процессов. Но у меня оно не существует отдельно от приложения - надо выколупывать. Это может занять некоторое время. Плюс к тому и весить оно будет килобайт 300...
Цитата:
Наверно можно найти подходящий исходник.
Вот приглядываюсь к классу TPerformanceGraph, придется тогда немного помучиться, чтоб его заточить под GDI.
почему не написать что-то удовлетворяющее своим нужнам? вроде не накладно, с первого взгляда
Тебе на си или на паскале нужен?
Цитата: 0nni
Тебе на си или на паскале нужен?
Желательно на С, мона и на паскале :) переделаю, а есть что предложить ?
Вот целый класс, Графика конечно не ах, (да и комментариев нет), но минимум что надо
Кстати fpc, выдает obj-файлы. если есть возможность их подключить то код можно и не переписывать (с массивом динамическим что делать будуте?). Есть еще вариант оформить класс в dll.
Ды нет, я все-таки перепишу на С, а с массивом что-нить придумаю :) что получится, выложу тут.
ок. Там только в коде WriteLn; лишний. Я для отладки все в консоль вывожу, вот и забыл убрать.
Для тех кто заинтересовался: в коде на паскале используется 32-разрядное значение в дополнительном пространстве памяти об окне для хранения информации для графика, можно использовать либо глобальные переменные, либо если это класс, защищенные переменые! Вместо паскалевского динамического массива использем вектор,а если проще, то просто буффер с DWORD значениями. При изменении размера окна просто делаем realloc памяти! Вообщем-то все! Как будет время выложу полный исходник класса.