Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.08.24;
Скачать: CL | DM;

Вниз

Как получиьт изображение окна?   Найти похожие ветки 

 
@!!ex ©   (2007-12-06 21:27) [0]

Задача.
Есть несколько открытых окон. Некоторые видны полностью, некоторые частично перекрыты, некоторые вообще не видны под другими окнами.
Задача в том, чтобы в программе получит скриншот для всех окон.
Способ точно есть, но я даже не представляю куда копать.


 
Черный Шаман   (2007-12-06 21:42) [1]

Тебе скриншот всего десктопа или каждого из окон?


 
@!!ex ©   (2007-12-06 21:43) [2]

> [1] Черный Шаман   (06.12.07 21:42)

Каждого окна.


 
ANTPro ©   (2007-12-06 22:02) [3]

> [2] @!!ex ©   (06.12.07 21:43)

Бежать по всем верхним видимым окнам и сохранять нарисованное на DC?


 
@!!ex ©   (2007-12-06 22:03) [4]

Нашел вот такой код:
procedure ScreenShot(hWindow: HWND; bm: TBitmap);
var
 Left, Top, Width, Height: Word;
 R: TRect;
 dc: HDC;
 lpPal: PLOGPALETTE;
begin
 {Check if valid window handle}
 if not IsWindow(hWindow) then Exit;
 {Retrieves the rectangular coordinates of the specified window}
 GetWindowRect(hWindow, R);
 Left := R.Left;
 Top := R.Top;
 Width := R.Right - R.Left;
 Height := R.Bottom - R.Top;
 bm.Width  := Width;
 bm.Height := Height;
 {get the screen dc}
 dc := GetDc(0);
 if (dc = 0) then
  begin
   Exit;
 end;
 {do we have a palette device?}
 if (GetDeviceCaps(dc, RASTERCAPS) and
   RC_PALETTE = RC_PALETTE) then
  begin
   {allocate memory for a logical palette}
   GetMem(lpPal,
     SizeOf(TLOGPALETTE) +
   (255 * SizeOf(TPALETTEENTRY)));
   {zero it out to be neat}
   FillChar(lpPal^,
     SizeOf(TLOGPALETTE) +
   (255 * SizeOf(TPALETTEENTRY)),
     #0);
   {fill in the palette version}
   lpPal^.palVersion := $300;
   {grab the system palette entries}
   lpPal^.palNumEntries :=
     GetSystemPaletteEntries(dc,
     0,
     256,
     lpPal^.palPalEntry);
   if (lpPal^.PalNumEntries <> 0) then
    begin
     {create the palette}
     bm.Palette := CreatePalette(lpPal^);
   end;
   FreeMem(lpPal, SizeOf(TLOGPALETTE) +
   (255 * SizeOf(TPALETTEENTRY)));
 end;
 {copy from the screen to the bitmap}
 BitBlt(bm.Canvas.Handle,
   0,
   0,
   Width,
   Height,
   Dc,
   Left,
   Top,
   SRCCOPY);
 {release the screen dc}
 ReleaseDc(0, dc);
end;

Но он задачку не решает.
Это все равно скриншот не окна, а области где это окно расположено. Соответственно, если поверх окна есть другое окно, изображение будет содержать это "другое" окно.
Он получает область окна, но если оно перекрыто, то получается


 
@!!ex ©   (2007-12-06 22:06) [5]

> [3] ANTPro ©   (06.12.07 22:02)

Не понял...


 
turbouser ©   (2007-12-06 22:09) [6]


> @!!ex ©   (06.12.07 22:06) [5]

Перебираешь все окна, выставляешь их на передний план и затем скриншот.
ps
честно говоря, непонятная затея...


 
@!!ex ©   (2007-12-06 22:11) [7]

> [6] turbouser ©   (06.12.07 22:09)

Если выставлять их на передний план, то юзер видит как это все происходит. Да и обратно окно уже не вернуть....
Затея банальна - делаю менеджер окон.


 
turbouser ©   (2007-12-06 22:29) [8]


> @!!ex ©   (06.12.07 22:11) [7]
> Затея банальна - делаю менеджер окон.

И при этом обязательно иметь скриншот?
В висте есть такая возможность, не спорю, в мсдн наверняка
можно найти информацию на эту тему.
Но вот под 2к/ХР - сильно сомневаюсь, что такое возможно.


 
@!!ex ©   (2007-12-06 23:02) [9]

> [8] turbouser ©   (06.12.07 22:29)

Я же в [0] сказал что возможно... :(
Не верите, см. TopDesk


 
Инс   (2007-12-06 23:06) [10]

procedure GetWindowBitmap(Wnd: HWND; Bmp: TBitmap);
var
R: TRect;
begin
GetWindowRect(Wnd, R);
Bmp.Width:= R.Right - R.Left;
Bmp.Height:= R.Bottom - R.Top;
Bmp.Canvas.Lock;
try
  SendMessage(Wnd, WM_PRINT, Integer(Bmp.Canvas.Handle), PRF_NONCLIENT or PRF_CHECKVISIBLE or
    PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN);
finally
  Bmp.Canvas.Unlock;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Bitmap: TBitmap;
begin
 Bitmap:=TBitmap.Create;
 try
   GetWindowBitmap(Handle,Bitmap);
   Bitmap.SaveToFile("C:\1.bmp");
 finally
   Bitmap.Free;
 end;
end;


На XP и выше можно использовать функцию PrintWindow


 
@!!ex ©   (2007-12-06 23:09) [11]

> [10] Инс   (06.12.07 23:06)

Хм. А вы уверены, что этот код работает?
А если окно не обрабатывает сообщение WM_PRINT?
Во всяком случае у меня получилось 12 белых прямоугольников после сохранения....

PrintWindow - это что? В хелпе не нашел...


 
Ins ©   (2007-12-06 23:12) [12]


> Хм. А вы уверены, что этот код работает?

С большинством окон работает, даже где-то в каком-то своем проекте использовал.


> PrintWindow - это что? В хелпе не нашел...

Плохо искали. В MSDN


 
@!!ex ©   (2007-12-06 23:13) [13]

> [10] Инс   (06.12.07 23:06)

Ваш код действительно работает... Получает скриншот формы.
А мой работать не хочет, сохраняет белые квадраты:
procedure GetWindowBitmap(Wnd: HWND; Bmp: TBitmap);
var
R: TRect;
begin
GetWindowRect(Wnd, R);
SetFocus(Wnd);
Bmp.Width:= R.Right - R.Left;
Bmp.Height:= R.Bottom - R.Top;
Bmp.Canvas.Lock;
try
 SendMessage(Wnd, WM_PRINT, Integer(Bmp.Canvas.Handle), PRF_NONCLIENT or PRF_CHECKVISIBLE or
   PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN);
finally
 Bmp.Canvas.Unlock;
end;
end;

Function EnumWindowsProc(WND:HWND; LParam:Integer):Boolean;
begin
if IsWindowVisible(WND)=True then begin
  GetWindowBitmap(WND,BitMap);
  BitMap.SaveToFile("C:\Temp\"+IntTOStr(Wnd)+".bmp");
end;
Result:=True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 BitMap:=TBitMap.Create;
 EnumWindows(@EnumWindowsProc,0);
 BitMap.Free;
end;


 
@!!ex ©   (2007-12-06 23:14) [14]

> Плохо искали. В MSDN

НЕту MSDN под рукой. :(
поищу в онлайн MSDN"e.


 
homm ©   (2007-12-06 23:15) [15]

> [9] @!!ex ©   (06.12.07 23:02)
> Я же в [0] сказал что возможно... :(

Ну раз сказал :)
Жаль что майкросовт об этом не знала, когда 9х и 2к писала :(


 
@!!ex ©   (2007-12-06 23:18) [16]

> [15] homm ©   (06.12.07 23:15)

Так я не от балды сказал. :)
Есть пример работающей программы, которая это делает.


 
homm ©   (2007-12-06 23:23) [17]

> [16] @!!ex ©   (06.12.07 23:18)
> Есть пример работающей программы, которая это делает.

в ХП ?


 
@!!ex ©   (2007-12-06 23:24) [18]

> [17] homm ©   (06.12.07 23:23)

Да. Вроде в 2000 она тоже работает. TopDesk


 
homm ©   (2007-12-06 23:25) [19]

> [18] @!!ex ©   (06.12.07 23:24)

Вроде?


 
@!!ex ©   (2007-12-06 23:27) [20]

> [19] homm ©   (06.12.07 23:25)

Под XP она работает. Если я правильно помню, под 2000 тоже.


 
@!!ex ©   (2007-12-06 23:27) [21]

Ты так докапываешься, какбудто я себя зарекомендовал как брехун редкостный.


 
homm ©   (2007-12-06 23:34) [22]

> [20] @!!ex ©   (06.12.07 23:27)

http://soft.mydiv.net/win/download-TopDesk.html
???

у меня при запуске она посемуто все окна передернула на верх по очереди в нужных размеров. Не догадываешся, зачем? :)


 
@!!ex ©   (2007-12-06 23:35) [23]

Инс, спасибо!
PrintWindow делает то что нужно!! Правда работает непрозрачно, явно чето над окнами творит, но результата достигает! что и нужно!


 
@!!ex ©   (2007-12-06 23:36) [24]

> [22] homm ©   (06.12.07 23:34)

При запуске чего?


 
homm ©   (2007-12-06 23:37) [25]

> [24] @!!ex ©   (06.12.07 23:36)

При запуске TopDesk.


 
turbouser ©   (2007-12-06 23:39) [26]


> homm ©   (06.12.07 23:34) [22]

Я же говорил :))


 
@!!ex ©   (2007-12-06 23:41) [27]

> [25] homm ©   (06.12.07 23:37)

Ну и как окна которые были видимы при запуске TopDesk скажутся на переключении окон в процессе работы?
Фича в том, что даже если окно обновилось на заднем фоне, то при переключении с помощью TopDesk"а оно все равно будет с корректной информацией.


 
@!!ex ©   (2007-12-06 23:42) [28]

> Я же говорил :))

