elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Rompecabezas de Bitcoin, Medio millón USD en premios


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Problema con BitBlt y C++/CLI
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con BitBlt y C++/CLI  (Leído 1,245 veces)
SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Problema con BitBlt y C++/CLI
« en: 17 Octubre 2014, 21:42 pm »

Hola a todos.

Tengo que usar la función BitBlt() en código C++/CLI. Lo he intentado de muchas formas y no consigo que funcione. Me da el error código 6 (invalid handle).
He leído bastantes posts etc. por internet, y para empezar veo que nadie que use esta función tiene que hacer un casting de IntPtr a HDC. Adjunto el código (comentado en inglés)

Código
  1. /*
  2. 1 - Get a bmp image from hard drive( i have it).
  3.  
  4. 2 - Copy it to byte array, or get its internal array, i have tested both ways (method1 and method2 in comments).
  5.  
  6. 3 - Prepare a PicutreBox and obtain from it my context device.
  7.  
  8. 4 - Use BitBlt function to copy only first 50 lines of the initial bitmap.
  9.  
  10. 5 - Display it in a windows form.
  11. */
  12.  
  13. #include "stdafx.h"
  14. #include <Windows.h>
  15. #include "MyForm.h"
  16. #include "string.h"
  17.  
  18. using namespace System;
  19. using namespace System::Runtime::InteropServices;
  20. using namespace System::Runtime::CompilerServices;
  21. using namespace System::IO;
  22. using namespace System::Windows::Forms;
  23. using namespace System::Drawing;
  24. using namespace System::Drawing::Imaging;
  25.  
  26. using namespace ConsoleApplication1;
  27.  
  28. [DllImport("gdi32.dll", CallingConvention = CallingConvention::StdCall, SetLastError = true)]
  29. extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
  30. IntPtr hdcSrc, int nXSrc, int nYSrc, long dwRop);
  31.  
  32. int main(array<System::String ^> ^args){
  33. Graphics ^gph = nullptr;
  34. try{
  35. //Get a test image and it's parameters
  36. Bitmap ^image = gcnew Bitmap("./img/Simple_tux0.bmp");
  37. int iWidth = image->Width;
  38. int iHeigth = image->Height;
  39. PixelFormat pxF = image->PixelFormat;
  40.  
  41.  
  42. //Prepare a PictureBo, whici will be given as parameter to Windows Form.
  43. PictureBox ^pb = gcnew PictureBox();
  44. pb->SizeMode = PictureBoxSizeMode::StretchImage;
  45. pb->Size = Drawing::Size(iWidth + 10, iHeigth + 10);
  46. pb->Location = Drawing::Point(3, 3);
  47.  
  48. //Get bitmap
  49. IntPtr prueba = image->GetHbitmap();
  50.  
  51. //Create my device context, where i will paint my lines.
  52. gph = pb->CreateGraphics();
  53. IntPtr deviceContext = gph->GetHdc();
  54.  
  55.  
  56. //Paint only 50 lines of the source Bitmap.
  57. BOOL b = BitBlt((HDC)deviceContext.ToPointer(), 0, 0, iWidth, 50,
  58. (HDC)prueba.ToPointer(), 0, 0, SRCCOPY);
  59.  
  60. //Get the error:
  61. unsigned long err = GetLastError();
  62. Console::WriteLine("error: {0}", err); //error 6 : Invalid Handle
  63.  
  64. //Create windows form with the PictureBox to display my 50 lines.
  65. MyForm ^f = gcnew MyForm(pb);
  66. Application::Run(f);
  67. Application::Exit();
  68. }
  69. finally{
  70. if (gph != nullptr){
  71. gph->ReleaseHdc();
  72. delete gph;
  73. }
  74.  
  75. }
  76. return 0;
  77. }
  78.  

He intentado usar también esto:

