Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

как получить изображение окна, которое скрыто другими [D6, Win2k]


Страницы:   1 2

Humorist ©   (2007-01-24 18:22:00) 

Стоит задача: получить изображение окна, которое скрыто другими. Два дня бьюсь.
Сочинил (с помощью инета) следующую прогу:

procedure CreateWindwowBitmap(Wnd: HWND);
var
 R: TRect;
 W, H: Integer;
 DC, memDC: HDC;
 bm, oldBM: HBITMAP;

 bmp:TBitmap;
begin
 GetWindowRect(Wnd, R);
 W := R.Right - R.Left;
 H := R.Bottom - R.Top;
 DC := GetWindowDC(Wnd);
 memDC := CreateCompatibleDC(DC);
 bm := CreateCompatibleBitmap(DC, W, H);
 oldBM := SelectObject(memDC, bm);
 BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY);
 SelectObject(memDC, oldBM);
 DeleteDC(memDC);
 DeleteObject(oldBM);
 ReleaseDC(Wnd, DC);

 bmp:=TbitMap.Create;
 bmp.Handle:=bm;
 bmp.SaveToFile('d:\eee.bmp');
 bmp.Free;

end;

Однако она сохраняет в файл то, что ВИДНО на экране.
Что не так делаю ? Помогите, плиз...


Humorist   (2007-02-02 11:21:00) [1]

Большое спасибо за помощь всем!

Честно говоря, еще до завершения дискуссии внедрил решение (TRUNK ©   (26.01.07 13:51) [15] ). Используется для отлова экранов с ссобщениями. Некоторые сообщения отображаются короткое время (т.е. хэндл окна получил, а к тому моменту, когда собираюсь писать его образ, окна уже и нет). Ни разу не возникло ни одного исключения. Сейчас переделаю в соответствии с последними рекомендациями. Еще раз спасибо.


Piroxyline   (2007-01-31 13:08:00) [2]

try тут не надо, так как при ошибке не будет останова, а вернется или 0 (что вероятнее), или Cardinal(-1)


GrayFace   (2007-01-31 13:01:00) [3]

DVM ©   (30.01.07 15:53) [31]
> В [15] создание не помещается в try

А то что же?
try
memDC := CreateCompatibleDC(DC);
try
bm := CreateCompatibleBitmap(DC, W, H);


DC := GetWindowDC(Wnd);
try
memDC := CreateCompatibleDC(DC);
try


DVM   (2007-01-30 15:53:00) [4]


> GrayFace ©   (30.01.07 15:16) [30]


> В [15] создание не помещается в try

А то что же?
try
memDC := CreateCompatibleDC(DC);
try
bm := CreateCompatibleBitmap(DC, W, H);

> Нет. Объект 1 не создастся, остальные инициализированы нулями,
>  поэтому их Free ничего плохого не даст.

Да, здесь верно. Я перепутал немного.

> Правда, исключения в Free очень маловероятны.

Да они тут вообще маловероятны.


GrayFace   (2007-01-30 15:16:00) [5]

Humorist   (29.01.07 13:11) [21]
Правильно ли я понимаю, что нужно организоваывать ловушку ?

Да, больше ничего в голову не приходит. На WH_CALLWNDPROCRET. А потом GetQueueStatus использовать.

DVM ©   (29.01.07 15:55) [27]
Оба варианта одинаково плохи.

Честно говоря, не смотрел, что там делается. Просто убрал нагромождения try..finally, да от Exit-ов посоветовал избавиться.

DVM ©   (30.01.07 11:19) [29]
Зачем создание помещать внутрь try. Если произойдет исключение при создании - будет выполнено освобождение того чего нет. В том конкретном коде так скорее всего не будет, но писать надо правильно всегда.

В [15] создание не помещается в try, в [17] первый объект тоже создается вне try.

DVM ©   (30.01.07 11:19) [29]
Если при уничтожении объекта 1 произойдет исключение, то следующие за нм не будут уничтожены.

