home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / ScrollCanvas.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  5.8 KB  |  255 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : scrollcanvas.cpp                                                     //
  10. //  Description: Scrolling window                                                    //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <assert.h>
  19. #include <tchar.h>
  20.  
  21. #include "win.h"
  22. #include "Canvas.h"
  23. #include "ScrollCanvas.h"
  24.  
  25.  
  26. // nBar should be eiter SB_HORZ or SB_VERT
  27. void KScrollCanvas::OnScroll(int nBar, int nScrollCode, int nPos)
  28. {
  29.     SCROLLINFO si;
  30.     
  31.     si.cbSize = sizeof(SCROLLINFO);
  32.     si.fMask  = SIF_PAGE;
  33.  
  34.     GetScrollInfo(m_hWnd, nBar, &si);
  35.     
  36.     int nPageSize = si.nPage;
  37.     int nDis;
  38.  
  39.     switch (nScrollCode)
  40.     {
  41.         case SB_LINEDOWN:             // One line right/down.
  42.             nDis = (nBar==SB_VERT) ? m_linedy : m_linedx;
  43.             break;
  44.  
  45.         case SB_LINEUP:               // One line left/up.
  46.             nDis = (nBar==SB_VERT) ? -m_linedy : - m_linedx;
  47.             break;
  48.  
  49.         case SB_PAGEDOWN:             // One page right/down.
  50.             nDis = nPageSize;
  51.             break;
  52.  
  53.         case SB_PAGEUP:               // One page left/up.
  54.             nDis = - nPageSize;
  55.             break;
  56.  
  57.         case SB_THUMBPOSITION:        // Absolute position.
  58.             nDis = nPos - GetScrollPos(m_hWnd, nBar);
  59.             break;
  60.  
  61.         default:                      // No change.
  62.             nDis = 0;
  63.             break;
  64.     }
  65.  
  66.     if (nDis)
  67.     {
  68.         int nMin, nMax;
  69.  
  70.         GetScrollRange(m_hWnd, nBar, &nMin, &nMax);
  71.  
  72.         nPos = GetScrollPos(m_hWnd, nBar) + nDis;
  73.         nPos = max(nMin, nPos);
  74.         nPos = min(nMax-nPageSize, nPos);
  75.  
  76.         nDis = nPos - GetScrollPos(m_hWnd, nBar);
  77.  
  78.         if ( nDis )
  79.         {
  80.             SetScrollPos(m_hWnd, nBar, nPos, TRUE);
  81.  
  82.             if (nBar == SB_HORZ)
  83.                 ScrollWindow(m_hWnd, - nDis, 0, NULL, NULL);
  84.             else
  85.                 ScrollWindow(m_hWnd, 0, - nDis, NULL, NULL);
  86.  
  87.         //    ::UpdateWindow(m_hWnd);
  88.         }
  89.     }
  90. }
  91.  
  92.  
  93. void KScrollCanvas::SetScrollBar(int side, int maxsize, int pagesize)
  94. {
  95.     if ( pagesize < maxsize )
  96.     {
  97.         SCROLLINFO si;
  98.  
  99.         si.cbSize = sizeof(SCROLLINFO);
  100.         si.fMask  = SIF_RANGE | SIF_PAGE;
  101.         si.nMin   = 0;
  102.         si.nMax   = maxsize - 1;
  103.         si.nPage  = pagesize;
  104.         si.nPos   = 0;
  105.  
  106.         ::EnableScrollBar(m_hWnd, side, ESB_ENABLE_BOTH);
  107.         ::SetScrollInfo(m_hWnd, side, &si, TRUE);
  108.     }
  109.     else
  110.     {
  111.         SetScrollPos(m_hWnd, side, 0, FALSE);
  112.         ::EnableScrollBar(m_hWnd, side, ESB_DISABLE_BOTH);
  113.     }
  114. }
  115.  
  116.  
  117. int GCD(int x, int y)
  118. {
  119.     while ( x!=y )
  120.         if ( x>y ) x-=y; else y-=x;
  121.  
  122.     return x;
  123. }
  124.  
  125.  
  126. void KScrollCanvas::OnZoom(int x, int y, int mul, int div)
  127. {
  128.     m_zoommul *= mul;
  129.     m_zoomdiv *= div;
  130.  
  131.     int factor = GCD(m_zoommul, m_zoomdiv);
  132.  
  133.     m_zoommul /= factor;
  134.     m_zoomdiv /= factor;
  135.  
  136.     // add scrollbar offset
  137.     x = ( x + GetScrollPos(m_hWnd, SB_HORZ) ) * mul / div;
  138.     y = ( y + GetScrollPos(m_hWnd, SB_VERT) ) * mul / div;
  139.  
  140.     // update canvas
  141.     m_width  = m_width  * mul / div;
  142.     m_height = m_height * mul / div;
  143.  
  144.     RECT rect;
  145.  
  146.     GetClientRect(m_hWnd, & rect);
  147.  
  148.     // reset scrollbars
  149.     SetScrollBar(SB_HORZ, m_width,  rect.right);
  150.     SetScrollBar(SB_VERT, m_height, rect.bottom);
  151.  
  152.     // x in center the center of window if needed
  153.     x -= rect.right/2;
  154.     if ( x<0 ) 
  155.         x = 0;
  156.     if ( x > m_width - rect.right ) 
  157.         x = m_width - rect.right;
  158.  
  159.     SetScrollPos(m_hWnd, SB_HORZ, x, FALSE);
  160.     
  161.     y -= rect.bottom/2;
  162.     if ( y<0) y = 0;
  163.     if ( y > m_height - rect.bottom ) 
  164.         y = m_height - rect.bottom;
  165.  
  166.     SetScrollPos(m_hWnd, SB_VERT, y, FALSE);
  167.  
  168.     // repaint            
  169.     InvalidateRect(m_hWnd, NULL, TRUE);
  170.     ::UpdateWindow(m_hWnd);
  171. }
  172.  
  173.  
  174. void KScrollCanvas::SetSize(int width, int height, int linedx, int linedy, bool resize)
  175. {
  176.     m_width  = width;
  177.     m_height = height;
  178.     m_linedx = linedx;
  179.     m_linedy = linedy;
  180.  
  181.     if ( resize )
  182.     {
  183.         RECT rect;
  184.  
  185.         GetClientRect(m_hWnd, & rect);
  186.  
  187.         SetScrollBar(SB_HORZ, m_width,  rect.right);
  188.         SetScrollBar(SB_VERT, m_height, rect.bottom);
  189.     }
  190. }
  191.  
  192.  
  193. LRESULT KScrollCanvas::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  194. {
  195.     switch( uMsg )
  196.     {
  197.         case WM_CREATE:
  198.             m_hWnd = hWnd;
  199.             OnCreate();
  200.             return 0;
  201.  
  202.         case WM_SIZE:
  203.             SetScrollBar(SB_HORZ, m_width,  LOWORD(lParam));
  204.             SetScrollBar(SB_VERT, m_height, HIWORD(lParam));
  205.             return 0;
  206.  
  207.         case WM_PAINT:
  208.             {
  209.                 PAINTSTRUCT ps; 
  210.  
  211.                 HDC hDC = BeginPaint(m_hWnd, &ps);
  212.  
  213.                 SetWindowOrgEx(hDC, 0, 0, NULL);
  214.                 SetViewportOrgEx(hDC, - GetScrollPos(hWnd, SB_HORZ), 
  215.                                       - GetScrollPos(hWnd, SB_VERT), NULL);
  216.  
  217.                 OnDraw(hDC, & ps.rcPaint);
  218.  
  219.                 EndPaint(m_hWnd, &ps);
  220.             }
  221.             return 0;
  222.  
  223.         case WM_RBUTTONDOWN:
  224.             OnZoom( LOWORD(lParam), HIWORD(lParam), 1, 2);
  225.             return 0;
  226.  
  227.         case WM_LBUTTONDOWN:
  228.             OnZoom( LOWORD(lParam), HIWORD(lParam), 2, 1);
  229.             return 0;
  230.  
  231.         case WM_HSCROLL:
  232.             OnScroll(SB_HORZ, LOWORD(wParam), HIWORD(wParam));
  233.             return 0;
  234.  
  235.         case WM_VSCROLL:
  236.             OnScroll(SB_VERT, LOWORD(wParam), HIWORD(wParam));
  237.             return 0;
  238.  
  239.         case WM_TIMER:
  240.             OnTimer(wParam, lParam);
  241.             return 0;
  242.  
  243.         case WM_MOUSEMOVE:
  244.             OnMouseMove(wParam, lParam);
  245.             return 0;
  246.         
  247.         case WM_DESTROY:
  248.             OnDestroy();
  249.             return 0;
  250.  
  251.         default:
  252.             return KCanvas::WndProc(hWnd, uMsg, wParam, lParam);
  253.     }
  254. }
  255.