Código
  1. [DllImport("coredll.dll", EntryPoint = "CreateCompatibleDC")]
  2. extern IntPtr CreateCompatibleDC(IntPtr hdc);
  3.  
  4. [DllImport("coredll.dll", EntryPoint = "GetDC")]
  5. extern IntPtr GetDC(IntPtr hwnd);
  6.  
  7. int main(){
  8. //...
  9. //...
  10. IntPtr dc = GetDC(deviceContext);
  11. IntPtr compDc = CreateCompatibleDC(dc);
  12.  
  13. //Paint only 50 lines of the source Bitmap.
  14. BOOL b = BitBlt((HDC)compDc.ToPointer(), 0, 0, iWidth, 50,
  15. (HDC)prueba.ToPointer(), 0, 0, SRCCOPY);
  16.  

La primera pregunta que me surge es por qué yo tengo que hacer esto:
Código:
(HDC)deviceContext.ToPointer()
Y en todos los post que leo nadie lo hace.

Saludos, gracias.


« Última modificación: 18 Octubre 2014, 08:17 am por Eleкtro » En línea

kub0x
Enlightenment Seeker
Moderador
***
Desconectado Desconectado

Mensajes: 1.443


S3C M4NI4C


Ver Perfil
Re: Problema con BitBlt y C++/CLI
« Respuesta #1 en: 18 Octubre 2014, 16:27 pm »

Muy buenas SARGE553413,

¿los posts que has revisado por internet son de C++/CLI? IntPtr es una clase del Framework, lo cual no pertenece a la WinAPI y por lo tanto no se puede castear a HDC, por lo cual debes de optener un pointer, a void (void*) supongo, y luego castear a HDC que realmente es lo que estás haciendo.

Aun así podrías hacer override al evento WM_PAINT del PictureBox, dentro de ahí haces la llamada a la siguiente función, la cual dibuja tu imagen:

Código
  1. void FromImageImage( PaintEventArgs^ e )
  2.   {
  3.      // Create image.
  4.      Image^ imageFile = Image::FromFile( "tuimagen.jpg" );
  5.  
  6.      // Create graphics object for alteration.
  7.      Graphics^ newGraphics = Graphics::FromImage( imageFile );
  8.  
  9.      // Alter image.
  10.      newGraphics->FillRectangle( gcnew SolidBrush( Color::Black ), 100, 50, 100, 100 );
  11.  
  12.      // Draw image to screen.
  13.      e->Graphics->DrawImage( imageFile, PointF(0.0F,0.0F) );
  14.  
  15.      // Dispose of graphics object.
  16.      delete newGraphics;
  17.   }

Saludos!


En línea

Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate

SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Problema con BitBlt y C++/CLI
« Respuesta #2 en: 19 Octubre 2014, 16:00 pm »

Hola de nuevo, respecto al IntPtr, tiene un método toPointer() que devuelve void*, y HDC es un void* realmente.
De todas formas ya he solucionado el error, el problema es que ahora no veo por pantalla lo que dibujo.
Adjunto el nuevo código en el que BitBlt() da error 0 (todo ok), por algún motivo el PictureBox no se actualiza bien:

Código
  1. [DllImport("gdi32.dll", CallingConvention = CallingConvention::StdCall, SetLastError = true)]
  2. extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
  3. IntPtr hdcSrc, int nXSrc, int nYSrc, long dwRop);
  4.  
  5. int main(array<System::String ^> ^args){
  6. Graphics ^gph = nullptr;
  7. try{
  8. //Get a test image and it's parameters
  9. Bitmap ^image = gcnew Bitmap("./img/Simple_tux0.bmp");
  10. int iWidth = image->Width;
  11. int iHeigth = image->Height;
  12. PixelFormat pxF = image->PixelFormat;
  13.  
  14. //Prepare a PictureBox, which will be given as parameter to Windows Form.
  15. //It has an image that's my "draw area".
  16. PictureBox ^pb = gcnew PictureBox();
  17. pb->SizeMode = PictureBoxSizeMode::Normal;
  18. pb->Size = Drawing::Size(iWidth, iHeigth);
  19. pb->Location = Drawing::Point(0, 0);
  20. Bitmap ^drawArea = gcnew Bitmap(pb->Width, pb->Height);
  21. pb->Image = drawArea;
  22.  
  23. //Get bitmap
  24. IntPtr prueba = image->GetHbitmap();
  25.  
  26. //Create my device context, where i will paint my lines.
  27. gph = Graphics::FromImage(drawArea);
  28. IntPtr deviceContext = gph->GetHdc();
  29.  
  30.  
  31. //Paint only 50 lines of the source Bitmap.
  32. BOOL b = BitBlt((HDC)deviceContext.ToPointer(), 0, 0, iWidth, 50,
  33. (HDC)prueba.ToPointer(), 0, 0, SRCCOPY);
  34.  
  35. //Get the error:
  36. unsigned long err = GetLastError();
  37. Console::WriteLine("error: {0}", err); //error 6 : Invalid Handle
  38.  
  39. //Refresh
  40. pb->Invalidate();
  41. pb->Refresh();
  42.  
  43. //Create windows form with the PictureBox to display my 50 lines.
  44. MyForm ^f = gcnew MyForm(pb);
  45. Application::Run(f);
  46. Application::Exit();
  47. }
  48. finally{
  49. if (gph != nullptr){
  50. gph->ReleaseHdc();
  51. delete gph;
  52. }
  53.  
  54. }
  55. return 0;
  56. }
  57.  

¿Qué hago mal?

Saludos, gracias.
« Última modificación: 19 Octubre 2014, 16:29 pm por Eleкtro » En línea

kub0x
Enlightenment Seeker
Moderador
***
Desconectado Desconectado

Mensajes: 1.443


S3C M4NI4C


Ver Perfil
Re: Problema con BitBlt y C++/CLI
« Respuesta #3 en: 19 Octubre 2014, 20:55 pm »

Hola de nuevo, respecto al IntPtr, tiene un método toPointer() que devuelve void*, y HDC es un void* realmente.

Exactamente igual que lo que te dije arriba. Si no encuentras posts por la red que usen toPointer() es que no es C++/CLI, ya que HDC es unmanaged e IntPtr es managed.

Por lo demás el code está bien, quizá te falte el añadir el PictureBox al formulario, espero sea eso, pues error 0 indica que todo fue bien.

Código
  1. f->Controls->Add(pb);

Aun así el otro código que te dí es funcional, haciendo override al WM_PAINT.

Saludos!
En línea

Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Problema BlueZScanner y problema de conexión
Hacking Mobile
Kasswed 3 4,827 Último mensaje 6 Mayo 2006, 22:04 pm
por Gospel
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines