Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как делать снимки экрана.


Автор: Sunvas 21.4.2006, 07:07
Нужно  написать небольшой просмотрщик удаленного экрана. Есть прома - как максимально бысто делать снимки с удаленного экрана?
Функция bitblt делает это очень вяло, да и удаленный комп страшно глючит, а дос режим вообще отказывается фоткать.
Помогите найти альтернативное решение. 

Автор: Guedda 21.4.2006, 07:15
Код

procedure TForm1.Button1Click(Sender: TObject);
var
  DeskTop: TCanvas;
begin
  DeskTop := TCanvas.Create;
  try
    with DeskTop do
      Handle := GetWindowDC(GetDesktopWindow);
    with Image1.Canvas do
      CopyRect(Rect(0, 0, 200, 200),
        DeskTop,
        Rect(0, 0, 200, 200))
  finally
    DeskTop.Free;
  end
end;
 

Автор: Snowy 21.4.2006, 09:07
Цитата(Sunvas @  21.4.2006,  07:07 Найти цитируемый пост)
 Есть прома - как максимально бысто делать снимки с удаленного экрана
У многих такая же проблема

Цитата(Sunvas @  21.4.2006,  07:07 Найти цитируемый пост)
а дос режим вообще отказывается фоткать.
Правильно. И не должно.

Цитата(Sunvas @  21.4.2006,  07:07 Найти цитируемый пост)
Помогите найти альтернативное решение. 
DirectDraw

Цитата(Guedda @  21.4.2006,  07:15 Найти цитируемый пост)
CopyRect
Это тот же BitBlt, только в дельфёвой обертке. 

Автор: Guedda 21.4.2006, 11:54
Цитата(Snowy @  21.4.2006,  10:07 Найти цитируемый пост)
Это тот же BitBlt, только в дельфёвой обертке.  

Извиняюсь... Не знал. Самому стало интересно...

Snowy, а как реализовать 
Цитата(Snowy @  21.4.2006,  10:07 Найти цитируемый пост)
DirectDraw

 

Автор: Sunvas 22.4.2006, 07:18
Цитата(Snowy @  21.4.2006,  09:07 Найти цитируемый пост)
У многих такая же проблема

Ну так давайте соберемся и обсудим вместе!



Цитата(Snowy @  21.4.2006,  09:07 Найти цитируемый пост)
Цитата(Sunvas @  21.4.2006,  07:07 )    
а дос режим вообще отказывается фоткать.    
Правильно. И не должно.

А как же быть?


Цитата(Guedda @  21.4.2006,  11:54 Найти цитируемый пост)
Snowy, а как реализовать 

Цитата(Snowy @  21.4.2006,  10:07 )    
DirectDraw

Меня это тоже заинтерисовало. 

Автор: Rouse_ 22.4.2006, 20:59
Скорость снятия снимка тебя не должна интересовать т.к. это делается достаточно быстро. Можешь проверить, отображая снимки сразуже на экране на той-же машине. Торможение в другом, а именно в ограничении пропускной способности канала. Правильное решение отправлять не картинку, а только изменения которые произошли с изображением с момента предыдущей передачи... 

Автор: Sunvas 23.4.2006, 00:19
Цитата(Rouse_ @  22.4.2006,  20:59 Найти цитируемый пост)
Торможение в другом, а именно в ограничении пропускной способности канала.

Ну с передачей данных у меня все хорошо.

Цитата(Rouse_ @  22.4.2006,  20:59 Найти цитируемый пост)
Скорость снятия снимка тебя не должна интересовать т.к. это делается достаточно быстро

Ну если делать снимков 12 в секунду то да, а вот если более чем 24 то тут происходят глюки.

Цитата(Rouse_ @  22.4.2006,  20:59 Найти цитируемый пост)
Можешь проверить, отображая снимки сразуже на экране на той-же машине.

Даже если это делать так. Но ведь есть и еще одна проблемма - фоткать Directdraw и ДОС режим такие функции вообще отказываются. Что ж делать?

Цитата(Rouse_ @  22.4.2006,  20:59 Найти цитируемый пост)
Правильное решение отправлять не картинку, а только изменения которые произошли с изображением с момента предыдущей передачи... 

