先理解一下“窗口”与“视区”的概念。“窗口”是逻辑坐标下的矩形区域,“视区”是设备坐标系下的区域。根据“窗口”和“视区”的大小可以确定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 = {,};
DPtoLP(hMemDC,&point,);
SetWindowOrgEx(hMemDC,-point.x,-point.y,NULL);
RECT rt = {-,-,,};
HBRUSH hBrush = CreateSolidBrush(RGB(,,));
FillRect(hMemDC,&rt,hBrush); //SetViewportOrgEx(hMemDC,0,0,NULL);
SetWindowOrgEx(hMemDC,,,NULL);
SetMapMode(hMemDC,OldMapMode);
BitBlt(hdc, , ,rtClient.right - rtClient.left, rtClient.bottom - rtClient.top,
hMemDC, , , 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/,rtClient.bottom/};
DPtoLP(hdc,&pt,);
SetWindowOrgEx(hdc,-pt.x,-pt.y,NULL);
HBRUSH hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc,hBrush);
int bigR = ;
int smallR = ;
for(int i=;i<;++i)
{
int x = (int)(cos(0.0+*i)*bigR);
int y = (int)(sin(0.0+*i)*bigR);
Ellipse(hdc,x-smallR,y-smallR,x+smallR,y+smallR);
}
SetWindowOrgEx(hdc,,,NULL);
SelectObject(hdc,hOldBrush); EndPaint(hwnd,&ps);

效果图:

  

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

win32窗口映射(部分)的更多相关文章

  1. 第一个手写Win32窗口程序

    第一个手写Win32窗口程序 一 Windows编程基础 1 Win32应用程序的基本类型 1.1 控制台程序 不需要完善的Windows窗口,可以使用DOS窗口 的方式显示. 1.2 Win32窗口 ...

  2. WIN32窗口程序

    // Win32.cpp : 定义应用程序的入口点. // #include "stdafx.h" #include "Win32.h" void TRACE( ...

  3. Win32窗口消息机制 x Android消息机制 x 异步执行

    如果你开发过Win32窗口程序,那么当你看到android代码到处都有的mHandler.sendEmptyMessage和 private final Handler mHandler = new ...

  4. 如何在Console下面生成一个WIN32窗口

    一个小挑战? VS2017里面,新建一个控制台工程,输入名字(你不需要也成,有默认的),得到一个控制台工程. 好了,生成的代码,如下: // Win32InConsole.cpp : This fil ...

  5. Win32窗口框架

    Win32窗口框架 WindowClass 单例,负责窗口初始化注册和取消注册: 负责提供静态方法: 放在Window类内部,方便初始化时,wndProc(HandleMsgSetup)的赋值: cl ...

  6. Win32 - 窗口

    Win32 - 窗口 目录 Win32 - 窗口 前言 流程图 创建项目 VS MinGW Win32API字符串 Unicode 和 ANSI 函数 TCHAR WinMain:Win32 Appl ...

  7. WIN32 窗口封装类实现

    CQWnd.h窗口类定义 // QWnd.h: interface for the CQWnd class. // ////////////////////////////////////////// ...

  8. 解决WIN32窗口不响应WM_LBUTTONDBLCLK消息

    原文链接: http://www.cnblogs.com/xukaixiang/archive/2012/05/27/2520059.html 今天在做一个软件时,发现win32创建的窗体不能响应WM ...

  9. win32窗口程序分析

    1.分析消息的附加参数 例如:为了查看程序处理了哪些消息   在回调函数中调用输出函数,在控制台中输出消息的值:

随机推荐

  1. HDU 4906 (dp胡乱搞)

    The Romantic Her Problem Description There is an old country and the king fell in love with a devil. ...

  2. poj 2823 二分法+单调队列

    #include<stdio.h> #include<string.h> #define N  1100000 int a[N]; int fmin[N],fmax[N]; i ...

  3. java查询MySQL时,MySQL中tinyint长度为1时转换为boolean

    看到别人代码,MySQL数据库中,有下面这个字段,tinyint(1) 这时候java代码中取出来的数据类型就是boolean类型,如果长度 > 1的话,就会变成int类型,特意查了一下,这里参 ...

  4. 2.1 shuffle sort(洗牌)

    1.目的:将数组以随机的顺序重新排序,类似洗牌的过程 2.用途用于快速排序或者任何以划分为基础的排序中,目的是减少最坏可能性发生的概率. 3.想法1:给数组的每一个元素产生一个随机的数字作为键,然后使 ...

  5. 在设计DJANGO用户更改密码时,出现NoReverseMatch at /account/password-change/这种妖精如何办?

    网上看到很多解决办法.但对于我来说, 好像加个post_change_redirect这个参数是最有效的. from django.conf.urls import url from . import ...

  6. 最小生成树 D - Constructing Roads

    There are N villages, which are numbered from 1 to N, and you should build some roads such that ever ...

  7. JNI/NDK开发指南(三)——JNI数据类型及与Java数据类型的映射关系

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/42047899 当我们在调用一个Java native方法的时候.方法中的參数是怎样传递给C ...

  8. 【翻译自mos文章】使用aum( Automatic Undo Management) 时遇到 ORA-01555错误--- 原因和解决方式。

    使用aum( Automatic Undo Management) 时遇到 ORA-01555错误--- 原因和解决方式. 參考原文: ORA-01555 Using Automatic Undo M ...

  9. 大数据技术之Flume研究摘要(一)

    Flume是Cloudera提供的一个高可用的,高可靠的.分布式的海量日志採集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同一时候,Flume提供对数据进行简单处理 ...

  10. Linux下一款可以使用命令行的pdf阅读器

    Zathura是linux下一款用命令行控制打pdf阅读器,并且基本打使用方法和vim很相似.对于喜欢键盘操作的用户来说的确是一个不错的选择. ubuntu下的安装命令: sudo apt-get i ...