VOID EtpGpuIconUpdateCallback( _In_ struct _PH_NF_ICON *Icon, _Out_ PVOID *NewIconOrBitmap, _Out_ PULONG Flags, _Out_ PPH_STRING *NewText, _In_opt_ PVOID Context ) { static PH_GRAPH_DRAW_INFO drawInfo = { 16, 16, 0, 2, RGB(0x00, 0x00, 0x00), 16, NULL, NULL, 0, 0, 0, 0 }; ULONG maxDataCount; ULONG lineDataCount; PFLOAT lineData1; HBITMAP bitmap; PVOID bits; HDC hdc; HBITMAP oldBitmap; HANDLE maxGpuProcessId; PPH_PROCESS_ITEM maxGpuProcessItem; PH_FORMAT format[8]; // Icon Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap); maxDataCount = drawInfo.Width / 2 + 1; lineData1 = _alloca(maxDataCount * sizeof(FLOAT)); lineDataCount = min(maxDataCount, EtGpuNodeHistory.Count); PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, lineData1, lineDataCount); drawInfo.LineDataCount = lineDataCount; drawInfo.LineData1 = lineData1; drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorCpuKernel"); drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1); if (bits) PhDrawGraphDirect(hdc, bits, &drawInfo); SelectObject(hdc, oldBitmap); *NewIconOrBitmap = bitmap; *Flags = PH_NF_UPDATE_IS_BITMAP; // Text if (EtMaxGpuNodeHistory.Count != 0) maxGpuProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxGpuNodeHistory, 0)); else maxGpuProcessId = NULL; if (maxGpuProcessId) maxGpuProcessItem = PhReferenceProcessItem(maxGpuProcessId); else maxGpuProcessItem = NULL; PhInitFormatS(&format[0], L"GPU Usage: "); PhInitFormatF(&format[1], EtGpuNodeUsage * 100, 2); PhInitFormatC(&format[2], '%'); if (maxGpuProcessItem) { PhInitFormatC(&format[3], '\n'); PhInitFormatSR(&format[4], maxGpuProcessItem->ProcessName->sr); PhInitFormatS(&format[5], L": "); PhInitFormatF(&format[6], EtGetProcessBlock(maxGpuProcessItem)->GpuNodeUsage * 100, 2); PhInitFormatC(&format[7], '%'); } *NewText = PhFormat(format, maxGpuProcessItem ? 8 : 3, 128); if (maxGpuProcessItem) PhDereferenceObject(maxGpuProcessItem); }
VOID EtpNetworkIconUpdateCallback( _In_ struct _PH_NF_ICON *Icon, _Out_ PVOID *NewIconOrBitmap, _Out_ PULONG Flags, _Out_ PPH_STRING *NewText, _In_opt_ PVOID Context ) { static PH_GRAPH_DRAW_INFO drawInfo = { 16, 16, PH_GRAPH_USE_LINE_2, 2, RGB(0x00, 0x00, 0x00), 16, NULL, NULL, 0, 0, 0, 0 }; ULONG maxDataCount; ULONG lineDataCount; PFLOAT lineData1; PFLOAT lineData2; FLOAT max; ULONG i; HBITMAP bitmap; PVOID bits; HDC hdc; HBITMAP oldBitmap; HANDLE maxNetworkProcessId; PPH_PROCESS_ITEM maxNetworkProcessItem; PH_FORMAT format[6]; // Icon Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap); maxDataCount = drawInfo.Width / 2 + 1; lineData1 = _alloca(maxDataCount * sizeof(FLOAT)); lineData2 = _alloca(maxDataCount * sizeof(FLOAT)); lineDataCount = min(maxDataCount, EtNetworkReceiveHistory.Count); max = 1024 * 1024; // minimum scaling of 1 MB. for (i = 0; i < lineDataCount; i++) { lineData1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, i); lineData2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, i); if (max < lineData1[i] + lineData2[i]) max = lineData1[i] + lineData2[i]; } PhDivideSinglesBySingle(lineData1, max, lineDataCount); PhDivideSinglesBySingle(lineData2, max, lineDataCount); drawInfo.LineDataCount = lineDataCount; drawInfo.LineData1 = lineData1; drawInfo.LineData2 = lineData2; drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorIoReadOther"); drawInfo.LineColor2 = PhGetIntegerSetting(L"ColorIoWrite"); drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1); drawInfo.LineBackColor2 = PhHalveColorBrightness(drawInfo.LineColor2); if (bits) PhDrawGraphDirect(hdc, bits, &drawInfo); SelectObject(hdc, oldBitmap); *NewIconOrBitmap = bitmap; *Flags = PH_NF_UPDATE_IS_BITMAP; // Text if (EtMaxNetworkHistory.Count != 0) maxNetworkProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxNetworkHistory, 0)); else maxNetworkProcessId = NULL; if (maxNetworkProcessId) maxNetworkProcessItem = PhReferenceProcessItem(maxNetworkProcessId); else maxNetworkProcessItem = NULL; PhInitFormatS(&format[0], L"Network\nR: "); PhInitFormatSize(&format[1], EtNetworkReceiveDelta.Delta); PhInitFormatS(&format[2], L"\nS: "); PhInitFormatSize(&format[3], EtNetworkSendDelta.Delta); if (maxNetworkProcessItem) { PhInitFormatC(&format[4], '\n'); PhInitFormatSR(&format[5], maxNetworkProcessItem->ProcessName->sr); } *NewText = PhFormat(format, maxNetworkProcessItem ? 6 : 4, 128); if (maxNetworkProcessItem) PhDereferenceObject(maxNetworkProcessItem); }
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: { context->Handle = hwnd; } break; case WM_DESTROY: { if (context->TooltipHandle) DestroyWindow(context->TooltipHandle); PhpDeleteBufferedContext(context); PhpFreeGraphContext(context); SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); } break; case WM_SIZE: { // Force a re-create of the buffered context. PhpCreateBufferedContext(context); SendMessage(hwnd, GCM_DRAW, 0, 0); } break; case WM_PAINT: { PAINTSTRUCT paintStruct; RECT clientRect; HDC hdc; if (hdc = BeginPaint(hwnd, &paintStruct)) { GetClientRect(hwnd, &clientRect); if (context->BufferedContext) { BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, context->BufferedContext, 0, 0, SRCCOPY); } EndPaint(hwnd, &paintStruct); } } break; case WM_ERASEBKGND: return 1; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case TTN_GETDISPINFO: { LPNMTTDISPINFO dispInfo = (LPNMTTDISPINFO)header; POINT point; RECT clientRect; PH_GRAPH_GETTOOLTIPTEXT getTooltipText; GetCursorPos(&point); MapWindowPoints(NULL, hwnd, &point, 1); GetClientRect(hwnd, &clientRect); getTooltipText.Header.hwndFrom = hwnd; getTooltipText.Header.code = GCN_GETTOOLTIPTEXT; getTooltipText.Index = (clientRect.right - point.x) / context->DrawInfo.Step; getTooltipText.TotalCount = context->DrawInfo.LineDataCount; getTooltipText.Text.Buffer = NULL; getTooltipText.Text.Length = 0; SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&getTooltipText); if (getTooltipText.Text.Buffer) { dispInfo->lpszText = getTooltipText.Text.Buffer; } } break; case TTN_SHOW: context->TooltipVisible = TRUE; break; case TTN_POP: context->TooltipVisible = FALSE; break; } } break; case WM_MOUSEMOVE: { if (context->TooltipHandle) { PhpUpdateTooltip(context); } } break; case WM_MOUSELEAVE: { if (context->TooltipHandle) { TOOLINFO toolInfo = { sizeof(toolInfo) }; toolInfo.hwnd = hwnd; toolInfo.uId = 1; SendMessage(context->TooltipHandle, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolInfo); } } break; case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDBLCLK: { PH_GRAPH_MOUSEEVENT mouseEvent; RECT clientRect; GetClientRect(hwnd, &clientRect); mouseEvent.Header.hwndFrom = hwnd; mouseEvent.Header.code = GCN_MOUSEEVENT; mouseEvent.Message = uMsg; mouseEvent.Keys = (ULONG)wParam; mouseEvent.Point.x = LOWORD(lParam); mouseEvent.Point.y = HIWORD(lParam); mouseEvent.Index = (clientRect.right - mouseEvent.Point.x) / context->DrawInfo.Step; mouseEvent.TotalCount = context->DrawInfo.LineDataCount; SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&mouseEvent); } break; case GCM_GETDRAWINFO: { PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)lParam; memcpy(drawInfo, &context->DrawInfo, sizeof(PH_GRAPH_DRAW_INFO)); } return TRUE; case GCM_SETDRAWINFO: { PPH_GRAPH_DRAW_INFO drawInfo = (PPH_GRAPH_DRAW_INFO)lParam; ULONG width; ULONG height; width = context->DrawInfo.Width; height = context->DrawInfo.Height; memcpy(&context->DrawInfo, drawInfo, sizeof(PH_GRAPH_DRAW_INFO)); context->DrawInfo.Width = width; context->DrawInfo.Height = height; } return TRUE; case GCM_DRAW: { if (!context->BufferedContext) PhpCreateBufferedContext(context); context->DrawInfo.Width = context->BufferedContextRect.right; context->DrawInfo.Height = context->BufferedContextRect.bottom; { PH_GRAPH_GETDRAWINFO getDrawInfo; getDrawInfo.Header.hwndFrom = hwnd; getDrawInfo.Header.code = GCN_GETDRAWINFO; getDrawInfo.DrawInfo = &context->DrawInfo; SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&getDrawInfo); } if (context->BufferedBits) PhDrawGraphDirect(context->BufferedContext, context->BufferedBits, &context->DrawInfo); } return TRUE; case GCM_MOVEGRID: { LONG increment = (LONG)wParam; context->DrawInfo.GridStart += increment; } return TRUE; case GCM_GETBUFFEREDCONTEXT: return (LRESULT)context->BufferedContext; case GCM_SETTOOLTIP: { if (wParam) { TOOLINFO toolInfo = { sizeof(toolInfo) }; context->TooltipHandle = CreateWindow( TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, PhLibImageBase, NULL ); context->TooltipOldWndProc = (WNDPROC)GetWindowLongPtr(context->TooltipHandle, GWLP_WNDPROC); SetProp(context->TooltipHandle, PhpMakeGraphTooltipContextAtom(), (HANDLE)context); SetWindowLongPtr(context->TooltipHandle, GWLP_WNDPROC, (LONG_PTR)PhpTooltipWndProc); SetWindowPos(context->TooltipHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); toolInfo.uFlags = TTF_ABSOLUTE | TTF_TRACK; toolInfo.hwnd = hwnd; toolInfo.uId = 1; toolInfo.lpszText = LPSTR_TEXTCALLBACK; SendMessage(context->TooltipHandle, TTM_ADDTOOL, 0, (LPARAM)&toolInfo); // Allow newlines (-1 doesn't work) // MAXINT doesn't work either on high DPI configurations for some reason. SendMessage(context->TooltipHandle, TTM_SETMAXTIPWIDTH, 0, 4096); } else { DestroyWindow(context->TooltipHandle); context->TooltipHandle = NULL; } } return TRUE; case GCM_UPDATETOOLTIP: { if (!context->TooltipHandle) return FALSE; if (context->TooltipVisible) { TOOLINFO toolInfo = { sizeof(toolInfo) }; toolInfo.hwnd = hwnd; toolInfo.uId = 1; toolInfo.lpszText = LPSTR_TEXTCALLBACK; SendMessage(context->TooltipHandle, TTM_UPDATETIPTEXT, 0, (LPARAM)&toolInfo); } else { PhpUpdateTooltip(context); } } return TRUE; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }