DPtoLP/LPtoDP 和 ScreenToClient/ClientToScreen

设备坐标(Device Coordinate)又称为物理坐标(Physical Coordinate),是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。

  逻辑坐标(Logical Coordinate)是系统用作记录的坐标。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。逻辑坐标和设备坐标即使在缺省模式下其数值也未必一致,除了在以下两种情况下:

  1. 窗口为非滚动窗口
  2. 窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。

  在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标,可以使用CDC 函数DPtoLP()将设备坐标转化为逻辑坐标,同样可以用LPtoDP()将逻辑坐标转化为设备坐标。

  
ScreenToClient和ClientToScreen实际上是转换一个参照物的概念,如ie客户区上一个button,相对于ie的坐标是(x, y),ie客户区相对于屏幕原点的坐标是(x0 , y0),那么button的screen坐标就是(x+x0, y+y0) 。ScreenToClient和ClientToScreen都假定坐标是设备坐标。

在EX05C中(EX05C是一个例子程序,只需看函数中的代码即可):

我们现在来看看逻辑坐标和物理坐标是怎么转换的。

void CEX05CView::OnInitialUpdate()

{

       CScrollView::OnInitialUpdate();

 

       // TODO: calculate the total size of this view

       CSize sizeTotal(800, 1050);

       CSize sizePage(sizeTotal.cx/2, sizeTotal.cy/2);

       CSize sizeLine(sizeTotal.cx/50, sizeTotal.cy/50);

       SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);

}

上面程序中的SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);制定了映射模式为

MM_LOENGLISH,整个客户端逻辑区域为800 x 1050逻辑单位(sizeTotal);横向翻页的大小为400逻辑单位,纵向翻页的大小为525逻辑单位(sizePage); 横向一列的大小为800 / 50 = 16逻辑单位,纵向一行的大小为1050 / 50 = 21逻辑单位。

在MM_LOENGLISH映射模式下,每逻辑单位是0.01英寸。

void CEX05CView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CRect rectEllipse(m_pointTopLeft, m_sizeEllipse);

       CRgn circle;

 

       CClientDC dc(this);

       OnPrepareDC(&dc);

//     TRACE("Check Point3: HORZSIZE = %d, VERTSIZE = %d/n",dc.GetDeviceCaps(HORZSIZE), dc.GetDeviceCaps(VERTSIZE));

//     HORZSIZE = 320mm, VERTSIZE = 240mm

       TRACE("/nBefore LPtoDP:/n");

       TRACE("rectEllipse.top = %d, rectEllipse.bottom = %d, rectEllipse.left = %d, rectEllipse.right = %d/n",

              rectEllipse.top, rectEllipse.bottom, rectEllipse.left, rectEllipse.right);

       dc.LPtoDP(rectEllipse);

       TRACE("/nAfter LPtoDP:/n");

       TRACE("rectEllipse.top = %d, rectEllipse.bottom = %d, rectEllipse.left = %d, rectEllipse.right = %d/n",

              rectEllipse.top, rectEllipse.bottom, rectEllipse.left, rectEllipse.right);

//     LPtoDP将rectEllipse从逻辑坐标转换成设备坐标

       circle.CreateEllipticRgnIndirect(rectEllipse);

//     TRACE("Check Point2: point = (%d, %d)/n", point.x, point.y);

//  point为物理设备坐标

       if(circle.PtInRegion(point))

       {

              SetCapture();

//            Causes all subsequent mouse input to be sent to the current CWnd object regardless of the

//            position of the cursor.

              m_bCaptured = TRUE;

              CPoint pointTopLeft(m_pointTopLeft);

              dc.LPtoDP(&pointTopLeft);

              m_sizeOffset = point - pointTopLeft;

//            m_sizeOffset, point, pointTopLeft皆为设备坐标

              ::SetCursor(::LoadCursor(NULL, IDC_CROSS));

       }

       CScrollView::OnLButtonDown(nFlags, point);

}

我们来看看rectEllipse在语句dc.LPtoDP(rectEllipse);前后的变化:

Before LPtoDP:

EX05C: rectEllipse.top = -219, rectEllipse.bottom = -319, rectEllipse.left = 199, rectEllipse.right = 299

After LPtoDP:

EX05C: rectEllipse.top = 178, rectEllipse.bottom = 259, rectEllipse.left = 162, rectEllipse.right = 243

 

-219(逻辑坐标)是怎样转换为178(设备坐标)的呢?