Ты был не прав.
Читай 27. В процессе работы он никакие окна на передний план не выносит.


 
@!!ex ©   (2007-12-06 23:53) [29]

Ну короч вопрос решенный.
PrintWindow получает изображения любого окна.
Единственно, после работы нужно InvalidateRect(0,nil,true); сделатЬ, чтобы изображение на экране было нормальное.


 
homm ©   (2007-12-06 23:54) [30]

> [27] @!!ex ©   (06.12.07 23:41)
> Фича в том, что даже если окно обновилось на заднем фоне,
> то при переключении с помощью TopDesk"а оно все равно будет
> с корректной информацией.

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


 
@!!ex ©   (2007-12-06 23:55) [31]

> [30] homm ©   (06.12.07 23:54)

PrintWindow работает заметно быстрее чем перебор окон у TopDesk"a. так что это не правильный метод, ИМХО


 
homm ©   (2007-12-06 23:58) [32]

> [31] @!!ex ©   (06.12.07 23:55)
> PrintWindow работает заметно быстрее чем перебор окон у
> TopDesk"a

Справку по PrintWindow внимательно читал? Устраивают ограничения? Ты вроде хотел, что-бы в 2к тоже работало.


 
turbouser ©   (2007-12-07 00:55) [33]


> @!!ex ©

