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

Вниз

delphi + скриншот + белый экран   Найти похожие ветки 

 
acyb   (2006-11-21 10:05) [0]

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

вот исходники

function Tservice1.CaptureScreenRect(ARect : TRect) : TBitmap;
var
ScreenDC : HDC;
begin
Result:=TBitmap.Create;
with result, ARect do
begin
Width:=Right-Left;
Height:=Bottom-Top;
ScreenDC:=GetDC(0);
try
BitBlt(Canvas.Handle, 0,0,Width,Height,ScreenDC, Left, Top, SRCCOPY );
finally
ReleaseDC(0, ScreenDC);
end;
Palette:=GetSystemPalette;
end;
end;

function GetSystemPalette : HPalette;
var
PaletteSize : integer;
LogSize : integer;
LogPalette : PLogPalette;
DC : HDC;
Focus : HWND;
begin
result:=0;
Focus:=GetFocus;
DC:=GetDC(Focus);
try
PaletteSize:=GetDeviceCaps(DC, SIZEPALETTE);
LogSize:=SizeOf(TLogPalette)+(PaletteSize-1)*SizeOf(TPaletteEntry);
GetMem(LogPalette, LogSize);
try
with LogPalette^ do
begin
palVersion:=$0300;
palNumEntries:=PaletteSize;
GetSystemPaletteEntries(DC, 0, PaletteSize, palPalEntry);
end;
result:=CreatePalette(LogPalette^);
finally
FreeMem(LogPalette, LogSize);
end;
finally
ReleaseDC(Focus, DC);
end;
end;


 
Stexen ©   (2006-11-21 15:27) [1]

Может перед битблт стоило указать формат битмапа


 
acyb   (2006-11-21 16:17) [2]

каким образом? я в этом не силен... всю жизнь базы программил


 
acyb   (2006-11-21 17:33) [3]

подсказали тут идею про SetThreadDesktop тк програ работает как сервис, сейчас сижу ковыряю инфу в инете


 
Stexen ©   (2006-11-21 19:40) [4]

не ты больно сложно берешь... зря! это в четыре строчки пишется....

вообще сейчас комилятора под рукой нет так что не могу точно сказать в чем ошибка но все таки попробуй на всяк случай
bitmap.pixelformat := pf24bit;

Перед битблт! И убери
Palette:=GetSystemPalette;


 
acyb   (2006-11-22 11:32) [5]

увы, не помогло


 
Чапаев ©   (2006-11-22 12:48) [6]

> [3] acyb   (21.11.06 17:33)
Если сервис неинтерактивный, то всё равно не поможет.


 
Чапаев ©   (2006-11-22 12:52) [7]

> [5] acyb   (22.11.06 11:32)
Может, WtsGetCurrentConsoleId()+WtsQueryUserToken()+ImpersonateLoggedOnUser()? (Это я сам недавно научился, теперь с восторгом неофита советую всем :о) )


 
acyb   (2006-11-22 13:18) [8]

делаю вот так вот - не помогает

procedure TService1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var
fs: TFileStream;
Data: TMemoryStream;
btm:tbitmap;
bmp: TBItmap;
jpg: TJpegImage;
scale: Double;
jpgImg: TJPEGImage;
JPEG: TJPEGImage;
Bitmap: TBitmap;
DC: HDC;
 Desk: HWND;

begin

case strtoint(Socket.ReceiveText) of
403:
begin
 OpenWindowStation("WinSta0",False,GENERIC_ALL);