Да, тут есть слабое место. Правда, исключения в Free очень маловероятны.

DVM ©   (30.01.07 11:19) [29]
А если при создании объекта 1 произойдет исключение? Каша.

Нет. Объект 1 не создастся, остальные инициализированы нулями, поэтому их Free ничего плохого не даст.


DVM   (2007-01-30 11:19:00) [6]


> Humorist   (29.01.07 18:31) [28]
> А какой хороший ?

Дело все в том, что нет гарантии, что после выполнения SetWindowPos() окно успеет себя перерисовать. И разные там задержки - это не выход.
Нормального решения ИМХО нет.

По поводу кода из 15. Обычно принято делать так:
Создание чего-либо
try
 ...
finally
 Освобождение чего-либо
end;

Зачем создание помещать внутрь try. Если произойдет исключение при создании - будет выполнено освобождение того чего нет. В том конкретном коде так скорее всего не будет, но писать надо правильно всегда.

По поводу кода 17.

try
Создаем объект 1
Создаем объект 2
 ....
finally
 Освобождаем 1
 Освобождаем 2
end;

Если при уничтожении объекта 1 произойдет исключение, то следующие за нм не будут уничтожены. А если при создании объекта 1 произойдет исключение? Каша.

В приведенном коде исключения маловероятны, т.к. использованные апи функции не генерят исключений, но все же.


Humorist   (2007-01-29 18:31:00) [7]


>
> DVM ©   (29.01.07 15:55) [27]
>
> > TRUNK ©   (26.01.07 13:51) [15]
>
>
> > GrayFace ©   (27.01.07 09:04) [17]
>
> Оба варианта одинаково плохи.


А какой хороший ?


DVM   (2007-01-29 15:55:00) [8]


> TRUNK ©   (26.01.07 13:51) [15]


> GrayFace ©   (27.01.07 09:04) [17]

Оба варианта одинаково плохи.


Piroxyline   (2007-01-29 15:45:00) [9]

Нет, я не это имел в виду! Если получить битмап данного дц, то тогда можно получить данные об изображении на данном дц, которое хранится в памяти, и массив точек этого изображения вроде бы как через GetDIBits). Что мешает так сделать и скопировать этот массив точек на свой битмап? Щас поэкспериментирую с этим и кинусь исходником.


Humorist   (2007-01-29 15:21:00) [10]


> Piroxyline ©   (29.01.07 15:15) [24]
> Чтобы на DC было изображение, нужно сделать ему SelectObject(DC,
>  Bitmap). В справке вроде это было где-то написано. Узнать
> можно при помощи функции GetObject с соответствующими параметрами
> (они указаны в справке).


Это делается (см. текст программы выше). Дело в том, что если окно изначально не на переднем плане, его нужно отобразить на передний план. И речь сейчас идет о том, как отловить момент, когда оно прорисовалось. (в программе делается поростая пауза по времени. )


Piroxyline   (2007-01-29 15:15:00) [11]

Чтобы на DC было изображение, нужно сделать ему SelectObject(DC, Bitmap). В справке вроде это было где-то написано. Узнать можно при помощи функции GetObject с соответствующими параметрами (они указаны в справке).


Humorist   (2007-01-29 14:34:00) [12]


> Piroxyline ©   (29.01.07 14:30) [22]
> А если получить дц, а потом узнать, какой битмап им используется,
>  и снять с него данные? И безо всяких хуков.


ДЦ известен. Что значит узнать какой битмап используется; и как это узнать ?


Piroxyline   (2007-01-29 14:30:00) [13]

А если получить дц, а потом узнать, какой битмап им используется, и снять с него данные? И безо всяких хуков.


Humorist   (2007-01-29 13:11:00) [14]


> homm ©   >
> Подход не верный. Нужно дожидатся выполнения последнего
> WM_PAINT в очереди, а не определенный промежуток времени


Правильно ли я понимаю, что нужно организоваывать ловушку ?


GrayFace   (2007-01-28 16:13:00) [15]

