восстановление морды (частичное)
This commit is contained in:
1 parent
6ffec2f1e7
commit
b8ea33160d
9 files changed
+436
-143
No files matched your search
@@ -0,0 +1,40 @@
|
||||
# ETCP Monitor Makefile for MinGW
|
||||
# Usage: make [CC=gcc] [CFLAGS=...] [LDFLAGS=...]
|
||||
|
||||
# Compiler
|
||||
CC ?= gcc
|
||||
|
||||
# Target
|
||||
TARGET = etcpmon.exe
|
||||
|
||||
# Source files
|
||||
SRCS = etcpmon_main.c \
|
||||
etcpmon_gui.c \
|
||||
etcpmon_client.c \
|
||||
etcpmon_graph.c
|
||||
|
||||
# Object files
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
# Windows-specific libraries
|
||||
LIBS = -lws2_32 -lgdi32 -lcomdlg32 -lkernel32 -luser32 -lcomctl32
|
||||
# Compiler flags
|
||||
CFLAGS += -Wall -Wextra
|
||||
CFLAGS += -O2
|
||||
CFLAGS += -D_WIN32_WINNT=0x0601
|
||||
CFLAGS += -DUNICODE -D_UNICODE
|
||||
CFLAGS += -I.
|
||||
|
||||
# Build rule
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET) *.o
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* etcpmon_graph.c - ETCP Monitor Graph (20 SPS, 1px=1sample, left scroll, low CPU)
|
||||
*
|
||||
* Изменения по твоему запросу:
|
||||
* - Вертикальная линия курсора остаётся
|
||||
* - Строка с значениями под курсором ("RTT-L: 45.2 ...") полностью убрана
|
||||
* - Значения в блоках под графиком всегда живые (обновляются в on_metrics)
|
||||
*/
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include "etcpmon_graph.h"
|
||||
#include "etcpmon_client.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "etcpmon_gui.h"
|
||||
|
||||
const COLORREF graph_colors[GRAPH_METRICS_COUNT] = {
|
||||
RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(255,255,0),
|
||||
RGB(255,0,255), RGB(0,255,255), RGB(255,128,0), RGB(128,0,255)
|
||||
};
|
||||
|
||||
const char* graph_metric_names[GRAPH_METRICS_COUNT] = {
|
||||
"RTT Last","RTT Avg10","RTT Avg100","Jitter",
|
||||
"Retrns","ACKs","Inflght","Bytes/s"
|
||||
};
|
||||
|
||||
static void RecalculateMinMax(struct metrics_history* hist, int vis, int oldest)
|
||||
{
|
||||
for (int m = 0; m < GRAPH_METRICS_COUNT; m++) {
|
||||
float mn = 1e9f;
|
||||
float mx = -1e9f;
|
||||
|
||||
for (int i = 0; i < vis; i++) {
|
||||
float v = hist->values[m][(oldest + i) % GRAPH_HISTORY_SIZE];
|
||||
if (v < mn) mn = v;
|
||||
if (v > mx) mx = v;
|
||||
}
|
||||
|
||||
if (mx - mn < 0.001f) {
|
||||
if (mn > 0.0f) { mn *= 0.9f; mx *= 1.1f; }
|
||||
else { mx = 1.0f; }
|
||||
}
|
||||
|
||||
hist->min_val[m] = mn;
|
||||
hist->max_val[m] = mx;
|
||||
}
|
||||
}
|
||||
|
||||
void GetSelectedChannels(struct etcpmon_app* app, int* selected, int* count) {
|
||||
*count = 0;
|
||||
if (!app) return;
|
||||
for (int i = 0; i < GRAPH_METRICS_COUNT; i++) {
|
||||
if (app->hChannelCheck[i] &&
|
||||
SendMessageA(app->hChannelCheck[i], BM_GETCHECK, 0, 0) == BST_CHECKED) {
|
||||
selected[(*count)++] = i;
|
||||
}
|
||||
}
|
||||
if (*count == 0)
|
||||
for (int i = 0; i < 4 && i < GRAPH_METRICS_COUNT; i++)
|
||||
selected[(*count)++] = i;
|
||||
}
|
||||
|
||||
void DrawGraph(HDC hdc, RECT* rc, struct etcpmon_app* app)
|
||||
{
|
||||
if (!app || !rc) return;
|
||||
|
||||
int w = rc->right - rc->left;
|
||||
int h = rc->bottom - rc->top;
|
||||
|
||||
/* Off-screen буфер */
|
||||
HDC memDC = CreateCompatibleDC(hdc);
|
||||
HBITMAP bmp = CreateCompatibleBitmap(hdc, w, h);
|
||||
HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, bmp);
|
||||
|
||||
SetBkMode(memDC, TRANSPARENT);
|
||||
|
||||
/* Фон */
|
||||
HBRUSH bg = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
|
||||
FillRect(memDC, rc, bg);
|
||||
DeleteObject(bg);
|
||||
|
||||
/* Нет данных */
|
||||
if (!app->client || !etcpmon_client_get_history(app->client) ||
|
||||
etcpmon_client_get_history(app->client)->count < 2)
|
||||
{
|
||||
SetTextColor(memDC, RGB(128, 128, 128));
|
||||
DrawTextA(memDC, "Waiting for data...", -1, rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
struct metrics_history* hist = etcpmon_client_get_history(app->client);
|
||||
|
||||
/* Выбранные каналы */
|
||||
int sel[GRAPH_METRICS_COUNT];
|
||||
int sc = 0;
|
||||
GetSelectedChannels(app, sel, &sc);
|
||||
|
||||
int pad = 5;
|
||||
int gl = pad + 45; /* левая граница графика */
|
||||
int gr = w - pad; /* правая граница */
|
||||
int gt = pad; /* верх */
|
||||
int gb = h - 25; /* низ */
|
||||
int gh = gb - gt;
|
||||
|
||||
/* === Сетка === */
|
||||
HPEN grid = CreatePen(PS_DOT, 1, GetSysColor(COLOR_BTNSHADOW));
|
||||
HPEN old = (HPEN)SelectObject(memDC, grid);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
int y = pad + (h - 2 * pad) * i / 5;
|
||||
MoveToEx(memDC, pad, y, NULL);
|
||||
LineTo(memDC, w - pad, y);
|
||||
}
|
||||
SelectObject(memDC, old);
|
||||
DeleteObject(grid);
|
||||
|
||||
/* === Оси === */
|
||||
HPEN axis = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWTEXT));
|
||||
old = (HPEN)SelectObject(memDC, axis);
|
||||
MoveToEx(memDC, gl, gt, NULL); LineTo(memDC, gl, gb);
|
||||
MoveToEx(memDC, gl, gb, NULL); LineTo(memDC, gr, gb);
|
||||
SelectObject(memDC, old);
|
||||
DeleteObject(axis);
|
||||
|
||||
/* Сколько точек видно */
|
||||
int vis = (hist->count < gr - gl) ? hist->count : (gr - gl);
|
||||
int oldest = (hist->head - vis + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
|
||||
int startx = gr - vis;
|
||||
|
||||
/* Пересчёт min/max 5 раз в секунду */
|
||||
DWORD now = GetTickCount();
|
||||
if (now - hist->last_minmax_update >= 200) {
|
||||
RecalculateMinMax(hist, vis, oldest);
|
||||
hist->last_minmax_update = now;
|
||||
}
|
||||
|
||||
/* Буфер точек */
|
||||
POINT* points = (POINT*)malloc((vis + 1) * sizeof(POINT));
|
||||
|
||||
/* Рисуем графики */
|
||||
for (int ch = 0; ch < sc; ch++) {
|
||||
int m = sel[ch];
|
||||
float mn = hist->min_val[m];
|
||||
float mx = hist->max_val[m];
|
||||
|
||||
SelectObject(memDC, app->hGraphPens[m]);
|
||||
|
||||
for (int i = 0; i < vis; i++) {
|
||||
float v = hist->values[m][(oldest + i) % GRAPH_HISTORY_SIZE];
|
||||
int x = startx + i;
|
||||
int y = gb - (int)((v - mn) / (mx - mn + 1e-9f) * (float)gh);
|
||||
if (y < gt) y = gt;
|
||||
if (y > gb) y = gb;
|
||||
points[i].x = x;
|
||||
points[i].y = y;
|
||||
}
|
||||
Polyline(memDC, points, vis);
|
||||
}
|
||||
|
||||
free(points);
|
||||
|
||||
/* === ВЕРТИКАЛЬНАЯ ЛИНИЯ КУРСОРА (только линия, без текста) === */
|
||||
if (app->graph_cursor_active) {
|
||||
HPEN cp = CreatePen(PS_SOLID, 1, RGB(80, 80, 80));
|
||||
old = (HPEN)SelectObject(memDC, cp);
|
||||
MoveToEx(memDC, app->graph_cursor_x, gt, NULL);
|
||||
LineTo(memDC, app->graph_cursor_x, gb);
|
||||
SelectObject(memDC, old);
|
||||
DeleteObject(cp);
|
||||
}
|
||||
|
||||
end:
|
||||
/* Копируем на экран */
|
||||
BitBlt(hdc, 0, 0, w, h, memDC, 0, 0, SRCCOPY);
|
||||
|
||||
SelectObject(memDC, oldBmp);
|
||||
DeleteObject(bmp);
|
||||
DeleteDC(memDC);
|
||||
}
|
||||
|
||||
void UpdateChannelValues(struct etcpmon_app* app, int history_idx)
|
||||
{
|
||||
if (!app || !app->client) return;
|
||||
|
||||
struct metrics_history* h = etcpmon_client_get_history(app->client);
|
||||
if (!h || history_idx < 0 || history_idx >= GRAPH_HISTORY_SIZE) {
|
||||
for (int i = 0; i < GRAPH_METRICS_COUNT; i++) {
|
||||
if (app->hChannelValue[i])
|
||||
SetWindowTextA(app->hChannelValue[i], "-");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static char last_text[GRAPH_METRICS_COUNT][32] = {0};
|
||||
|
||||
for (int i = 0; i < GRAPH_METRICS_COUNT; i++) {
|
||||
if (!app->hChannelValue[i]) continue;
|
||||
|
||||
float val = h->values[i][history_idx];
|
||||
char buf[32] = {0};
|
||||
|
||||
if (i == GRAPH_METRIC_BYTES_SENT) {
|
||||
if (val >= 1024*1024) snprintf(buf, sizeof(buf), "%.1f MB/s", val/(1024.*1024.));
|
||||
else if (val >= 1024) snprintf(buf, sizeof(buf), "%.1f KB/s", val/1024.);
|
||||
else snprintf(buf, sizeof(buf), "%.0f B/s", val);
|
||||
} else if (i == GRAPH_METRIC_INFLIGHT) {
|
||||
if (val >= 1024) snprintf(buf, sizeof(buf), "%.1f KB", val/1024.);
|
||||
else snprintf(buf, sizeof(buf), "%.0f B", val);
|
||||
} else if (i == GRAPH_METRIC_RETRANS || i == GRAPH_METRIC_ACKS) {
|
||||
snprintf(buf, sizeof(buf), "%.0f /s", val);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%.1f ms", val);
|
||||
}
|
||||
|
||||
if (strcmp(buf, last_text[i]) == 0)
|
||||
continue;
|
||||
|
||||
strcpy(last_text[i], buf);
|
||||
|
||||
SendMessageA(app->hChannelValue[i], WM_SETREDRAW, FALSE, 0);
|
||||
SetWindowTextA(app->hChannelValue[i], buf);
|
||||
SendMessageA(app->hChannelValue[i], WM_SETREDRAW, TRUE, 0);
|
||||
InvalidateRect(app->hChannelValue[i], NULL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK GraphWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
struct etcpmon_app* app = (struct etcpmon_app*)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE: {
|
||||
CREATESTRUCTA* cs = (CREATESTRUCTA*)lParam;
|
||||
app = cs->lpCreateParams;
|
||||
SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)app);
|
||||
if (app) app->hGraphWnd = hWnd;
|
||||
break;
|
||||
}
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
RECT rc;
|
||||
GetClientRect(hWnd, &rc);
|
||||
DrawGraph(hdc, &rc, app);
|
||||
EndPaint(hWnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSEMOVE: {
|
||||
if (!app) break;
|
||||
|
||||
int x = LOWORD(lParam);
|
||||
int y = HIWORD(lParam);
|
||||
RECT rc;
|
||||
GetClientRect(hWnd, &rc);
|
||||
|
||||
BOOL inside = (x >= 0 && x < rc.right && y >= 0 && y < rc.bottom);
|
||||
|
||||
if (inside) {
|
||||
app->graph_cursor_x = x;
|
||||
app->graph_cursor_active = 1;
|
||||
|
||||
static DWORD last_invalidate = 0;
|
||||
DWORD now = GetTickCount();
|
||||
if (now - last_invalidate >= 10) {
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
last_invalidate = now;
|
||||
}
|
||||
} else {
|
||||
app->graph_cursor_active = 0;
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_MOUSELEAVE:
|
||||
if (app) {
|
||||
app->graph_cursor_active = 0;
|
||||
InvalidateRect(hWnd, NULL, FALSE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProcA(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* etcpmon_graph.h - ETCP Monitor Graph Definitions
|
||||
*/
|
||||
|
||||
#ifndef ETCPMON_GRAPH_H
|
||||
#define ETCPMON_GRAPH_H
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Graph constants */
|
||||
#define GRAPH_WIDTH 860
|
||||
#define GRAPH_HEIGHT 150
|
||||
#define CHANNEL_LIST_HEIGHT 80
|
||||
#define GRAPH_METRICS_COUNT 8
|
||||
#define GRAPH_HISTORY_SIZE 860
|
||||
|
||||
/* Forward declarations */
|
||||
struct etcpmon_app;
|
||||
struct metrics_history;
|
||||
|
||||
/* Graph colors for each metric */
|
||||
extern const COLORREF graph_colors[GRAPH_METRICS_COUNT];
|
||||
extern const char* graph_metric_names[GRAPH_METRICS_COUNT];
|
||||
|
||||
/* Graph functions */
|
||||
LRESULT CALLBACK GraphWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
void DrawGraph(HDC hdc, RECT* rc, struct etcpmon_app* app);
|
||||
void GetSelectedChannels(struct etcpmon_app* app, int* selected, int* count);
|
||||
void UpdateChannelValues(struct etcpmon_app* app, int cursor_sample);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ETCPMON_GRAPH_H */
|
||||
+33
-65
@@ -49,6 +49,14 @@ static void on_metrics(struct etcpmon_rsp_metrics* metrics,
|
||||
static void on_error(const char* msg, void* user_data);
|
||||
|
||||
/* Helper functions */
|
||||
static void SetDlgItemTextFmt(HWND hDlg, int nIDDlgItem, const char* fmt, ...) {
|
||||
char buf[256];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
SetDlgItemTextA(hDlg, nIDDlgItem, buf);
|
||||
}
|
||||
|
||||
int etcpmon_gui_init(struct etcpmon_app* app, HINSTANCE hInstance) {
|
||||
if (!app) return -1;
|
||||
@@ -76,7 +84,7 @@ int etcpmon_gui_init(struct etcpmon_app* app, HINSTANCE hInstance) {
|
||||
wcex.lpszClassName = ETCPMON_WINDOW_CLASS;
|
||||
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||
|
||||
if (!RegisterClassExA(&wcex)) {
|
||||
if (!RegisterClassExA(&wcex)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -205,10 +213,8 @@ static void CreateControls(struct etcpmon_app* app) {
|
||||
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
|
||||
x, y + 20, 300, 120, hWnd, (HMENU)IDC_LIST_CONNECTIONS, hInst, NULL);
|
||||
|
||||
/* Graph area - between Connections and ETCP Metrics */
|
||||
/* Graph area */
|
||||
y += 140;
|
||||
// app->hGraphWnd = CreateWindowA("STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
|
||||
// 10, y, GRAPH_WIDTH, GRAPH_HEIGHT, hWnd, (HMENU)IDC_GRAPH, hInst, app);
|
||||
|
||||
app->hGraphWnd = CreateWindowExA(
|
||||
WS_EX_CLIENTEDGE,
|
||||
@@ -217,8 +223,8 @@ static void CreateControls(struct etcpmon_app* app) {
|
||||
10, y, GRAPH_WIDTH, GRAPH_HEIGHT,
|
||||
hWnd, (HMENU)IDC_GRAPH, hInst, app);
|
||||
|
||||
/* Channel list - grid blocks below graph */
|
||||
y += GRAPH_HEIGHT + 5;
|
||||
/* Channel blocks below graph (checkbox + name в одной строке, значение ниже) */
|
||||
y += GRAPH_HEIGHT + 8;
|
||||
|
||||
const char* channel_short_names[] = {
|
||||
"RTT-L", "RTT10", "RTT100", "Jitter",
|
||||
@@ -226,9 +232,9 @@ static void CreateControls(struct etcpmon_app* app) {
|
||||
};
|
||||
|
||||
int block_w = 200;
|
||||
int block_h = 28;
|
||||
int block_h = 48; /* компактная высота */
|
||||
int cols = 4;
|
||||
int spacing = 5;
|
||||
int spacing = 6;
|
||||
|
||||
for (int i = 0; i < GRAPH_METRICS_COUNT; i++) {
|
||||
int col = i % cols;
|
||||
@@ -236,17 +242,23 @@ static void CreateControls(struct etcpmon_app* app) {
|
||||
int bx = 10 + col * (block_w + spacing);
|
||||
int by = y + row * (block_h + spacing);
|
||||
|
||||
/* Галочка слева */
|
||||
app->hChannelCheck[i] = CreateWindowExA(0, "BUTTON", "",
|
||||
WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BST_CHECKED,
|
||||
bx, by + 4, 16, 14, hWnd, (HMENU)(UINT_PTR)(IDC_CH_CHECK_0 + i), hInst, NULL);
|
||||
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BST_CHECKED,
|
||||
bx, by, 20, 18,
|
||||
hWnd, (HMENU)(UINT_PTR)(IDC_CH_CHECK_0 + i), hInst, NULL);
|
||||
|
||||
/* Название сразу справа от галочки */
|
||||
app->hChannelName[i] = CreateWindowExA(0, "STATIC", channel_short_names[i],
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
bx + 20, by + 4, 60, 16, hWnd, (HMENU)(UINT_PTR)(IDC_CH_NAME_0 + i), hInst, NULL);
|
||||
WS_CHILD | WS_VISIBLE | SS_LEFT,
|
||||
bx + 24, by + 2, block_w - 30, 16,
|
||||
hWnd, (HMENU)(UINT_PTR)(IDC_CH_NAME_0 + i), hInst, NULL);
|
||||
|
||||
/* Значение под названием */
|
||||
app->hChannelValue[i] = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
|
||||
WS_CHILD | WS_VISIBLE | ES_READONLY,
|
||||
bx + 85, by + 2, 110, 20, hWnd, (HMENU)(UINT_PTR)(IDC_CH_VALUE_0 + i), hInst, NULL);
|
||||
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
|
||||
bx, by + 21, block_w, 22,
|
||||
hWnd, (HMENU)(UINT_PTR)(IDC_CH_VALUE_0 + i), hInst, NULL);
|
||||
}
|
||||
|
||||
int channel_grid_h = ((GRAPH_METRICS_COUNT + cols - 1) / cols) * (block_h + spacing) - spacing;
|
||||
@@ -505,34 +517,6 @@ static void OnTimer(struct etcpmon_app* app) {
|
||||
InvalidateRect(app->hGraphWnd, NULL, FALSE);
|
||||
UpdateWindow(app->hGraphWnd); /* форсируем немедленную перерисовку */
|
||||
}
|
||||
|
||||
/* 5. Цифры под графиком — обновляем если курсор не активен */
|
||||
if (!app->graph_cursor_active) {
|
||||
struct metrics_history* h = etcpmon_client_get_history(app->client);
|
||||
if (h && h->count > 0) {
|
||||
int last_idx = (h->head - 1 + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
|
||||
UpdateChannelValues(app, last_idx);
|
||||
}
|
||||
} else {
|
||||
RECT rc;
|
||||
GetClientRect(app->hGraphWnd, &rc);
|
||||
struct metrics_history* h = etcpmon_client_get_history(app->client);
|
||||
if (h && h->count > 2) {
|
||||
int w = rc.right - rc.left;
|
||||
int pad = 5;
|
||||
int gl = pad + 45;
|
||||
int gr = w - pad;
|
||||
int vis = (h->count < gr - gl) ? h->count : (gr - gl);
|
||||
int oldest = (h->head - vis + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
|
||||
int startx = gr - vis;
|
||||
int x = app->graph_cursor_x;
|
||||
if (x >= startx && x < startx + vis) {
|
||||
int rel = x - startx;
|
||||
int idx = (oldest + rel) % GRAPH_HISTORY_SIZE;
|
||||
UpdateChannelValues(app, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateUIState(struct etcpmon_app* app) {
|
||||
@@ -545,17 +529,11 @@ static void UpdateUIState(struct etcpmon_app* app) {
|
||||
}
|
||||
|
||||
/* Client callbacks */
|
||||
//static void on_connected(void* user_data) {
|
||||
// struct etcpmon_app* app = (struct etcpmon_app*)user_data;
|
||||
// etcpmon_gui_set_status(app, "Connected");
|
||||
//}
|
||||
|
||||
static void on_connected(void* user_data) {
|
||||
struct etcpmon_app* app = (struct etcpmon_app*)user_data;
|
||||
app->isConnected = 1;
|
||||
UpdateUIState(app);
|
||||
etcpmon_gui_set_status(app, "Connected");
|
||||
// Добавьте для теста
|
||||
if (app->client->log_file) {
|
||||
fprintf(app->client->log_file, "[DEBUG] on_connected called\n");
|
||||
fflush(app->client->log_file);
|
||||
@@ -579,7 +557,6 @@ void etcpmon_gui_update_graph(struct etcpmon_app* app, struct etcpmon_rsp_metric
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_disconnected(void* user_data) {
|
||||
struct etcpmon_app* app = (struct etcpmon_app*)user_data;
|
||||
app->isConnected = 0;
|
||||
@@ -587,21 +564,14 @@ static void on_disconnected(void* user_data) {
|
||||
etcpmon_gui_set_status(app, "Disconnected");
|
||||
}
|
||||
|
||||
//static void on_conn_list(struct etcpmon_conn_info* list, uint8_t count, void* user_data) {
|
||||
// struct etcpmon_app* app = (struct etcpmon_app*)user_data;
|
||||
// etcpmon_gui_update_conn_list(app, list, count);
|
||||
//}
|
||||
static void on_conn_list(struct etcpmon_conn_info* list, uint8_t count, void* user_data) {
|
||||
struct etcpmon_app* app = (struct etcpmon_app*)user_data;
|
||||
etcpmon_gui_update_conn_list(app, list, count);
|
||||
etcpmon_gui_set_status(app, "Connection list updated");
|
||||
|
||||
// Automatically select the first connection if available
|
||||
/* Automatically select the first connection if available */
|
||||
if (count > 0 && app->hListConnections) {
|
||||
// Select the first item (index 0)
|
||||
SendMessage(app->hListConnections, LB_SETCURSEL, 0, 0);
|
||||
|
||||
// Trigger the selection handler to request metrics
|
||||
OnConnectionSelect(app);
|
||||
}
|
||||
}
|
||||
@@ -614,12 +584,10 @@ static void on_metrics(struct etcpmon_rsp_metrics* metrics,
|
||||
etcpmon_gui_update_metrics(app, metrics, links, links_count);
|
||||
etcpmon_client_add_to_history(app->client, metrics);
|
||||
|
||||
if (!app->graph_cursor_active) {
|
||||
struct metrics_history* h = etcpmon_client_get_history(app->client);
|
||||
if (h && h->count > 0) {
|
||||
int last_idx = (h->head - 1 + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
|
||||
UpdateChannelValues(app, last_idx);
|
||||
}
|
||||
struct metrics_history* h = etcpmon_client_get_history(app->client);
|
||||
if (h && h->count > 0) {
|
||||
int last_idx = (h->head - 1 + GRAPH_HISTORY_SIZE) % GRAPH_HISTORY_SIZE;
|
||||
UpdateChannelValues(app, last_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -699,7 +667,7 @@ static BOOL UpdateEditIfChanged(HWND hDlg, int nIDDlgItem, const char* fmt, ...)
|
||||
GetDlgItemTextA(hDlg, nIDDlgItem, old_text, sizeof(old_text));
|
||||
|
||||
if (strcmp(old_text, new_text) == 0)
|
||||
return FALSE; /* ничего не изменилось — не трогаем */
|
||||
return FALSE;
|
||||
|
||||
SetDlgItemTextA(hDlg, nIDDlgItem, new_text);
|
||||
InvalidateRect(GetDlgItem(hDlg, nIDDlgItem), NULL, FALSE);
|
||||
@@ -734,7 +702,7 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
|
||||
UpdateEditIfChanged(hMain, IDC_EDIT_TUN_READ_ERRS, "%u", metrics->tun.read_errors);
|
||||
UpdateEditIfChanged(hMain, IDC_EDIT_TUN_WRITE_ERRS, "%u", metrics->tun.write_errors);
|
||||
|
||||
/* Links list (перестраивается всегда — он маленький, моргание почти незаметно) */
|
||||
/* Links list */
|
||||
if (app->hListLinks) {
|
||||
SendMessage(app->hListLinks, LB_RESETCONTENT, 0, 0);
|
||||
for (uint8_t i = 0; i < links_count; i++) {
|
||||
|
||||
@@ -62,12 +62,10 @@ extern "C" {
|
||||
/* Link list control ID */
|
||||
#define IDC_LIST_LINKS 400
|
||||
|
||||
/* Graph control IDs */
|
||||
/* Graph control ID */
|
||||
#define IDC_GRAPH 500
|
||||
#define IDC_STATIC_GRAPH 501
|
||||
#define IDC_LIST_CHANNELS 502
|
||||
|
||||
/* Channel block IDs - 8 channels, 4 columns x 2 rows */
|
||||
/* Channel block IDs */
|
||||
#define IDC_CH_NAME_0 510
|
||||
#define IDC_CH_VALUE_0 520
|
||||
#define IDC_CH_CHECK_0 530
|
||||
@@ -100,6 +98,7 @@ struct etcpmon_app {
|
||||
HWND hWndStatus;
|
||||
|
||||
HPEN hGraphPens[GRAPH_METRICS_COUNT];
|
||||
|
||||
/* Connection controls */
|
||||
HWND hEditAddr;
|
||||
HWND hEditPort;
|
||||
@@ -130,19 +129,21 @@ struct etcpmon_app {
|
||||
/* Links list */
|
||||
HWND hListLinks;
|
||||
|
||||
/* Graph controls (managed by graph module) */
|
||||
/* Graph controls */
|
||||
HWND hGraphWnd;
|
||||
HWND hChannelName[GRAPH_METRICS_COUNT];
|
||||
HWND hChannelValue[GRAPH_METRICS_COUNT];
|
||||
HWND hChannelCheck[GRAPH_METRICS_COUNT];
|
||||
|
||||
/* Cursor (вертикальная линия остаётся) */
|
||||
int graph_cursor_x;
|
||||
int graph_cursor_y;
|
||||
int graph_cursor_active;
|
||||
|
||||
/* Client state - pointer to actual client structure */
|
||||
/* Client state */
|
||||
struct etcpmon_client* client;
|
||||
|
||||
/* Timer ID */
|
||||
/* Timer */
|
||||
UINT_PTR updateTimer;
|
||||
DWORD last_poll_time;
|
||||
int isConnected;
|
||||
|
||||
Reference in new issue
Block a user