windows程序设计中clover程序中划线的坐标是怎么计算的,想不明白,那位大侠解释一下!
谢谢!

解决方案 »

  1.   

    CLOVER程序用四个椭圆组成一个剪裁区域,将这个剪裁区域选进设备内容中,然后画出从窗口显示区域的中心出发的一系列直线,这些直线只出现在剪裁区域所限定的范围,结果显示如图5-20所示。 图5-20 CLOVER利用复杂的剪裁区域画出的图像 要用常规的方法画出这个图形,就必须根据椭圆的边线公式计算出每条直线的端点。利用复杂的剪裁区域,可以直接画出这些线条,而让Windows确定其端点。CLOVER如程序5-8所示。
    程序5-8 CLOVER
            
    CLOVER.C
            
    /*--------------------------------------------------------------------------
            
        CLOVER.C --   Clover Drawing Program Using Regions
            
                       (c) Charles Petzold, 1998
            
    ----------------------------------------------------------------------*/
            
    #include <windows.h>
            
    #include <math.h>
            
    #define TWO_PI (2.0 * 3.14159)
            
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
            
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
            
                       PSTR szCmdLine, int iCmdShow)
            
    {
            
        static TCHAR szAppName[] = TEXT ("Clover") ;
            
        HWND          hwnd ;
            
        MSG           msg ;
            
        WNDCLASS      wndclass ;
            
       
            
        wndclass.style        = CS_HREDRAW | CS_VREDRAW ;
            
        wndclass.lpfnWndProc= WndProc ;
            
        wndclass.cbClsExtra   = 0 ;
            
        wndclass.cbWndExtra   = 0 ;
            
        wndclass.hInstance    = hInstance ;
            
        wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
            
        wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ;
            
        wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
            
        wndclass.lpszMenuName = NULL ;
            
        wndclass.lpszClassName= szAppName ;
            
       
            
        if (!RegisterClass (&wndclass))
            
        {
            
                MessageBox (NULL, TEXT ("This program requires Windows NT!"),
            
                         szAppName, MB_ICONERROR) ;
            
                return 0 ;
            
        }
            
       
            
        hwnd = CreateWindow (szAppName, TEXT ("Draw a Clover"),
            
                               WS_OVERLAPPEDWINDOW,
            
                               CW_USEDEFAULT, CW_USEDEFAULT,
            
                               CW_USEDEFAULT, CW_USEDEFAULT,
            
                               NULL, NULL, hInstance, NULL) ;
            
        ShowWindow (hwnd, iCmdShow) ;
            
        UpdateWindow (hwnd) ;
            
       
            
        while (GetMessage (&msg, NULL, 0, 0))
            
        {
            
                TranslateMessage (&msg) ;
            
                DispatchMessage (&msg) ;
            
        }
            
        return msg.wParam ;
            
    }
            
     
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
            
    {
            
        static HRGN hRgnClip ;
            
        static int    cxClient, cyClient ;
            
        double fAngle, fRadius ;
            
        HCURSORhCursor ;
            
        HDC           hdc ;
            
        HRGN          hRgnTemp[6] ;
            
        int           i ;
            
        PAINTSTRUCT ps ;
            
        switch (iMsg)
            
        {
            
        case   WM_SIZE:
            
                cxClient      = LOWORD (lParam) ;
            
                cyClient      = HIWORD (lParam) ;
            
                hCursor= SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
            
                ShowCursor (TRUE) ;
            
            
            
                if (hRgnClip)
            
                       DeleteObject (hRgnClip) ;
            
            
            
                hRgnTemp[0]   = CreateEllipticRgn (0, cyClient / 3,
            
                                              cxClient / 2, 2 * cyClient / 3) ;
            
                hRgnTemp[1]   = CreateEllipticRgn (cxClient / 2, cyClient / 3,
            
                                              cxClient, 2 * cyClient / 3) ;
            
                hRgnTemp[2]   = CreateEllipticRgn (cxClient / 3, 0,
            
                                              2 * cxClient / 3, cyClient / 2) ;
            
                hRgnTemp[3]   = CreateEllipticRgn (cxClient / 3, cyClient / 2,
            
    2 * cxClient / 3, cyClient) ;
            
                hRgnTemp[4]   = CreateRectRgn (0, 0, 1, 1) ;
            
                hRgnTemp[5]   = CreateRectRgn (0, 0, 1, 1) ;
            
                hRgnClip      = CreateRectRgn (0, 0, 1, 1) ;
            
     
                CombineRgn (hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR) ;
            
                CombineRgn (hRgnTemp[5], hRgnTemp[2], hRgnTemp[3], RGN_OR) ;
            
                CombineRgn (hRgnClip,    hRgnTemp[4], hRgnTemp[5], RGN_XOR) ;
            
            
            
                for (i = 0 ; i < 6 ; i++)
            
                       DeleteObject (hRgnTemp[i]) ;
            
            
            
                SetCursor (hCursor) ;
            
                ShowCursor (FALSE) ;
            
                return 0 ;
            
            
            
        case   WM_PAINT:
            
                hdc = BeginPaint (hwnd, &ps) ;
            
            
            
                SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
            
             SelectClipRgn (hdc, hRgnClip) ;
            
                fRadius = _hypot (cxClient / 2.0, cyClient / 2.0) ;
            
                for (fAngle = 0.0 ; fAngle < TWO_PI ; fAngle += TWO_PI / 360)
            
                {
            
                       MoveToEx (hdc, 0, 0, NULL) ;
            
                       LineTo (hdc, (int) ( fRadius * cos (fAngle) + 0.5),
            
                               (int) (-fRadius * sin (fAngle) + 0.5)) ;
            
                }
            
                EndPaint (hwnd, &ps) ;
            
                return 0 ;
            
        case WM_DESTROY:
            
                DeleteObject (hRgnClip) ;
            
                PostQuitMessage (0) ;
            
                return 0 ;
            
        }
            
        return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
            
    }
             由于剪裁区域总是使用设备坐标,CLOVER程序必须在每次接收到WM_SIZE消息时重新建立剪裁区域。几年前,这可能需要几秒钟。现在的快速机器在一瞬间就可以画出来。
    CLOVER从建立四个椭圆剪裁区域开始,这四个椭圆存放在hRgnTemp数组的头四个元素中,然后建立三个「空」剪裁区域:
    hRgnTemp [4]= CreateRectRgn (0, 0, 1, 1) ;
            
    hRgnTemp [5]= CreateRectRgn (0, 0, 1, 1) ;
            
    hRgnClip      = CreateRectRgn (0, 0, 1, 1) ;
            
    显示区域左右的两个椭圆区域组合起来:
    CombineRgn (hRgnTemp [4], hRgnTemp [0], hRgnTemp [1], RGN_OR) ;
            
    同样,显示区域上下两个椭圆区域组合起来:
    CombineRgn (hRgnTemp [5], hRgnTemp [2], hRgnTemp [3], RGN_OR) ;
            
    最后,两个组合后的区域再组合到hRgnClip中:
    CombineRgn (hRgnClip, hRgnTemp [4], hRgnTemp [5], RGN_XOR) ;
            
    RGN_XOR标识符用于从结果区域中排除重迭部分。最后,删除6个临时区域:
    for (i = 0 ; i < 6 ; i++)
            
        DeleteObject (hRgnTemp [i]) ;
            
    与画出的图形比起来,WM_PAINT的处理很简单。视端口原点设定为显示区域的中心(使画直线更容易一些),在WM_SIZE消息处理期间建立的区域选择为设备内容的剪裁区域:
    SetViewportOrg (hdc, xClient / 2, yClient / 2) ;
            
    SelectClipRgn (hdc, hRgnClip) ;
            
    现在,剩下的就是画直线了,共360条,每隔一度画一条。每条线的长度为变量fRadius,这是从中心到显示区域的角落的距离:
    fRadius = hypot (xClient / 2.0, yClient / 2.0) ;
            
    for (fAngle = 0.0 ; fAngle < TWO_PI ; fAngle += TWO_PI / 360)
            
    {
            
        MoveToEx (hdc, 0, 0, NULL) ;
            
        LineTo (hdc, (int) ( fRadius * cos (fAngle) + 0.5),
            
                       (int) (-fRadius * sin (fAngle) + 0.5)) ;
            
    }
            
    在处理WM_DESTROY消息时,删除该剪裁区域:
    DeleteObject (hRgnClip) ;
      

  2.   

    我想问一下
    MoveToEx (hdc, 0, 0, NULL) ; 
            
        LineTo (hdc, (int) ( fRadius * cos (fAngle) + 0.5), 
            
                      (int) (-fRadius * sin (fAngle) + 0.5)) ; 
            
    lineto中坐标怎么计算出来的!可以解释一下嘛?
      

  3.   

    四楼你好为什么deleteobject(hrgnclip)要放在WM_DESTROY里面啊? 为什么要循环删除hrgntemp?
     还有if(hrgnclip) deleteobject(hrgnclip)起到什么作用啊? 我是新手不懂。希望能给我解答一下!谢谢!!