Как можно использовать pywin32, чтобы получить прямоугольник окна и контекст устройства без дублирования работы? - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь понять пакет win32 api / pywin32, и у меня есть код, который делает скриншот окна с определенным именем. Мне трудно понять API Win32, и текущий код эффективно ищет одно и то же окно два раза. Я предполагаю, что это возможно сделать лучше. Вот код:

1 - Предварительные сведения:

from PIL import Image
import win32ui, win32gui, win32con

#name of window to screenshot
name = "Photos"

2 - Когда я в первый раз нахожу окно, я могу использовать результат, чтобы получить информацию о его форме и местоположении:

window = win32ui.FindWindow(None, name)
left, top, right, bottom = window.GetWindowRect()
width = right - left
height = bottom - top

3 - во второй раз, когда я нахожу окно, я могу передать результат в функцию 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 в первый раз, когда я вычисляю их по сравнению со вторыми. Меня больше интересует это понимание, чем фактический снимок экрана, поэтому код, который выполняет эту работу совершенно по-другому, вероятно, не будет полезным.

1 Ответ

1 голос
/ 13 апреля 2020

Пожалуйста, используйте 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 с одним и тем же именем возвращает разные типы в разных библиотеках.

Например win32gui.FindWindow и win32ui.FindWindow

При создании снимка экрана определенного приложения c вы столкнетесь с рядом других проблем, таких как невозможность сделать снимок экрана Firefox правильно .

Существует еще один способ решения этой проблемы, см .: Снимки экрана с win32api python возвращает черное изображение

В качестве дополнения:

Я протестировал EnumWindows и FindWindow в C ++, они будут возвращать одни и те же данные, и при использовании 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...