Outlining, Dragging, and Pasting a Region (C++ 5.0 and later)
Take the following steps to add code that lets you outline an area with a mouse, drag a copy of the selected area, and paste the copy into another part of the bitmap:
1. |
Start with the project that you created in Loading and Displaying an Image. |
2. |
Add another LEAD RasterView control with an ID of IDC_LEADRASTERVIEW2, set its Visible property to FALSE, and give it a variable name of m_LEADRasterView2. (You can follow the same instructions as when adding the first LEAD control.) Note, for simplicity, we are using a 2nd RasterView control. In reality, to reduce memory requirements, you would probably want to use an ILEADRaster Object. |
3. |
Go to the Project WorkSpace and click the FileView tab. |
4. |
Edit TUTORDLG.H and insert the following lines in the definition of CTutorDlg after DECLARE_MESSAGE_MAP(): |
BOOL ReadyToDrag; //The state after marking the region but before dragging
BOOL Dragging; //The state when the mouse is used for dragging the floater
float StartX; //Starting X position in screen pixels
float StartY; //Starting Y position in screen pixels
float FloaterX; //Floater X position in screen pixels
float FloaterY; //Floater Y position in screen pixels
float ZoomFactorX; //Used for translating positioning information
float ZoomFactorY; //Used for translating positioning information
5. |
Go to the Project Workspace and click the ResourceView tab. |
|
6. |
Double-click Dialog and double-click IDD_TUTOR_DIALOG to bring up the application's dialog box. |
|
7. |
|
|
8. |
Double-click each button and change its values as follows: |
|
|
ID |
Caption |
|
IDC_SELRGN |
Select Region |
|
IDC_PASTEFLOATER |
Paste Floater |
9. |
Start the Class Wizard and add code for the IDC_SELRGN button. To do so, press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CTutorDlg. |
|
c. |
In the Object IDs list box, select IDC_SELRGN. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnSelRgn). |
|
f. |
Click the Edit Code button to start entering the code. |
10. |
Enter new code as follows: |
void CTutorDlg::OnSelrgn()
{
// TODO: Add your control notification handler code here
m_LEADRasterView1.SetRgnMarkingMode(RGNMARK_FREEHAND);
MessageBox(TEXT("Draw a freehand region"));
}
11. |
Start the Class Wizard and add code for the IDC_PASTEFLOATER button. To do so, press Ctrl-W to go to the MFC Class Wizard; then do the following: |
|
|
a. |
Click the Message Maps tab. |
|
b. |
In the Class Name combo box, select CTutorDlg. |
|
c. |
In the Object IDs list box, select IDC_PASTEFLOATER. |
|
d. |
In the Messages list box, select BN_CLICKED. |
|
e. |
Click the Add function button. Choose OK for the default function name (OnPastefloater). |
|
f. |
Click the Edit Code button to start entering the code. |
12. |
Enter new code as follows: |
void CTutorDlg::OnPastefloater()
{
// Variable for the Combine operation.
CombineConstants MyOp;
// Variables for the client area coordinates.
float LCRgnX, LCRgnY , LCRgnWidth, LCRgnHeight;
// Variables for the bitmap coordinates.
float LBRgnX, LBRgnY , LBRgnWidth, LBRgnHeight;
// Do nothing if there is no floater.
if (m_LEADRasterView1.GetFloater() == 0) return;
// Set the scale mode to pixels so that we do not have to
// translate mouse coordinates
m_LEADRasterView1.SetScaleMode(3);
// Get the floater into another bitmap
m_LEADRasterView2.SetScaleMode(m_LEADRasterView1.GetScaleMode());
m_LEADRasterView2.GetRaster().SetBitmap(m_LEADRasterView1.GetFloater());
// Get the floater's client coordinates into local variables.
LCRgnX = m_LEADRasterView1.GetFloaterDstLeft();
LCRgnY = m_LEADRasterView1.GetFloaterDstTop();
LCRgnWidth = m_LEADRasterView1.GetFloaterDstWidth();
LCRgnHeight = m_LEADRasterView1.GetFloaterDstHeight();
// Delete the floater.
m_LEADRasterView1.SetFloaterVisible(FALSE);
m_LEADRasterView1.SetFloater(0);
// Translate the client coordinates to bitmap coordinates.
LBRgnX = ((LCRgnX - m_LEADRasterView1.GetDstLeft()) / ZoomFactorX)
+ m_LEADRasterView1.GetSrcLeft();
LBRgnY = ((LCRgnY - m_LEADRasterView1.GetDstTop()) / ZoomFactorY)
+ m_LEADRasterView1.GetSrcTop();
LBRgnWidth = LCRgnWidth / ZoomFactorX;
LBRgnHeight = LCRgnHeight / ZoomFactorY;
// Reposition the region to use as a mask for the Combine method.
m_LEADRasterView1.GetRaster().OffsetRgn(LBRgnX - m_LEADRasterView1.GetRaster().GetRgnLeft(),
LBRgnY - m_LEADRasterView1.GetRaster().GetRgnTop());
// Use the Combine method to paste the LEADRasterView2 bitmap into the LEADRasterView1 bitmap
ILEADRasterProcess *pRasterProc=NULL;
CoCreateInstance(CLSID_LEADRasterProcess, NULL, CLSCTX_ALL,
IID_ILEADRasterProcess, (void**)&pRasterProc);
MyOp = (CombineConstants)(CB_OP_ADD | CB_DST_0); // Operation flags for a simple paste.
pRasterProc->Combine(m_LEADRasterView1.GetRaster(),
LBRgnX, LBRgnY, LBRgnWidth, LBRgnHeight,
m_LEADRasterView2.GetRaster(), 0.0f, 0.0f, MyOp);
pRasterProc->Release();
// Repaint the part of the client area that has changed.
m_LEADRasterView1.RepaintRect(LCRgnX, LCRgnY, LCRgnWidth, LCRgnHeight, FALSE);
// Free the region.
m_LEADRasterView1.GetRaster().FreeRgn();
}
13. |
To add the code for LEAD RasterView mouse events, do the following: |
|
|
a. |
Press Ctrl-W to go to the MFC ClassWizard. |
|
b. |
In the Class Name combo box, select CTutorDlg. |
|
c. |
In the Object IDs list box, select IDC_LEADRASTERVIEW1. |
|
d. |
Continue with the remaining steps for each mouse event. |
14. |
In the MFC ClassWizard, double-click the MouseDown event and add code as follows: |
void CTutorDlg::OnMouseDownLeadrasterview1(short Button, short Shift, float x, float y)
{
// Declare local variables.
float BitmapX, BitmapY;
float NewX, NewY, NewWidth, NewHeight;
// Do nothing if we are drawing a region.
if (m_LEADRasterView1.GetRgnMarkingMode() != RGNMARK_NONE) return;
// Save the starting position, in case we need it.
StartY = y;
StartX = x;
// if we are ready to drag the selection, get a floater.
if (ReadyToDrag == TRUE)
{
// Translate the current mouse coordinates.
// These coordinates account for the zoom factor and offset.
ZoomFactorX = m_LEADRasterView1.GetDstWidth() / m_LEADRasterView1.GetSrcWidth();
ZoomFactorY = m_LEADRasterView1.GetDstHeight() / m_LEADRasterView1.GetSrcHeight();
BitmapX = (x / ZoomFactorX) - (m_LEADRasterView1.GetDstLeft() / ZoomFactorX)
+ m_LEADRasterView1.GetSrcLeft();
BitmapY = (y / ZoomFactorY) - (m_LEADRasterView1.GetDstTop() / ZoomFactorY)
+ m_LEADRasterView1.GetSrcTop();
// Continue to create the floater if the mouse is pointing to
// the region we marked.
if (m_LEADRasterView1.GetRaster().IsPtInRgn(BitmapX, BitmapY))
{
// Hide the region frame.
m_LEADRasterView1.SetRgnFrameType(RGNFRAME_NONE);
// Create the floater bitmap, which will be the part of the main bitmap
// that is in the region's bounding rectangle.
m_LEADRasterView1.SetFloater(m_LEADRasterView1.GetRaster().GetBitmap());
// Translate the bitmap region coordinates to client area coordinates.
NewY = ((m_LEADRasterView1.GetRaster().GetRgnTop()
- m_LEADRasterView1.GetSrcTop()) * ZoomFactorY)
+ m_LEADRasterView1.GetDstTop();
NewX = ((m_LEADRasterView1.GetRaster().GetRgnLeft()
- m_LEADRasterView1.GetSrcLeft()) * ZoomFactorX)
+ m_LEADRasterView1.GetDstLeft();
NewWidth = m_LEADRasterView1.GetRaster().GetRgnWidth() * ZoomFactorX;
NewHeight = m_LEADRasterView1.GetRaster().GetRgnHeight() * ZoomFactorY;
// Set the initial display position of the floater.
m_LEADRasterView1.SetFloaterDstRect(NewX, NewY, NewWidth, NewHeight);
// Set form-level variables.
FloaterY = m_LEADRasterView1.GetFloaterDstTop();
FloaterX = m_LEADRasterView1.GetFloaterDstLeft();
m_LEADRasterView1.SetFloaterVisible(TRUE);
Dragging = TRUE;
ReadyToDrag = FALSE;
}
}
}
15. |
In the MFC ClassWizard, double-click the MouseMove event and add code as follows: |
void CTutorDlg::OnMouseMoveLeadrasterview1(short Button, short Shift, float x, float y)
{
// Variables for repositioning the floater.
float NewX, NewY, NewWidth, NewHeight, XDelta, YDelta;
// Do nothing if we are drawing a region.
if (m_LEADRasterView1.GetRgnMarkingMode() != RGNMARK_NONE) return;
// Reposition the floater if we are dragging it.
if ((Dragging == TRUE) && (Button == 1) && (m_LEADRasterView1.GetFloater() != 0))
{
if (m_LEADRasterView1.IsPtInFloater(x, y))
{
// Update the position variables.
XDelta = x - StartX;
YDelta = y - StartY;
NewX = FloaterX + XDelta;
NewY = FloaterY + YDelta;
NewWidth = m_LEADRasterView1.GetFloaterDstWidth();
NewHeight = m_LEADRasterView1.GetFloaterDstHeight();
// Reposition the floater.
m_LEADRasterView1.SetFloaterDstRect(NewX, NewY, NewWidth, NewHeight);
// Save the form-level position variables.
FloaterY = NewY;
FloaterX = NewX;
StartY = y;
StartX = x;
}
}
}
16. |
In the MFC ClassWizard, double-click the MouseUp event and add code as follows: |
void CTutorDlg::OnMouseUpLeadrasterview1(short Button, short Shift, float x, float y)
{
// If we were drawing a region, set up for the next operation.
if (m_LEADRasterView1.GetRgnMarkingMode() != RGNMARK_NONE)
{
m_LEADRasterView1.SetRgnMarkingMode( RGNMARK_NONE);
m_LEADRasterView1.SetRgnFrameType( RGNFRAME_STATIC);
ReadyToDrag = TRUE;
MessageBox(TEXT("Now, drag the selection to another place."));
}
}
17. |
Run your program to test it. |