#include
#include
#include
// The structure stores the boundaries of all displays
typedef struct {
int left;
int top;
int right;
int bottom;
} MonitorBounds;
// Callback function: Calculate the total area of all displays
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
MonitorBounds* bounds = (MonitorBounds*)dwData;
// Update the minimum/maximum boundaries of all displays
bounds->left = min(bounds->left, lprcMonitor->left);
bounds->top = min(bounds->top, lprcMonitor->top);
bounds->right = max(bounds->right, lprcMonitor->right);
bounds->bottom = max(bounds->bottom, lprcMonitor->bottom);
return TRUE; // Continue enumerating
}
// Limit window movement within all screens and allow coverage of taskbar
void ClampWindowPosition(HWND hwnd, WINDOWPOS* wp) {
RECT windowRect;
GetWindowRect(hwnd, &windowRect);
int windowWidth = windowRect.right - windowRect.left;
int windowHeight = windowRect.bottom - windowRect.top;
// Get the regions of all displays
MonitorBounds screenBounds = { INT_MAX, INT_MAX, INT_MIN, INT_MIN };
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&screenBounds);
// Limit the left and top of the window
if (wp->x < screenBounds.left) {
wp->x = screenBounds.left;
}
if (wp->y < screenBounds.top) {
wp->y = screenBounds.top;
}
// Limit the right and bottom of the window (allow to overwrite the taskbar)
if (wp->x + windowWidth > screenBounds.right) {
wp->x = screenBounds.right - windowWidth;
}
if (wp->y + windowHeight > screenBounds.bottom) {
wp->y = screenBounds.bottom - windowHeight;
}
}
COLORREF transparentColor = RGB(255, 255, 255);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char text[100];
static int i = 0;
sprintf_s(text, "WindowProc %d\n", i++);
OutputDebugStringA(text);
switch (uMsg)
{
case WM_CREATE:
{
LONG_PTR exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
exStyle |= WS_EX_NOPARENTNOTIFY;
exStyle |= WS_EX_LAYERED;
exStyle |= WS_EX_TOPMOST;
exStyle |= WS_EX_LEFT;
exStyle |= WS_EX_NOACTIVATE;
//exStyle |= WS_EX_TOOLWINDOW; // Set as a tool window so that icons do not appear on the taskbar
SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
SetLayeredWindowAttributes(hWnd, transparentColor, 255, LWA_COLORKEY | LWA_ALPHA);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// Text to be displayed
LPCWSTR text = TEXT("");
wchar_t buffer[1024] = { 0 };
for (int i = 0; i < 4; i++) {
wcscat_s(buffer, 1024, TEXT("This is a line of lyrics This is a line of lyrics\n"));
}
text = buffer;
// Create Font
HFONT hFont = CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, TEXT("Consolas"));
HFONT oldFont = (HFONT)SelectObject(hdc, hFont);
// Calculate text size
RECT textRect = { 0, 0, 800, 600 };
DrawText(hdc, text, -1, &textRect, DT_CALCRECT | DT_WORDBREAK); // Only calculate size, do not draw
// Set window size
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, textRect.right - textRect.left,
textRect.bottom - textRect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
// Set Text Color
SetTextColor(hdc, RGB(255, 0, 0));
SetBkMode(hdc, TRANSPARENT);
// Draw text (centered)
DrawText(hdc, text, -1, &textRect, DT_WORDBREAK);
// clean
SelectObject(hdc, oldFont);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
break;
}
case WM_SIZE:
{
break;
}
case WM_COMMAND:
{
break;
}
case WM_LBUTTONDOWN:
{
PostMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
break;
}
case WM_LBUTTONDBLCLK:
{
break;
}
case WM_RBUTTONDOWN:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
TCHAR buffer[256];
StringCchPrintf(buffer, 256, TEXT("xPos: %d, yPos: %d\nThe window is about to close"), xPos, yPos);
MessageBox(hWnd, buffer, TEXT("tip"), MB_OK);
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
case WM_MOUSEMOVE:
{
SetLayeredWindowAttributes(hWnd, NULL, 255, LWA_COLORKEY);
// Track the mouse and check if it moves out of the window
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
tme.dwHoverTime = 0;
TrackMouseEvent(&tme);
break;
}
case WM_MOUSELEAVE:
{
OutputDebugString(TEXT("The mouse has been moved out of the window!"));
SetLayeredWindowAttributes(hWnd, transparentColor, 255, LWA_COLORKEY);
break;
}
case WM_KEYDOWN:
{
break;
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
break;
}
LPCTSTR lpWindowplace = TEXT("./WinConfig.ini");
if (uMsg == WM_CREATE) {
// Window place
WINDOWPLACEMENT wp = { 0 };
GetPrivateProfileStruct(TEXT("MainFrame"), TEXT("WindowPlace"), &wp, sizeof(wp), lpWindowplace);
SetWindowPlacement(hWnd, &wp);
}
else if (uMsg == WM_DESTROY) {
// Window place
WINDOWPLACEMENT wp = { 0 };
GetWindowPlacement(hWnd, &wp);
WritePrivateProfileStruct(TEXT("MainFrame"), TEXT("WindowPlace"), &wp, sizeof(wp), lpWindowplace);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hbrBackground = CreateSolidBrush(transparentColor);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WindowProc;
wcex.lpszClassName = TEXT("MainClass");
wcex.lpszMenuName = NULL;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TOPMOST,
wcex.lpszClassName, TEXT("MainFrame"), WS_OVERLAPPEDWINDOW,
1000,1350,100,100,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
return 0;
}
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Я рассмотрел следующие соли:
. Чтобы сделать окно сверху < /li>
< /ol>
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
while (1)
{
HWND hWnd = (HWND)lpParam;
if (hWnd)
{
OutputDebugStringA("ThreadFunction");
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
Sleep(100);
}
return 0;
}
< /code>
Используйте таймер, чтобы сделать окно сверху < /p>
< /li>
Установить клавиатуру и крючки для мыши, чтобы сделать окно сверху, если есть событие, но это идеал. После долгого размышлений я до сих пор не нашел подходящего решения. Разное. Поскольку TrafficMonitor довольно сложный, я не понимаю принципов реализации ключей. Если у кого -то есть соответствующий опыт или реализовал аналогичные приложения, предоставьте некоторые идеи или пример кода, большое спасибо!
Я заинтересован только в Win11 и выше, и реализация Win10 и ниже не находится в рамках обсуждения. https://github.com/leandrosa81/taskbar-monitorобразное/> 360: https://weishi.360.cn/clear/xfjsq/ В настоящее время я создал самое основное окно. Даже если окно установлено как верхнее окно, оно все равно будет покрыто панелью задач. < /P> [code]#include #include #include
// The structure stores the boundaries of all displays typedef struct { int left; int top; int right; int bottom; } MonitorBounds;
// Callback function: Calculate the total area of all displays BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { MonitorBounds* bounds = (MonitorBounds*)dwData;
// Update the minimum/maximum boundaries of all displays bounds->left = min(bounds->left, lprcMonitor->left); bounds->top = min(bounds->top, lprcMonitor->top); bounds->right = max(bounds->right, lprcMonitor->right); bounds->bottom = max(bounds->bottom, lprcMonitor->bottom);
return TRUE; // Continue enumerating }
// Limit window movement within all screens and allow coverage of taskbar void ClampWindowPosition(HWND hwnd, WINDOWPOS* wp) { RECT windowRect; GetWindowRect(hwnd, &windowRect);
int windowWidth = windowRect.right - windowRect.left; int windowHeight = windowRect.bottom - windowRect.top;
// Get the regions of all displays MonitorBounds screenBounds = { INT_MAX, INT_MAX, INT_MIN, INT_MIN }; EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&screenBounds);
// Limit the left and top of the window if (wp->x < screenBounds.left) { wp->x = screenBounds.left; } if (wp->y < screenBounds.top) { wp->y = screenBounds.top; }
// Limit the right and bottom of the window (allow to overwrite the taskbar) if (wp->x + windowWidth > screenBounds.right) { wp->x = screenBounds.right - windowWidth; } if (wp->y + windowHeight > screenBounds.bottom) { wp->y = screenBounds.bottom - windowHeight; } }
COLORREF transparentColor = RGB(255, 255, 255); LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { char text[100]; static int i = 0; sprintf_s(text, "WindowProc %d\n", i++); OutputDebugStringA(text); switch (uMsg) { case WM_CREATE: { LONG_PTR exStyle = GetWindowLong(hWnd, GWL_EXSTYLE); exStyle |= WS_EX_NOPARENTNOTIFY; exStyle |= WS_EX_LAYERED; exStyle |= WS_EX_TOPMOST; exStyle |= WS_EX_LEFT; exStyle |= WS_EX_NOACTIVATE; //exStyle |= WS_EX_TOOLWINDOW; // Set as a tool window so that icons do not appear on the taskbar SetWindowLong(hWnd, GWL_EXSTYLE, exStyle); SetLayeredWindowAttributes(hWnd, transparentColor, 255, LWA_COLORKEY | LWA_ALPHA); break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);
// Text to be displayed LPCWSTR text = TEXT(""); wchar_t buffer[1024] = { 0 };
for (int i = 0; i < 4; i++) { wcscat_s(buffer, 1024, TEXT("This is a line of lyrics This is a line of lyrics\n")); }
. Чтобы сделать окно сверху < /li> < /ol> DWORD WINAPI ThreadFunction(LPVOID lpParam) { while (1) { HWND hWnd = (HWND)lpParam; if (hWnd) { OutputDebugStringA("ThreadFunction"); SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } Sleep(100); } return 0; } < /code>
Используйте таймер, чтобы сделать окно сверху < /p> < /li> Установить клавиатуру и крючки для мыши, чтобы сделать окно сверху, если есть событие, но это идеал. После долгого размышлений я до сих пор не нашел подходящего решения. Разное. Поскольку TrafficMonitor довольно сложный, я не понимаю принципов реализации ключей. Если у кого -то есть соответствующий опыт или реализовал аналогичные приложения, предоставьте некоторые идеи или пример кода, большое спасибо!