Axaptapedia is now maintained by AgileCadence For more information please click here.

FormTreeControl AutoScrolling when draging over top and bottom

From Axaptapedia
Jump to: navigation, search

Been working with trees, looking for common behaviors but not implemented in standard AX FormTreeControl...I encountered the same situation, so I decided to add this behavior to the tree in my form:

What's this doing ?

When using a FormTreeControl that contains scrollbars (vertical scrollbars in this example), you might need to drag'n drop a tree node to another tree node that is currently hidden, and you'll need to scroll while drag'n dropping.

Basically, when the mouse comes close to the top or the bottom of the tree, you want to have your tree automatically scrolling to have the same behavior that you would find in Windows Explorer...

You need 2 different algorithms to do this:

  1. Scroll Up or Down algorithm,
  2. Timer Algorithm to enable moving even when the mouse is not moving (ie dragOver not called but still expecting the tree do scroll),

You can find attached to this page a simple XPO for this example.

First algorithm looks like the following <xpp>void doAutoScroll(int upDown) {

   #WinApi
   ;
   element.scrollWindow(tree.hWnd(), 0, (-#IconHeight) * upDown);
   winAPI::sendMessage(tree.hWnd(), #WM_VSCROLL,  upDown == -1 ? 0 : 1, );
   winApi::invalidateRect(tree.hWnd());

} </xpp>

You'll need the scrollWindow method. For this example, I put it into the form, but I believe that it's best place would be in the WinApi Class: <xpp>int scrollWindow( int hwnd,

                  int     XAmount,
                  int     YAmount)

{

   DLL         _winApiDLL     = new DLL('USER32');
   DLLFunction _scrollWindow  = new DLLFunction(_winApiDLL, 'ScrollWindow');
   _scrollWindow.returns(ExtTypes::DWord);
   _scrollWindow.arg(ExtTypes::DWord,
                      ExtTypes::DWord,
                      ExtTypes::DWord,
                      ExtTypes::DWord,
                      ExtTypes::DWord);
   return _scrollWindow.call(hwnd, XAmount, YAmount, 0,0);

}</xpp> Note that if you put this method in the WinApi class, you probably would specify that this method is static

Finally, you need to setup timeouts so that these methods are called accurately, matching the common behavior of GUI trees (see Download) To set the timers, use a method like this: <xpp>void AutoScroll(int x, int y) {

   #define.SBPosMin(1)
   #define.SBPosMax(2)
   #define.SBPosPageSize(3)
   #define.SBPosPosition(4)
   int scrollPos;
   #WinApi
   int height = tree.heightValue();
   container scrollInfo;
   ;
   this.endTimerScroll();
   scrollPos = WinApi::getScrollPos(tree.hWnd(), #SB_VERT);
   if (y < 2 * #IconHeight && scrollPos > 0)//bottom of first displayed line in tree
       timerScroll = this.setTimeOut(#TimerScrollUp, #TimerScrollTime, false);
   else if (y > height - (2 * #IconHeight))//top of last displayed line in tree
   {
       scrollInfo = winApi::getScrollInfo(tree.hWnd(), #SB_VERT);
       if (conPeek(scrollInfo, #SBPosMax) > conPeek(scrollInfo, #SBPosPageSize) + conPeek(scrollInfo, #SBPosPosition))//only if not at the bottom already
           timerScroll = this.setTimeOut(#TimerScrollDown, #TimerScrollTime, false);
   }

} void TimerScrollUp() {

   ;
   this.doAutoScroll(-1);
   timerScroll = this.setTimeOut(#TimerScrollUp, #TimerScrollTime, false);

} void TimerScrollDown() {

   ;
   this.doAutoScroll(1);
   timerScroll = this.setTimeOut(#TimerScrollDown, #TimerScrollTime, false);

} </xpp>

Constants[edit]

<xpp>

  1. define.TimerScrollUp("TimerScrollUp")
  2. define.TimerScrollDown("TimerScrollDown")
  3. define.TimerScrollTime(150)
  4. define.IconHeight(16)

</xpp>

Download[edit]

DEV_FormTreeControl_AutoScroll version 1.0 - [1] This version is compatible with Dynamics AX 2009, but it suppose it should work with previous versions as well