SetThreadDesktop(OpenInputDesktop(0,False,GENERIC_ALL));
 
 btm:=TBitmap.Create;
 JPG:=TJpegImage.Create;
 
 try
   Desk := GetDesktopWindow;
   DC := GetWindowDC(Desk);
   try
     btm.PixelFormat:=pf24bit;
     Btm.Height := Screen.Height;
     Btm.Width := Screen.Width;
     BitBlt(Btm.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DC, 0, 0, SRCCOPY);
   finally
     ReleaseDC(Desk, DC);
   end;
   
 finally
   Btm.Free;
 end;

   JPG.Assign(btm);

 //===
 if jpg.Height > jpg.Width then scale := 1280 / jpg.Height
 else scale := 1024/ jpg.Width;
 bmp:= Tbitmap.Create;
 try
   bmp.Width:=Round( jpg.Width * scale );
   bmp.Height:=Round( jpg.Height * scale );
   bmp.Canvas.StretchDraw( bmp.Canvas.Cliprect, jpg );
   jpg.Assign( bmp );
 finally
   bmp.free;
 end;
 jpg.SaveToFile("c:\scr.jpg");
 jpg.free;
 btm.Free;
 //===

 fs:=TFileStream.Create("c:\scr.jpg", fmOpenRead);
 try
   fs.Position:= 0;
   Socket.SendText("Size:"+IntToStr(fs.Size) + #0);
   Socket.SendStream(fs);
 finally
 end;
end;

405:


 
RASkov   (2006-11-23 04:29) [9]

procedure TForm1.Button1Click(Sender: TObject);
var Bmp: TBitMap; SDC: HDC; Jpg: TJpegImage;
begin
 Bmp:=TBitMap.Create;
 Jpg:=TJpegImage.Create;
 SDC:=GetDC(0);
 try
  Bmp.Width:=Screen.Width;
  Bmp.Height:=Screen.Height;
  case GetDeviceCaps(SDC, BITSPIXEL) of
   16: Bmp.PixelFormat:=pf16bit;
   32: Bmp.PixelFormat:=pf32bit;
   else Bmp.PixelFormat:=pf16bit;
  end;
  BitBlt(Bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, SDC, 0, 0, SRCCOPY );
  Jpg.CompressionQuality:=10;
  Jpg.Assign(Bmp);
  Bmp.SaveToFile("C:\1.bmp");
  Jpg.SaveToFile("C:\1.jpg");
  Canvas.StretchDraw(Canvas.ClipRect, Jpg);
 finally
  ReleaseDC(0, SDC);
  Bmp.Free;
  Jpg.Free;
 end;
end;


Но может я не совсем въехал в вопрос, тогда sorry:(


 
acyb   (2006-11-23 10:00) [10]

увы, не помогло...


 
acyb   (2006-11-23 10:13) [11]

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


 
Чапаев ©   (2006-11-23 12:20) [12]

Вот работающий код. Писался "на коленке", просто из любопытства, без всяких проверок на корректность и возврата к исходному состоянию.
procedure TService1.ServiceExecute(Sender: TService);
var
 Bmp:TBitmap;
 Screen:TCanvas;
 R:TRect;
 WinSta:HWINSTA;
 Desk:HDESK;
begin
 Sleep(3000);
 GetDesktopWindow;
 WinSta:=OpenWindowStation("WinSta0",False,WINSTA_READSCREEN);
 SetProcessWindowStation(WinSta);
 Desk:=OpenDesktop("Default",0,False,DESKTOP_SWITCHDESKTOP);
 SetThreadDesktop(Desk);
 Bmp:=TBitmap.Create;
 Bmp.Width:=1024;
 Bmp.Height:=768;
 Screen:=TCanvas.Create;
 Screen.Handle:=GetDC(0);
 R:=Rect(0,0,1023,767);
 Bmp.Canvas.CopyRect(R,Screen,R);
 ReleaseDC(0,Screen.Handle);
 Screen.Free;
 Bmp.SaveToFile("d:\snap.bmp");
 Bmp.Free;
end;


 
RASkov   (2006-11-23 13:03) [13]

> [10] acyb   (23.11.06 10:00)

А что не получается-то? Код который я привел, я проверил - работает.


 
acyb   (2006-11-23 13:17) [14]

RASkov  , код-то работает. но не под сервис =(


 
acyb   (2006-11-23 15:04) [15]

Чапаев ©, на моей машине все работает... а удаленно, опять то же самое... белый файл. нет никаких тонкостей под удаленную работу?


 
Чапаев ©   (2006-11-23 15:15) [16]

Не понял про "удалённо". Опиши ситуацию.


 
acyb   (2006-11-23 15:19) [17]

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


 
Чапаев ©   (2006-11-23 15:39) [18]

Я же предупреждал, пример без проверок. По совести, надо проверять, успешно ли вызвались функции OpenWindowStation(), OpenDesktop() и прочие. Перед установкой оконной станции и рабочего стола нужно сохранить текущие оконную станцию и рабочий стол и восстановить их после снятия скриншота. Вот когда это будет сделано, тогда уже можно думать, где собака порылась.


 
acyb   (2006-11-23 15:46) [19]

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


 
Чапаев ©   (2006-11-23 16:37) [20]

В хелпе Делфи есть хорошая тема Interacting with the User in a Service (в МСДН её не могу найти почему-то), там пример, как сохранять и восстанавливать.

Для отладки сервиса (щас Мастера меня кирпичами закидают, наверное) я вывожу консоль AllocConsole и в неё обычным, с детства знакомым WriteLn"ом вывожу всё, что мне надо, в том числе и результаты вызова функций, и сообщения об ошибках.

Только сервис для этого должен быть интерактивным.


 
acyb   (2006-11-23 17:15) [21]

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


 
Чапаев ©   (2006-11-23 18:34) [22]

> так что спасибо огромное
Пожалуйста, тоже немаленькое.


> когда пользователь блокирует компьютер, то опять ничего
> не видно
Если не ошибаюсь, его при этом переключают с оконной станции WinSta0 не то на Winlogon, не то на WinLogon (имена станций чувствительны к регистру). Только, по-моему, к той станции доступ не удастся получить даже из сервиса.


 
kami ©   (2006-12-05 15:26) [23]

Чапаев ©   (23.11.06 18:34) [22]
Только, по-моему, к той станции доступ не удастся получить даже из сервиса

Почему? Довольно-таки очень удается. Если не включено Fast User Switching, либо вошел только один пользователь.

Чапаев ©   (23.11.06 12:20) [12]
Desk:=OpenDesktop("Default",

Не лучше ли будет использовать OpenInputDesktop ? Есть какие-то преимущества у Вашего способа?



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

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

Наверх




Память: 0.53 MB
Время: 0.023 c
15-1187094594
Админостратар
2007-08-14 16:29
2007.09.09
Что-то терзает мутное сомнение...


2-1187172658
vegarulez
2007-08-15 14:10
2007.09.09
Вопрос про отчистку памяти.


15-1186913958
Kostafey
2007-08-12 14:19
2007.09.09
Что мне не нравится в командной строке?


15-1186354511
lookin
2007-08-06 02:55
2007.09.09
За что уважаю ДДТ...


15-1186646028
Andy BitOff (ppc)
2007-08-09 11:53
2007.09.09
Футболки !?