1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
// Copyright © 2022, 飞麦 <[email protected]>, All rights reserved. #include <tchar.h> #include <windows.h> #include "Shlwapi.h" // StrStrI #pragma comment(lib, "ShLwApi.Lib") struct HWND_RECT { HWND hwnd; // 窗口句柄 RECT rect; // 窗口位置 }; static HWND_RECT hwnd_rect_a[MAX_PATH]; // 260:最多命令行窗口数 static int hwnd_num; // 实际命令行窗口数 typedef HWND_RECT const* LP_HWND_RECT; typedef void(__cdecl* MyDealFunc)(HWND& hwnd, RECT& cmd_rect); // 根据窗口标题筛选命令行窗口 static BOOL CALLBACK enum_child_proc(_In_ HWND hwnd, _In_ LPARAM lParam) { static TCHAR caption[MAX_PATH]; if (GetWindowText(hwnd, caption, MAX_PATH) > 0) // 获取窗口标题成功 if (StrStrI(caption, _T("\\Windows\\System32\\cmd.exe"))) // 是命令行窗口 if (hwnd_num < MAX_PATH) // 未超过最大个数 hwnd_rect_a[hwnd_num++].hwnd = hwnd; return TRUE; // 表示继续枚举窗口 } // 枚举桌面的所有子窗口 static void got_cmd_windows() { HWND hWndParent = GetDesktopWindow(); WNDENUMPROC lpEnumFunc = enum_child_proc; LPARAM lParam = NULL; EnumChildWindows(hWndParent, lpEnumFunc, lParam); } // 获取桌面位置与大小 static RECT got_desk_rect() { HWND desk_hwnd = GetDesktopWindow(); RECT desk_rect; GetWindowRect(desk_hwnd, &desk_rect); return desk_rect; } // 根据最左边的位置比较各命令行窗口的顺序 static int compare_left(LPCVOID a, LPCVOID b) { LP_HWND_RECT p_hwnd_rect_a = reinterpret_cast<LP_HWND_RECT>(a); LP_HWND_RECT p_hwnd_rect_b = reinterpret_cast<LP_HWND_RECT>(b); return p_hwnd_rect_a->rect.left - p_hwnd_rect_b->rect.left; } // 计算任务栏高度 static LONG calc_tray_height() { LPCTSTR lpClassName = _T("Shell_TrayWnd"); // 任务栏窗口类名 LPCTSTR lpWindowName = NULL; // 所有窗口名称都匹配 HWND tray_hwnd = FindWindow(lpClassName, lpWindowName); RECT tray_rect; GetWindowRect(tray_hwnd, &tray_rect); LONG tray_height = tray_rect.bottom - tray_rect.top; return tray_height; } // 获取某命令行窗口的位置与大小 static void got_rects(HWND& hwnd, RECT& cmd_rect) { // SW_NORMAL:激活并显示窗口,如果窗口最小化、最大化或隐藏,系统会将其还原到其原始大小和位置 ShowWindow(hwnd, SW_NORMAL); // 窗口隐藏或最小化时无法获得其位置与大小 GetWindowRect(hwnd, &cmd_rect); // 获取命令行窗口位置与大小 } // 对各命令行窗口排序(按照最左边的位置) static void sort_cmd_windows() { qsort(hwnd_rect_a, hwnd_num, sizeof(HWND_RECT), compare_left); } // 计算各命令行窗口的合理位置与大小 static void calc_loc_size() { if (hwnd_num <= 0) return; RECT desk_rect = got_desk_rect(); LONG desk_width = desk_rect.right - desk_rect.left; LONG tray_height = calc_tray_height(); RECT& cmd_rect = hwnd_rect_a[0].rect; // 以首个命令行窗口为准 LONG cmd_width = cmd_rect.right - cmd_rect.left; // 计算命令行窗口统一宽度 LONG desk_height = desk_rect.bottom - desk_rect.top; // 计算桌面高度 LONG rest_width = desk_width - cmd_width; // 剩余宽度 = 桌面宽度 - 命令行窗口宽度 LONG from = 0; // 最左命令行窗口左边坐标 LONG distance = 0; // 各命令行窗口左边坐标的间距 if (hwnd_num > 1) // 如果有多个命令行窗口 distance = rest_width / (hwnd_num - 1); // 使命令行窗口均匀分布 else from = rest_width / 2; // 使命令行窗口位于中央 LONG cmd_height = desk_height - 16 - tray_height; // 各命令行窗口与桌面(除远程桌面栏及任务栏外)等高 LONG top = desk_rect.top + 16; // 各命令行窗口顶坐标与桌面(扣除远程桌面栏)相同 LONG bottom = top + cmd_height; // 各命令行窗口底位置 for (auto i = 0; i < hwnd_num; i++) { RECT& cmd_rect = hwnd_rect_a[i].rect; cmd_rect.left = from + distance * i; cmd_rect.right = cmd_rect.left + cmd_width; cmd_rect.top = top; cmd_rect.bottom = bottom; } } // 设置某命令行窗口的位置与大小 static void chg_rects(HWND& hwnd, RECT& cmd_rect) { LONG cmd_width = cmd_rect.right - cmd_rect.left; LONG cmd_height = cmd_rect.bottom - cmd_rect.top; // HWND_TOP:将窗口置于 Z 顺序的顶部 // SWP_ASYNCWINDOWPOS:如果调用线程和拥有窗口的线程附加到不同的输入队列,则系统会将请求发布到拥有窗口的线程 SetWindowPos(hwnd, HWND_TOP, cmd_rect.left, cmd_rect.top, cmd_width, cmd_height, SWP_ASYNCWINDOWPOS); } // 枚举处理各命令行窗口 static void deal_cmd_windows(MyDealFunc func) { for (auto i = 0; i < hwnd_num; i++) { HWND_RECT& hwnd_rect = hwnd_rect_a[i]; func(hwnd_rect.hwnd, hwnd_rect.rect); } } // 自动对多个命令行窗口设置位置与大小 int WINAPI _tWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPTSTR, _In_ int) { got_cmd_windows(); deal_cmd_windows(got_rects); sort_cmd_windows(); calc_loc_size(); deal_cmd_windows(chg_rects); return 0; } |