• 0
Sign in to follow this  
Paulo Nobre

Capturando Desktop

Question

Estou desenvolvendo, a título de estudo, um programa para capturar

telas;total,janela ativa e recorte.Só que é mais difícil do que imaginava.

As próximas perguntas, como esta, que postarei aqui no forum, dirão respeito

a isto.

Espero poder contar com a ajuda do forum para desenvolver este estudo.

Consegui a seguinte função para capturar o desktop:

procedure TForm1.ScreenCapture(Filename: TFilename);

var
DHDC: HDC;
Buffer : TBitmap;

Begin

 begin

 DHDC := GetWindowDC(GetDesktopWindow);
 Buffer := tBitmap.Create;
 Buffer.Width  := Screen.Width;
 Buffer.Height := Screen.Height;
 BitBlt(Buffer.Canvas.Handle,0,0,Screen.Width,Screen.Height,DHDC,0,0,SRCCOPY);
 Buffer.SaveToFile(Filename);
 Buffer.Free;
 ReleaseDC(GetDesktopWindow,DHDC);
 end;
End;
Gostaria de criar o bitmap(com o nome flash01.bmp) relativo a esta captura num caminho determinado, por exemplo C:\temp e exibí-lo num image. Como poderia fazer isto com função acima? Mesmo alterando FileName:String e colocando 'C:\temp'na chamada da função dá erro. Uma outra função que peguei por aí é a seguinte:
function CaptureScreenRect( ARect: TRect ): TBitmap;
//
// Captura a tela e salva-a em um Bitmap
//
// Use-a assim:
//
// Image1.picture.Assign(CaptureScreenRect(Rect(0,0,Width,Height)));
//
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;
Usando Image1.picture.Assign(CaptureScreenRect(Rect(0,0,Width,Height))); consigo colocar o desktop na image1, porém não consigo salvar image1.Picture.SaveToFile('C:\temp');dá erro. O erro que aparece é o mesmo que aparece com o uso da procedure anteriormente citada: Não é possível criar o arquivo C:\temp, o acesso está negado Em resumo preciso do seguinte: 1) Capturar o desktop 2) Exibir num image 3) Salvar o desktop, num bitmap de nome Flash01.bmp, num diretório pré determinado, por exemplo C:\temp Dá para adaptar a procedure ou a função para fazer isto que preciso? O código abaixo também salva o desktop
keybd_event(vk_snapshot,0, 0, 0); {Tela toda.}

porém como pegar a tela toda salvar num arquivo .bmp e ainda

salvar este arquivo no C:\temp, por exemplo.

HELP,HELP,HELP.

Share this post


Link to post
Share on other sites

16 answers to this question

Recommended Posts

  • 0

Acho que utilizando Keybd_Event é a mais prática:

var Bmp:TBitmap;
begin
  Bmp := TBitmap.Create;
  Keybd_Event(VK_Snapshot,0, 0, 0);
  Bmp.LoadFromClipboardFormat(CF_BitMap, Clipboard.GetAsHandle(CF_Bitmap), 0);
  Image1.Picture.Bitmap.Assign(Bmp);
  Bmp.SaveToFile('C:\Temp\Flash01.bmp');
  Bmp.Free;
end;

Share this post


Link to post
Share on other sites
  • 0

S3C,

ESTOU TENDO DOIS PROBLEMAS:

1) ACHO QUE NÃO ESTOU SABENDO ALOCAR O CÓDIGO DE MANEIRA CORRETA.

APARECE O ERRO DE QUE O FORMATO DO CLIPBOARD NÀO ESTA CORRETO, POIS OU ESTÁ VAZIO OU ESTÁ COM TEXTO, POIS DA MANEIRA COMO ESTOU USANDO O CÓDIGO AO APERTAR PRINT

NÀO ESTÁ INDO O DESKTOP PARA O CLIPBOARD.

NO ONCREAT COLOQUEI:
{== Desabilita a tecla Print Screen ==}
 RegisterHotkey( Handle, 500, 0, VK_SNAPSHOT );
CRIEI A PROCEDURE(COM O CÓDIGO QUE VOCÊ FORNECEU-ESTÁ NA SEÇÃO PÚBLIC)
Procedure TfrmPrincipal.CapturarTelaTodaSalvarBitmap(Filename:TFilename);
Var
  Bmp:TBitmap;