homm ©   (27.01.07 16:16) [19]
Подход не верный. Нужно дожидатся выполнения последнего WM_PAINT в очереди, а не определенный промежуток времени

Простого решения в голову не приходит.


homm   (2007-01-27 16:16:00) [16]

> (Для моей задачи некоторое время ожидания окончания перерисовки
> - пусть даже заданное с запасом и заведомо большее требуемого
> - не столь важно. Образ окна требуется получать достаточно
> редко).

Подход не верный. Нужно дожидатся выполнения последнего WM_PAINT в очереди, а не определенный промежуток времени


GrayFace   (2007-01-27 09:05:00) [17]

Exitвезде лучше заменить на RaiseLastOSError


GrayFace   (2007-01-27 09:04:00) [18]

Sapersky   (25.01.07 13:50) [3]
http://expire.free.fr/board/index.php?showtopic=109

Я в шоке!
TRUNK ©   (26.01.07 13:51) [15]
Если нужна полная защита, тогда пиши так:

procedure CreateWindwowBitmap(Wnd: HWND);
var
R: TRect;
W,H: Integer;
DC,memDC: HDC;
bm,oldBM: HBITMAP;
bmp: TBitmap;
begin
SetWindowPos(Wnd,HWND_TOP,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
sleep(100);
GetWindowRect(Wnd,R);
W := R.Right - R.Left;
H := R.Bottom - R.Top;
DC := GetWindowDC(Wnd);
if (DC = 0) then
Exit;
bm:=0;
bmp:=nil;
memDC:=0;
try
memDC := CreateCompatibleDC(DC);
if (memDC = 0) then
  Exit;
  bm := CreateCompatibleBitmap(DC, W, H);
  if (bm = 0) then
    Exit;
    oldBM := SelectObject(memDC, bm);
    if (oldBM = 0) then
      Exit;
    if (BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY) = 0) then
      Exit;
    bm := SelectObject(memDC, oldBM);
    if (bm = 0) then
      Exit;
    bmp := TBitmap.Create;
      bmp.Handle := bm;
      bmp.SaveToFile('d:\eee.bmp');
finally
ReleaseDC(Wnd, DC);
DeleteDC(memDC);
DeleteObject(bm);
bmp.Free;
end;
end;

(Отступы как попало, т.к. не менял)


Humorist   (2007-01-26 13:56:00) [19]


> TRUNK ©   (26.01.07 13:51) [15]


Ок. Спасибо большое за деятельное участие ! Буду внедрять.


TRUNK   (2007-01-26 13:51:00) [20]

Если нужна полная защита, тогда пиши так:

procedureCreateWindwowBitmap(Wnd: HWND);
var
R: TRect;
W,H: Integer;
DC,memDC: HDC;
bm,oldBM: HBITMAP;
bmp: TBitmap;
begin
SetWindowPos(Wnd,HWND_TOP,0,0,0,0,SWP_NOMOVE orSWP_NOSIZE);
sleep(100);
GetWindowRect(Wnd,R);
W := R.Right - R.Left;
H := R.Bottom - R.Top;
DC := GetWindowDC(Wnd);
if(DC = 0) then
 Exit;
try
 memDC := CreateCompatibleDC(DC);
  if(memDC = 0) then
   Exit;
  try
   bm := CreateCompatibleBitmap(DC, W, H);
    if(bm = 0) then
     Exit;
    try
     oldBM := SelectObject(memDC, bm);
      if(oldBM = 0) then
       Exit;
      if(BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY) = 0) then
       Exit;
     bm := SelectObject(memDC, oldBM);
      if(bm = 0) then
       Exit;
     bmp := TBitmap.Create;
      try
       bmp.Handle := bm;
       bmp.SaveToFile('d:\eee.bmp');
      finally
       bmp.Free;
      end;
    finally
     DeleteObject(bm);
    end;
  finally
   DeleteDC(memDC);
  end;
finally
 ReleaseDC(Wnd, DC);
end;
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо