Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > скриншот ( Canvas ) объекта чужого окна...


Автор: CompWorm 25.7.2007, 01:31
приветствую!

есть задача - 
снять скриншот с окна чужого приложения или одного из его объектов.

чего есть - 
1) вопрос решен тут http://forum.vingrad.ru/faq/topic-157640.html

2) на основе инета (конечно же  smile ) сочинил упрощенно-укороченный вариан

Код


var MyCanvas:   TCanvas;
var ScreenDC: HDC;
begin
 ScreenDC := GetDC($029604BC); 
 MyCanvas:=TCanvas.Create();
 MyCanvas.Handle:=ScreenDC;

 Image1.Canvas.Copyrect(MyCanvas.ClipRect, MyCanvas, MyCanvas.ClipRect );  
 Image1.AutoSize :=true;

 ReleaseDC(0,ScreenDC);
 MyCanvas.Free;
end;


где ScreenDC := GetDC($029604BC);  - хэндл нужного мне объекта чужого окна. 
// для общего скриншота юзаем GetDC(0);

проблема - 
часто, я бы даже сказал очень часто, нужное окно свернуто или перекрыто другими окнами. 
даже в случае скриншота рабочего стола, все равно видны окна.
оба метода в таком случае не выдают желаемого результата, то есть чистой картинки, снятой с канвы. 
есть так же спасительный вариант, что в окне чужой программы предусмотрена автоперерисовка, но это скорее исключение, чем правило.

вопрос - как снять изображение с канвы свернутого или перекрытого другими окнами объекта?

Автор: misha_mike 25.7.2007, 10:17
Странно что всегда работает это:
Код
ScreenDC := GetDC($029604BC);


Хендл это не глобальный идентификатор конкретного объекта, а просто ссылка на его экземпляр. При каждом создании объекта это число будет разным.

А что касается самого вопроса, то если приложение само не захочет свою картинку одать, через канву ее не взять. Есть такое понятие как Clipping, обозначающее доступную для рисования/считывания область. Если какой-то контрол не попал в Clipping Area, то он себя просто не отрисовывает, и его изображение так сказать вообще не определено и никто не может знать как он должен выглядеть.

Можно попробовать заставить его отрисоваться на созданную отдельно канву, для чего служат сообщения WM_ERASEBKGND и WM_PAINT, но с ними не всегда все гладко, как оказалось.

Автор: CompWorm 25.7.2007, 20:10
Цитата(misha_mike @  25.7.2007,  10:17 Найти цитируемый пост)
Странно что всегда работает это:
ScreenDC := GetDC($029604BC);

ну это я естественно каждый раз беру с Winspector Spy... это я просто для примера число написал.


Цитата(misha_mike @  25.7.2007,  10:17 Найти цитируемый пост)
Можно попробовать заставить его отрисоваться на созданную отдельно канву, для чего служат сообщения WM_ERASEBKGND и WM_PAINT, но с ними не всегда все гладко, как оказалось. 

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

Автор: MetalFan 25.7.2007, 21:30
посмотри решение на http://delphimaster.ru/cgi-bin/forum.pl?id=1183639569&n=0

Автор: misha_mike 25.7.2007, 23:43
Ну пример можно посмотреть в исходнике TWinControl.PaintTo, где оба этих сообщения собственно используются. А проблемы тут могут быть со стилями XP/Vista и если отрисовкой контрола занимается не он сам, а например, его Parent.

Автор: CompWorm 31.7.2007, 00:33
Большое спасибо за помощь )

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)