Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » why you don't use ::DragDetect() api in D&D operations in customize mode? Collapse All
Subject Author Date
Phillip Bernard Feb 7, 2008 - 6:49 AM

In customize mode when you simply try to select any menu item or toolbar button accidental D&D operation can be performed.
It may looks as you just click on menu item and then it disapears.

This happens because you call pSite->DoDragCmdNode() in CExtToolControlBar::OnLButtonDown() and CExtPopupMenuWnd::OnLButtonDown() without checking if D&D operation is realy required.

But for this purpose exists winAPI function DragDetect(). It check if D&D begins by drag rectangle and drag time (the last is undocumented).

Because in Office 2003 D&D is checked only by drag rectangle i suggest following variant of DragDetect

bool MyDragDetect(CWnd *pWnd, CPoint point)
{
pWnd->ClientToScreen(&point);
while (::DragDetect(pWnd->GetSafeHwnd(), point))
{
CPoint pt;
::GetCursorPos(&pt);
if (pt == point) continue; //only drag time elapsed but mouse is not moved
return true;
}
return false;
}

e.g. using this func in ExtPopupMenuWnd.cpp
fragment of CExtPopupMenuWnd::OnLButtonDown()
....
WND hWndOwn = m_hWnd;
    _ItemFocusSet( nIndex, TRUE, TRUE, FALSE );
    if( ! ::IsWindow( hWndOwn ) )
        return;
ASSERT( hWndOwn != NULL && ::IsWindow(hWndOwn) );

if (!MyDragDetect(this, point))
{
     m_pDragSrcNode = NULL;
     m_bHelperNoHideChild = false;
     m_nDragSrcIdx = -1;
     m_bHelperNoRemoveSrc = false;
     m_bHelperDragOverPassed = false;
return;
}

    pSite->DoDragCmdNode(
        this,
        NULL,
        m_pDragSrcNode,
        rcItem
        );
....



Technical Support Feb 9, 2008 - 1:28 AM

We completely agree with you so we added the following static method to the CExtControlBar class and invoked it from CExtPopupMenuWnd::OnLButtonDown() exactly as you advise:

bool CExtControlBar::stat_DoDragDetect(
      HWND hWnd,
      const POINT & ptWndClient
      )
{
      if( hWnd == NULL || (! ::IsWindow( hWnd ) ) )
            return false;
CPoint ptScreen = ptWndClient;
      ::ClientToScreen( hWnd, &ptScreen );
      while( ::DragDetect( hWnd, ptScreen ) )
      {
            POINT ptCursorPos;
            if( ! ::GetCursorPos( ptScreen) )
                  return false;
            if(  ptScreen == ptCursorPos )
                  continue; //only drag time elapsed but mouse is not moved
            return true;
      }
      return false;
}
We have also invoked it from the CExtToolControlBar::OnLButtonDown() method:
      m_pDragSourceTBB = pTBB;
      m_pDragTargetTBB = NULL;
      m_nDragTargetShift = 0;
      m_bHelperSeparatorAction = false;
      _InvalidateButton( nBtnDragSrc );
      //UpdateWindow();
      if( CExtControlBar::stat_DoDragDetect( m_hWnd, point ) )
            pSite->DoDragCmdNode( this, pNodeI, pNodeC, rcItem );
      m_pDragSourceTBB = NULL;
      m_pDragTargetTBB = NULL;
      m_nDragTargetShift = 0;
      m_bHelperSeparatorAction = false;
      return;