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-01-26 13:08:00) [21]


> TRUNK ©   (26.01.07 10:46) [11]
>
>
> Попробуй заменить HWND_TOP на HWND_TOPMOST.


Попробовал. Родительское окно становится активным; однако дочернее все равно находится поверх него. Поробовал разные последоватенльности HWND_TOPMOST и HWND_BOTTOM в отношении родительского и дочернего окна; то что нужно не получилось. Может попробовать скрывать дочернее окно или отправлять его за пределы рабочего стола, а затем возвращать на место ?



> окончательный вариант:
>
> BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY);
> bm := SelectObject(memDC, oldBM);
>
> bmp := TBitmap.Create;
> bmp.Handle := bm;
> bmp.SaveToFile('d:\eee.bmp');
> bmp.Free;
>
> DeleteObject(bm);
> DeleteDC(memDC);


Все работает. Не стоит ли для корректности поставть try - finally ? В окончательном варианте что-то типа

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

bmp:TBitmap;
k:integer;
begin
try
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);
memDC := CreateCompatibleDC(DC);

bm := CreateCompatibleBitmap(DC, W, H);
oldBM := SelectObject(memDC, bm);

BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY);
bm := SelectObject(memDC, oldBM);

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

DeleteObject(bm);
DeleteDC(memDC);
ReleaseDC(Wnd, DC);
end;

end;


> Sapersky


Спасибо за письмо. Однако с SPrintWindow еще не разбирался: вроде появился другой путь решения задачи. А PrintWindow  все-таки не подходит: имеется в наличии W2K.


TCrash   (2007-01-26 12:14:00) [22]

Сорри, не дочитав ветку нарисовал ответ :)


TCrash   (2007-01-26 12:12:00) [23]

Humorist   (25.01.07 14:28) [5]
SetForegroundWindow(Wnd)


TRUNK   (2007-01-26 10:46:00) [24]


> наше окно, перекрытое его дочерним

Попробуй заменить HWND_TOP на HWND_TOPMOST.


> После переделки результирующий файл оказался пустым

Признаю свою ошибку: я забыл посмотреть на следующие четыре строки в которых происходит сохранение битмэпа. Приведу окончательный вариант:

BitBlt(memDC, 0,0, w, h, DC, 0,0, SRCCOPY);
bm := SelectObject(memDC, oldBM);

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

DeleteObject(bm);
DeleteDC(memDC);
ReleaseDC(Wnd, DC);


Humorist   (2007-01-25 19:44:00) [25]


> TRUNK ©   (25.01.07 14:52) [7]
> Примерно так (не проверял):
>
> SetWindowPos(Wnd,HWND_TOP,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
>
> // ждём немного
> // делаем снимок
> SetWindowPos(Wnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
>


Отчично !
Работает так, как надо.
(Есть, конечно, нюанс: если у окна, образ которого мы хотим получить, есть дочернее окно, и оно перекрывает наше, то получается именно такая картинка (наше окно, перекрытое его дочерним). И убрать на задний план дочернее окно не удается.)

Но в любом случае это огромный прогресс. Большое спасибо.

> Эти строки надо переделать так:
> bm := SelectObject(memDC, oldBM);
> DeleteObject(bm);
> DeleteDC(memDC);


После переделки результирующий файл оказался пустым. Оставил так как было.


Sapersky   (2007-01-25 15:36:00) [26]

Не могли бы Вы выслать архив по SPrintWindow() на адрес antol2004@rambler.ru, плиз.

Отправил, но версия там (не помню уж где её добыл) 0.1.1 BETA, со всеми возможными вытекающими. Поищи SPrintWindow гуглом, может быть есть новее.
Я сам сейчас предпочёл бы скорее стандартный PrintWindow (если он даст более-менее приличную скорость). По приводимой здесь
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1168458032&n=3([43], [99])
статистике XP стоит у 70-80% пользователей.


TRUNK   (2007-01-25 14:59:00) [27]


> SelectObject(memDC, oldBM);
> DeleteDC(memDC);
> DeleteObject(oldBM);

Эти строки надо переделать так:
bm := SelectObject(memDC, oldBM);
DeleteObject(bm);
DeleteDC(memDC);


TRUNK   (2007-01-25 14:52:00) [28]

Примерно так (не проверял):

SetWindowPos(Wnd,HWND_TOP,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);
// ждём немного
// делаем снимок
SetWindowPos(Wnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE);


Humorist   (2007-01-25 14:35:00) [29]


> Sapersky  

> В XP есть функция PrintWindow.
> + хакерские методы вроде:
> http://expire.free.fr/board/index.php?showtopic=109
> <Цитата>


Спасибо за совет.
1. Однако W2K.
2. По указанному адресу требуется регистрация, я, вроде, сделал все что нужно, однако на указанный адрес обещанные дальнейшие инструкции не пришли. Не могли бы Вы выслать архив по SPrintWindow() на адрес antol2004@rambler.ru, плиз.


Humorist   (2007-01-25 14:28:00) [30]


> Я думал о таком варианте. Вопрос в том сколько времени уйдёт
> на перерисовку окна после того, как оно будет выведено на
> передний план.
> Другими словами, после вывода окна вперёд возможно придётся
> некоторое время подождать перед тем, как делать его снимок.
>


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

ShowWindow(Wnd,SW_RESTORE);

Однако результата это не дало


TRUNK   (2007-01-25 14:12:00) [31]


> Humorist   (25.01.07 11:41) [2]
> А нельзя ли требуемое окно вывести на передний план, взять
> его изображение, а затем снова спрятать

Я думал о таком варианте. Вопрос в том сколько времени уйдёт на перерисовку окна после того, как оно будет выведено на передний план.
Другими словами, после вывода окна вперёд возможно придётся некоторое время подождать перед тем, как делать его снимок.


Sapersky   (2007-01-25 13:50:00) [32]

В XP есть функция PrintWindow.
+ хакерские методы вроде:
http://expire.free.fr/board/index.php?showtopic=109


Humorist   (2007-01-25 11:41:00) [33]

1. Правильно ли я понял, что  получить изображение окна, которое скрыто другими, нельзя в принцине ?
А нельзя ли требуемое окно вывести на передний план, взять его изображение, а затем снова спрятать (или не прятать - если это не так уж необходимо) ?

2. Попробовал WM_PRINT:

procedure CreateWindwowBitmap2(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);

bmp:=TbitMap.Create;
bmp.Width:=W;
bmp.Height:=H;

 SendMessage(bmp.Canvas.Handle,WM_PRINT,DC,PRF_CHILDREN or PRF_CLIENT or PRF_ERASEBKGND or PRF_NONCLIENT or PRF_OWNED);
 ReleaseDC(Wnd, DC);

bmp.SaveToFile('d:\qqq.bmp');
bmp.Free;

end;

Однако результа представляет из себя белый прямоугольник.

Может все-таки существуют варианты ?


TRUNK   (2007-01-24 21:44:00) [34]


> Что не так делаю ?

Всё так. Просто если часть окна закрыта другим окном, эта закрытая часть окном вообще не рисуется для экономии времени.


Страницы:   1 2

Наверх

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