为什么要保证我们的软件产品或应用程序中的文本、图像和字体、布局等问题呢,因为我们用户的终端显示设备通常型号和设置各异,如最近出现的16×9,低于8”的等最新款式移动手提电脑,我们的应用程序和软件产品通常会在这样的终端变得面目全非,而这显然给用户的使用带来了严重的问题,直接导致的问题如:操作易用性Usability、功能可接近性Accessibility、文本可读性Readability 等,而这样的问题并非不可逾越,要解决如何让我们的应用程序在高分辨率的显示下仍然保持正常可视,重点需要解决四个方面的问题文本和字体、图像(图形、图标和鼠标指针)、版面设置和重绘等。

前言

所有的应用程序都可以工作在高分辨率下显示吗?答案当然是否定的。现在比较标准的计算机显示器都已经可以支持显示大概96像素点/英寸的分辨率了,而且越来越多的应用程序都可以运行在这种分辨率下,但是却仍然面临分辨率日益增长的带来的危险。现在,我们可以轻松的买到一台133-DPI显示分辨率的笔记本电脑,甚至还有170DPI的,也许几年以后200-DPI的显示分辨率已经随处可见了,著名的工业杂志DisplaySearch曾经预言在2002年底有40%的膝上电脑已经超过100-DPI的屏幕分辨率了,而且这个数字还在增长。

例图 1.各种常见分辨率下字体外观

高分辨率下界面布局的解决方案

现在大多数的应用程序要想显示正常都依赖于分辨率,我们有些应用程序如果没有高分辨率的支持将会变得非常丑陋并且导致用户易用性降低,与此同时越来越多的用户使用了大字体。但是遗憾的是当分辨率在130-DPI和200-DPI的时候是不成比例的,在96-DPI下的同一个应用程序在这种分辨率下会变得无法使用,有的时候这些应用程序的字体或控件会一律变得很小,但是更多的情况是一部分界面元素的尺寸正确的(例如,应用程序使用了缺省的字体,那么将会在这个基础上比原来大一些)而另外一部分不正确,如下图所示:

例图2. 改变分辨率带来的影响

高分辨率下界面布局的解决方案

由此可见,增强和改善我们应用程序在高分辨率下的显示支持是非常有必要的,那么重要的标准应该是:图片看起来更好,文本也应该看起来更清晰。比如文本在200-DPI分辨率显示器上清晰的像激光打印机输出的一样(因为计算机显示有更多的颜色像素和灰度缩放支持,200-DPI的显示器的质量相当于600-DPI的打印机)所以PDA和Smartphone的厂商相对于纸介更看重高分辨率下的显示。

开发一个适应多分辨率的应用程序不是很简单,尤其对于一个已经成形的应用程序和系统来说,动静可能不小,但是它的好处是可以使我们不必再假设分辨率的各种情况,避免不能缩放带来的质量下降(比如说位图和位图字体),而且开发支持高分辨率的应用程序有时候会觉得有些单调和乏味,但是如果我们的产品或应用程序是为了服务于特定人群的(比如说视力不好、和需要长时间工作的人以及视弱人群),那么我们的工作就会变得非常有必要(在高对比度下和使用扩展大字体的情况都和高分辨率有关)。

系统韵律

Windows平台本身提供了帮助解决用户系统高分辨率问题的解决途径,我们可以通过一个小函数GetDeviceCaps()先获得当前的显示分辨率,然后通过GetSystemMetrics()这个系统韵律函数和读取系统信息和参数的SystemParametersInfo()函数提供的方法来改变windows中的图形以及控件元素、和字体的尺寸,从一个3d的边框效果乃至到一个小图标的尺寸,都可以随心所欲的改变。

高分辨率下界面布局的解决方案

大概原理是首先利用GetDeviceDaps()这个函数获得当前分辨下的X、和Y轴的数值作为基准;然后再确定要缩放到多少。

关键问题

在设计高分辨率的应用程序过程中,我们要特别注意四个重要的方面:文本和字体、图像(图形、图标和鼠标指针),版面设置以及重绘。

文本和字体

这里有两种字体:位图(光栅)字体和TrueType字体,而我们要想实现高分辨率的应用程序就只能使用Truetype字体,因为位图(光栅)字体只能在96-DPI的屏幕分辨率下正常,而且不能够缩放,Windows已经支持TrueType字体很长时间了,所以找到一个很好的TrueType字体并且定义到我们的应用系统中并不是什么大的问题,另外一个原因只能使用Truetype字体,因为一些最新的技术,比如说GDI+,但是它只支持Truetype字体的操作。

高分辨率下界面布局的解决方案

缺省的字体可以通过windows句柄(HWNDs)和得到,而图形设备(HDCs)获得的是位图(光栅)字体,所以有时候在改变字体的时候,不管缺省字体不是HWNDs和HDC字体,只要它是TrueType字体,我们就可以改变它:

高分辨率下界面布局的解决方案

HFONT font = (HFONT) GetStockObject (DEFAULT_GUI_FONT);

SendMessage (hwnd, WM_SETFONT, (WPARAM) font, 0);

SelectObject (hdc, font);

当我们在窗口上创建字体的时候,可以使用像素指定字体尺寸,然后调整分辨率。

高分辨率下界面布局的解决方案

LOGFONT lf;

Memset (&lf, 0, sizeof (lf));

lf.lfHeight = SCALEY (13);

HFONT font = CreateFontIndirect (&lf);

或者可以使用Windows API提供的选择文字通用对话框,允许使用更准确的像素点来指定字体尺寸,然后经过一些算法后转化字体尺寸为像素,可以指定只使用TrueType字体来显示。

高分辨率下界面布局的解决方案

CHOOSEFONT data;

Memset (&data, 0, sizeof (data));

data.lStructSize = sizeof (data);

data.hwndOwner = form;

data.Flags = CF_TTONLY | CF_SCREENFONTS;

ChooseFont (&data);

最好的方法常常是在各种高分辨率下指定一个尺寸和一个区域的尺寸并且使用字体尺寸作为度量比例尺来指定这个页面中的其它元素,比如说,可以设定按钮之间的间距为缺省字体的高度的多少,使用GetTextMetrics()这个函数可以重新设定一个字体的高度。

TEXTMETRIC metrics;

GetTextMetrics (hdc, &metrics);

Int height = metrics.tmHeight;

最好不要使用TEXTMETRIC提供的tmAveCharWidth 方法,因为它只可以处理英文字母,除此以外我们还可以使用GetTextExtent()的这个方法来确认所关心的字符串的尺寸,我们可以用GetTextExtentPoint32()绘制一个环绕字符串的矩形,示例如下:

高分辨率下界面布局的解决方案

SIZE size;

GetTextExtentPoint32 (hdc, string, strlen (string), &size);

Int paddingX = SCALEX (8);

Int paddingY = SCALEX (8);

Rectangle (hdc, x - paddingX, y - paddingY, x + size.cx

+ paddingX, y + size.cy + paddingY);

TextOut (hdc, x, y, string, strlen (string));

最后,我们意识到尽管TrueType字体缩放精细,但是他们不是线性缩放,也就是说在DPI增加10%以后字符串的长度不能正确的增加10%,(使用GDI+就没有这个问题),因为一些特定的字母只能在几个尺寸上看起来不错,而TrueType却可以自动选择一个近似的尺寸正确显示,这是使用GetTextExtent这个函数的原因。

 

标签:界面布局

相关文章

随机推荐