Como posso capturar como bitmap apenas o que uma checkbox de imagem está exibindo, sem usar “copiar da canvas”?

Especificamente: Eu preciso capturar como um bitmap uma região específica do que um picturebox está realmente exibindo. As coordenadas da região são especificadas pelos limites de um controle que eu sobreponho na parte superior da checkbox de figuras (mas que pertence à checkbox de figuras). O controle fica oculto quando eu faço o “instantâneo” da região.

Eu tentei usar methods normais de captura de canvas (CopyFromScreen), mas você não pode realmente controlar o tempo lá. Por isso, estava capturando estados “intersticiais”, como transições entre fotos na minha checkbox de imagens. Freqüentemente, capturava imagens puramente negras (a cor de fundo da checkbox de imagem).

Então eu tentei apenas converter a imagem (propriedade picturebox.image) sendo exibida em um bitmap. O problema é que a checkbox de imagem raramente mostra exatamente a imagem. Ele está exibindo uma parte da imagem, dimensionada e recortada conforme apropriado para o tamanho da imagem (que é zoom). Então, eu não posso simplesmente pegar minhas coordenadas de controle e recortá-las da imagem como um todo.

Então tentei estimar qual parte da imagem estava sendo exibida e corrigi o retângulo com base nisso. Acontece que eu estava basicamente recriando o código “zoom” da checkbox de imagem para fazer isso (usando a proporção da checkbox de imagem, a proporção da imagem, adivinhando em que nível de escala está ocorrendo na imagem se ela é maior ou menor que o picturebox, etc). Não foi bonito.

Então, agora eu preciso de um método de apenas capturar apenas o bitmap atualmente sendo exibido na área do cliente da checkbox de imagem, incluindo a foto e qualquer “letterboxing” preto atualmente sendo exibido em torno dele. Alguém tem um?

Lembre-se que não posso confiar em usar o CopyFromScreen. Não é confiável o suficiente para meus propósitos. Eu acho que preciso de um método de obter o picturebox para me dizer os bits que ele está exibindo.

Isso irá copiar e salvar o conteúdo mostrado atualmente da PictureBox incluindo um BackgroundImage (se houver um e se ele brilhar) e também todos os Controls que pertencem ao PictureBox , como Labels etc. Também estão incluídos elementos desenhados no evento Paint . As coisas desenhadas fora do evento Paint não são persistentes e não serão incluídas.

 using (Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height)) { pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle); bmp.Save(yourfilename, ImageFormat.Png); } 

Nota: No meu formulário de teste, a PicureBox está dentro de um AutoScroll Panel pan_PBscroll . A PictureBox está exibindo pixels 1: 1 e é, portanto, com uma fotografia carregada, muito maior que o Painel, o Formulário ou até mesmo a Tela. Então, para recortar as partes realmente visíveis, não pude usar o pictureBox1.ClientSize e o pictureBox1.ClientRectangle mas usei as dimensões desse Panel. Isso também pode se aplicar a você.

Não tenho certeza sobre seus problemas de tempo. Mas desde que você mencionou CopyFromScreen aqui estão algumas diferenças:

  • CopyFromScreen faz uma cópia de 1: 1 de cada pixel da canvas
  • Isso inclui desenhos não persistentes e exclui qualquer coisa coberta ou oculta
  • Control.DrawToBitmap faz o controle desenhar-se em um bitmap, assim como ele se desenha durante o Paint
  • Isso exclui tudo o que não pertence ao Controle, mas inclui todos os membros de sua coleção Controls
  • Isso também exclui desenhos não persistentes, mas inclui o tamanho total do Controle, se ele se encheckbox no Formulário ou Tela ou não e se está oculto ou coberto ou não.
  • Para controles com barras de rolagem ativas, somente as partes visíveis são copiadas. Para copiar tudo o que você precisa resize temporariamente. Então você pode obter uma imagem completa de uma checkbox de listview, mesmo que tenha mil itens.

Desde que você está usando um PictureBox eu diria para dar uma olhada PictureBox.Image onde você pode obter o object Bitmap .

Espero que ajude.