|
|
|
|
Spin on a Dime� With NT! By Robert Vivrette - RobertV@mail.com This article originally appeared in the Janurary 1999 issue of Delphi Informant Magazine and is being reprinted here with permission from Informant Communications. Many of you are no-doubt familiar with the BitBlt Windows API function. For those of you who don�t, it stands for �Bit Block Transfer� and is simply one of the functions Windows uses to paint images on the screen. It�s close-relative is the StretchBlt function which performs a similar function, but allows you to stretch or shrink the image you are drawing. Delphi wraps each of these commands in far simpler to use mechanisms� namely the Draw and StretchDraw methods. In addition to a few other relatives (including MaskBlt for masking operations, and PatBlt for painting an area with a pattern), Windows also includes a little-known function called PlgBlt. Part of the reason why it is not in many peoples graphics vocabulary is that it is currently an WinNT/Win2K-only function (so is MaskBlt by the way). This means that users of Win31, Win95 and Win98 are out of luck here. It won�t work. However, if you use WinNT/Win2K and have to do some fancy footwork with graphics, you will find PlgBlt to be an incredibly powerful tool. In a nutshell, PlgBlt is pretty much the same as a StretchBlt except that the destination of the painting doesn�t need to be rectilinear� hence the �Plg� in its name (which stands for parallelogram). All PlgBlt needs to perform this magic is 3 points on a canvas� (sounds like a song!) Now wait a minute, you say� why only 3 points? Well, as it turns out, it really does use 4 points to make this parallelogram. However, it doesn�t trust you to generate the 4th one. If you were to place 3 dots on a piece of paper in a specific order, there would be only one spot where you could place the fourth and still have a parallelogram. Note here that the sequence of those first three points is important in making this determination. As a demonstration on the use of PlgBlt, I decided to write a quick little application that would allow the user to spin a bitmap in real-time. As you can see from the listing below, there is no rocket science here, but the capability PlgBlt adds is undeniably cool. Even if you are using a non WinNT/Win2K development environment, there are a couple of interesting techniques that are in use in this code that you may find useful anyway. Read On! unit PlgBltU;
Next, we setup an array of points. There are four points in this array (numbered 0 to 3) and we will be using them for two purposes: The first is to pass the array into the PlgBlt command (remember, it will ignore the last point); and the second purpose is to provide locations for drawing handles on the image (so we can see where to grab when rotating it). All I do here in the FormCreate is place the points in their proper locations� one at each corner of the image. Next we calculate a MidPt. This TPoint variable will hold the rotational center of the image and is an average of the 4 corners of the image. The next variable defined is �R� which will hold the distance (radius) from one corner of the image to the MidPt. This is used in the rotation calculations later on. Next, we fill an array of 4 real numbers (Double�s actually) with the initial angle that each corner of the image has in relation to the midpoint. This is also used in our rotation calculations. Lastly, we set the OverHandle variable to a known value. This variable is used to track the handle number that the mouse is over. When it is �1, it is not over a handle. The FormDestroy method simply cleans up a little by deleting our background bitmap we created in the FormCreate. The FormPaint is where PlgBlt comes into play. Remember I said earlier that we were going to use the background bitmap to avoid flicker. Well, the way this is done is that all drawing is done on this bitmap first. When it is all done, then the entire contents are plastered on the form�s canvas with a single call to its Draw method. Flicker occurs when you have multiple (and conflicting) draw actions occurring in the same space. Since the background bitmap is an in-memory TBitmap we can draw on it all we want and the user won�t see it until it is transferred to the form. Since it is a single drawing event, there is no flicker. Back to the FormPaint� First, we clear the background bitmap using FillRect. Then we do our call to PlgBlt. The parameters it expects are as follows (partially excerpted from the Win32 API Help): hdcDest - Identifies the destination device context. This is the handle to the destination canvas (BkBmp.Canvas.Handle)The last three parameters (hbmMask, xMask, and yMask) have to do with an optional bitmap that can be used to mask colors. We aren�t using these in this example, so we set them all to zero. If the call to PlgBlt is successful, then we draw the 4 handles on the image, using the same array of points we passed into PlgBlt. If the call is not successful, it generally is a sign that we are not running on a WinNT platform, so we make an appropriate mention using TextOut. After all this is done, the background bitmap is transferred all at once to the form using its Draw method. The last method we have in this demo is the mouse management for working with the handles on the corners of the image. When the mouse is moved, we first look to see if the left mouse button is down. If so, we also check to make sure that OverHandle contains the number of a handle that has been grabbed. Assuming this is also true, we determine the angle from where the mouse is to the mid-point of the image (calculated earlier). We use this angle to re-calculate the locations of each of the four handles on the image. If the left mouse button is not down, we make sure the OverHandle variable is reset and then we use PtInRect to determine if the mouse is over any of the four handles. If so, we store that handle�s number in OverHandle, and switch the cursor to a hand pointer. That is pretty much it for this demonstration. Notice that there is no code to rotate the image as such. The PlgBlt routine handles that all for us. When you run the application, you will see something like what is shown in Figure 1.
Grabbing one of the handles and spinning it a little counter-clockwise would result in what is shown in Figure 2.
These static pictures of course really don�t do the demo much justice. Suffice it to say that the rotation is perfectly smooth and very fast, thanks in part to the amazing power of PlgBlt. |
|
|
Copyright © 2007 undu.com Powered by Engineer Partner The One Stop Outsource
|