设备坐标:屏幕的左上方为(0, 0),屏幕的右边为x坐标的正方向,屏幕的下边为y轴的正方向。

逻辑坐标:屏幕的左上方为(0, 0),右边为x坐标的正方向,对于不同的映射模式,y轴的正方向是不一样的,对

于MM_LOENGLISH而言,向上的方向是正方向,向下的方向是负方向。

在MM_LOENGLISH映射模式下,219个逻辑单位的长度为:

219 * 0.01 = 2.19英寸 = 2.19 * 2.54 = 5.5626 厘米

在上面程序中的CheckPoint3中,我们可以得到屏幕的物理尺寸为:320毫米 x 240毫米,另外补充说明一下,本电脑的屏幕分辨率是1024 * 768。因此,

(5.5626 / 24) * 768 = 178.0032像数

以上就是-219(逻辑坐标)转换为178(设备坐标)的详解。其他几个坐标也是如此转换而来。

 

现在我们看看卷动右边的滚动条的情况下,坐标是怎样变化的。

先将滚动条往下滚动两行,然后随便将椭圆拖放到一个位置,如下图所示:

 

 

TRACE语句的输出结果为:

Before LPtoDP:

EX05C: rectEllipse.top = -469, rectEllipse.bottom = -569, rectEllipse.left = 801, rectEllipse.right = 901

After LPtoDP:

EX05C: rectEllipse.top = 347, rectEllipse.bottom = 428, rectEllipse.left = 651, rectEllipse.right = 732

 

逻辑坐标-469是怎样转换成设备坐标347的呢?

在不考虑卷动的情况下,逻辑坐标-469应该转换成的设备坐标为:

(469 * 0.01 * 2.54 / 24) * 768 = 381.2032像数 = 381像数。

由于在垂直方向向下滚动了两行即 (1050 / 50) * 2 = 42逻辑单位,转换成设备坐标为:

(42 * 0.0.1 * 2.54 / 24) * 768 = 34.1736像数 = 34像数。

因此,考虑到卷动了2行的情况,逻辑坐标-469转换成设备坐标应该是:

381 - 34 = 347像数

这就是在有卷动的情况下,逻辑坐标和设备坐标转换的详细说明。

转载于:https://www.cnblogs.com/duyy/p/3796965.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(1126):递归求数学题

阶乘1*2*3.....*n <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </he…

1007 素数对猜想 (20分)

1007 素数对猜想 (20分) 让我们定义 ​​ 为&#xff1a;dnpn1−pnd_{n} p_{n1} - p_{n}dn​pn1​−pn​&#xff0c;其中pip_{i}pi​是第iii个素数。显然有d11d_{1} 1d1​1&#xff0c;且对于n>1n>1n>1有dnd_{n}dn​是偶数。“素数对猜想”认为“存在无穷多对相邻且…

Spring工作原理

一、 IoC(Inversion of control): 控制反转1、IoC&#xff1a;概念&#xff1a;控制权由对象本身转向容器&#xff1b;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系核心&#xff1a;bean工厂&#xff1b;在Spring中&#xff0c;bean工厂创建的各个实例称作bean二…

前端学习(1127):递归求数学题2

斐波那契数列 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head>…

注解和反射实现dao层增删改查

注解和反射写dao1. 注解的使用2. 使用注解体现映射关系针对上一篇文章&#xff0c;使用xml映射文件和反射实现dao&#xff0c;提出了扩展功能&#xff0c;利用注解来体现实体类和表的映射关系本文是上一篇文章的扩展使用反射和xml实现dao 1. 注解的使用 什么是注解&#xff1…

1008 数组元素循环右移问题 (20分)

输入样例: 6 2 1 2 3 4 5 6 输出样例: 5 6 1 2 3 4 # -*- coding: utf-8 -*- import mathdef right_shift(lst, m):n len(lst)m m % nfor j in range(math.gcd(m, n)):temp lst[j]i jwhile (i - m) % n > j:lst[i] lst[(i - m) % n]i (i - m) % nlst[i] tempretur…

其它数据类型和Json的转化

