koffi 获取指定 hwnd 句柄 id 的窗口坐标
使用 GetWindowRect 获取
GetWindowRect:https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
getAllRectangles.js
const koffi = require("koffi");
// 加载 user32.dll
const user32 = koffi.load("user32.dll");
const LPRECT = koffi.struct("LPRECT", {
left: "long",
top: "long",
right: "long",
bottom: "long",
});
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
const GetWindowRect = user32.func(
"bool __stdcall GetWindowRect(int32, LPRECT* lpRect)"
// 也可以这么写:
// "__stdcall", "GetWindowRect", "bool", [
// "int32",
// koffi.pointer(LPRECT),
// ]
);
const getRectangleOfWindow = (hwnd) => {
const rectBuffer = Buffer.alloc(16);
console.log("hwnd", hwnd);
if (GetWindowRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
throw new Error(`Failed to get rectangle for hwnd: ${hwnd}`);
};
function convertToXYWH({ rect, className }) {
const newItem = {
x: rect.left,
y: rect.top,
width: rect.right - rect.left,
height: rect.bottom - rect.top,
className,
};
if (!className) {
delete newItem.className;
}
return newItem;
}
function getAllRectangles(hwndArray) {
const rectangles = [];
hwndArray.forEach((hwnd) => {
try {
const rect = getRectangleOfWindow(hwnd);
rectangles.push(convertToXYWH({ rect }));
} catch (err) {
console.error(err.message);
}
});
return rectangles;
}
const hwndArray = ["655872"].map(Number);
const result = getAllRectangles(hwndArray);
console.log("result", result);
代码提示
提示
hwndArray
句柄 ID 可以通过 electron desktopCapturer.getSources API 获取
提示
bool __stdcall GetWindowRect(int32, LPRECT* lpRect)
这里的 LPRECT*
是一个指针类型,必须要带*
下面两种写法都是正确的,表示的同一个效果,Node.js 为了表示引用 LPRECT
,可以使用写法 2
写法 1:
const GetWindowRect = user32.func(
"bool __stdcall GetWindowRect(int32, LPRECT* lpRect)"
);
写法 2:
const GetWindowRect = user32.func(
"__stdcall", "GetWindowRect", "bool", [
"int32",
koffi.pointer(LPRECT),
]
);
提示
在这段代码中,koffi.decode
与 rectBuffer.readInt32LE
可以达到相同的效果
const getRectangleOfWindow = (hwnd) => {
const rectBuffer = Buffer.alloc(16);
console.log("hwnd", hwnd);
if (GetWindowRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
throw new Error(`Failed to get rectangle for hwnd: ${hwnd}`);
};
下面代码 1 和代码 2 效果一样
区别:代码 2 更通用,适用于 Node.js 所有的库,代码 1 在 koffi 中适用
代码 1:
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
代码 2:
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
代码运行结果
下面的结果有 6 像素的误差,原理可以看微软的官方文档 https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect#remarks
PS C:\Users\Administrator\Documents\mycode\electron-screenshot> node .\main\koffi\getAllRectangles.js
hwnd 655872
koffi.decode(LPRECT) { left: -6, top: -6, right: 2055, bottom: 1111 }
result [ { x: -6, y: -6, width: 2061, height: 1117 } ]
PS C:\Users\Administrator\Documents\mycode\electron-screenshot>
这个“6”的误差可能是由窗口的边框和阴影造成的。Windows 系统中的窗口通常带有外部边框和阴影区域,这些区域属于窗口的一部分,因此在使用 GetWindowRect
函数获取窗口的矩形坐标时,返回的坐标会包含窗口的边框、阴影等外部装饰部分。
具体的原因如下:
- 窗口边框:默认情况下,Windows 的窗口有边框,边框的厚度会导致坐标有一定的偏移。
- 窗口阴影:现代 Windows 系统(如 Windows 10 和 11)在窗口外部增加了阴影效果,阴影部分也是窗口区域的一部分,因此也会影响坐标计算。
如何解决
如果你只想获取窗口的客户端区域(不包括边框和阴影),可以使用 GetClientRect
函数而不是 GetWindowRect
。GetClientRect
函数只返回窗口内容区域的坐标,而不包含窗口装饰(如标题栏、边框、阴影)。
你可以在现有代码基础上增加对 GetClientRect
的调用,来获取更精确的窗口坐标。
如果你依然需要 GetWindowRect
的结果,但想去掉边框和阴影的影响,可以使用 AdjustWindowRectEx
函数,它可以根据窗口的样式调整矩形区域,从而排除边框和阴影的影响。
使用 GetWindowRect 获取,修复 6 像素误差
修改后的代码
const koffi = require("koffi");
// 加载 user32.dll
const user32 = koffi.load("user32.dll");
const LPRECT = koffi.struct("LPRECT", {
left: "long",
top: "long",
right: "long",
bottom: "long",
});
// 加载 GetWindowRect 函数
const GetWindowRect = user32.func(
"bool __stdcall GetWindowRect(int32, LPRECT* lpRect)"
);
// 加载 GetClientRect 函数
const GetClientRect = user32.func(
"bool __stdcall GetClientRect(int32, LPRECT* lpRect)"
);
// 获取窗口矩形函数
const getRectangleOfWindow = (hwnd) => {
const rectBuffer = Buffer.alloc(16);
console.log("hwnd", hwnd);
// 优先获取窗口的客户区矩形
if (GetClientRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
// 如果 GetClientRect 失败,则尝试获取完整窗口区域
if (GetWindowRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
throw new Error(`Failed to get rectangle for hwnd: ${hwnd}`);
};
// 将矩形转为 x, y, width, height
function convertToXYWH({ rect, className }) {
const newItem = {
x: rect.left,
y: rect.top,
width: rect.right - rect.left,
height: rect.bottom - rect.top,
className,
};
if (!className) {
delete newItem.className;
}
return newItem;
}
function getAllRectangles(hwndArray) {
const rectangles = [];
hwndArray.forEach((hwnd) => {
try {
const rect = getRectangleOfWindow(hwnd);
rectangles.push(convertToXYWH({ rect }));
} catch (err) {
console.error(err.message);
}
});
return rectangles;
}
const hwndArray = ["655872"].map(Number);
const result = getAllRectangles(hwndArray);
console.log("result", result);
// module.exports = { getAllRectangles };
代码运行结果如下:
PS C:\Users\Administrator\Documents\mycode\electron-screenshot> node .\main\koffi\getAllRectangles.js
hwnd 655872
koffi.decode(LPRECT) { left: 0, top: 0, right: 2048, bottom: 1104 }
result [ { x: 0, y: 0, width: 2048, height: 1104 } ]
PS C:\Users\Administrator\Documents\mycode\electron-screenshot>
已修复存在 6 像素误差的问题
增加任务栏图标坐标获取
const koffi = require("koffi");
// 加载 user32.dll
const user32 = koffi.load("user32.dll");
const LPRECT = koffi.struct("LPRECT", {
left: "long",
top: "long",
right: "long",
bottom: "long",
});
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
// 加载 GetWindowRect 函数
const GetWindowRect = user32.func(
"bool __stdcall GetWindowRect(int32, LPRECT* lpRect)"
);
// 加载 GetClientRect 函数
const GetClientRect = user32.func(
"bool __stdcall GetClientRect(int32, LPRECT* lpRect)"
// 也可以这么写:
// "__stdcall", "GetWindowRect", "bool", [
// "int32",
// koffi.pointer(LPRECT),
// ]
);
// FindWindowW: ["int32", ["string", "string"]],
const FindWindowW = user32.func("__stdcall", "FindWindowW", "int32", [
"string",
"string",
]);
// 定义 GetClassNameW 函数
const GetClassNameW = user32.func(
"int __stdcall GetClassNameW(int32 hWnd, char* lpClassName, int nMaxCount)"
);
// 获取窗口矩形函数
const getRectangleOfWindow = (hwnd) => {
const rectBuffer = Buffer.alloc(16);
console.log("hwnd", hwnd);
// 优先获取窗口的客户区矩形
if (GetClientRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
// 如果 GetClientRect 失败,则尝试获取完整窗口区域
if (GetWindowRect(hwnd, rectBuffer)) {
console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
const right = rectBuffer.readInt32LE(8);
const bottom = rectBuffer.readInt32LE(12);
return { left, top, right, bottom };
}
throw new Error(`Failed to get rectangle for hwnd: ${hwnd}`);
};
const BUFFER_SIZE = 256; // 缓冲区大小,足够存储类名
const classNameBuffer = Buffer.alloc(BUFFER_SIZE * 2); // WCHAR 是 2 字节
// 定义 EnumWindowsProc 回调函数的签名
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(int32 hwnd, long lParam)"
);
// 定义 EnumChildWindows 函数
const EnumChildWindows = user32.func(
// "bool __stdcall EnumChildWindows(int32 hWndParent, void* lpEnumFunc, int32 lParam)"
"__stdcall",
"EnumChildWindows",
"bool",
["int32", koffi.pointer(EnumWindowsProc), "int32"]
);
const IsWindowVisible = user32.func(
"bool __stdcall IsWindowVisible(int32 hwnd)"
);
const getClassNameOfWindow = (hwnd) => {
const length = GetClassNameW(hwnd, classNameBuffer, BUFFER_SIZE);
if (length > 0) {
return classNameBuffer.toString("ucs2", 0, length * 2); // 使用 ucs2 解码宽字符
}
throw new Error(`Failed to get class name for hwnd: ${hwnd}`);
};
// 将矩形转为 x, y, width, height
function convertToXYWH({ rect, className }) {
const newItem = {
x: rect.left,
y: rect.top,
width: rect.right - rect.left,
height: rect.bottom - rect.top,
className,
};
if (!className) {
delete newItem.className;
}
return newItem;
}
function getTaskBarWindows(rectangles) {
const hwnd = FindWindowW(Buffer.from(`Shell_TrayWnd\0`, "ucs2"), null);
if (hwnd !== 0) {
const cb1 = koffi.register((hwndChild, lParam) => {
if (!IsWindowVisible(hwndChild)) {
console.log("[hwndChild, lParam false]", hwndChild, lParam);
return true;
}
console.log("[hwndChild, lParam true]", hwndChild, lParam);
try {
const rect = getRectangleOfWindow(hwndChild);
const className = getClassNameOfWindow(hwndChild);
if (rect && className && !["Static"].includes(className)) {
rectangles.unshift(convertToXYWH({ rect, className }));
}
} catch (err) {
console.error(err.message);
}
return true;
}, koffi.pointer(EnumWindowsProc));
EnumChildWindows(hwnd, cb1, 0);
koffi.unregister(cb1);
const parentRect = getRectangleOfWindow(hwnd);
const parentClassName = getClassNameOfWindow(hwnd);
if (parentRect && parentClassName) {
rectangles.push(
convertToXYWH({ rect: parentRect, className: parentClassName })
);
}
} else {
console.error("Window not found.");
}
}
function getAllRectangles(hwndArray) {
const rectangles = [];
hwndArray.forEach((hwnd) => {
try {
const rect = getRectangleOfWindow(hwnd);
rectangles.push(convertToXYWH({ rect }));
} catch (err) {
console.error(err.message);
}
});
getTaskBarWindows(rectangles);
return rectangles;
}
const hwndArray = ["655872"].map(Number);
const result = getAllRectangles(hwndArray);
console.log("result", result);
module.exports = { getAllRectangles };
代码执行结果
PS C:\Users\Administrator\Documents\mycode\electron-screenshot> node .\main\koffi\getAllRectangles.js
hwnd 655872
koffi.decode(LPRECT) { left: 0, top: 0, right: 2048, bottom: 1104 }
[hwndChild, lParam false] 66176 0
[hwndChild, lParam false] 196688 0
[hwndChild, lParam true] 196690 0
hwnd 196690
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 0 }
[hwndChild, lParam true] 196692 0
hwnd 196692
koffi.decode(LPRECT) { left: 0, top: 0, right: 316, bottom: 48 }
[hwndChild, lParam true] 196694 0
hwnd 196694
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 48 }
[hwndChild, lParam false] 196696 0
[hwndChild, lParam true] 196666 0
hwnd 196666
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 0 }
[hwndChild, lParam true] 393350 0
hwnd 393350
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 0 }
[hwndChild, lParam false] 131252 0
[hwndChild, lParam false] 131248 0
[hwndChild, lParam false] 131246 0
[hwndChild, lParam false] 131242 0
[hwndChild, lParam true] 131238 0
hwnd 131238
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 48 }
[hwndChild, lParam true] 131236 0
hwnd 131236
koffi.decode(LPRECT) { left: 0, top: 0, right: 356, bottom: 48 }
[hwndChild, lParam true] 131228 0
hwnd 131228
koffi.decode(LPRECT) { left: 0, top: 0, right: 356, bottom: 48 }
[hwndChild, lParam false] 196642 0
[hwndChild, lParam true] 66214 0
hwnd 66214
koffi.decode(LPRECT) { left: 0, top: 0, right: 2048, bottom: 48 }
[hwndChild, lParam true] 66216 0
hwnd 66216
koffi.decode(LPRECT) { left: 0, top: 0, right: 0, bottom: 0 }
hwnd 196684
koffi.decode(LPRECT) { left: 0, top: 0, right: 2048, bottom: 48 }
result [
{
x: 0,
y: 0,
width: 0,
height: 0,
className: 'Windows.UI.Input.InputSite.WindowClass'
},
{
x: 0,
y: 0,
width: 2048,
height: 48,
className: 'Windows.UI.Composition.DesktopWindowContentBridge'
},
{ x: 0, y: 0, width: 356, height: 48, className: 'MSTaskSwWClass' },
{ x: 0, y: 0, width: 356, height: 48, className: 'ReBarWindow32' },
{
x: 0,
y: 0,
width: 0,
height: 48,
className: 'TrayShowDesktopButtonWClass'
},
{ x: 0, y: 0, width: 0, height: 0, className: 'SysPager' },
{ x: 0, y: 0, width: 0, height: 0, className: 'ToolbarWindow32' },
{ x: 0, y: 0, width: 0, height: 48, className: 'Button' },
{ x: 0, y: 0, width: 316, height: 48, className: 'TrayNotifyWnd' },
{
x: 0,
y: 0,
width: 0,
height: 0,
className: 'TrayDummySearchControl'
},
{ x: 0, y: 0, width: 2048, height: 1104 },
{ x: 0, y: 0, width: 2048, height: 48, className: 'Shell_TrayWnd' }
]
PS C:\Users\Administrator\Documents\mycode\electron-screenshot>
上面的 left,top 是错误的,但是 right,bottom 是对的。
DANGER
根据官方的文档得知:GetClientRect 的 left,top 都为零,所以需要用 ClientToScreenz 转换成屏幕坐标,具体如何做继续往下看
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect#parameters
修复 GetClientRect left,right 为 0 的问题
ClientToScreen https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-clienttoscreen
const koffi = require("koffi");
// 加载 user32.dll
const user32 = koffi.load("user32.dll");
const LPRECT = koffi.struct("LPRECT", {
left: "long",
top: "long",
right: "long",
bottom: "long",
});
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
// 加载 GetWindowRect 函数
const GetWindowRect = user32.func(
"bool __stdcall GetWindowRect(int32, LPRECT* lpRect)"
);
// 加载 GetClientRect 函数
const GetClientRect = user32.func(
"bool __stdcall GetClientRect(int32, LPRECT* lpRect)"
// 也可以这么写:
// "__stdcall", "GetWindowRect", "bool", [
// "int32",
// koffi.pointer(LPRECT),
// ]
);
// FindWindowW: ["int32", ["string", "string"]],
const FindWindowW = user32.func("__stdcall", "FindWindowW", "int32", [
"string",
"string",
]);
// 定义 GetClassNameW 函数
const GetClassNameW = user32.func(
"int __stdcall GetClassNameW(int32 hWnd, char* lpClassName, int nMaxCount)"
);
const ClientToScreen = user32.func(
"bool __stdcall ClientToScreen(int32, LPRECT* lpRect)"
);
// 获取窗口矩形函数
const getRectangleOfWindow = (hwnd, type) => {
const rectBuffer = Buffer.alloc(16);
// console.log("hwnd", hwnd);
// 优先获取窗口的客户区矩形
// 根据官方的文档得知:GetClientRect 的 left,top都为零,所以需要转换成屏幕坐标
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect#parameters
if (GetClientRect(hwnd, rectBuffer)) {
// 获取客户区的矩形
const rect = koffi.decode(rectBuffer, LPRECT);
// 将客户区坐标转换为屏幕坐标
if (ClientToScreen(hwnd, rectBuffer)) {
const left = rectBuffer.readInt32LE(0);
const top = rectBuffer.readInt32LE(4);
// 计算客户区的宽度和高度
const width = rect.right - rect.left;
const height = rect.bottom - rect.top;
// 将左上角更新为屏幕坐标
rect.left = left;
rect.top = top;
// 右下角坐标转换为屏幕坐标
rect.right = rect.left + width;
rect.bottom = rect.top + height;
}
return rect;
// return koffi.decode(rectBuffer, LPRECT);
// console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
// const left = rectBuffer.readInt32LE(0);
// const top = rectBuffer.readInt32LE(4);
// const right = rectBuffer.readInt32LE(8);
// const bottom = rectBuffer.readInt32LE(12);
// console.log("{ left, top, right, bottom }", { left, top, right, bottom });
// return { left, top, right, bottom };
}
// 如果 GetClientRect 失败,则尝试获取完整窗口区域
if (GetWindowRect(hwnd, rectBuffer)) {
return koffi.decode(rectBuffer, LPRECT);
// console.log("koffi.decode(LPRECT)", koffi.decode(rectBuffer, LPRECT));
// const left = rectBuffer.readInt32LE(0);
// const top = rectBuffer.readInt32LE(4);
// const right = rectBuffer.readInt32LE(8);
// const bottom = rectBuffer.readInt32LE(12);
// return { left, top, right, bottom };
}
throw new Error(`Failed to get rectangle for hwnd: ${hwnd}`);
};
const BUFFER_SIZE = 256; // 缓冲区大小,足够存储类名
const classNameBuffer = Buffer.alloc(BUFFER_SIZE * 2); // WCHAR 是 2 字节
// 定义 EnumWindowsProc 回调函数的签名
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(int32 hwnd, long lParam)"
);
// 定义 EnumChildWindows 函数
const EnumChildWindows = user32.func(
// "bool __stdcall EnumChildWindows(int32 hWndParent, void* lpEnumFunc, int32 lParam)"
"__stdcall",
"EnumChildWindows",
"bool",
["int32", koffi.pointer(EnumWindowsProc), "int32"]
);
const IsWindowVisible = user32.func(
"bool __stdcall IsWindowVisible(int32 hwnd)"
);
const getClassNameOfWindow = (hwnd) => {
const length = GetClassNameW(hwnd, classNameBuffer, BUFFER_SIZE);
if (length > 0) {
return classNameBuffer.toString("ucs2", 0, length * 2); // 使用 ucs2 解码宽字符
}
throw new Error(`Failed to get class name for hwnd: ${hwnd}`);
};
// 将矩形转为 x, y, width, height
function convertToXYWH({ rect, className }) {
const newItem = {
x: rect.left,
y: rect.top,
width: rect.right - rect.left,
height: rect.bottom - rect.top,
className,
};
if (!className) {
delete newItem.className;
}
return newItem;
}
function getTaskBarWindows(rectangles = []) {
const hwnd = FindWindowW(Buffer.from(`Shell_TrayWnd\0`, "ucs2"), null);
if (hwnd !== 0) {
const cb1 = koffi.register((hwndChild, lParam) => {
if (!IsWindowVisible(hwndChild)) {
// console.log("[hwndChild, lParam false]", hwndChild, lParam);
return true;
}
// console.log("[hwndChild, lParam true]", hwndChild, lParam);
try {
const rect = getRectangleOfWindow(hwndChild, "TaskBarWindows");
const className = getClassNameOfWindow(hwndChild);
if (rect && className && !["Static"].includes(className)) {
rectangles.unshift(convertToXYWH({ rect, className }));
}
} catch (err) {
console.error(err.message);
}
return true;
}, koffi.pointer(EnumWindowsProc));
EnumChildWindows(hwnd, cb1, 0);
koffi.unregister(cb1);
const parentRect = getRectangleOfWindow(hwnd);
const parentClassName = getClassNameOfWindow(hwnd);
if (parentRect && parentClassName) {
rectangles.push(
convertToXYWH({ rect: parentRect, className: parentClassName })
);
}
} else {
console.error("Window not found.");
}
return rectangles;
}
function getAllRectangles(hwndArray) {
const rectangles = [];
hwndArray = hwndArray.map((item) => Number(item));
console.log("hwndArray", hwndArray);
hwndArray.forEach((hwnd) => {
try {
const rect = getRectangleOfWindow(hwnd);
rectangles.push(convertToXYWH({ rect }));
} catch (err) {
console.error(err.message);
}
});
getTaskBarWindows(rectangles);
console.log("rectangles", rectangles);
return rectangles;
}
// const hwndArray = ["655872"].map(Number);
// const result = getAllRectangles(hwndArray);
// console.log("result", result);
module.exports = { getAllRectangles };
最终输出了正确的坐标
hwndArray [ 655872, 1705290 ]
rectangles [
{
x: 0,
y: 2760,
width: 0,
height: 0,
className: 'Windows.UI.Input.InputSite.WindowClass'
},
{
x: 0,
y: 2760,
width: 5120,
height: 120,
className: 'Windows.UI.Composition.DesktopWindowContentBridge'
},
{
x: 2005,
y: 2760,
width: 890,
height: 120,
className: 'MSTaskSwWClass'
},
{
x: 2005,
y: 2760,
width: 890,
height: 120,
className: 'ReBarWindow32'
},
{
x: 4330,
y: 2760,
width: 0,
height: 120,
className: 'TrayShowDesktopButtonWClass'
},
{ x: 4330, y: 2760, width: 0, height: 0, className: 'SysPager' },
{
x: 4330,
y: 2760,
width: 0,
height: 0,
className: 'ToolbarWindow32'
},
{ x: 4330, y: 2760, width: 0, height: 120, className: 'Button' },
{
x: 4330,
y: 2760,
width: 790,
height: 120,
className: 'TrayNotifyWnd'
},
{
x: 0,
y: 2760,
width: 0,
height: 0,
className: 'TrayDummySearchControl'
},
{ x: 514, y: 162, width: 3930, height: 2085 },
{ x: 5120, y: 0, width: 3840, height: 2064 },
{
x: 0,
y: 2760,
width: 5120,
height: 120,
className: 'Shell_TrayWnd'
}
]