如何在不重复工作的情况下使用 pywin32 获取 window 矩形和设备上下文?
How can pywin32 be used to get the window rectangle and device context without duplicating work?
我正在尝试了解 win32 api / pywin32 包,并且我有截取具有特定名称的 window 屏幕截图的代码。我很难理解 win32 api,并且当前代码在两个不同的时间有效地搜索相同的 window。我假设有可能做得更好。这是代码:
1 - 预赛:
from PIL import Image
import win32ui, win32gui, win32con
#name of window to screenshot
name = "Photos"
2- 我第一次找到 window,我能够使用结果来获取有关其形状和位置的信息:
window = win32ui.FindWindow(None, name)
left, top, right, bottom = window.GetWindowRect()
width = right - left
height = bottom - top
3 - 我第二次找到 window,我能够将结果输入 GetWindowDC
函数。我的代码的其余部分(未显示)使用此设备上下文信息来执行屏幕截图。
def findit(hwnd,ctx):
if win32gui.GetWindowText(hwnd) == name: # check the title
return hwnd
window = win32gui.EnumWindows(findit,None)
#convert this into a device context handle
windowDC = win32gui.GetWindowDC(window)
我想知道是否有一种方法可以重现 left, top, right, bottom
和 windowDC
而无需使用两种不同的方法来找到我想要的 window。此外,我想直观地了解 window
中包含的数据是第一次计算还是第二次计算。我对这种理解比实际截屏更感兴趣,所以以完全不同的方式完成这项工作的代码可能不会有帮助。
请使用win32gui.FindWindow(None, name)
.
最小代码:
import win32gui
import win32ui
import win32con
name = "test.txt - Notepad"
hwnd = win32gui.FindWindow(None, name)
left, top, right, bot = win32gui.GetWindowRect(hwnd)
w = right - left
h = bot - top
print(w,h)
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
dataBitMap.SaveBitmapFile(cDC, "1.bmp")
# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
我的猜测是 winapi
同名 return 不同库中的不同类型。
例如win32gui.FindWindow
和win32ui.FindWindow
在对特定应用程序进行截图时,您会遇到一些其他问题,例如无法正确对Firefox进行截图。
还有另一种方法可以解决这个问题,参考:
作为补充:
我用C++测试了EnumWindows
和FindWindow
,它们会return相同的数据,使用GetWindowDC
不会出错。
这是 C++ 代码:
#include <Windows.h>
#include <string>
#include <iostream>
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM m) {
RECT rc;
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
if (!strcmp(buffer, "Photos"))
{
HDC hdc = GetWindowDC(hWnd);
GetWindowRect(hWnd, &rc);
std::cout <<"EnumWindows: "<< rc.right-rc.left <<" "<< rc.bottom-rc.top<<std::endl;
std::cout <<"EnumWindows: "<< hWnd << std::endl;
}
return TRUE;
}
int main()
{
RECT rc;
HWND window = FindWindow(NULL, "Photos");
GetWindowRect(window, &rc);
std::cout <<"FindWindow: "<< rc.right - rc.left <<" "<< rc.bottom - rc.top << std::endl;
std::cout <<"FindWindow: "<< window << std::endl;
HDC hdc = GetWindowDC(window);
EnumWindows(enumWindowCallback, NULL);
return 0;
}
调试:
FindWindow: 649 640
FindWindow: 00080A6A
EnumWindows: 649 640
EnumWindows: 00080A6A
我正在尝试了解 win32 api / pywin32 包,并且我有截取具有特定名称的 window 屏幕截图的代码。我很难理解 win32 api,并且当前代码在两个不同的时间有效地搜索相同的 window。我假设有可能做得更好。这是代码:
1 - 预赛:
from PIL import Image
import win32ui, win32gui, win32con
#name of window to screenshot
name = "Photos"
2- 我第一次找到 window,我能够使用结果来获取有关其形状和位置的信息:
window = win32ui.FindWindow(None, name)
left, top, right, bottom = window.GetWindowRect()
width = right - left
height = bottom - top
3 - 我第二次找到 window,我能够将结果输入 GetWindowDC
函数。我的代码的其余部分(未显示)使用此设备上下文信息来执行屏幕截图。
def findit(hwnd,ctx):
if win32gui.GetWindowText(hwnd) == name: # check the title
return hwnd
window = win32gui.EnumWindows(findit,None)
#convert this into a device context handle
windowDC = win32gui.GetWindowDC(window)
我想知道是否有一种方法可以重现 left, top, right, bottom
和 windowDC
而无需使用两种不同的方法来找到我想要的 window。此外,我想直观地了解 window
中包含的数据是第一次计算还是第二次计算。我对这种理解比实际截屏更感兴趣,所以以完全不同的方式完成这项工作的代码可能不会有帮助。
请使用win32gui.FindWindow(None, name)
.
最小代码:
import win32gui
import win32ui
import win32con
name = "test.txt - Notepad"
hwnd = win32gui.FindWindow(None, name)
left, top, right, bot = win32gui.GetWindowRect(hwnd)
w = right - left
h = bot - top
print(w,h)
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
dataBitMap.SaveBitmapFile(cDC, "1.bmp")
# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
我的猜测是 winapi
同名 return 不同库中的不同类型。
例如win32gui.FindWindow
和win32ui.FindWindow
在对特定应用程序进行截图时,您会遇到一些其他问题,例如无法正确对Firefox进行截图。
还有另一种方法可以解决这个问题,参考:
作为补充:
我用C++测试了EnumWindows
和FindWindow
,它们会return相同的数据,使用GetWindowDC
不会出错。
这是 C++ 代码:
#include <Windows.h>
#include <string>
#include <iostream>
static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM m) {
RECT rc;
int length = GetWindowTextLength(hWnd);
char* buffer = new char[length + 1];
GetWindowText(hWnd, buffer, length + 1);
if (!strcmp(buffer, "Photos"))
{
HDC hdc = GetWindowDC(hWnd);
GetWindowRect(hWnd, &rc);
std::cout <<"EnumWindows: "<< rc.right-rc.left <<" "<< rc.bottom-rc.top<<std::endl;
std::cout <<"EnumWindows: "<< hWnd << std::endl;
}
return TRUE;
}
int main()
{
RECT rc;
HWND window = FindWindow(NULL, "Photos");
GetWindowRect(window, &rc);
std::cout <<"FindWindow: "<< rc.right - rc.left <<" "<< rc.bottom - rc.top << std::endl;
std::cout <<"FindWindow: "<< window << std::endl;
HDC hdc = GetWindowDC(window);
EnumWindows(enumWindowCallback, NULL);
return 0;
}
调试:
FindWindow: 649 640
FindWindow: 00080A6A
EnumWindows: 649 640
EnumWindows: 00080A6A