![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
как получить изображение окна, которое скрыто другими [D6, Win2k]
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;