|
|
Title | Overlay a picture on another and use BitBlt to repaint only the modified parts of the background |
Description | |
Keywords | drag picture, BitBlt |
Categories | Graphics |
|
|
Use a hidden PictureBox to store the background image. To move the foreground object, erase it using BitBlt to draw from the hidden picture to the visible picture. Use BitBlt and the image mask with opcode MERGEPAINT to knock out the mask. Finally, use BitBlt with the foreground image and opcode SRCAND to drop in the foreground image.
This program lets the user either drag an image or drag a rectangle showing where the image will be placed. Dragging only the rectangle can be much faster for large images.
The program's picMask PictureBox contains a mask of the image to be dragged. Pixels that should be drawn are black and pixels that should let the background show through are white.
In the MouseDown event handler, the program subtracts the overlay picture's current position from the mouse's coordinates to see where on the overlay picture the user clicked. If the corresponding mask pixel is white, the user is pressing where the background should show through so the event is ignored.
If the corresponding mask pixel is black, the user is pressing the mouse on part of the image and the program begins a drag. In that case, the program determines whether it should drag only an outline and saves the result in the Boolean UseOutline.
|
|
' See if the mouse is over a point corresponding
' to a black part of the mask.
Private Sub picCanvas_MouseDown(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
OffsetX = PicX - X
OffsetY = PicY - Y
If picMask.Point(-OffsetX, -OffsetY) <> vbBlack Then _
Exit Sub
' Start dragging.
UseOutline = (chkUseOutline.Value = vbChecked)
If UseOutline Then DrawOutline
Dragging = True
End Sub
|
|
In the MouseMove event handler, the program checks whether it is drawing an outline. If it is, the code calls subroutine DrawOutline to erase the previous outline.
The event handler then determines where the picture should be placed and calls DrawOutline or DrawPic to draw the outline or picture as appropriate.
|
|
' Drag.
Private Sub picCanvas_MouseMove(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
If Not Dragging Then Exit Sub
If UseOutline Then DrawOutline
PicX = X + OffsetX
If PicX < 0 Then
PicX = 0
ElseIf PicX > CanvasWid - PicWid Then
PicX = CanvasWid - PicWid
End If
PicY = Y + OffsetY
If PicY < 0 Then
PicY = 0
ElseIf PicY > CanvasHgt - PicHgt Then
PicY = CanvasHgt - PicHgt
End If
If UseOutline Then
DrawOutline
Else
DrawPic
End If
End Sub
|
|
Subroutine DrawOutline simply draws a rectangle where the picture should be. The picCanvas control has drawing mode set to invert so the rectangle is erasable.
Subroutine DrawPic restores the background picture by using BitBlt to copy the part of the background that is currently covered by the overlay onto picCanvas. It then uses BitBlt to copy the overlay mask onto picCanvas using the opcode MERGEPAINT. This knocks out the mask's outline on the background so a white image of the overlay appears.
Next the code copies the overlay image onto the background using the SRCAND opcode. This combines the pixel values of the overlay image with the background image. The overlay image is white where it should not show and the background image is white where the overlay should show. The result is the overlay is dropped into its correct position.
|
|
' Draw an outline of the picture.
Private Sub DrawOutline()
picCanvas.Line _
(PicX, PicY)-Step(PicWid, PicHgt), , B
End Sub
' Draw the picture at (CurX, CurY).
Private Sub DrawPicture()
' Fix the part of the image that was covered.
BitBlt picCanvas.hDC, _
OldX, OldY, PicWid, PicHgt, _
picHidden.hDC, OldX, OldY, SRCCOPY
OldX = CurX
OldY = CurY
' Paint on the new image.
BitBlt picCanvas.hDC, _
CurX, CurY, PicWid, PicHgt, _
picXMask.hDC, 0, 0, MERGEPAINT
BitBlt picCanvas.hDC, _
CurX, CurY, PicWid, PicHgt, _
picX.hDC, 0, 0, SRCAND
' Update the display.
picCanvas.Refresh
End Sub
|
|
If the user is dragging only an outline, the MouseUp event handler calls subroutine DrawPic to draw the overlay image at the desired location. This covers the previous outline.
If the user is not dragging only an outline, the picture is already in its new position.
|
|
' Stop dragging.
Private Sub picCanvas_MouseUp(Button As Integer, Shift As _
Integer, X As Single, Y As Single)
If UseOutline Then DrawPic
Dragging = False
End Sub
|
|
My book Visual Basic Graphics Programming has more information on this kind of graphic manipulation.
See also:
|
|
|
|
|
|