Programming with Microsoft Visual C++.NET 6ed [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming with Microsoft Visual C++.NET 6ed [Electronic resources] - نسخه متنی

George Shepherd, David Kruglinski

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید








The Ex24b Example: OLE Drag and Drop


This example picks up where the Ex24a example left off. It adds drag-and-drop support, using the existing SaveDib and DoPasteDib helper functions. All of the Clipboard code is the same. You should be able to adapt Ex24b to other applications that require drag and drop for data objects.

To prepare Ex24b, open the \vcppnet\Ex24b\

Ex24b.sln solution and build the project. Run the application, and test drag and drop between child windows and between instances of the program.


The CEx24bDoc Class


This class is just like the Ex24a version except for an added flag data member, m_bDragHere. This flag is TRUE when a drag-and-drop operation is in progress for this document. The flag is in the document and not in the view because it is possible to have multiple views attached to the same document. It doesn't make sense to drag a DIB from one view to another if both views reflect the document's m_dib member.



The CEx24bView Class


To start with, this class has three additional data members and a constructor that initializes all the data members, as shown here:

CRect m_rectTrackerEnter; // original logical coordinates
COleDropTarget m_dropTarget;
CSize m_dragOffset; // device coordinates
CEx24bView::CEx24bView() : m_sizeTotal(800, 1050), // 8-by-10.5 inches
// when printed
m_rectTracker(50, 50, 250, 250),
m_dragOffset(0, 0),
m_rectTrackerEnter(50, 50, 250, 250)
{
}

The OnInitialUpdate function needs one additional line to register the drop target:

m_dropTarget.Register(this);

Following are the drag-and-drop virtual override functions. Note that OnDrop replaces the DIB only if the document's m_bDragHere flag is TRUE, so if the user drops the DIB in the same window or in another window connected to the same document, nothing happens.

DROPEFFECT CEx24bView::OnDragEnter(COleDataObject* pDataObject, 
DWORD dwKeyState, CPoint point)
{
TRACE("Entering CEx24bView::OnDragEnter, point = (%d, %d)\n",
point.x, point.y);
m_rectTrackerEnter = m_rectTracker; // Save original coordinates
// for cursor leaving
// rectangle
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DrawFocusRect(m_rectTracker); // will be erased in OnDragOver
return OnDragOver(pDataObject, dwKeyState, point);
}
void CEx24bView::OnDragLeave()
{
TRACE("Entering CEx24bView::OnDragLeave\n");
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DrawFocusRect(m_rectTracker);
m_rectTracker = m_rectTrackerEnter; // Forget it ever happened
}
DROPEFFECT CEx24bView::OnDragOver(COleDataObject* pDataObject, DWORD
dwKeyState, CPoint point)
{
if (!pDataObject->IsDataAvailable(CF_DIB)) {
return DROPEFFECT_NONE;
}
MoveTrackRect(point);
if((dwKeyState & MK_CONTROL) == MK_CONTROL) {
return DROPEFFECT_COPY;
}
// Check for force move
if ((dwKeyState & MK_ALT) == MK_ALT) {
return DROPEFFECT_MOVE;
}
// default -- recommended action is move
return DROPEFFECT_MOVE;
}
BOOL CEx24bView::OnDrop(COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point)
{
TRACE("Entering CEx24bView::OnDrop -- dropEffect = %d\n", dropEffect);
BOOL bRet;
CEx24bDoc* pDoc = GetDocument();
MoveTrackRect(point);
if(pDoc->m_bDragHere) {
pDoc->m_bDragHere = FALSE;
bRet = TRUE;
}
else {
bRet = DoPasteDib(pDataObject);
}
return bRet;
}

The handler for the WM_LBUTTONDOWN message needs a substantial overhaul. It must call DoDragDrop if the cursor is inside the rectangle and Track if it is on the rectangle border. The revised code is shown here:

void CEx24bView::OnLButtonDown(UINT nFlags, CPoint point)
{
CEx24bDoc* pDoc = GetDocument();
if(m_tracker.HitTest(point) == CRectTracker::hitMiddle) {
COleDataSource* pSource = SaveDib();
if(pSource) {
// DoDragDrop returns only after drop is complete
CClientDC dc(this);
OnPrepareDC(&dc);
CPoint topleft = m_rectTracker.TopLeft();
dc.LPtoDP(&topleft);
// 'point' here is not the same as the point parameter in
// OnDragEnter, so we use this one to compute the offset
m_dragOffset = point - topleft; // device coordinates
pDoc->m_bDragHere = TRUE;
DROPEFFECT dropEffect = pSource->DoDragDrop(
DROPEFFECT_MOVE|DROPEFFECT_COPY, CRect(0, 0, 0, 0));
TRACE("after DoDragDrop -- dropEffect = %ld\n", dropEffect);
if (dropEffect == DROPEFFECT_MOVE && pDoc->m_bDragHere) {
pDoc->OnEditClearall();
}
pDoc->m_bDragHere = FALSE;
delete pSource;
}
}
else {
if(m_tracker.Track(this, point, FALSE, NULL)) {
CClientDC dc(this);
OnPrepareDC(&dc);
// should have some way to prevent it going out of bounds
m_rectTracker = m_tracker.m_rect;
dc.DPtoLP(m_rectTracker); // Update logical coords
}
}
Invalidate();
}

Finally, the new MoveTrackRect helper function, shown here, moves the tracker's focus rectangle each time the OnDragOver function is called. This job was done by CRectTracker::Track in the Ex24a example.

void CEx24bView::MoveTrackRect(CPoint point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DrawFocusRect(m_rectTracker);
dc.LPtoDP(m_rectTracker);
CSize sizeTrack = m_rectTracker.Size();
CPoint newTopleft = point - m_dragOffset; // still device
m_rectTracker = CRect(newTopleft, sizeTrack);
m_tracker.m_rect = m_rectTracker;
dc.DPtoLP(m_rectTracker);
dc.DrawFocusRect(m_rectTracker);
}

I tested Ex24b against the Microsoft Office XP suite using both drag-and-drop and Clipboard transfers. The CF_DIB format isn't supported. If you want pictures from Microsoft Excel, you must enhance Ex24b to process metafiles.



/ 319