AllAPI Network - The KPD-Team

 
Allapi Network
 API-Guide
 ApiViewer

 API List

 
API Resources
 Tips & Tricks
 VB Tutorials
 Error Lookup
 
Misc Stuff
 VB examples
 VB Tools
 VB Links
 Top Downloads
 
This Site
 Search Engine
 Contact Form
 

Donate to AllAPI.net

Creating and using your own VC++ dlls
Author: Pieter Philippaerts

2. Simple Graphical function

In part 2, we’re going to discuss an easy graphical function that converts a picture to a DuoTone version of that picture. The function itself isn’t too hard to understand, but the algorithm explains some very useful methods to pass handles of objects to your VC++ procedure.
Before we’re going to write the algorithm in C, I’ll first explain how it works.
Take a look at the pseudo-code version of the function:

DuoTone function {
      Create a temporary memory bitmap;
      Paint it with the color specified by the user (=parameter);
      ‘And’ the source picture over the temporary memory bitmap;
      Copy the result to the destination Device Context;
}

To explain the algorithm, let us assume that we specified the color Red (RGB(255,0,0)) as DuoColor. This way, the memory bitmap will be completely filled with red pixels.
If we then ‘And’ the source picture with the red memory bitmap, every pixel will be converted to its red component.
For instance, if we ‘And’ a pixel with the color &HD34F19 (RGB(25, 79, 211)) with the color red (&H0000FF), the result will be &H000019, or RGB(25, 0, 0).

 

We first declare the function:

int _stdcall DuoTone(HBITMAP hSrcBitmap, COLORREF DuoColor, HDC hDestDC, int destx, int desty) {

The function follows the standard calling convention, since this is required for Visual Basic.
It returns an ‘int’ variable that corresponds to a ‘Long’ variable in Visual Basic.
The function has five parameters: two ints that are converted to Longs in Visual Basic, two handles and a COLORREF. All handles are converted to Longs in Visual Basic and because a COLORREF is a 32-bit value, it is also converted to a Long.

The VB declaration looks like this:

Declare Function DuoTone Lib “MyDll.dll” ( _
 
Byval hSrcBitmap as Long,
Byval DuoColor as Long, _
  Byval hDestDC as Long,
Byval destx as Long, _
 
Byval desty as Long) as Long

Do note that all the parameters are passed by value. We only have to pass a parameter by reference if the VC++ declaration of that variable is defined as a pointer (i.e. int *myValue).

   int retval = 1;
   BITMAP bminfo;
   GetObject(hSrcBitmap, sizeof(bminfo), &bminfo);

In this code, we declared a variable that contains the return value of the function. If something fails within the function, this variable will be set to 0.
We also declare a BITMAP structure and fill it with the information of the source bitmap. The ampersand (‘&’) before ‘bminfo’ means that we pass a pointer to bminfo instead of copying the entire structure on the stack.

   HDC hSrcDC = CreateCompatibleDC(hDestDC);
    HGDIOBJ oldsrc = SelectObject (hSrcDC, hSrcBitmap);

We now create a new device context, compatible with the destination device context, and we associate it with the source bitmap so we can access the bitmap trough our device context.

   if (oldsrc != 0) {
      BITMAPINFOHEADER bi = {
         sizeof(BITMAPINFOHEADER), // biSize
         bminfo.bmWidth,           // biWidth;
         bminfo.bmHeight,          // biHeight;
         1,                        // biPlanes;
         24,                       // biBitCount
         BI_RGB,                   // biCompression;
         0,                        // biSizeImage;
         0,                        // biXPelsPerMeter;
         0,                        // biYPelsPerMeter;
         0,                        // biClrUsed;
                                 // biClrImportant;
      };
      HBITMAP hTempBitmap = CreateDIBSection(hDestDC,
         (BITMAPINFO *)&bi, DIB_RGB_COLORS,
         NULL, NULL, 0);
      HDC hTempDC = CreateCompatibleDC(hDestDC);
      HGDIOBJ oldtemp = SelectObject(hTempDC, 
         hTempBitmap);

After checking whether the device context was successfully associated with the source bitmap, we create a temporary 24-bit memory bitmap, with the same size as the source bitmap. We then create a device context and associate that new device context with our memory bitmap.

      if (oldtemp != 0) {
         RECT r = {0, 0, bminfo.bmWidth, 
            bminfo.bmHeight};
         HBRUSH dBrush = CreateSolidBrush(DuoColor);

If the association was completed successfully, we define a rectangle structure and initialize it with the width and height of the source bitmap. We also create a new solid brush with the color specified by the caller.

         if (dBrush != 0 && 
            FillRect(hTempDC, &r, dBrush) != 0) {
            if (!BitBlt(hTempDC, 0, 0, bminfo.bmWidth,
               bminfo.bmHeight, hSrcDC, 0, 0, SRCAND)
               || !BitBlt(hDestDC, destx, desty,
               bminfo.bmWidth, bminfo.bmHeight,
               hTempDC, 0, 0, SRCCOPY))
                  retval = 0;
 

We check for successful creation of the brush and whether the temporary memory bitmap was filled with the DuoColor, and if both calls are completed correctly, we start blitting the source bitmap to our DuoColor memory bitmap, and then copy the result to the destination device context. If an error occurs, we set retval to 0.

         } else {
            retval = 0;
         }
         DeleteObject(dBrush);
      } else {
         retval = 0;
      }
      DeleteObject(SelectObject(hTempDC, oldtemp));
      DeleteDC(hTempDC);
   } else {
      retval = 0;
   }
   SelectObject(hSrcDC, oldsrc);
   DeleteDC(hSrcDC);
   return retval;
}

The last few lines are clean up code. If an error occurs they make sure retval is set to 0, and they make sure that all the memory is released before returning to the caller.

If you now paste all the parts of the C source code into your VC++ DLL, you’ll have a working DuoTone function. However, you don’t need a DLL to implement such a function in Visual Basic. You could easily write the same function in Visual Basic, and you would hardly notice a difference in speed, since the Win32 API functions are doing the work in this function.
That’s why we’ll see in the next part how to program processor intensive functions, which use pointers as parameters.

You can download the VC++ source code and the VB example project over here.

Part 1 - Part 2 - Part 3 - Part 4 isn't available yet

 

 


Copyright © 1998-2007, The Mentalis.org Team - Privacy statement
Did you find a bug on this page? Tell us!
This site is located at http://allapi.mentalis.org/