⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 5. 图形基础.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
    MSG           msg ;
        
    WNDCLASS      wndclass ;
        
   
        
    wndclass.style        = CS_HREDRAW | CS_VREDRAW ;
        
    wndclass.lpfnWndProc= WndProc ;
        
    wndclass.cbClsExtra   = 0 ;
        
    wndclass.cbWndExtra = 0 ;
        
    wndclass.hInstance    = hInstance ;
        
    wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
        
    wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ;
        
    wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
    wndclass.lpszMenuName= NULL ;
        
    wndclass.lpszClassName= szAppName ;
        
   
        
    if (!RegisterClass (&wndclass))
        
    {
        
            MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                         szAppName, MB_ICONERROR) ;
        
            return 0 ;
        
    }
        
   
        
    hwnd = CreateWindow (szAppName, TEXT ("Device Capabilities"),
        
                                         WS_OVERLAPPEDWINDOW,
        
                                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                                  CW_USEDEFAULT, CW_USEDEFAULT,
        
                          NULL, NULL, hInstance, NULL) ;
        
   
        
    ShowWindow (hwnd, iCmdShow) ;
        
    UpdateWindow (hwnd) ;
        
  
        
    while (GetMessage (&msg, NULL, 0, 0))
        
    {
        
            TranslateMessage (&msg) ;
        
            DispatchMessage (&msg) ;
        
    }
        
    return msg.wParam ;
        
}
        

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
    static int    cxChar, cxCaps, cyChar ;
        
    TCHAR         szBuffer[10] ;
        
    HDC           hdc ;
        
    int           i ;
        
    PAINTSTRUCT   ps ;
        
    TEXTMETRIC    tm ;
        
   
        
    switch (message)
        
    {
        
    case WM_CREATE:
        
            hdc = GetDC (hwnd) ;
        
            GetTextMetrics (hdc, &tm) ;
        
            cxChar= tm.tmAveCharWidth ;
        
            cxCaps= (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
        
            cyChar= tm.tmHeight + tm.tmExternalLeading ;
        
        
        
            ReleaseDC (hwnd, hdc) ;
        
            return 0 ;
        
        
        
    case WM_PAINT:
        
            hdc = BeginPaint (hwnd, &ps) ;
        
            for (i = 0 ; i < NUMLINES ; i++)
        
            {
        
                   TextOut (     hdc, 0, cyChar * i,
        
                           devcaps[i].szLabel,
        
                           lstrlen (devcaps[i].szLabel)) ;
        
             
        
                   TextOut (     hdc, 14 * cxCaps, cyChar * i,
        
                           devcaps[i].szDesc,
        
                           lstrlen (devcaps[i].szDesc)) ;
        
             
        
                   SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
        
                   TextOut (hdc, 14*cxCaps+35*cxChar, cyChar*i, szBuffer,
        
                           wsprintf (szBuffer, TEXT ("%5d"),
        
                           GetDeviceCaps (hdc, devcaps[i].iIndex))) ;
        
             
        
            SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
        
            }
        
        
        
            EndPaint (hwnd, &ps) ;
        
            return 0 ;
        
       
        
    case WM_DESTROY:
        
            PostQuitMessage (0) ;
        
            return 0 ;
        
    }
        
    return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
可以看到,这个程序非常类似第四章的SYSMETS1。为了保持程序代码的短小,我没有使用滚动条,因为我知道信息可以在一个画面上显示出来。在256色,640×480的VGA上显示的结果如图5-1所示。


 



图5-1 256色,640×480VGA上的DEVCAPS1显示
 

设备的大小


假定要绘制边长为1英寸的正方形,您(程序写作者)或Windows(操作系统)需要知道视讯显示上1英寸对应多少图素。使用GetDeviceCaps函数能取得有关如视讯显示器和打印机之类输出设备的实际显示大小信息。

视讯显示器和打印机是两个不同的设备。但也许最不明显的区别是「分辨率」与设备联系起来的方式。对于打印机,我们经常用「每英寸的点数(dpi)」表示分辨率。例如,大多数激光打印机有300或600dpi的分辨率。然而,视讯显示器的分辨率是以水平和垂直的总图素数来表示的,例如,1024×768。大多数人不会告诉您他的打印机在一张纸上水平和垂直打印多少图素或他们的视讯显示器上每英寸有多少图素。

在本书中,我用「分辨率」来严格定义每度量单位(一般为英寸)内的图素数。我使用「图素大小」或「图素尺寸」表示设备水平或垂直显示的总图素数。「度量大小」或「度量尺寸」是以英寸或毫米为单位的设备显示区域的大小。(对于打印机页面,它不是整个页面,只是可打印的区域。)图素大小除以度量大小就得到分辨率。

现在Windows使用的大多数视讯显示器的屏幕都是宽比高多33%。这就表示纵横比为1.33:1或(一般写法)4:3。历史上,该比例可追溯到Thomas Edison制作电影的年代。它一直作为电影的标准纵横比,直到1953年出现各种型态的宽银幕投影机。电视机屏幕的纵横比也是4:3。

然而,Windows应用程序不应假设视讯显示器具有4:3的纵横比。人们进行文字处理时希望视讯显示器与一张纸的长和宽类似。最普通的选择是把4:3变为3:4显示,把标准显示翻转一下。

如果设备的水平分辨率与垂直分辨率相等,就称设备具有「正方形图素」。现在,Windows普遍使用的视讯显示器都具有正方形图素,但也有例外。(应用程序也不应假设视讯显示器总是具有正方形图素。)Windows第一次发表时,标准显示卡卡是IBM Color Graphics Adapter(CGA),它有640×200的图素大小;Enhanced Graphics Adapter(EGA)有640×350的图素大小;Hercules Graphics Card有720×348的图素大小。所有这些显示卡都使用4:3纵横比的显示器,但是水平和垂直图素数的比值都不是4:3。

执行Windows的使用者很容易确定视讯显示器的图素大小。在「控制台」中执行「显示器」,并选择「设定」页面标签。在标有「桌面区域」的字段中,可以看到这些图素尺寸之一:

640×480图素
  
800×600图素
  
1024×768图素
  
1280×1024图素
  
1600×1200图素
  
所有这些都是4:3。(除了1280×1024图素大小。这不但有些不好,还有些令人反感。所有这些图素尺寸都认为在4:3的显示器上会产生正方形的图素。)

Windows应用程序可以使用SM_CXSCREEN和SM_CYSCREEN参数从GetSystemMetrics得到图素尺寸。从DEVCAPS1程序中您会注意到,程序可以用HORZRES(水平分辨率)和VERTRES参数从GetDeviceCaps中得到同样的值。这里「分辨率」指的是图素大小而不是每度量单位的图素数。

这些是设备大小的简单部分,现在开始复杂的部分。

前两个设备能力,HORZSIZE和VERTSIZE,文件中称为「以毫米计的实际屏幕的宽度」及「以毫米计的实际屏幕的高度」(在/Platform SDK/Graphics和Multimedia Services/GDI/Device Contexts/Device Context Reference/Device Context Functions/GetDeviceCaps中)。这些看起来更像直接的定义。例如,给出视讯显示卡和显示器的接口特性,Windows如何真正知道显示器的大小呢?如果您有台膝上型计算机(它的视讯驱动程序能知道准确的屏幕大小)并且连接了外部显示器,又是哪种情况呢?如果把视讯投影机连接到计算机上呢?

在Windows的16位版本中(及在Windows NT中),Windows为HORZSIZE和VERTSIZE使用「标准」的显示大小。然而,从Windows 95开始,HORZSIZE和VERTSIZE值是从HORZRES、VERTRES、LOGPIXELSX和LOGPIXELSY值中衍生出来的。这是它的工作方式。

当您在「控制台」中使用「显示器」程序选择显示的图素大小时,也可以选择系统字体的大小。这个选项的原因是用于640×480显示的字体在提升到1024×768或更大时字太小,而您可能想要更大的系统字体。这些系统字体大小指「显示器」程序的「设定」页面卷标中的「小字体」和「大字体」。

在传统的排版中,字体的字母大小由「点」表示。1点大约1/72英寸,在计算机排版中1点正好为1/72英寸。

理论上,字体的点值是从字体中最高的字符顶部到例如j、p、q和y等字母下部的字符底部的距离,其中不包括重音符号。例如,在10点的字体中此距离是10/72英寸。根据TEXTMETRIC结构,字体的点值等于tmHeight字段减去tmInternalLeading字段,如图5-2所示(该图与上一章的图4-3一样)。


 



图5-2 小字体和TEXTMETRIC字段。
 

在真正的排版中,字体的点值与字体字母的实际大小并不正好相等。字体的设计者做出的实际字符比点值指示的要大一些或小一些。毕竟,字体设计是一种艺术而不是科学。

TEXTMETRIC结构的tmHeight字段指出文字的连续行在屏幕或打印机上间隔的方式。这也可以用点来测量。例如,12点的行距指出文字连续行的基准线应该间隔12/72(或1/6)英寸。不应该为10点字体使用10点行距,因为文字的连续行会碰到一起。

10点字体读起来很舒服。小于10点的字体不益于长时间阅读。

Windows系统字体-不考虑是大字体还是小字体,也不考虑所选择的视频图素大小-固定假设为10点字体和12点行距。这听起来很奇怪,如果字体都是10点,为什么还把它们称为大字体和小字体呢?

解答是:当您在「控制台」的「显示」程序上选择小字体或大字体时,实际上是选择了一个假定的视讯显示分辨率,单位是每英寸的点数 。当选择小字体时,即要Windows假定视讯显示分辨率为每英寸96点。当选择大字体时,即要Windows假定视讯显示分辨率为每英寸120点。

再看看图5-2。那是小字体,它依据的显示分辨率为每英寸96点。我说过它是10点字体。10点即是10/72英寸,如果乘以96点,每英寸大概就为13图素。这即是tmHeight减去tmInternalLeading的值。行距是12点,或12/72英寸,它乘以96点,每英寸就为16图素。这即是tmHeight的值。

图5-3显示大字体。这是依据每英寸120点的分辨率。同样,它是10点字体,10/72乘以120点,每英寸等于16图素,即是tmHeight减tmInternalLeading的值。12点行距等于20图素,即是tmHeight的值。(像第四章一样,再次强调所显示的是实际的度量大小,因此您可以理解它工作的方式。不要在您的程序中对此写作程序。)


 



图5-3 大字体和FONTMETRIC字段
 

在Windows程序中,您可以使用GetDeviceCaps函数取得使用者在「控制台」的「显示器」程序中选择的以每英寸的点数为单位的假定分辨率。要得到这些值(如果视讯显示器不具有正方形图素,在理论上这些值是不同的),可以使用索引LOGPIXELSX和LOGPIXELSY。LOGPIXELS指逻辑图素,它的基本意思是「以每英寸的图素数为单位的非实际分辨率」。

用HORZSIZE和VERTSIZE索引从GetDeviceCaps得到的设备能力,在文件上称为「实际屏幕的宽度,单位毫米」及「实际屏幕的高度,单位毫米」。因为这些值是从HORZRES、VERTRES、LOGPIXELSX和LOGPIXELSY值中衍生出来的,所以它们应该称为「逻辑宽度」和「逻辑高度」。公式是:


 




 


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -