views:

674

answers:

4

Hi everybody!

I used once BitBlt to save a screenshot to an image file (.Net Compact Framework V3.5, Windows Mobile 2003 and later). Worked fine. Now I want to draw a bitmap to a form. I could use this.CreateGraphics().DrawImage(mybitmap, 0, 0), but I was wondering if it would work with BitBlt like before and just swap the params. So I wrote:

[DllImport("coredll.dll")]
public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);

(and further down:)

IntPtr hb = mybitmap.GetHbitmap();
BitBlt(this.Handle, 0, 0, mybitmap.Width, mybitmap.Height, hb, 0, 0, 0x00CC0020);

But the form stays plain white. Why is that? Where is the error I commited? Thanks for your opinions. Cheers, David

A: 

I've done it this way before:

private Bitmap _splash = null;

// Form constructor
public SplashScreen(Bitmap splash)
{
    _splash = splash;
    InitializeComponent();
}

...

protected override void OnPaint(PaintEventArgs e)
{
    e.Graphics.DrawImage(_splash, this.ClientRectangle,
                         new Rectangle(0, 0, _splash.Width, _splash.Height), GraphicsUnit.Pixel);
}
Mitch Wheat
A: 

Are you sure that this.Handle refers to a valid device context? Have you tried checking the return value of the BitBlt function?

Try the following:

[DllImport("coredll.dll", EntryPoint="CreateCompatibleDC")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("coredll.dll", EntryPoint="GetDC")]
public static extern IntPtr GetDC(IntPtr hwnd);

IntPtr hdc     = GetDC(this.Handle);
IntPtr hdcComp = CreateCompatibleDC(hdc);

BitBlt(hdcComp, 0, 0, mybitmap.Width, mybitmap.Height, hb, 0, 0, 0x00CC0020);
arul
+1  A: 

You mean something along these lines?

    public void CopyFromScreen(int sourceX, int sourceY, int destinationX, 
                               int destinationY, Size blockRegionSize, 
                               CopyPixelOperation copyPixelOperation)
    {
        IntPtr desktopHwnd = GetDesktopWindow();
        if (desktopHwnd == IntPtr.Zero)
        {
            throw new System.ComponentModel.Win32Exception();
        }
        IntPtr desktopDC = GetWindowDC(desktopHwnd);
        if (desktopDC == IntPtr.Zero)
        {
            throw new System.ComponentModel.Win32Exception();
        }
        if (!BitBlt(hDC, destinationX, destinationY, blockRegionSize.Width, 
             blockRegionSize.Height, desktopDC, sourceX, sourceY, 
             copyPixelOperation))
        {
            throw new System.ComponentModel.Win32Exception();
        }
        ReleaseDC(desktopHwnd, desktopDC);
    }

FYI, this is right out of the SDF.

EDIT: It's not real clear in this snippet, but hDC in the BitBlt is the HDC of the target bitmap (into which you wish to paint).

ctacke
+1  A: 

this.Handle is a Window handle not a device context.

Replace this.Handle with this.CreateGraphics().GetHdc()

Of course you'll need to destroy the graphics object etc...

IntPtr hb = mybitmap.GetHbitmap(); 
using (Graphics gfx = this.CreateGraphics())
{
  BitBlt(gfx.GetHdc(), 0, 0, mybitmap.Width, mybitmap.Height, hb, 0, 0, 0x00CC0020);
}

In addition hb is a Bitmap Handle not a device context so the above snippet still won't work. You'll need to create a device context from the bitmap:

    using (Bitmap myBitmap = new Bitmap("c:\test.bmp"))
    {
        using (Graphics gfxBitmap = Graphics.FromImage(myBitmap))
        {
            using (Graphics gfxForm = this.CreateGraphics())
            {
                IntPtr hdcForm = gfxForm.GetHdc();
                IntPtr hdcBitmap = gfxBitmap.GetHdc();
                BitBlt(hdcForm, 0, 0, myBitmap.Width, myBitmap.Height, hdcBitmap, 0, 0, 0x00CC0020);
                gfxForm.ReleaseHdc(hdcForm);
                gfxBitmap.ReleaseHdc(hdcBitmap);
            }
        }
    }
One little comment :) Shouldn't you call ReleaseHdc() on the hdc's you got from the two graphics objects?
Matt