VB:Tutorials:WINAPI:bitblt from stdPicture

From GPWiki

Contents

Introduction

Have you ever wanted to load a picture, then use bitblt to display the picture without having to add a picturebox control?

You can use the stdPicture object to do just that.

The stdPicture object can load an image just like a picturebox can, and it has a few useful properties to allow you to manipulate it in much the same way as you would in a picturebox.

If you have ever used this object, you know that it has a .Render method. You can certainly use this method, but it is pretty slow. Bitblt is much faster, but you can't just use the .handle property in bitblt to blit the image. The .handle property is not the same has the .hDC property of a picturebox, its more like the .hwnd property. So the challenge is to create a new hDC and attach it to the .handle of the stdPicture object.


Declarations

First you will need a few API declarations.

Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long _
, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long _
, ByVal dwRop As Long) As Long

When I said few I meant a bunch. Don't worry, I will explain the use of each of them when I use them.

Next you need to have three declarations. You should place these in the declarations section of the form or module.

Dim stdPic As StdPicture
Dim stdHDC As Long
Dim OrigHandle As Long
  • stdPic is the StdPicture object that will hold the image.
  • stdHDC will be the hDC that will be created so that you can use bitblt to blit your image.
  • OrigHandle will hold a handle that will be needed when you clean up at the end, to prevent memory leaks.


Loading a Picture and Creating an HDC

Now on to the nitty gritty.

The best thing to do at this point is to create a new sub or function to hold the following code.

First, load your picture into the stdPicture object.

'change the location to your own picture :)
Set stdPic = LoadPicture("c:\mypicture.jpg")

Notice how, unlike a PictureBox, you have to use the Set command.

Next, in the same sub, add these two declarations.

Dim DT_hwnd As Long
Dim DC As Long
DT_hwnd = GetDesktopWindow()
DC = GetDC(DT_hwnd)
  • DT_hwnd is loaded with the window handle of the desktop.
  • DC gets the device context of the desktop.
  • From Microsoft Knowledgebase
    • The GetDesktopWindow function returns a handle to the desktop window.
    • The GetDC function retrieves a handle to a device context (DC) for the client area of a specified window or for the entire screen.


Next you need to create a hardware device context that is compatible with the desktop.

stdHDC = CreateCompatibleDC(DC)

As I said before, stdHDC will be used by bitblt to blit the image.

  • From Microsoft Knowledgebase
    • The CreateCompatibleDC function creates a memory device context (DC) compatible with the specified device. In our case, the desktop


It's best to release the device context of the desktop now that you are done using it.

ReleaseDC DT_hwnd, DC


Finally you are ready to attach the newly created hDC to the stdPicture

OrigHandle = SelectObject(stdHDC, stdPic.Handle)
  • From Microsoft Knowledgebase
    • The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.

Notice that the return value of SelectObject is stored in OrigHandle. SelectObject returns the handle to the previously selected object. This is important because when you are done using stdHDC, you have to re-select the original handle back or you will get some memory leaks.


BITBLT

Now you are ready to bitblt to your hearts content.

BitBlt Me.hdc, 0, 0, 128, 96, stdHDC, 0, 0, vbSrcCopy

Unfortunatly, you may notice that the Width and Height property values of the stdPic object aren't in pixels. These values are in himetrics, and you can use the forms ScaleX and ScaleY methods to convert them to pixels. Me.ScaleX(<width>, vbHimetric, vbPixels)

Clean Up

When you are done blitting, and are ready to either load a new picture or close the form, you should clean up your memory.

SelectObject stdHDC, OrigHandle
DeleteDC stdHDC
Set stdPic = Nothing
  • From Microsoft Knowledgebase
    • The DeleteDC function deletes the specified device context (DC).