• win32窗口映射(部分)


      先理解一下“窗口”与“视区”的概念。“窗口”是逻辑坐标下的矩形区域,“视区”是设备坐标系下的区域。根据“窗口”和“视区”的大小可以确定x方向和y方向的比例因子。

        例子如下:

    VOID OnPaint(HWND hwnd,WPARAM wParam,LPARAM lParam)
    {
        PAINTSTRUCT     ps; 
        RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        HDC hdc = BeginPaint(hwnd, &ps);  
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rtClient.right - rtClient.left, rtClient.bottom - rtClient.top);//rt为RECT变量;
        SelectObject(hMemDC, hBitmap);
        FillRect(hMemDC, &rtClient,WHITE_BRUSH);
    
        int OldMapMode =SetMapMode(hMemDC,MM_ANISOTROPIC);
        //SetViewportOrgEx(hMemDC,0,rtClient.bottom,NULL);
        POINT point = {100,100};
        DPtoLP(hMemDC,&point,1);
        SetWindowOrgEx(hMemDC,-point.x,-point.y,NULL);
        RECT rt = {-100,-100,0,0};
        HBRUSH hBrush = CreateSolidBrush(RGB(0,0,255));
        FillRect(hMemDC,&rt,hBrush);
    
        //SetViewportOrgEx(hMemDC,0,0,NULL);
        SetWindowOrgEx(hMemDC,0,0,NULL);
        SetMapMode(hMemDC,OldMapMode);
        BitBlt(hdc, 0, 0,rtClient.right - rtClient.left, rtClient.bottom - rtClient.top, 
           hMemDC, 0, 0, SRCCOPY);
        DeleteDC(hMemDC);
        DeleteObject(hBitmap);
        EndPaint(hwnd,&ps);
    }

    注:最后最好把设置都改回来(SetViewportOrgEx(hMemDC,0,0,NULL)或者SetWindowOrgEx(hMemDC,0,0,NULL))。

    如果设置SetViewportOrgEx则比较简单,直接把逻辑坐标平移就好。

    如何设置SetWindowOrgEx则比较麻烦,比如我想平移到100,100这个点,则先要调用DPtoLP进行转换,然后参数是转换后值的取反。(如果不调用DPtoLP函数,则逻辑坐标与设备坐标方向一样,如果不一样,则不需要取反)

       比如居中的两种方法,直接写上书中的例子吧(理解就好,MFC版):

          设置x轴正方向向右,y轴正方向向上,客户区中心为坐标系为原点。

      (1)、设置视口

           pDC->SetWindowExt(rc.Width(),rc.Height());

      pDC->SetViewportExt(rc.Width(),-rc.Height());

          pDC->SetViewportOrg(rc.Width()/2,rc.Heigth()/2);

         (2)、设置窗口

      pDC->SetWindowExt(rc.Width(),-rc.Height());

      pDC->SetViewportExt(rc.Width(),rc.Height());

          pDC->SetWindowOrg(-rc.Width()/2,rc.Heigth()/2);

         分析第二种:由于设备与逻辑坐标比率是1比1,所以不需要转换坐标,准备偏移点为(rc.Width()/2,rc.Heigth()/2),由于逻辑与设备坐标系x方向相同,y方向不同,所以x取反,y不需要取反,结果为(-rc.Width()/2,rc.Heigth()/2);

      第二种亦可以换成类似:(win32资料,这是我自己的测试代码)

        SetWindowExtEx(hMemDC,rtClient.right,-2*rtClient.bottom,NULL);
        SetViewportExtEx(hMemDC,rtClient.right,rtClient.bottom,NULL);
        POINT point = {rtClient.right/2,rtClient.bottom/2};
        DPtoLP(hMemDC,&point,1);
        SetWindowOrgEx(hMemDC,-point.x,-point.y,NULL);

         

    通过设置原点变成极坐标,然后可以方便计算。比如计算机图形学基础教程有一道题。

    把一个半径为R的圆40等份,以每个等分点为圆心,以r为半径画圆。

      

      RECT rtClient;
        GetClientRect(hwnd,&rtClient);
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd,&ps);
        SetMapMode(hdc,MM_ANISOTROPIC);
        SetViewportExtEx(hdc,rtClient.right,rtClient.bottom,NULL);
        SetWindowExtEx(hdc,rtClient.right,-rtClient.bottom,NULL);
        POINT pt = {rtClient.right/2,rtClient.bottom/2};
        DPtoLP(hdc,&pt,1);
        SetWindowOrgEx(hdc,-pt.x,-pt.y,NULL);
        HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
        HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);
        int bigR = 100;
        int smallR = 150;
        for(int i=0;i<40;++i)
        {
            int x = (int)(cos(0.0+9*i)*bigR);
            int y = (int)(sin(0.0+9*i)*bigR);
            Ellipse(hdc,x-smallR,y-smallR,x+smallR,y+smallR);
        }
        SetWindowOrgEx(hdc,0,0,NULL);
        SelectObject(hdc,hOldBrush);
        
        EndPaint(hwnd,&ps);

    效果图:

      

    注:参考资料:http://www.cppblog.com/dragon/archive/2012/09/07/64005.html

  • 相关阅读:
    HDU_2955_Robberies_01背包
    01背包
    最长升序子序列
    快速排序
    HDU_1875_畅通工程再续
    iOS app 设计推荐
    iOS 两种方法实现左右滑动出现侧边菜单栏 slide view
    iOS 8自动调整UITableView和UICollectionView布局
    iOS app发布流程
    iOS博客推荐
  • 原文地址:https://www.cnblogs.com/jlyg/p/8442798.html
Copyright © 2020-2023  润新知