Как получить только видимую часть окна (Windows, gdi32, user32 и т. Д.) - PullRequest
4 голосов
/ 16 ноября 2010

Я хочу получить только видимую часть окна в окнах, как регион.

Хотите получить только ту область, которую видит пользователь.Программно, конечно.Вот пример.У меня есть следующая композиция окна:

+------------------------------------------+
 |                                          |
 |           +=============+                |
 |           |             |                |
 |           |    A   +--------------------------+
 |           |        |                          |
 |    C      |        |             B            |
 |           |        +--------------------------+
 |           |             |                |
 +-----------|             |----------------+
             |             |
             +-------------+

Допустим, меня интересует только окно А. Тогда мне понадобится дескриптор области, которая будет выглядеть следующим образом:

          +=============+                
          |             |                
          |    A  +-----+
          |       |                          
          |       |                         
          |       +-----+
          |             |                
          |             |
          |             |
          +-------------+

Кроме того, я мог бы получить область любого другого окна следующим образом.

До сих пор я использовал это руководство: http://blogs.msdn.com/b/oldnewthing/archive/2003/09/02/54758.aspx

И я согласен, что GetClipBox возвращает 0, 1, 2 или 3, если у вас, соответственно, 0 -> Ошибка, 1 для NULLREGION(полученный rgn невидим для пользователя), 2 -> SIMPLEREGION и 3 для COMPLEXREGION.Итак, мне нужен комплексный регион.

Основной вопрос: Но как мне получить его координаты и размеры ?

(Дополнительная информация)

Можно ли реконструировать COMPLEXREGION (созданный ОС, а не я) в простые РЕГИОНЫ, из которых он состоит.Фэн Юань предполагает, что вы не можете:

http://www.codeguru.com/forum/archive/index.php/t-126543.html

(дополнительная информация)

Итак, есть ли способ найти регионА и перевести его в PolyPath или симпатичную геометрическую фигуру, имеющую координаты его углов ?

Кстати, я использую JNA (Java), но для решения той же проблемы достаточно кода C # или .VB.

Приветствия.

Ответы [ 2 ]

2 голосов
/ 16 ноября 2010

Вы можете перечислить все окна рабочего стола, а также все мониторы и объединить их прямоугольники.Я не уверен, что есть лучший способ.

Обратите внимание, что в наши дни Windows "лжет" о точных размерах окон (граница окна Aero немного больше, чем фактически сообщалось, если вы не установили специальный флаг).

Также обратите внимание, что окна могут иметь прозрачные участки, определяемые каждым приложением (в дополнение к границам прозрачного окна, которые всегда есть под Aero).

Вам также необходимо соблюдать осторожностьв системах с высоким DPI, где Windows «лжет» вашему приложению о координатах, если только вы не сделаете все возможное, чтобы пометить его как DPI с поддержкой.

А также обратите внимание, что даже «невидимое» окно может быть видно черезфункция миниатюр Aero на панели задач, Alt-Tab или Flip3D ... Итак, действительно, в Vista и Windows 7 с включенным DWM ответ таков: ваше окно потенциально всегда полностью видно.:)

1 голос
/ 14 декабря 2012

Я написал небольшую функцию, которая вычисляет видимую область любого окна.Передайте дескриптор окна этой функции, и он вернет видимую область окна.

HRGN GetVisibleRegion(HWND hwnd)
{   
    //Store the region of window hwnd
    RECT hwndRect={0,0,0,0};
    ::GetWindowRect(hwnd,&hwndRect);
    HRGN rgn=::CreateRectRgn(hwndRect.left,hwndRect.top,hwndRect.right,hwndRect.bottom);


    //HWND hParentWnd=::GetParent(hwnd);
    HWND hParentWnd=::GetAncestor(hwnd,GA_PARENT);
    HWND hChildWnd=hwnd;
    //until we reaches desktop window
    while(hChildWnd!=NULL && hChildWnd!=GetDesktopWindow())
    {
        HWND topWnd=::GetTopWindow(hParentWnd);
        do
        {
            if(topWnd==hChildWnd) 
            {
                break;
            }
            RECT topWndRect={0,0,0,0}; ::GetWindowRect(topWnd,&topWndRect);
            RECT tempRect={0,0,0,0};
            //Other window overlapping with hwnd
            if(::IsWindowVisible(topWnd) && !::IsIconic(topWnd) && IntersectRect(&tempRect,&topWndRect,&hwndRect)!=0) 
            {
                HRGN topWndRgn=::CreateRectRgn(topWndRect.left,topWndRect.top,topWndRect.right,topWndRect.bottom);
                ::CombineRgn(rgn,rgn,topWndRgn,RGN_DIFF);
                ::RealDeleteObject(topWndRgn);
            }
            topWnd = GetNextWindow(topWnd, TWO);

        }while(topWnd!=NULL);
        hChildWnd=hParentWnd;
        //hParentWnd=::GetParent(hParentWnd);
        hParentWnd=::GetAncestor(hParentWnd,GA_PARENT);
    }   
    return rgn;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...