Посоветуй, пожалуйста, как это реализовать.
 

Автор: Rouse_ 23.4.2006, 08:42
Цитата(Sunvas @  23.4.2006,  01:19 Найти цитируемый пост)
фоткать Directdraw и ДОС режим такие функции вообще отказываются. Что ж делать

Естественно отказываются т.к. вывод в данных режимах происходит насобственный оверлей. Тебе нужно подключиться к нему и снять изображение. Как это сделать читай тут: http://www.delphimaster.ru/articles/directx/index.html

Добавлено @ 08:45 
Цитата(Sunvas @  23.4.2006,  01:19 Найти цитируемый пост)
Посоветуй, пожалуйста, как это реализовать.

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

Автор: Loader 23.4.2006, 15:05
Самый быстрый из известных мне способов. Чистый WinAPI и никакого BitBlt(). Снимает и DOS окна и все остальное.

Код

procedure ScreenShot(const Width, Height: LongInt; const Filename: PChar);
var
  Bih: TBitmapInfoHeader;
  Bfh: TBitmapFileHeader;
  CDC, DC: HDC;
  CBmp: HBitMap;
  Bmp: Pointer;
  BmpInfo: TBitMapInfo;
  F, Written, Size: LongWord;
  
begin
  DC := GetDC(0);
  CDC := CreateCompatibleDC(DC);

  Bih.biSize := SizeOf(TBitmapInfoHeader);
  Bih.biWidth := Width;
  Bih.biHeight := Height;
  Bih.biPlanes := 1;
  Bih.biBitCount := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
  if Bih.biBitCount = 32 then Bih.biBitCount := 24;

  Bfh.bfType := $4D42;
  Bfh.bfOffBits := SizeOf(TBitmapFileHeader) + SizeOf(TBitmapInfoHeader);

  Size := Width * Height * 3;
  BmpInfo.bmiHeader := Bih;
  CBmp := CreateDIBSection(DC, BmpInfo, 0, Bmp, 0, 0);
  SelectObject(CDC, CBmp);
  StretchBlt(CDC, 0, 0, Width, Height, DC, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY);

  F := CreateFile(Filename, GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
  WriteFile(F, Bfh, SizeOf(TBitmapFileHeader), Written, nil);
  WriteFile(F, Bih, SizeOf(TBitmapInfoHeader), Written, nil);
  WriteFile(F, Bmp^, Size, Written, nil);
  CloseHandle(F);
end;
  

Автор: Rouse_ 23.4.2006, 15:26
Loader
1. данный способ не может быть самым быстрым т.к. используется вызов StretchBlt заведомо дольше исполняющийся в отличие от BitBlt.
2. в данном примере присутствуют утечки памяти, ввиду неразрушения захваченых обьектов ядра. 

Автор: Yanis 23.4.2006, 20:15
Цитата(Loader @  23.4.2006,  15:05 Найти цитируемый пост)
Чистый WinAPI и никакого BitBlt().

Может быть тебя это расстроит, но BitBlt и есть функция Windows API

Автор: Sunvas 24.4.2006, 00:19
Цитата(Rouse_ @  23.4.2006,  08:42 Найти цитируемый пост)
Сканировать две картинки и орагинизовывать массив по каким координатам какой пиксель изменился. Отправлять этот массив и отображать его на конечной машине. Ну а реализацию, думаю сам смошь нарисовать 

Так еще больше глючить будет... 

Автор: Yanis 24.4.2006, 00:34
Цитата(Sunvas @  24.4.2006,  00:19 Найти цитируемый пост)
Так еще больше глючить будет...  

А RAdmin по твоему картинки по сети шлёт smile 

Автор: Sunvas 24.4.2006, 00:45
Loader, а в каком формате сохраняет твоя процедура рисунок?? - у меня сохраненный файл весит 54 байта, какой программой его нужно открывать? smile

Добавлено @ 00:57 
Цитата(Yanis @  24.4.2006,  00:34 Найти цитируемый пост)
А RAdmin по твоему картинки по сети шлёт  

А я не знаю, как он действует, да и ты я думаю тоже не знаешь до конца. Или у тебя есть исходники? К тому же ДОС режим и режим игры он тоже не фоткает.. 

Автор: Yanis 24.4.2006, 01:01
Цитата(Sunvas @  24.4.2006,  00:45 Найти цитируемый пост)
К тому же ДОС режим и режим игры он тоже не фоткает..

Это подтверждает, что он не использует сниятие скриншотов для передачи состояния удалённого экрана. 

Автор: Sunvas 24.4.2006, 01:19
Цитата(Yanis @  24.4.2006,  01:01 Найти цитируемый пост)
Это подтверждает, что он не использует сниятие скриншотов для передачи состояния удалённого экрана. 

Я не обсуждаю Радмин, он мне не нужен. Мне всего лишь нужно сделать небольшой просмотрщий удаленного экрана. 

Автор: Rouse_ 24.4.2006, 09:14
Цитата(Sunvas @  24.4.2006,  01:19 Найти цитируемый пост)
Так еще больше глючить будет...  

как реализуешь - так и будет глючить smile Я тебе обьяснил принцип. Использовать его или изобретать очередной велосипед- дело твое smile 

Автор: Sunvas 25.4.2006, 00:24
Цитата(Rouse_ @  24.4.2006,  09:14 Найти цитируемый пост)
как реализуешь - так и будет глючить 

Ты намекашь на то, что это безвыходная ситуация - чтобы я не сделал, то все равно будет глючить?

Цитата(Rouse_ @  24.4.2006,  09:14 Найти цитируемый пост)
Я тебе обьяснил принцип. Использовать его или изобретать очередной велосипед- дело твое  

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

Автор: <Spawn> 25.4.2006, 06:51
Sunvas, Тебе верно говорят. Но данный подход будет несколько не быстрым, если ты его реализуешь, например, через SetPixel, которая черезвычайно медленна. Если хочется быстро менять нужные пикселы на своем изображении, то ищи клас TQuickPixel, либо на этом форуме, либо на мастерах дельфи (не помню точно). Скорость там потрясная из за прямого доступа к видеопамяти, если мне не изменяет память. Реализация на ассемблереsmile 

Автор: Rouse_ 25.4.2006, 10:07
Цитата(Sunvas @  25.4.2006,  01:24 Найти цитируемый пост)
Ну это ж надо циклически сравнивать почти каждый пиксель, а затем отправлять части изображения

Не обязательно каждый, можно сравнивать блоками, тогда получишь прирост производительности.
Цитата(Sunvas @  25.4.2006,  01:24 Найти цитируемый пост)
Ты намекашь на то, что это безвыходная ситуация - чтобы я не сделал, то все равно будет глючить?

Ни на что не намекаю smile Просто ты так сам сказал что будет глючить еще больше smile 

Автор: Sunvas 26.4.2006, 07:00
Цитата(<Spawn> @  25.4.2006,  06:51 Найти цитируемый пост)
 Если хочется быстро менять нужные пикселы на своем изображении, то ищи клас TQuickPixel,

Немного не понял, а зачем менять пиксели? 

Автор: Yanis 26.4.2006, 07:55
Цитата(Sunvas @  26.4.2006,  07:00 Найти цитируемый пост)
Немного не понял, а зачем менять пиксели?  

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

Автор: Sunvas 27.4.2006, 07:50
Цитата(Yanis @  26.4.2006,  07:55 Найти цитируемый пост)
Ты же не только получать изображение будешь, но и выводить на устройство... 

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

Автор: Yanis 27.4.2006, 08:47
Цитата(Sunvas @  27.4.2006,  07:50 Найти цитируемый пост)
а не быстро выводить картинку на устройство

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

Автор: Sunvas 27.4.2006, 17:04
Цитата(Yanis @  27.4.2006,  08:47 Найти цитируемый пост)
т.е. тебе нужно только получить снимок удалённого экрана, а отображать ты его нигде не собираешься?  

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

Автор: Тьма 27.4.2006, 17:12
но тебе все равно надо будет выводить эти пикселя на какой нибуть битмап 

Автор: Sunvas 27.4.2006, 17:23
Но это уже совсем другая проблемма!!! 

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