关于使用CDC画图的问题:
我设置用0.1mm作为单位
void CCircleView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode( MM_LOMETRIC );
CView::OnPrepareDC(pDC, pInfo);
}
画一个7cm直径的正圆
void CCircleView::OnDraw(CDC* pDC)
{
CCircleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->Ellipse( 0,0,700,-700 );
}
但实际画出来的不是7cm,却是5.1cm,为什么会这样?
答:
首先介绍下用GetDeviceCaps函数得到的信息:
HORZSIZE = 25.4*HORZRES/72
HORZRES为水平方向的像素总数
LOGPIXELSX 逻辑像素(小字体为96,大字体为120)
屏幕为15.4寸的,长为33.2cm,宽为20.7cm
注意GDI函数中的700只是一个逻辑单位,如果要得到实际的尺寸还得转化成像素再转化实际的长度。
70mm(逻辑)------ 70*(72/25.4=1280/452表示1mm有多少个像素)*(332/1280表示每个像素的实际宽度)
70mm(逻辑)=70*1280/452*332/1280=70*332/452=51.41(实际)
因为任何逻辑单位假定的分辨率为72DPI,所以HORZSIZE VERTSIZE只在这个假定的分辨率下得到逻辑长度而不是实际长度。
1366 768 - - - 482 271 1366/72*25.4 = 481.8944444444444
800 600 ---282 212 800/72*25.4=282.2222222 其他也可以通过同样的公式得到
1024 768 --- 361 271
1280 720 ----452 254
1280 800 ---452 282
而LOGPIXELSX和LOGPIXELXY这两个量是系统为显示字体而搞的鬼,比如10磅(或者说成10点)的字体,由于1磅为1/72英寸,所以系统的DPI为96的话,则一个字应该占10/72*96=13个像素,而如果这个值为120的话,则一个字应该占10/72*120=16个像素。所以这两个量跟本问题无关。
所以70mm是假定分辨率为72DPI下的逻辑长度,任何逻辑坐标都要转成设备坐标即像素(为了显示)。72DPI表示1英寸有72个点(像素)。那么逻辑长度1mm有多少个点(像素)呢?1英寸有72个点,1英寸又有25.4mm,所以1mm就应该有72/25.4个点,即70mm就应该有70*(72/25.4)个像素。
我们知道HORZSIZE=25.4*HORZRES/72,所以72/25.4=HORZRES/HORSIZE(即水平方向上的像素总数/水平方向上在假定分辨率为72DPI下的逻辑总长度)=1280/452
而我们的屏幕是33.2cm宽,像素为1280个,所以每个像素的实际长度应为332/1280mm
所以70mm的逻辑长度转成实际的物理长度就应该为70*(72/25.4)*33.2/1280=70*(1280/452)*332/1280=70*332/452=51.41mm的实际物理长度。
所以要想画出真实的物理长度得进行一翻转换。
我们注意在70mm(逻辑长度)在转化的时候只用到了332和452这两个数字,即屏幕的物理长度和水平方向像素总量为1280时在假定分辨率72DPI下的逻辑总长度(即HORZSIZE的值,这个值会随分辨率不同而不同,但不会随LOGPIXELSX而变化),所以在编程序时得考虑这两个量,HORZSIZE可以通过GetDeviceCaps轻松获取,而屏幕的物理长度怎么获取呢?这个问题我也不知道,我是自己用直尺量的(过后在网上查了下电脑的屏幕是15.4寸的)所以这样的程序没有可移植性,正如Charles Petzold说的那样(如果程序需要实际的视频显示大小的该怎么办?也话最好的解决方法是用对话框让用户输入它们)
哎,真蛋疼,那就搞个对话框让他输吧?coding....
void CCircleDlg::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
CDC *pDC=GetDC();
pDC->SetMapMode( MM_LOMETRIC );
int Horzsize=pDC->GetDeviceCaps(HORZSIZE);
int Vertsize=pDC->GetDeviceCaps(VERTSIZE);
if(m_Width!=0 && m_Height!=0)
pDC->Ellipse(0,0,10*m_Radius*Horzsize/m_Width,0-10*m_Radius*Vertsize/m_Height);//由于是UINT类型注意第4个参数的写法,否则当无符号数处理
}
量一量,呵呵,果然是7cm,啊哈哈!~~~
最后说明下,我的显示分辨率为1280*800,屏幕为15.4寸,332mm*207mm
希望大家读了这篇文章能对图形基础知识有所了解,Charles Petzold第5章讲得真是一塌糊涂,看了一下午不知道他要说啥,哎,高手就是高手没办法。你们若有问题请留言。。。