Заставил таки меня влезть в мсдн :-)


 
KSergey ©   (2007-12-07 07:10) [34]

Прикольно, при этом написано, что WM_PRINT поддержана на NT 4.0 and later, а вот PrintWindow - XP and .NET Server.
Однако же: This function [PrintWindow] is similar to WM_PRINT


 
ЗапомниСынок   (2007-12-07 09:32) [35]

Я в свое время хотел написать простенький бот для PartyPoker, пытался считывать инфу со стола, несколько дней возился, пытаясь снять скрин-шот с закрытого окна, так и не удалось. Оказывается плохо искал...


 
@!!ex ©   (2007-12-07 10:58) [36]

> [34] KSergey ©   (07.12.07 07:10)

Может быть фича в том, что PrintWindow хитро окна перебирает. Во всяком случае визуально это очень быстрая операция. Скорее всего такой перебор возможен только через хитрую функциЮ, которой раньше не было.


> [35] ЗапомниСынок   (07.12.07 09:32)

Не факт, что с закрытыми окнами будет работать, с перекрытыми точно работает. Еще вопрос как оно будет с StayOnTop. Но это легко проверяется.


 
@!!ex ©   (2007-12-07 11:00) [37]

С invisible окон тоже скриншот снимается! *COOL* :)


 
Sapersky   (2007-12-07 14:15) [38]

Есть ещё такая библиотека SPrintWindow, которая, как утверждает автор, может работать и в 2000, но она, похоже, так и не вышла из состояния "беты". С учётом того, что используется хакерский метод (собственный драйвер), это вызывает определённые опасения...
http://expire.free.fr/board/index.php?showtopic=109



Страницы: 1 вся ветка

Текущий архив: 2008.08.24;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.019 c
15-1215551592
AFHU
2008-07-09 01:13
2008.08.24
Биллу Гейтсу будет вручена премия Эйнштейна


2-1216296933
Dmitry87
2008-07-17 16:15
2008.08.24
Быстродействие алгоритмов


2-1216282915
Артур Пирожков
2008-07-17 12:21
2008.08.24
Проблемы с Tidftp


15-1215089131
Kolan
2008-07-03 16:45
2008.08.24
Как управлять проектами?


15-1215145232
Slider007
2008-07-04 08:20
2008.08.24
С днем рождения ! 4 июля 2008 пятница