Manipulating pixels with the SetPixelV() and GetPixelV() functions is significantly faster than using their Visual Basic counterparts, but it is still slow. There’s a better method, but it requires even more API functions.
When you draw with Visual Basic methods on a Form, the drawing takes place it an area of the memory that is mapped on the Form’s window. Visual Basic has a handle to this memory, and there are several layers between your Visual Basic code and the actual window. The API functions discussed in the previous section do the same, but they are faster than Visual Basic code. (After all, Visual Basic has no call the same function internally; it hides some of the complexity of drawing operations, but it’s slower.
Windows doesn’t allow an application to draw directly on the screen. Remember under Windows, you can run multiple applications, switch between them, arid rel on Windows to take care of chores such as updating the windows on the screen an manipulating palettes. Windows simply wouldn’t be able to handle all these detail if applications had direct access to the windows bitmaps on the screen. That’s why drawing operations under Windows are inherently slow.
No matter how Windows handles drawing and painting operations, eventually, the bitmap must be stored somewhere in memory. There are API functions that allow applications to access this area of the memory and draw by setting bits and bytes in memory. Drawing in memory is faster than drawing on device contexts, be more complicated, Moreover, when you’re drawing in memory, nothing appears 0 the screen. You must also provide the code to transfer the bitmap from the memory to a window on the monitor. Even with this additional step, drawing in memory is considerably faster than drawing on device contexts.
To draw in memory, you must create a bitmap structure in memory. This structure must also be compatible with the device context on which it will be displayed. other words, a different bitmap structure is required for the monitor and a different one for a printer.. To create a bitmap structure in memory, use the CreateCompatibleBitmap() function, whose syntax is:
The first argument of the function is the device context with which the bitmap must be compatible. This is also the device context where the bitmap’s contents m be transferred in order to be displayed on the monitor. The other two argument are the dimensions of the bitmap in pixels.
Since you’ll be drawing off-screen, you must also create a device context with CreateCompatibleDC() function and then select the bitmap structure into the device context with the SelectObject() function. The syntax of the CreateCompatibleDC() function is:
Public Declare Function CreateCompatibleDC Lib ‘gdi32’ _
Alias “Create(ompatibleDC (ByVal hDc As Long) As Long
Its argument is the device context of the control (or·the Form) where the drawing will be displayed. If you want to prepare a bitmap in memory and then display it on the Picture Box1 control, use the following statements:
After these statements are executed, you can draw on the hSourceDC device context using the drawing functions we have discussed already. Notice that the hSourceDC device context isn’t directly mapped to the monitor. It lives in the memory and can be updated really quickly. To display it, you must transfer its contents to the PictureBox2 control with the BitBlt() function.
The third Command button on the CopyPix project’s Form, Copy Fast, uses this technique to read the pixels of the top Picture Box control and set the pixels on the bottom Picture Box. The code behind the Copy Fast button is shown next.
The Copy Fast Command Button’s Code
The code starts by creating two device contexts in memory, the hSourceDC (which represents the bitmap of the top PictureBox control) and the hDestDC (which represents the bitmap of the bottom PictureBox control). Then it copies the pixels of the PictureBox1 control into the corresponding device context (when a device context is first created in memory it contains random data). The double loop that follows copies the pixels from the hsourceDC context to the hDestDC context with the Get- PixelV() and SetPixelV() API functions. As you can see, the same methods that draw on actual device contexts can also draw on memory device contexts.
While the pixels are being copied, the screen isn’t updated. You’re drawing something in memory and Windows doesn’t know what you intend to do with it, so it doesn’t display it anywhere. After all the pixels have been copied, we must move the bitmap ~m. the memory (the hDestDC context) into the destination control (PictureBox2 control), This is done with the BitBlt() function, Finally the program releases all the’resources it created during its operation by calling the DeleteDC() and DeleteObject() functions.
Run the CopyPix project, and click the Copy Fast button to see how much faster it is than the other two methods. The drawback of this method is that you can’t watch the progress of the pixel copying operation. You’ll see the second image only after all pixels have been copied. If you’re manipulating large images, you may wish to call the BitBlt() function more often (after copying each column of pixels, for example). This will introduce some delay, but the method described in this section is still faster than the other two. You may want to use a progress indicator to let the user know that the program is running and to estimate how much time is left before the operation is finished.
This example concludes the discussion of API functions. Next, youll see ~ to extend Visual Basic by contacting external applications, such as Excel and Word, and manipulating their objects through VBA. Office applications provide so many features you can use from within your VisualBasic applications that it doesn’t make much sense implement them from scratch on your own.