M
Martijn Mulder
/*
BitBlt.cs
C# code using P/Invoke
I have good reasons to use P/Invoke to get access to the Win32 API
function BitBlt(). But I have trouble understanding the workings of it.
Below is a small, compilable and runnable program that shows the
problem. In words, it may seem complicated, but once you see it, it's
obvious.
First, I create a Bitmap with a green background and a red circle in the
middle. This Bitmap I alter slightly and copy it to the screen, four
times. Twice with Graphics.Drawimage(), twice with BitBlt() (so fast!).
The first attempt in the left-top corner with DrawImage() poses no problem.
The second attempt next to it with BitBlt() shows an Empty Black Square.
Then I copy part of the screen to the in-memory Bitmap. When I copy the
in-memory Bitmap back to the screen with BitBlt(), only the part copied
from the screen shows. The rest is black. This you see in the
left-bottom corner.
Finally, on the right-bottom corner, I use DrawImage() to show the
now-altered Bitmap on screen. The Bitmap is there, but only part of it
is BitBltable.
The question is:
How can I arrange things so that I can directly BitBlt an in-memory
Bitmap to the screen?
*/
namespace MyNamespace
{
using System.Drawing;
using System.Windows.Forms;
class MyForm:Form
{
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern long BitBlt
(
System.IntPtr a,
int b,
int c,
int d,
int e,
System.IntPtr f,
int g,
int h,
int i
);
MyForm()
{
Text="The Mighty BitBlt";
}
override protected void OnPaint(PaintEventArgs a)
{
//Create Bitmap with Red Circle on Green Background
Bitmap bitmap=new Bitmap(100,100,a.Graphics);
Graphics graphics=Graphics.FromImage(bitmap);
graphics.Clear(Color.Green);
graphics.FillEllipse(Brushes.Red,10,10,80,80);
//Left-Top: Draw the newly made Bitmap with DrawImage()
//Result: Green Square with Red Circle Inside
a.Graphics.DrawImage(bitmap,0,0);
//Get Handle to Screen-Graphics and to Bitmap-Graphics
System.IntPtr hdc_screen=a.Graphics.GetHdc();
System.IntPtr hdc_bitmap=graphics.GetHdc();
//Right-Top: Copy Bitmap to Screen with BitBlt()
//Result: Black Empty Square
BitBlt(hdc_screen,100,0,100,100,hdc_bitmap,0,0,0xCC0020);
//Copy Part of Screen to Bitmap with BitBlt()
BitBlt(hdc_bitmap,50,50,50,50,hdc_screen,0,0,0xCC0020);
//Left-Bottom: Copy Bitmap to Screen with BitBlt()
//Result: Three Quarters Black, Quarter Circle Showing
BitBlt(hdc_screen,0,100,100,100,hdc_bitmap,0,0,0xCC0020);
//Get Rid of Handles and Temporary Graphics Object
a.Graphics.ReleaseHdc(hdc_screen);
graphics.ReleaseHdc(hdc_bitmap);
graphics.Dispose();
//Right-Bottom: Copy Bitmap to Screen with DrawImage()
//Result: Red PacMan with Quarter Pie in Corner
a.Graphics.DrawImage(bitmap,100,100);
}
[System.STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
}
BitBlt.cs
C# code using P/Invoke
I have good reasons to use P/Invoke to get access to the Win32 API
function BitBlt(). But I have trouble understanding the workings of it.
Below is a small, compilable and runnable program that shows the
problem. In words, it may seem complicated, but once you see it, it's
obvious.
First, I create a Bitmap with a green background and a red circle in the
middle. This Bitmap I alter slightly and copy it to the screen, four
times. Twice with Graphics.Drawimage(), twice with BitBlt() (so fast!).
The first attempt in the left-top corner with DrawImage() poses no problem.
The second attempt next to it with BitBlt() shows an Empty Black Square.
Then I copy part of the screen to the in-memory Bitmap. When I copy the
in-memory Bitmap back to the screen with BitBlt(), only the part copied
from the screen shows. The rest is black. This you see in the
left-bottom corner.
Finally, on the right-bottom corner, I use DrawImage() to show the
now-altered Bitmap on screen. The Bitmap is there, but only part of it
is BitBltable.
The question is:
How can I arrange things so that I can directly BitBlt an in-memory
Bitmap to the screen?
*/
namespace MyNamespace
{
using System.Drawing;
using System.Windows.Forms;
class MyForm:Form
{
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern long BitBlt
(
System.IntPtr a,
int b,
int c,
int d,
int e,
System.IntPtr f,
int g,
int h,
int i
);
MyForm()
{
Text="The Mighty BitBlt";
}
override protected void OnPaint(PaintEventArgs a)
{
//Create Bitmap with Red Circle on Green Background
Bitmap bitmap=new Bitmap(100,100,a.Graphics);
Graphics graphics=Graphics.FromImage(bitmap);
graphics.Clear(Color.Green);
graphics.FillEllipse(Brushes.Red,10,10,80,80);
//Left-Top: Draw the newly made Bitmap with DrawImage()
//Result: Green Square with Red Circle Inside
a.Graphics.DrawImage(bitmap,0,0);
//Get Handle to Screen-Graphics and to Bitmap-Graphics
System.IntPtr hdc_screen=a.Graphics.GetHdc();
System.IntPtr hdc_bitmap=graphics.GetHdc();
//Right-Top: Copy Bitmap to Screen with BitBlt()
//Result: Black Empty Square
BitBlt(hdc_screen,100,0,100,100,hdc_bitmap,0,0,0xCC0020);
//Copy Part of Screen to Bitmap with BitBlt()
BitBlt(hdc_bitmap,50,50,50,50,hdc_screen,0,0,0xCC0020);
//Left-Bottom: Copy Bitmap to Screen with BitBlt()
//Result: Three Quarters Black, Quarter Circle Showing
BitBlt(hdc_screen,0,100,100,100,hdc_bitmap,0,0,0xCC0020);
//Get Rid of Handles and Temporary Graphics Object
a.Graphics.ReleaseHdc(hdc_screen);
graphics.ReleaseHdc(hdc_bitmap);
graphics.Dispose();
//Right-Bottom: Copy Bitmap to Screen with DrawImage()
//Result: Red PacMan with Quarter Pie in Corner
a.Graphics.DrawImage(bitmap,100,100);
}
[System.STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
}