1.ResultSet→Json public static String resultSetToJson(ResultSet rs) throws SQLException,JSONException { // json数组 JSONArray array new JSONArray(); // 获取列数 ResultSetMetaData metaData rs.getMetaData(); int columnCount metaData.getColumnCount(…

MVC分层开发模式

MVC 1. 什么是mvc开发模式2. 基于servlet手写mvc框架1. 什么是mvc开发模式 mvc不是一种技术&#xff0c;只是一种开发模式使用分层开发模式能在大型项目中&#xff0c;让开发人员更好的协同工作便于项目的维护和扩展 M: Model 模型层->数据库层->daoV: View 视图层->…

1009 说反话 (20分)

1009 说反话 (20分) 给定一句英语&#xff0c;要求你编写程序&#xff0c;将句中所有单词的顺序颠倒输出。 输入格式&#xff1a; 测试输入包含一个测试用例&#xff0c;在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成&#xff0c;其中单词是由英文字…

C#_uploadify_mvc_version

jQuery Uploadify在ASP.NET MVC3中的使用 1、Uploadify简介 Uploadify是基于jQuery的一种上传插件&#xff0c;支持多文件、带进度条显示上传&#xff0c;在项目开发中常被使用。 Uploadify官方网址&#xff1a;http://www.uploadify.com/ 2、ASP.NET MVC3中的使用Uploadify 搭…

1010 一元多项式求导 (25分)

输入样例: 3 4 -5 2 6 1 -2 0 输出样例: 12 3 -10 1 6 0 # -*- coding: utf-8 -*-def get_derivation(lst):length len(lst)idx 0while idx < length:if lst[idx 1] ! 0:lst[idx] * lst[idx 1]lst[idx 1] - 1else:lst[idx] 0idx 2return lstif __name__ __main__…

VS2012 发布网站步骤

VS2012中发布网站的方式与以往有了不同&#xff0c;前面的版本发布如图 而2012点publish的时候弹出框有所不同&#xff0c;这边需要新建一个profile名字随便起&#xff0c;发布的方式有好几种&#xff0c; 当然不同的方式配置不同&#xff0c;用的最多的就是files system了 选择…

python 生成个性二维码

1. 效果 gif 图片二维码 带背景图二维码&#xff08;修改了&#xff09; 2. 依赖库 核心库myqr pip install myqr其它依赖库安装pip install pip install pillow, numpy, imageio3. 核心代码 我这里是F盘下的joy文件夹下面代码改变路径&#xff0c;图片名称参数即可 im…

1011 A+B 和 C (15分)

输入样例&#xff1a; 4 1 2 3 2 3 4 2147483647 0 2147483646 0 -2147483648 -2147483647 输出样例&#xff1a; Case #1: false Case #2: true Case #3: true Case #4: false # -*- coding: utf-8 -*-if __name__ __main__:n eval(input())input_list []for i in range…

SharePoint 2013:解决添加域名后每次都需要登录的问题

在SharePoint 2013中&#xff0c;当我们添加一个域名给SP后&#xff08;添加域名的方法请参考此文&#xff1a;http://www.cnblogs.com/jianyus/archive/2013/08/10/3249461.html &#xff09;&#xff0c;每次用域名访问都需要输入用户名和密码&#xff0c;即使该用户已经正确…

1012 数字分类 (20分)

输入样例 1&#xff1a; 13 1 2 3 4 5 6 7 8 9 10 20 16 18 输出样例 1&#xff1a; 30 11 2 9.7 9 输入样例 2&#xff1a; 8 1 2 4 5 6 7 9 16 输出样例 2&#xff1a; N 11 2 N 9 # -*- coding: utf-8 -*-def class_numbers(nums):arr [0] * 5exists [0] * 5flag1 1…

mvc框架upgrade

upgrade...1. actionservlet核心控制器更改以上1&#xff0c;2点2. 工具类&#xff08;对反射拿到的属性对象数据转型&#xff09;3. 业务服务类使用适配器设计模式针对上一篇文字做出了改造&#xff0c;既然要写手写lowb版mvc框架&#xff0c;就得付出一定代价&#xff0c;加大…

discuz中又拍云在ie8,chrome22下不能上传的问题

chrome22: 解决方法&#xff1a;http://www.baidufe.com/item/b17db6c1136a986b4272.html ie8&#xff1a;flash不能生成 重新安装flash player 14转载于:https://www.cnblogs.com/zhaozhilu/p/3807440.html

1013 数素数 (20分)

输入样例&#xff1a; 5 27 输出样例&#xff1a; 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 # -*- encoding: utf-8 -*- import mathdef get_primes(n):prime_list [1] * (n 1)for i in range(2, int(math.sqrt(n)) 1):if prime_list[i]…