begin
  Bmp := TBitmap.Create;
  Keybd_Event(VK_Snapshot,0, 0, 0);
  Bmp.LoadFromClipboardFormat(CF_BitMap, Clipboard.GetAsHandle(CF_Bitmap), 0);
  Image1.Picture.Bitmap.Assign(Bmp)// o erro acontece aqui pois o clipbarde está vazio ou com um formato diferente do de imagem.
  Bmp.SaveToFile(FileName);
  Bmp.Free;
end;
QUE ESTÁ SENDO CHAMADA PELA PROCEDURE
procedure TfrmPrincipal.WMHotKey (var Msg : TWMHotKey);
Var
  Destino:String;
  Numero:Integer;
begin
  if Msg.HotKey = 500 then
  begin
    reg.RootKey:=HKEY_LOCAL_MACHINE;
    reg.OpenKey('SOFTWARE\NOBRE INFORMÁTICA\FLASH',FALSE);
    Numero:= reg.ReadInteger('Número do último screen salvo')+ 1;
    Destino:= reg.ReadString('Diretório de Destino')+'\Flash'+IntToStr(Numero)+'.bmp';
    If reg.ReadString('Formato')= 'BMP 256' then
      If reg.ReadString('Capturar')= 'A tela toda' then
        begin
          CapturarTelaTodaSalvarBitmap(Destino);
        end
      Else If reg.ReadString('Capturar')= 'A janela ativa' then
        begin
          CapturarJanelaAtivaSalvarBitmap(Destino);
        end;
    //Else If reg.ReadString('Formato')= 'BMP TRUE ' then
  reg.CloseKey;
  end;
end;

QUANDO SAIO DO PROGRAMA E CLICO EM PRINT COLOCO O DESKTOP NO CLIPBOARD(o que mostra não ser do código o problema e sim como estou usando), PORÉM COM UM PROBLEMA: DEMORA MUUUUUUUUITO(2 MINUTOS-ESTE É O OUTRO PROBLEMA) PARA A IMAGEM APARECER NO IMAGE E O ÍCONE DO BITMAP APARECER NO DESTINO ESCOLHIDO(PASTA).

Eu achava que a função Keybd_Event(VK_Snapshot,0, 0, 0);já copiava o desktop para a área de tranferencia.

VOCÊ CONSEGUE VER ALGO ERRADO?

DESCONFIEI QUE DEVERIA COLOCAR ALGO NO EVENTO ONKEYDOW, MAS NÃO SEI COMO.

PENSEI EM

If Key = VK_SNAPSHOT then WMHOTKEY(?), MAS NÃO CONSEGUI PERCEBER O QUE COLOCAR NO LUGAR DA INTERROGAÇÀO(QUAL O PARÂMETRO).

A procedure WMHotkey não está sendo chamada em lugar nenhum apenas está declarada, talvez este possa ser o erro, mas não estou sabendo alocá-la, como mencionei acima.

Share this post


Link to post
Share on other sites
  • 0

Olá Paulo, bom como você registrou a VK_Snapshot como uma tecla de atalho pelo RegisterHotKey, quando você pressiona PrintScreen, ele executa a procedure WMHotKey e nesta procedure você manda executar CapturarTelaTodaSalvarBitmap.

O que acontece:

CapturarTelaTodaSalvarBitmap executa Keybd_Event(VK_Snapshot,0, 0, 0);

Isso simula o pressionamento da tecla Print Screen e WMHotKey é novamente chamado.

Então é um looping infinito, pois WMHotKey executa CapturarTelaTodaSalvarBitmap que por sua vez executa WMHotKey através de Keybd_Event.

Como PrintScreen já foi pressionado, então você não precisa mais chamar Keybd_Event.

Share this post


Link to post
Share on other sites
  • 0

Olá, s3c,

Mas o que eu faço para que o desktop vá para o clipboard.

Do jeito que o código está nada vai para o clipboard, porisso dá o erro.

O que está faltando para que isso aconteça?

O que você acha melhor fazer?

Tirar o registro?

Estou meio confuso!

Share this post


Link to post
Share on other sites
  • 0

Deve ser porque você ainda está no evento WM_HotKey e a mensagem ainda não foi processada; ou seja; após terminar esse evento é que você terá acesso ao Clipboard com a imagem.

Sugiro que você capture as msgs diretamente do Clipboard e despreze RegisterHotKey. Tem um exemplo em: http://scriptbrasil.com.br/forum/index.php?showtopic=71182

