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

转载于:https://www.cnblogs.com/jlyg/p/8442798.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值