autoscrl.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 6k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //===========================================================================
  2. // Image dragging API (definitely private)
  3. //===========================================================================
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include "autoscrl.h"
  7. #include "common.h"
  8. #include "debug.h"
  9. #if 0
  10. BOOL DAD_SetDragImage(HIMAGELIST him, POINT FAR* pptOffset);
  11. BOOL DAD_DragEnter(HWND hwndTarget);
  12. BOOL DAD_DragEnterEx(HWND hwndTarget, const POINT ptStart);
  13. BOOL DAD_ShowDragImage(BOOL fShow);
  14. BOOL DAD_DragMove(POINT pt);
  15. BOOL DAD_DragLeave(void);
  16. BOOL DAD_SetDragImageFromListView(HWND hwndLV, POINT ptOffset);
  17. #endif
  18. // -------------- auto scroll stuff --------------
  19. BOOL _AddTimeSample(AUTO_SCROLL_DATA *pad, const POINT *ppt, DWORD dwTime)
  20. {
  21.     pad->pts[pad->iNextSample] = *ppt;
  22.     pad->dwTimes[pad->iNextSample] = dwTime;
  23.     pad->iNextSample++;
  24.     if (pad->iNextSample == ARRAYSIZE(pad->pts))
  25.         pad->bFull = TRUE;
  26.     pad->iNextSample = pad->iNextSample % ARRAYSIZE(pad->pts);
  27.     return pad->bFull;
  28. }
  29. #ifdef DEBUG
  30. // for debugging, verify we have good averages
  31. DWORD g_time = 0;
  32. int g_distance = 0;
  33. #endif
  34. int _CurrentVelocity(AUTO_SCROLL_DATA *pad)
  35. {
  36.     int i, iStart, iNext;
  37.     int dx, dy, distance;
  38.     DWORD time;
  39.     Assert(pad->bFull);
  40.     distance = 0;
  41.     time = 1; // avoid div by zero
  42.     i = iStart = pad->iNextSample % ARRAYSIZE(pad->pts);
  43.     do {
  44. iNext = (i + 1) % ARRAYSIZE(pad->pts);
  45. dx = abs(pad->pts[i].x - pad->pts[iNext].x);
  46. dy = abs(pad->pts[i].y - pad->pts[iNext].y);
  47. distance += (dx + dy);
  48. time += abs(pad->dwTimes[i] - pad->dwTimes[iNext]);
  49. i = iNext;
  50.     } while (i != iStart);
  51. #ifdef DEBUG
  52.     g_time = time;
  53.     g_distance = distance;
  54. #endif
  55.     // scale this so we don't loose accuracy
  56.     return (distance * 1024) / time;
  57. }
  58. // NOTE: this is duplicated in shell32.dll
  59. //
  60. // checks to see if we are at the end position of a scroll bar
  61. // to avoid scrolling when not needed (avoid flashing)
  62. //
  63. // in:
  64. //      code        SB_VERT or SB_HORZ
  65. //      bDown       FALSE is up or left
  66. //                  TRUE  is down or right
  67. BOOL CanScroll(HWND hwnd, int code, BOOL bDown)
  68. {
  69.     SCROLLINFO si;
  70.     si.cbSize = sizeof(SCROLLINFO);
  71.     si.fMask = SIF_ALL;
  72.     GetScrollInfo(hwnd, code, &si);
  73.     if (bDown)
  74.     {
  75.      if (si.nPage)
  76.          si.nMax -= si.nPage - 1;
  77.      return si.nPos < si.nMax;
  78.     }
  79.     else
  80.     {
  81.      return si.nPos > si.nMin;
  82.     }
  83. }
  84. #define DSD_NONE 0x0000
  85. #define DSD_UP 0x0001
  86. #define DSD_DOWN 0x0002
  87. #define DSD_LEFT 0x0004
  88. #define DSD_RIGHT 0x0008
  89. //---------------------------------------------------------------------------
  90. DWORD DAD_DragScrollDirection(HWND hwnd, const POINT *ppt)
  91. {
  92.     RECT rcOuter, rc;
  93.     DWORD dwDSD = DSD_NONE; // 0
  94.     DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  95.     // BUGBUG: do these as globals
  96. #define g_cxVScroll GetSystemMetrics(SM_CXVSCROLL)
  97. #define g_cyHScroll GetSystemMetrics(SM_CYHSCROLL)
  98. #define g_cxSmIcon  GetSystemMetrics(SM_CXSMICON)
  99. #define g_cySmIcon  GetSystemMetrics(SM_CYSMICON)
  100. #define g_cxIcon    GetSystemMetrics(SM_CXICON)
  101. #define g_cyIcon    GetSystemMetrics(SM_CXICON)
  102.     GetClientRect(hwnd, &rc);
  103.     if (dwStyle & WS_HSCROLL)
  104. rc.bottom -= g_cyHScroll;
  105.     if (dwStyle & WS_VSCROLL)
  106. rc.right -= g_cxVScroll;
  107.     // the explorer forwards us drag/drop things outside of our client area
  108.     // so we need to explictly test for that before we do things
  109.     //
  110.     rcOuter = rc;
  111.     InflateRect(&rcOuter, g_cxSmIcon, g_cySmIcon);
  112.     InflateRect(&rc, -g_cxIcon, -g_cyIcon);
  113.     if (!PtInRect(&rc, *ppt) && PtInRect(&rcOuter, *ppt))
  114.     {
  115.      // Yep - can we scroll?
  116.      if (dwStyle & WS_HSCROLL)
  117.      {
  118.          if (ppt->x < rc.left)
  119.          {
  120.           if (CanScroll(hwnd, SB_HORZ, FALSE))
  121.               dwDSD |= DSD_LEFT;
  122.          }
  123.          else if (ppt->x > rc.right)
  124.          {
  125.           if (CanScroll(hwnd, SB_HORZ, TRUE))
  126.               dwDSD |= DSD_RIGHT;
  127.          }
  128.      }
  129.      if (dwStyle & WS_VSCROLL)
  130.      {
  131.          if (ppt->y < rc.top)
  132.          {
  133.           if (CanScroll(hwnd, SB_VERT, FALSE))
  134.               dwDSD |= DSD_UP;
  135.          }
  136.          else if (ppt->y > rc.bottom)
  137.          {
  138.           if (CanScroll(hwnd, SB_VERT, TRUE))
  139.               dwDSD |= DSD_DOWN;
  140.          }
  141.      }
  142.     }
  143.     return dwDSD;
  144. }
  145. #define SCROLL_FREQUENCY (GetDoubleClickTime()/4) // 1 line scroll every 1/4 second
  146. #define MIN_SCROLL_VELOCITY 20 // scaled mouse velocity
  147. #define DAD_ShowDragImage(f) // BUGBUG
  148. BOOL DAD_AutoScroll(HWND hwnd, AUTO_SCROLL_DATA *pad, const POINT *pptNow)
  149. {
  150.     // first time we've been called, init our state
  151.     int v;
  152.     DWORD dwTimeNow = GetTickCount();
  153.     DWORD dwDSD = DAD_DragScrollDirection(hwnd, pptNow);
  154.     if (!_AddTimeSample(pad, pptNow, dwTimeNow))
  155. return dwDSD;
  156.     v = _CurrentVelocity(pad);
  157.     if (v <= MIN_SCROLL_VELOCITY)
  158.     {
  159.         // Nope, do some scrolling.
  160.         if ((dwTimeNow - pad->dwLastScroll) < SCROLL_FREQUENCY)
  161.          dwDSD = 0;
  162. if (dwDSD & (DSD_UP | DSD_DOWN | DSD_LEFT | DSD_RIGHT))
  163.             DAD_ShowDragImage(FALSE);
  164.         if (dwDSD & DSD_UP)
  165.         {
  166.             FORWARD_WM_VSCROLL(hwnd, NULL, SB_LINEUP, 1, SendMessage);
  167.         }
  168.         else if (dwDSD & DSD_DOWN)
  169.         {
  170.             FORWARD_WM_VSCROLL(hwnd, NULL, SB_LINEDOWN, 1, SendMessage);
  171.         }
  172.         if (dwDSD & DSD_LEFT)
  173.         {
  174.             FORWARD_WM_HSCROLL(hwnd, NULL, SB_LINEUP, 1, SendMessage);
  175.         }
  176.         else if (dwDSD & DSD_RIGHT)
  177.         {
  178.             FORWARD_WM_HSCROLL(hwnd, NULL, SB_LINEDOWN, 1, SendMessage);
  179.         }
  180.         DAD_ShowDragImage(TRUE);
  181. if (dwDSD)
  182. {
  183.          DebugMsg(DM_TRACE, "v=%d", v);
  184.     pad->dwLastScroll = dwTimeNow;
  185. }
  186.     }
  187.     return dwDSD; // bits set if in scroll region
  188. }