📄 uidragdroptree.cpp
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// You may use this source code, compile or redistribute it as part of your application
// for free. You cannot redistribute it as a part of a software development
// library without the agreement of the author. If the sources are
// distributed along with the application, you should leave the original
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES at your own risk.
//
// For the latest updates to this code, check this site:
// http://www.masmex.com
// after Sept 2000
//
// Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
//*******************************************************************************
//////////////////////////////////////////////////////////////////////////////////////--*/
// UIDragDropTree.cpp : implementation file
//
#include "stdafx.h"
#include "UICtrl.h"
#include "UIDragDropTree.h"
#include "cbformats.h"
#include "UIRes.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CUIDragDropTree,CTreeCtrl)
/////////////////////////////////////////////////
//
// For OLE drag and drop
//
/////////////////////////////////////////////////
void CUI_TreeDropTarget::OnDragLeave(CWnd* pWnd)
{
CUIDragDropTree *pTree = static_cast<CUIDragDropTree*>(pWnd);
if (pTree == NULL)
return;
pTree->KillDragTimer();
pTree->SelectDropTarget(NULL);
CDD_OleDropTargetInfo Info(pWnd->GetSafeHwnd());
Info.SetItem(pTree->GetDropHilightItem());
BOOL bRet = pTree->SendMessage(WM_APP_OLE_DD_LEAVE,(WPARAM)&Info);
if (bRet == FALSE)
bRet = pTree->GetParent()->SendMessage(WM_APP_OLE_DD_LEAVE,(WPARAM)&Info);
}
DROPEFFECT CUI_TreeDropTarget::OnDragEnter( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
// ASSERT_KINDOF(CUIDragDropTree,pWnd);
CUIDragDropTree *pTree = static_cast<CUIDragDropTree*>(pWnd);
if (pTree == NULL)
return DROPEFFECT_NONE;
((CUIDragDropTree*)pWnd)->SetDragTimer();
CDD_OleDropTargetInfo Info(pWnd->GetSafeHwnd(),point,pDataObject);
m_dwEnterKeyboardState = dwKeyState;
Info.SetKeyboardState(dwKeyState);
Info.SetItem(pTree->GetDropHilightItem());
BOOL bRet = pTree->SendMessage(WM_APP_OLE_DD_ENTER,(WPARAM)&Info);
if (bRet == FALSE)
bRet = pTree->GetParent()->SendMessage(WM_APP_OLE_DD_ENTER,(WPARAM)&Info);
return Info.GetDropEffect();
}
DROPEFFECT CUI_TreeDropTarget::OnDragOver( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
// disallow if the control key pressed
EraseOldImage();
CUIDragDropTree *pTree = static_cast<CUIDragDropTree*>(pWnd);
if (pTree == NULL)
return DROPEFFECT_NONE;
// ASSERT_KINDOF(CUIDragDropTree,pWnd);
CDD_OleDropTargetInfo Info(pWnd->GetSafeHwnd(),point,pDataObject);
m_dwKeyboardState = dwKeyState;
Info.SetKeyboardState(dwKeyState);
// WM_APP_OLE_DD_OVER message sent in SelectCurrentTarget
DROPEFFECT dropEffect = pTree->SelectCurrentTarget(&Info);
CUI_ImageDropTarget::OnDragOver(pWnd,pDataObject,dwKeyState,point);
return dropEffect;
}
BOOL CUI_TreeDropTarget::OnDrop( CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point )
{
CUIDragDropTree *pTree = static_cast<CUIDragDropTree*>(pWnd);
if (pTree == NULL)
return FALSE;
// ASSERT_KINDOF(CUIDragDropTree,pWnd);
pTree->KillDragTimer();
HTREEITEM hItem = pTree->GetDropHilightItem();
BOOL bRet=FALSE;
if (hItem)
{
CDD_OleDropTargetInfo Info(pWnd->GetSafeHwnd(),point,pDataObject);
Info.SetDropEffect(dropEffect);
Info.SetItem(hItem);
if (m_dwEnterKeyboardState & MK_RBUTTON)
m_dwKeyboardState |= MK_RBUTTON;
if (m_dwEnterKeyboardState & MK_LBUTTON)
m_dwKeyboardState |= MK_LBUTTON;
Info.SetKeyboardState(m_dwKeyboardState);
bRet = pTree->SendMessage(WM_APP_OLE_DD_DROP,(WPARAM)&Info);
if (bRet == FALSE)
bRet = pTree->GetParent()->SendMessage(WM_APP_OLE_DD_DROP,(WPARAM)&Info);
}
pTree->SelectDropTarget(NULL);
return bRet;
}
// During slow scroll, process every third message.
#define SLOWSCROLL_FREQUENCY 3
/////////////////////////////////////////////////////////////////////////////
// CUIDragDropTree
CUIDragDropTree::CUIDragDropTree(bool bDragDrop): m_nUpperYCoor(0),
m_nLowerYCoor(0),
m_nSlowScrollTimeout(0),
m_nTimerID(0),
m_bDragging(FALSE),
m_pImageList(NULL),
m_hitemDrag(NULL),
m_hitemDrop(NULL),
m_bDragDrop(bDragDrop),
m_bDropFiles(true)
{
m_nScrollBarSize = GetSystemMetrics( SM_CYHSCROLL );
m_CopyMode = eDDCancel;
}
CUIDragDropTree::~CUIDragDropTree()
{
}
void CUIDragDropTree::OnDropFile(HTREEITEM hItem,LPCTSTR pszFile,UINT nFlags)
{
}
BEGIN_MESSAGE_MAP(CUIDragDropTree, CTreeCtrl)
//{{AFX_MSG_MAP(CUIDragDropTree)
ON_NOTIFY_REFLECT_EX(TVN_BEGINDRAG, OnBegindrag)
ON_NOTIFY_REFLECT_EX(TVN_BEGINRDRAG, OnBeginRDrag)
ON_WM_TIMER()
ON_WM_RBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_DESTROY()
ON_WM_CREATE()
ON_WM_DROPFILES()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CUIDragDropTree message handlers
void CUIDragDropTree::OnDropFiles(HDROP hDropInfo)
{
UINT wNumFilesDropped = DragQueryFile(hDropInfo, 0XFFFFFFFF, NULL, 0);
TCHAR szFile[MAX_PATH];
UINT nLen;
UINT nFlags;
POINT pt;
::DragQueryPoint(hDropInfo,&pt);
HTREEITEM hitemDrag = HitTest(CPoint(pt), &nFlags);
for(UINT i=0; i < wNumFilesDropped;i++)
{
nLen = DragQueryFile(hDropInfo,i,szFile,sizeof(szFile)/sizeof(TCHAR));
if (nLen)
OnDropFile(hitemDrag,szFile,nFlags);
}
}
BOOL CUIDragDropTree::OnBeginRDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
return StartDragDrop(pNMTreeView);
}
BOOL CUIDragDropTree::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
return StartDragDrop(pNMTreeView);
}
BOOL CUIDragDropTree::StartDragDrop(NM_TREEVIEW* pNMTreeView)
{
if (GetDragDrop() == false || pNMTreeView->itemNew.hItem == GetRootItem())
return FALSE;
// See if COM drag drop is implemented in this window or parent window
DWORD dwDragEffect = SendMessage(WM_APP_OLE_DD_DODRAGDROP,(WPARAM)pNMTreeView,(LPARAM)&m_OleDataSource);
if (dwDragEffect == 0)
dwDragEffect = GetParent()->SendMessage(WM_APP_OLE_DD_DODRAGDROP,(WPARAM)pNMTreeView,(LPARAM)&m_OleDataSource);
if (dwDragEffect)
{
CRect rcDrag;
m_hitemDrag = pNMTreeView->itemNew.hItem;
// Define starting rect
GetItemRect(pNMTreeView->itemNew.hItem,rcDrag,TRUE);
// Start the DragDrop
DWORD dwEffect = m_OleDataSource.DoDragDrop(dwDragEffect,rcDrag);
// Clear the cache
m_OleDataSource.Empty();
}
else // otherwise start local drag drop
{
CPoint ptAction;
UINT nFlags;
GetCursorPos(&ptAction);
ScreenToClient(&ptAction);
m_bDragging = TRUE;
m_hitemDrag = HitTest(pNMTreeView->ptDrag, &nFlags);
m_hitemDrop = NULL;
// Create drag image and begin dragging
m_pImageList = CreateDragImage(m_hitemDrag);
m_pImageList->BeginDrag(0, CPoint(0,0));
m_pImageList->DragEnter(GetDesktopWindow(), ptAction);
SetCapture();
SetDragTimer();
}
return TRUE;
}
void CUIDragDropTree::SetDragTimer()
{
// Set the timer to slow down the scrolling when the dragging cursor
// is close to the top/bottom border of the tree control
if (!m_nTimerID)
{
m_nTimerID = SetTimer(1, 75, NULL);
CRect rect;
GetClientRect(&rect);
ClientToScreen(&rect);
m_nUpperYCoor = rect.top;
m_nLowerYCoor = rect.bottom;
}
}
void CUIDragDropTree::KillDragTimer()
{
if (m_nTimerID)
{
KillTimer(m_nTimerID);
}
m_nTimerID = 0;
m_nUpperYCoor = 0;
m_nLowerYCoor = 0;
m_nSlowScrollTimeout = 0;
}
void CUIDragDropTree::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (nIDEvent != m_nTimerID)
{
CTreeCtrl::OnTimer(nIDEvent);
return;
}
// Get the "current" mouse position
const MSG* pMessage;
CPoint ptMouse;
pMessage = GetCurrentMessage();
ASSERT(pMessage);
ptMouse = pMessage->pt;
// Move the ghost image
if (m_pImageList)
m_pImageList->DragMove(ptMouse);
// Find out if scrolling is needed.
// Scrolling is not needed for example, if the dragging cursor is
// within the tree control itself
if(!NeedToScroll(ptMouse))
{
CTreeCtrl::OnTimer(nIDEvent);
return;
}
if (!m_bDragging)
m_OleDropTarget.EraseOldImage();
// Refine the scrolling mode -
// Scroll Up/Down, Slow/Normal
int nScrollMode = RefineScrollMode(ptMouse);
switch(nScrollMode)
{
case SCROLL_UP_SLOW:
case SCROLL_DOWN_SLOW:
if( m_nSlowScrollTimeout == 0)
SendMessage( WM_VSCROLL,
nScrollMode == SCROLL_UP_SLOW ? SB_LINEUP : SB_LINEDOWN);
m_nSlowScrollTimeout = ++m_nSlowScrollTimeout%SLOWSCROLL_FREQUENCY;
break;
case SCROLL_UP_NORMAL:
case SCROLL_DOWN_NORMAL:
SendMessage( WM_VSCROLL,
nScrollMode == SCROLL_UP_NORMAL ? SB_LINEUP : SB_LINEDOWN);
break;
default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -