home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_07 / ClipRegion / ClipRegion.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-20  |  9.4 KB  |  403 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   : clipregion.cpp                                                         //
  10. //  Description: Clip/meta region demo program, Chapter 7                            //
  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 "..\..\include\win.h"
  22. #include "..\..\include\Canvas.h"
  23. #include "..\..\include\Status.h"
  24. #include "..\..\include\FrameWnd.h"
  25. #include "..\..\include\LogWindow.h"
  26.  
  27. #include "Resource.h"
  28.  
  29.  
  30. class KMyCanvas : public KCanvas
  31. {
  32.     virtual void    OnDraw(HDC hDC, const RECT * rcPaint);
  33.     virtual LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  34.  
  35.     int                m_nRepaint;    
  36.     
  37.     int                m_Red, m_Green, m_Blue;
  38.     HRGN            m_hRegion;
  39.     KLogWindow        m_Log;
  40.     DWORD            m_Redraw;
  41.     bool            m_bValid[5];
  42.     HRGN            m_hRandomRgn[5];
  43.     int                m_test;
  44.  
  45. public:
  46.  
  47.     BOOL OnCommand(WPARAM wParam, LPARAM lParam);
  48.  
  49.     void DumpRegions(HDC hDC);
  50.     void DrawRegions(HDC hDC);
  51.     void TestClipMeta(HDC hDC, const RECT & rect);
  52.  
  53.     KMyCanvas()
  54.     {
  55.         m_nRepaint = 0;
  56.         m_hRegion  = CreateRectRgn(0, 0, 1, 1);
  57.         
  58.         m_Red       = 0x4F;
  59.         m_Green    = 0x8F;
  60.         m_Blue     = 0xCF;
  61.         m_Redraw   = 0;
  62.         m_test     = IDM_TEST_DEFAULT;
  63.  
  64.         for (int i=1; i<=4; i++)
  65.         {
  66.             m_hRandomRgn[i] = CreateRectRgn(0, 0, 1, 1);
  67.             m_bValid[i]     = false;
  68.         }
  69.     }
  70. };
  71.  
  72.  
  73. #ifndef SYSRGN
  74.  
  75. #define SYSRGN 4
  76.  
  77. __declspec(dllimport) extern "C" BOOL WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, int which);
  78.  
  79. #endif
  80.  
  81. BOOL KMyCanvas::OnCommand(WPARAM wParam, LPARAM lParam)
  82. {
  83.     switch ( LOWORD(wParam) )
  84.     {
  85.         case IDM_VIEW_HREDRAW:
  86.         case IDM_VIEW_VREDRAW:
  87.             {
  88.                 HMENU hMenu = GetMenu(GetParent(m_hWnd));
  89.  
  90.                 MENUITEMINFO mii;
  91.                 
  92.                 memset(& mii, 0, sizeof(mii));
  93.                 mii.cbSize = sizeof(mii);
  94.                 mii.fMask  = MIIM_STATE;
  95.                 
  96.                 if ( GetMenuState(hMenu, LOWORD(wParam), MF_BYCOMMAND) & MF_CHECKED )
  97.                     mii.fState = MF_UNCHECKED;
  98.                 else
  99.                     mii.fState = MF_CHECKED;
  100.                 
  101.                 SetMenuItemInfo(hMenu, LOWORD(wParam), FALSE, & mii);
  102.                 
  103.                 if ( LOWORD(wParam)==IDM_VIEW_HREDRAW )
  104.                     m_Redraw ^= WVR_HREDRAW;
  105.                 else
  106.                     m_Redraw ^= WVR_VREDRAW;
  107.             }
  108.             return TRUE;
  109.  
  110.         case IDM_TEST_DEFAULT:
  111.         case IDM_TEST_SETCLIP:
  112.         case IDM_TEST_SETMETA:
  113.         case IDM_TEST_SETMETACLIP:
  114.             m_test = LOWORD(wParam);
  115.             InvalidateRect(m_hWnd, NULL, TRUE);
  116.             ::UpdateWindow(m_hWnd);
  117.             break;
  118.  
  119.         case IDM_FILE_EXIT:
  120.             DestroyWindow(GetParent(m_hWnd));
  121.             return TRUE;
  122.     }
  123.  
  124.     return FALSE;    // not processed
  125. }
  126.  
  127.  
  128. LRESULT KMyCanvas::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  129. {
  130.     LRESULT lr;
  131.  
  132.     switch( uMsg )
  133.     {
  134.         case WM_CREATE:
  135.             m_hWnd = hWnd;
  136.             m_Log.Create(m_hInst, _T("ClipRegion"), LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH)));
  137.             return 0;
  138.  
  139.         case WM_NCCALCSIZE:
  140.             lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
  141.  
  142.             if ( wParam )
  143.             {
  144.                 lr &= ~ (WVR_HREDRAW | WVR_VREDRAW);
  145.                 lr |= m_Redraw;
  146.             }
  147.             break;
  148.  
  149.         case WM_PAINT:
  150.             {
  151.                 PAINTSTRUCT ps; 
  152.  
  153.                 HDC hDC = BeginPaint(m_hWnd, &ps);
  154.  
  155.             //    HRGN hRgn1 = CreateRectRgn(0, 0, 100, 100);
  156.             //    HRGN hRgn2 = CreateRectRgn(50, 50, 300, 300);
  157.             //    int value = CombineRgn(hRgn1, hRgn1, NULL, RGN_AND);
  158.             //    DeleteObject(hRgn1);
  159.             //    DeleteObject(hRgn2);
  160.                 
  161.                 OnDraw(hDC, &ps.rcPaint);
  162.  
  163.                 EndPaint(m_hWnd, &ps);
  164.  
  165.                 hDC = GetDC(m_hWnd);
  166.                 
  167.                 DrawRegions(hDC);
  168.  
  169.                 ReleaseDC(m_hWnd, hDC);
  170.             }
  171.             return 0;
  172.  
  173.         default:
  174.             lr = DefWindowProc(hWnd, uMsg, wParam, lParam);
  175.     }
  176.  
  177.     return lr;
  178. }
  179.  
  180.  
  181. void KMyCanvas::DumpRegions(HDC hDC)
  182. {
  183.     for (int i=1; i<=4; i++)
  184.     {
  185.         m_bValid[i] = false;
  186.         int rslt = GetRandomRgn(hDC, m_hRandomRgn[i], i);
  187.  
  188.         switch ( rslt )
  189.         {
  190.             case 1:
  191.                 m_bValid[i] = true;
  192.                 m_Log.DumpRegion("RandomRgn(%d)", m_hRandomRgn[i], false, i);
  193.                 break;
  194.  
  195.             case -1:
  196.                 m_Log.Log("RandomRgn(%d) Error\r\n", i);
  197.                 break;
  198.  
  199.             case 0:
  200.                 m_Log.Log("RandomRgn(%d) no region\r\n", i);
  201.                 break;
  202.  
  203.             default:
  204.                 m_Log.Log("Unexpected\r\n");
  205.         }
  206.     }
  207. }
  208.  
  209.  
  210. void KMyCanvas::DrawRegions(HDC hDC)
  211. {
  212.     HBRUSH hBrush;
  213.  
  214.     SetBkMode(hDC, TRANSPARENT);
  215.  
  216.     if ( m_bValid[1] )
  217.     {
  218.         hBrush = CreateHatchBrush(HS_VERTICAL, RGB(0xFF, 0, 0));
  219.         FillRgn(hDC, m_hRandomRgn[1], hBrush);
  220.         DeleteObject(hBrush);
  221.     }
  222.  
  223.     if ( m_bValid[2] )
  224.     {
  225.         hBrush = CreateHatchBrush(HS_HORIZONTAL, RGB(0, 0xFF, 0));
  226.         FillRgn(hDC, m_hRandomRgn[2], hBrush);
  227.         DeleteObject(hBrush);
  228.     }
  229.  
  230. //    if ( m_bValid[3] )
  231. //    {
  232. //        hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 0xFF));
  233. //        FillRgn(hDC, m_hRandomRgn[3], hBrush);
  234. //        DeleteObject(hBrush);
  235. //    }
  236. }
  237.  
  238.  
  239. void KMyCanvas::OnDraw(HDC hDC, const RECT * rcPaint)
  240. {
  241.     RECT rect;
  242.     TCHAR mess[64];
  243.     
  244.     GetClientRect(m_hWnd, & rect);
  245.     
  246.     GetRandomRgn(hDC, m_hRegion, SYSRGN);
  247.  
  248.     POINT Origin;
  249.     GetDCOrgEx(hDC, & Origin);
  250.  
  251.     if ( ((unsigned) hDC) & 0xFFFF0000 )
  252.         OffsetRgn(m_hRegion, - Origin.x, - Origin.y);
  253.  
  254.     m_nRepaint ++;
  255.  
  256.     switch ( m_nRepaint % 3 )
  257.     {
  258.         case 0: m_Red  = (m_Red   + 0x31) & 0xFF; break;
  259.         case 1: m_Green= (m_Green + 0x31) & 0xFF; break;
  260.         case 2: m_Blue = (m_Blue  + 0x31) & 0xFF; break;
  261.     }
  262.  
  263.     SetTextAlign(hDC, TA_TOP | TA_CENTER);
  264.  
  265.     int size = GetRegionData(m_hRegion, 0, NULL);
  266.     int rectcount = 0;
  267.  
  268.     if ( size )
  269.     {
  270.         RGNDATA * pRegion = (RGNDATA *) new char[size];
  271.         GetRegionData(m_hRegion, size, pRegion);
  272.  
  273.         const RECT * pRect = (const RECT *) & pRegion->Buffer;
  274.         rectcount = pRegion->rdh.nCount;
  275.  
  276.         TEXTMETRIC tm;
  277.         GetTextMetrics(hDC, & tm);
  278.         int lineheight = tm.tmHeight + tm.tmExternalLeading; 
  279.  
  280.         for (unsigned i=0; i<pRegion->rdh.nCount; i++)
  281.         {
  282.             int x = (pRect[i].left + pRect[i].right)/2;
  283.             int y = (pRect[i].top + pRect[i].bottom)/2;
  284.  
  285.             wsprintf(mess, "sysrgn rect %d", i+1);
  286.             ::TextOut(hDC, x, y - lineheight, mess, _tcslen(mess));
  287.  
  288.             wsprintf(mess, "(%d, %d, %d, %d)", pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom);
  289.             ::TextOut(hDC, x, y, mess, _tcslen(mess));
  290.         }
  291.  
  292.         delete [] (char *) pRegion;
  293.  
  294.     }
  295.  
  296.     HBRUSH hBrush = CreateSolidBrush(RGB(m_Red, m_Green, m_Blue));
  297.  
  298.     FrameRgn(hDC, m_hRegion, hBrush, 4, 4);
  299.     FrameRgn(hDC, m_hRegion, (HBRUSH) GetStockObject(WHITE_BRUSH), 1, 1);
  300.  
  301.     DeleteObject(hBrush);
  302.  
  303.     TestClipMeta(hDC, rect);
  304. }
  305.  
  306.  
  307. void KMyCanvas::TestClipMeta(HDC hDC, const RECT & rect)
  308. {
  309.     /////////////////////////////////
  310.     // Play with clip and meta region
  311.     HRGN hRgn;
  312.  
  313.     switch ( m_test )
  314.     {
  315.         case IDM_TEST_DEFAULT:
  316.             break;
  317.  
  318.         case IDM_TEST_SETCLIP:
  319.             hRgn = CreateEllipticRgn(0, 0, rect.right*3/4, rect.bottom);
  320.             SelectClipRgn(hDC, hRgn);
  321.             DeleteObject(hRgn);
  322.             break;
  323.  
  324.         case IDM_TEST_SETMETA:
  325.             hRgn = CreateEllipticRgn(0, 0, rect.right, rect.bottom*3/4);
  326.             SelectClipRgn(hDC, hRgn);
  327.             SetMetaRgn(hDC);
  328.             break;
  329.  
  330.         case IDM_TEST_SETMETACLIP:
  331.             hRgn = CreateEllipticRgn(0, 0, rect.right, rect.bottom*3/4);
  332.             SelectClipRgn(hDC, hRgn);
  333.             SetMetaRgn(hDC);
  334.             DeleteObject(hRgn);
  335.             hRgn = CreateEllipticRgn(0, 0, rect.right*3/4, rect.bottom);
  336.             SelectClipRgn(hDC, hRgn);
  337.             break;
  338.     }
  339.     DeleteObject(hRgn);
  340.  
  341.     // with meta and clip region selected, only the
  342.     // intersection of system region, meta region, clip region can be painted
  343.     HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0xFF));
  344.     FillRect(hDC, & rect, hBrush);
  345.     DeleteObject(hBrush);
  346.  
  347.     DumpRegions(hDC);
  348.  
  349.     char mess[64];
  350.  
  351.     mess[0] = 0;
  352.  
  353.     strcat(mess, "Clip: ");
  354.     if ( m_bValid[1] ) strcat(mess, "Y"); else strcat(mess, "N");
  355.         
  356.     strcat(mess, ", Meta: ");
  357.     if ( m_bValid[2] ) strcat(mess, "Y"); else strcat(mess, "N");
  358.  
  359.     strcat(mess, ", API: ");
  360.     if ( m_bValid[3] ) strcat(mess, "Y"); else strcat(mess, "N");
  361.  
  362.     m_pStatus->SetText(0, mess);
  363.  
  364. }
  365.  
  366. class KLogoFrame : public KFrame
  367. {
  368.     void GetWndClassEx(WNDCLASSEX & wc)
  369.     {
  370.         KFrame::GetWndClassEx(wc);
  371.  
  372.         wc.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_GRAPH));
  373.     }
  374.  
  375. public:
  376.     KLogoFrame(HINSTANCE hInstance, const TBBUTTON * pButtons, int nCount,
  377.         KToolbar * pToolbar, KCanvas * pCanvas, KStatusWindow * pStatus) :
  378.             KFrame(hInstance, pButtons, nCount, pToolbar, pCanvas, pStatus)
  379.     {
  380.     }
  381.  
  382. };
  383.  
  384. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow)
  385. {
  386.     KMyCanvas     canvas;
  387.     KStatusWindow status;
  388.  
  389.     KLogoFrame frame(hInst, NULL, 0, NULL, & canvas, & status);
  390.  
  391.     frame.CreateEx(0, _T("ClassName"), _T("Regions in a Device Context: System/Meta/Clip Regions"),
  392.         WS_OVERLAPPEDWINDOW,
  393.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
  394.         NULL, LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAIN)), hInst);
  395.  
  396.     frame.ShowWindow(nShow);
  397.     frame.UpdateWindow();
  398.  
  399.     frame.MessageLoop();
  400.  
  401.     return 0;
  402. }
  403.