home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_06 / CoordinateSpace / CoordinateSpace.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-20  |  13.9 KB  |  582 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   : coordinatespace.cpp                                                 //
  10. //  Description: Coordinate space demo program, Chapter 6                            //
  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. #include <math.h>
  21.  
  22. #include "..\..\include\Affine.h"
  23. #include "..\..\include\win.h"
  24. #include "..\..\include\Canvas.h"
  25. #include "..\..\include\FrameWnd.h"
  26. #include "..\..\include\Status.h"
  27.  
  28. #include "resource.h"
  29.  
  30.  
  31. class KFixedString
  32. {
  33.     int      m_len;
  34.  
  35. public:
  36.  
  37.     TCHAR m_buffer[MAX_PATH];
  38.  
  39.     KFixedString(void)
  40.     {
  41.         m_buffer[0] = 0;
  42.         m_len       = 0;
  43.     }
  44.  
  45.     void Add(TCHAR ch)
  46.     {
  47.         m_buffer[m_len++] = ch;
  48.         m_buffer[m_len  ] = 0;
  49.     }
  50.  
  51.     void Add(PCTSTR pStr)
  52.     {
  53.         _tcscat(m_buffer + m_len, pStr);
  54.  
  55.         m_len += _tcslen(pStr);
  56.     }
  57.  
  58.     void Add(int i)
  59.     {
  60.         wsprintf(m_buffer + m_len, "%d ", i);
  61.         m_len = _tcslen(m_buffer);
  62.     }
  63.  
  64.     void Add(int x, int y)
  65.     {
  66.         wsprintf(m_buffer + m_len, "(%d, %d)", x, y);
  67.  
  68.         m_len = _tcslen(m_buffer);
  69.     }
  70. };
  71.  
  72.  
  73. void DumpMapMode(HDC hDC)
  74. {
  75.     POINT p;
  76.     SIZE  s;
  77.     KFixedString str;
  78.  
  79.     str.Add( GetMapMode(hDC) );
  80.  
  81.     str.Add( GetDeviceCaps(hDC, HORZSIZE) );
  82.     str.Add( GetDeviceCaps(hDC, VERTSIZE) );
  83.     
  84.     str.Add( GetDeviceCaps(hDC, HORZRES) );
  85.     str.Add( GetDeviceCaps(hDC, VERTRES) );
  86.     str.Add( GetDeviceCaps(hDC, LOGPIXELSX) );
  87.     str.Add( GetDeviceCaps(hDC, LOGPIXELSY) );
  88.  
  89.     GetWindowOrgEx(hDC, & p); str.Add(p.x, p.y);
  90.     GetWindowExtEx(hDC, & s); str.Add(s.cx, s.cy);
  91.  
  92.     GetViewportOrgEx(hDC, & p); str.Add(p.x, p.y);
  93.     GetViewportExtEx(hDC, & s); str.Add(s.cx, s.cy);
  94.  
  95.     MessageBox(NULL, str.m_buffer, "Map mode", MB_OK);
  96. }
  97.  
  98.  
  99. void SetEnglish(HDC hDC)
  100. {
  101.     SetWindowOrgEx(hDC, 5, 5, NULL);
  102.     SetViewportOrgEx(hDC, 10, 10, NULL);
  103.  
  104.     SetMapMode(hDC, MM_TEXT);
  105.     DumpMapMode(hDC);
  106.     
  107.     SetMapMode(hDC, MM_ISOTROPIC);
  108.     DumpMapMode(hDC);
  109.     
  110.     SetWindowExtEx(hDC, 3, 5, NULL);
  111.  
  112.     DumpMapMode(hDC);
  113.  
  114.     SetViewportExtEx(hDC, 5, 3, NULL);
  115.  
  116.     DumpMapMode(hDC);
  117.  
  118.     SetMapMode(hDC, MM_ANISOTROPIC);
  119.     BOOL rslt = SetViewportExtEx(hDC, 1, 1, NULL);
  120.     
  121.     DumpMapMode(hDC);
  122.  
  123.     rslt = SetViewportExtEx(hDC, 0, 0, NULL);
  124.     
  125.     DumpMapMode(hDC);
  126.  
  127. }
  128.  
  129.  
  130. // Demonstrate world transformation using dotted-lines
  131. void Transform_DottedLine(HDC hDC, int width, int height)
  132. {
  133.     KAffine af;
  134.  
  135.     SetMapMode(hDC, MM_ANISOTROPIC);
  136.     SetWindowExtEx  (hDC, 1, 1,                   NULL); // default
  137.     SetWindowOrgEx  (hDC, 0, 0,                   NULL);
  138.     
  139.     SetViewportExtEx(hDC, 1, -1,               NULL); // y axis goes up
  140.     SetViewportOrgEx(hDC, width/2, height*3/4, NULL); // 1/2, 3/4
  141.  
  142.     SetGraphicsMode(hDC, GM_ADVANCED);                  // using world coordinate space    
  143.  
  144.     for (int i=0; i<=72*5; i++)
  145.     {
  146.         SetWorldTransform(hDC, & af.m_xm);        // set transformation 
  147.  
  148.         for (int x=0; x<=200; x+=3)                // dotted line
  149.             SetPixel(hDC, x+50, 0, 0);
  150.  
  151.         af.Translate(5, 5);                        // translate
  152.  
  153.         af.Scale((FLOAT) 0.98, (FLOAT) 0.98);    // scale 0.98
  154.         af.Rotate(5);                            // rotate
  155.     }
  156. }
  157.  
  158.  
  159. // size x size square in logical coordinate space
  160. void Face(HDC hDC, COLORREF color, int size)
  161. {
  162.     for (int x=0; x<size; x++)
  163.     for (int y=0; y<size; y++)
  164.         SetPixel(hDC, x, y, color);
  165. }
  166.  
  167.  
  168. // use three transformations to map square in logical coordinate space to faces of a 3D cube
  169. void Draw_Cube(HDC hDC, int width, int height, int degree)
  170. {
  171.     KAffine af;
  172.  
  173.     SetMapMode(hDC, MM_ANISOTROPIC);
  174.     SetWindowExtEx  (hDC, 1, 1,                   NULL); // default
  175.     SetWindowOrgEx  (hDC, 0, 0,                   NULL);
  176.     
  177.     SetViewportExtEx(hDC, 1, -1,               NULL); // y axis goes up
  178.     SetViewportOrgEx(hDC, width/2, height*3/4, NULL); // 1/2, 3/4
  179.  
  180.     SetGraphicsMode(hDC, GM_ADVANCED);
  181.  
  182.     const float pi   = (float) 3.1415926;
  183.     const int   size = 150;
  184.     const float dx   = (float) (size * cos(pi*degree/180));
  185.     const float dy   = (float) (size * sin(pi*degree/180));
  186.     
  187.     af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, 0, dx, dy, 0, (float)size);
  188.     SetWorldTransform(hDC, & af.m_xm);
  189.  
  190.     Face(hDC, RGB(0xFF, 0, 0), size);
  191.  
  192.     af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, 0, -dx, dy, 0, (float)size);
  193.     SetWorldTransform(hDC, & af.m_xm);
  194.     Face(hDC, RGB(0, 0xFF, 0), size);
  195.  
  196.     af.MapTri(0, 0, (float)size, 0, 0, (float)size,   0, (float)size, dx, size + dy, -dx, size + dy);
  197.     SetWorldTransform(hDC, & af.m_xm);
  198.     Face(hDC, RGB(0, 0, 0xFF), size);
  199. }    
  200.  
  201.  
  202.  
  203. class KRotate
  204. {
  205.     int m_x0, m_y0, m_dx, m_dy;
  206.  
  207. public:
  208.  
  209.     int m_ds;
  210.     
  211.     KRotate(int x0, int y0, int x1, int y1)
  212.     {
  213.         m_x0 = x0;
  214.         m_y0 = y0;
  215.         m_dx = x1 - x0;
  216.         m_dy = y1 - y0;
  217.         m_ds = (int) sqrt( m_dx * m_dx + m_dy * m_dy);
  218.     }
  219.  
  220.     int RotateX(int x, int y)
  221.     {
  222.         return x * m_dx / m_ds - y * m_dy / m_ds;
  223.     }
  224.  
  225.     int RotateY(int x, int y)
  226.     {
  227.         return x * m_dy / m_ds + y * m_dx / m_ds;
  228.     }
  229. };
  230.  
  231.  
  232. // Draw a line with an arrow    
  233. void Arrow(HDC hDC, int x0, int y0, int x1, int y1, int width, int height)
  234. {
  235.     MoveToEx(hDC, x0, y0, NULL);
  236.     LineTo(hDC, x1, y1);
  237.  
  238.     KRotate rotate(x0, y0, x1, y1);
  239.  
  240.     POINT arrow[4] = 
  241.     { 
  242.         x1, y1, 
  243.         
  244.         rotate.RotateX(rotate.m_ds-width,  height) + x0, 
  245.         rotate.RotateY(rotate.m_ds-width,  height) + y0,
  246.         
  247.         rotate.RotateX(rotate.m_ds-width, -height) + x0, 
  248.         rotate.RotateY(rotate.m_ds-width, -height) + y0,
  249.         
  250.         x1, y1
  251.     };
  252.  
  253.     HGDIOBJ hOld = SelectObject(hDC, GetStockObject(BLACK_BRUSH));
  254.     Polygon(hDC, arrow, 4);
  255.     SelectObject(hDC, hOld);
  256. }
  257.  
  258.  
  259. // Convert size in points to device coordinate
  260. void PointToDevice(HDC hDC, SIZE & size)
  261. {
  262.     int dpix = GetDeviceCaps(hDC, LOGPIXELSX);
  263.     int dpiy = GetDeviceCaps(hDC, LOGPIXELSY);
  264.  
  265.     size.cx = size.cx * dpix / 72;
  266.     size.cy = size.cy * dpiy / 72;
  267. }
  268.  
  269.  
  270. // Convert size in device coordinate to logical coordinate
  271. void DeviceToLogical(HDC hDC, SIZE & size)
  272. {
  273.     POINT p[2] = { 0, 0, size.cx, size.cy };
  274.  
  275.     DPtoLP(hDC, p, 2);
  276.  
  277.     size.cx = abs(p[1].x - p[0].x);
  278.     size.cy = abs(p[1].y - p[0].y);
  279. }
  280.  
  281.  
  282. // Generic algorithm for axes display: width height in device coordinate
  283. void ShowAxes(HDC hDC, int width, int height)
  284. {
  285.     POINT corner[2];
  286.  
  287.     // display axes for the area [10, 10, width-10, height-10]
  288.     corner[0].x = 10;
  289.     corner[0].y = 10;
  290.     corner[1].x = width - 10;
  291.     corner[1].y = height - 10;
  292.  
  293.     // covert to logical coordinate
  294.     DPtoLP(hDC, corner, 2);
  295.  
  296.     // we need to display a 10x2 point arrow, convert to device coordinate, then to logical
  297.     SIZE s = { 10, 2 };
  298.     PointToDevice(hDC, s);
  299.     DeviceToLogical(hDC, s);
  300.  
  301.     // X-axis
  302.     Arrow(hDC, min(corner[0].x, corner[1].x), 0, 
  303.                max(corner[0].x, corner[1].x), 0, s.cx, s.cy);
  304.  
  305.     // Y-axis
  306.     Arrow(hDC, 0, min(corner[0].y, corner[1].y), 
  307.                0, max(corner[0].y, corner[1].y), s.cx, s.cy);
  308. }
  309.  
  310.  
  311. // Decode world transformation and mapping mode
  312. void DecodeTransform(HDC hDC)
  313. {
  314.     POINT windoworg;   GetWindowOrgEx(hDC, & windoworg);
  315.     SIZE  windowext;   GetWindowExtEx(hDC, & windowext);
  316.  
  317.     POINT viewportorg; GetViewportOrgEx(hDC, & viewportorg);
  318.     SIZE  viewportext; GetViewportExtEx(hDC, & viewportext);
  319.  
  320.     TCHAR formulax[128];
  321.     TCHAR formulay[128];
  322.  
  323.     wsprintf(formulax, "x' = (x-%d) %d / %d + %d", windoworg.x, viewportext.cx, windowext.cx, viewportorg.x);
  324.     wsprintf(formulay, "y' = (y-%d) %d / %d + %d", windoworg.y, viewportext.cy, windowext.cy, viewportorg.y);
  325.  
  326.     POINT p[2] = { 10, 10, 10, 35 };
  327.     DPtoLP(hDC, p, 2);
  328.  
  329.     TextOut(hDC, p[0].x, p[0].y, formulax, _tcslen(formulax));
  330.     TextOut(hDC, p[1].x, p[1].y, formulay, _tcslen(formulay));
  331. }
  332.  
  333.  
  334. // a scene (screen, page) with drawing and message handling
  335. class KScene
  336. {
  337. public:
  338.     virtual  ~KScene()
  339.     {
  340.     }
  341.  
  342.     virtual void          OnDraw(HDC hDC)                         = 0;
  343.     virtual void          OnMouseMove(int x, int y, TCHAR mess[]) = 0;
  344.     virtual const TCHAR * GetTitle(void)                          = 0;
  345. };
  346.  
  347.  
  348. // Mapping mode demostration
  349. class KMapMode : public KScene
  350. {
  351.     HWND m_hWnd;
  352.     int  m_width;
  353.     int  m_height;
  354.     int  m_mapmode;
  355.     int  m_dpix;
  356.     int  m_dpiy;
  357.  
  358.     // setup a mapping mode with origin in the center
  359.     void Setup(HDC hDC)
  360.     {
  361.         RECT rect;
  362.  
  363.         GetClientRect(m_hWnd, & rect);
  364.         m_width  = rect.right;
  365.         m_height = rect.bottom;
  366.  
  367.         SetMapMode(hDC, m_mapmode);
  368.  
  369.         if ( m_dpix )
  370.         {
  371.             SetViewportExtEx(hDC, GetDeviceCaps(hDC, LOGPIXELSX), GetDeviceCaps(hDC, LOGPIXELSY), NULL);
  372.               SetWindowExtEx(hDC, m_dpix,                         m_dpiy,                          NULL);
  373.         }
  374.  
  375.         SetWindowOrgEx(hDC,   0,         0,          NULL);
  376.         SetViewportOrgEx(hDC, m_width/2, m_height/2, NULL);
  377.     }
  378.  
  379.     // draw axes
  380.     void OnDraw(HDC hDC)
  381.     {
  382.         Setup(hDC);
  383.         
  384.         ShowAxes(hDC, m_width, m_height);
  385.         DecodeTransform(hDC);
  386.  
  387.         SelectObject(hDC, GetStockObject(NULL_BRUSH));
  388.         Ellipse(hDC, -100, -100, 100, 100);
  389.     }
  390.  
  391.     // display device coordinate and logical coordinate
  392.     void OnMouseMove(int x, int y, TCHAR mess[])
  393.     {
  394.         POINT p = { x, y };
  395.  
  396.         wsprintf(mess, _T("Client: %d x %d"), p.x, p.y);
  397.  
  398.         HDC hDC = GetDC(m_hWnd);
  399.  
  400.         Setup(hDC);
  401.         DPtoLP(hDC, & p, 1);
  402.         wsprintf(mess + _tcslen(mess), ", Logical: %d x %d", p.x, p.y);
  403.  
  404.         ReleaseDC(m_hWnd, hDC);
  405.     }
  406.  
  407. public:
  408.     KMapMode(HWND hWnd, int mapmode, int dpix=0, int dpiy=0)
  409.     {
  410.         m_hWnd    = hWnd;
  411.         m_mapmode = mapmode;
  412.         m_dpix    = dpix;
  413.         m_dpiy    = dpiy;
  414.     }
  415.  
  416.     const TCHAR * GetTitle(void)
  417.     {
  418.         switch ( m_mapmode )
  419.         {
  420.             case MM_TEXT       : return _T("MappingMode: MM_TEXT");
  421.             case MM_LOENGLISH  : return _T("MappingMode: MM_LOENGLISH");
  422.             case MM_HIENGLISH  : return _T("MappingMode: MM_HIENGLISH");
  423.             case MM_LOMETRIC   : return _T("MappingMode: MM_LOMETRIC");
  424.             case MM_HIMETRIC   : return _T("MappingMode: MM_HIMETRIC");
  425.             case MM_TWIPS      : return _T("MappingMode: MM_TWIPS");
  426.             case MM_ISOTROPIC  : return _T("MappingMode: MM_ISOTROPIC");
  427.             case MM_ANISOTROPIC: return _T("MappingMode: MM_ANISOTROPIC");
  428.         }
  429.  
  430.         return NULL;
  431.     }
  432.  
  433. };
  434.  
  435.  
  436.  
  437. class KMyCanvas : public KCanvas
  438. {
  439.     int      mode;
  440.     KScene * scene;
  441.  
  442.     void GetWndClassEx(WNDCLASSEX & wc)
  443.     {
  444.         memset(& wc, 0, sizeof(wc));
  445.  
  446.         wc.cbSize        = sizeof(WNDCLASSEX);
  447.         wc.style         = CS_HREDRAW | CS_VREDRAW;  // repaint when resize
  448.         wc.lpfnWndProc   = WindowProc;
  449.         wc.cbClsExtra    = 0;
  450.         wc.cbWndExtra    = 0;       
  451.         wc.hInstance     = NULL;
  452.         wc.hIcon         = NULL;
  453.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  454.         wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  455.         wc.lpszMenuName  = NULL;
  456.         wc.lpszClassName = NULL;
  457.         wc.hIconSm       = NULL;
  458.     }
  459.  
  460. public:
  461.     KMyCanvas()
  462.     {
  463.         mode  = 0;
  464.         scene = NULL;
  465.     }
  466.  
  467.     virtual void OnDraw(HDC hDC, const RECT * rcPaint)
  468.     {
  469.         if ( scene )
  470.             scene->OnDraw(hDC);
  471.         else
  472.         {
  473.             RECT rect;
  474.  
  475.             GetClientRect(m_hWnd, & rect);
  476.     
  477.             switch (mode )
  478.             {
  479.                 case IDM_VIEW_DOTLINE:
  480.                     Transform_DottedLine(hDC, rect.right, rect.bottom);
  481.                     break;
  482.  
  483.                 case IDM_VIEW_CUBE30:
  484.                     Draw_Cube(hDC, rect.right, rect.bottom, 30);
  485.                     break;
  486.  
  487.                 case IDM_VIEW_CUBE45:
  488.                     Draw_Cube(hDC, rect.right, rect.bottom, 45);
  489.                     break;
  490.             }
  491.         }
  492.     }
  493.  
  494.     virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
  495.     {
  496.         if ( mode != LOWORD(wParam) )
  497.         {
  498.             mode = LOWORD(wParam);
  499.         
  500.             if ( scene )
  501.             {
  502.                 delete scene;
  503.                 scene = NULL;
  504.             }
  505.  
  506.             switch ( mode )
  507.             {
  508.                 case IDM_VIEW_MMTEXT     :   scene = new KMapMode(m_hWnd, MM_TEXT);        break;
  509.                 case IDM_VIEW_MMLOENGLISH:   scene = new KMapMode(m_hWnd, MM_LOENGLISH);   break;
  510.                 case IDM_VIEW_MMHIENGLISH:   scene = new KMapMode(m_hWnd, MM_HIENGLISH);   break;
  511.                 case IDM_VIEW_MMLOMETRIC:    scene = new KMapMode(m_hWnd, MM_LOMETRIC);    break;
  512.                 case IDM_VIEW_MMHIMETRIC:    scene = new KMapMode(m_hWnd, MM_HIMETRIC);    break;
  513.                 case IDM_VIEW_MMTWIPS:         scene = new KMapMode(m_hWnd, MM_TWIPS);       break;
  514.                 case IDM_VIEW_MMISOTROPIC:   scene = new KMapMode(m_hWnd, MM_ISOTROPIC, 300, 300);   break;
  515.                 case IDM_VIEW_MMANISOTROPIC: scene = new KMapMode(m_hWnd, MM_ANISOTROPIC, 600, 300); break;
  516.             }
  517.  
  518.             if ( scene )
  519.                 m_pStatus->SetText(0, scene->GetTitle());
  520.             
  521.             InvalidateRect(m_hWnd, NULL, TRUE);
  522.         }
  523.         
  524.         return TRUE;
  525.     }
  526.  
  527.     LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  528.     {
  529.         if ( uMsg==WM_MOUSEMOVE )
  530.         {
  531.             TCHAR temp[64];
  532.  
  533.             temp[0] = 0;
  534.             if ( scene )
  535.                 scene->OnMouseMove(LOWORD(lParam), HIWORD(lParam), temp);
  536.  
  537.             if ( temp[0] )
  538.                 m_pStatus->SetText(1, temp);
  539.  
  540.             return 0;
  541.         }
  542.         else
  543.             return KCanvas::WndProc(hWnd, uMsg, wParam, lParam);
  544.     }
  545. };
  546.  
  547. class KMyFrame : public KFrame
  548. {
  549.     void GetWndClassEx(WNDCLASSEX & wc)
  550.     {
  551.         KFrame::GetWndClassEx(wc);
  552.         wc.hIcon  = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH));
  553.     }
  554.  
  555. public:
  556.     KMyFrame(HINSTANCE hInstance, const TBBUTTON * pButtons, int nCount,
  557.             KToolbar * pToolbar, KCanvas * pCanvas, KStatusWindow * pStatus) :
  558.         KFrame(hInstance, pButtons, nCount, pToolbar, pCanvas, pStatus)
  559.     {
  560.     }
  561.  
  562. };
  563.  
  564.  
  565. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow)
  566. {
  567.     KMyCanvas        canvas;
  568.     KStatusWindow   status;
  569.  
  570.     KMyFrame        frame(hInst, NULL, 0, NULL, & canvas, & status);
  571.     
  572.     frame.CreateEx(0, _T("CoorinateSpace"), _T("Coordinate Space"),
  573.         WS_OVERLAPPEDWINDOW,
  574.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
  575.         NULL, LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), hInst);
  576.  
  577.     frame.ShowWindow(nShow);
  578.     frame.UpdateWindow();
  579.     frame.MessageLoop();
  580.  
  581.     return 0;
  582. }