Troque Clipboard.HasFormat(CF_TEXT) por Clipboard.HasFormat(CF_Bitmap)

Share this post


Link to post
Share on other sites
  • 0

Ok, s3c,

Mas me diga uma coisa...

Você forneceu o código abaixo

Procedure TfrmPrincipal.CapturarTelaTodaSalvarBitmap(Filename:TFilename);
Var
 Bmp:TBitmap;
begin
 Bmp := TBitmap.Create;
 Bmp.LoadFromClipboardFormat(CF_BitMap, Clipboard.GetAsHandle(CF_Bitmap), 0);
 Image1.Picture.Bitmap.Assign(Bmp)
 Bmp.SaveToFile(FileName);
 Bmp.Free;
end;
Para salvar em forma de bitmap: Você poderia me dizer se para salvar em formato GIF e JPEG, basta trocar as extensões acima, ou seja ficaria:
Procedure TfrmPrincipal.CapturarTelaTodaSalvarGIF(JPEG)(Filename:TFilename);
Var
 GIF(JPEG):TGIF(TJPeg);
begin
 GIF(JPEG) := TGIF(JPEG).Create;
 GIF(JPEG).LoadFromClipboardFormat(CF_BitMap, Clipboard.GetAsHandle(CF_Bitmap), 0);
 Image1.Picture.Bitmap.Assign(Bmp)
 Bmp.SaveToFile(FileName);
 Bmp.Free;
end;

ou seria algo diferente?

Você poderia me dizer como fazer?

Outra coisa é em relação a como foi salvo em BITMAP.

Existe BMP 256 e BMP TRUE, como mando salvar de uma maneira e de outra?

O código que voce forneceu foi para 256 ou TRUE?

Share this post


Link to post
Share on other sites
  • 0

Você poderia me dizer se para salvar em formato GIF e JPEG...
O que sei que dá para fazer é assinalar um jpeg para um bitmap, o que reduz em muito o tamanho do arquivo: JPEG.Assign(Bitmap);

Já o formato GIF, nunca testei.

Outra coisa é em relação a como foi salvo em BITMAP.

Existe BMP 256 e BMP TRUE, como mando salvar de uma maneira e de outra?

O código que voce forneceu foi para 256 ou TRUE?

Também nunca me aprofundei nisso, mas acho que a imagem Bitmap no Clipboard fica conforme está sua resolução de tela.

Share this post


Link to post
Share on other sites
  • 0

A procedure adaptada da anterior e esta para jpeg só que dá erro

Procedure TfrmPrincipal.CapturarTelaTodaSalvarJPEG(Filename:TFilename);
Var
  JPEG:TJPEGImage;
begin
  JPEG := TJPEGImage.Create;
  JPEG.LoadFromClipboardFormat(CF_BitMap,Clipboard.GetAsHandle(CF_BitMap),0);
  Image1.Picture.Assign(JPEG);//o erro está aqui.
  JPEG.SaveToFile(FileName);
  JPEG.Free;
end;

dá erro mesmo colocando Image1.Picture.Bitmap.Assign(JPEG);

não encontrei parametros como cf_jPeg

quero salvar como jpeg.

Será que tem que converter primeiro de bitmap para jpeg par depois entrar com

a procedure?

Share this post


Link to post
Share on other sites
  • 0

Primeiro você cria o JPEG:

JPEG := TJPEGImage.Create;

Depois você carrega o bitmap do Image pelo Clipboard:

Image1.Picture.Bitmap.LoadFromClipboardFormat(CF_BitMap,Clipboard.GetAsHandle(CF_BitMap),0);

Depois você assinala o JPEG a partir do Bitmap:

JPEG.Assign(Image1.Picture.Bitmap);

Depois você salva o JPEG:

JPEG.SaveToFile(FileName);

JPEG.Free;

Share this post


Link to post
Share on other sites
  • 0

Alguém já trabalhou em GIF neste tipo de código?

Share this post


Link to post
Share on other sites
  • 0

Alguém sabe como fazer para capturar apenas uma parte do desktop.

Vi num programa o seguinte:

O usuário clicava em printscreen, o ponteiro do mouse mudava para uma cruz,

clicava num ponto do desktop, deslocava o mouse abria-se um retângulo pontilhado(tipo programas de desenho onde você desenha um retângulo), clicava-se num outro ponto e a região compreendida dentro do retângulo era capturada.

Não tenho a mínima idéia. Pesquisei na rede e não encontrei nada.

Alguém já fez?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this