Windows程序设计零基础自学_5_GDI基础_之获取设备内容信息

    不知道怎么回事,最近火气特别大, 而且也难以静下心来学习。

     非常不适应国有企业中的明争暗斗的, 整天在刀光剑影中挣扎,而且还战战兢兢的,如履薄冰。不知道外资企业怎么样,是不是没有这样的东西。

一直听说外资企业就是看技术看能力,基本没有这种的东西,不知道是不是.....................

     已经好几天没有静心学习了,昨天半夜被叫醒处理故障,今天虽然是周末但上午还到厂子里面处理故障,实在是累啊.....下午睡了一觉,感觉精神稍好,就

起来看看书。

    下面是今天总结的内容......

5.2.2 取得设备内容信息
     一个设备内容通常指一个实际显示设备,通常可以通过呼叫系统函数取得有关该设备的信息: 例如显示器大小和色彩显示能力。可以通过
GetDeviceCaps函数来取得这些消息。
Exp:
     iValue=GetDeviceCaps(hdc,iIndex);
  Tip:
       iIndex为WINGDI.H头文件中定义的29个宏之一。
    例如:
       iIndex为HORZRES将使GetDeviceCaps传回设备的宽度(单位为图素), iIndex为VERTRES时GetDeviceCaps将
    返回设备的高度信息。如果hdc是打印机设备内容句柄,则GetDeviceCaps将返回打印机显示区域的高度和宽度(单位
    是图素)。

5.2.3 设备的大小
    为了绘制一个边长是1英寸的正方形,则需要知道显示器上1英寸对应多少图素。在Windows程序里面可以使用GetDeviceCaps
函数获取有关显示器和打印机之类输出设备的实际显示大小信息。
    分辨率:
            打印机用每英寸点数表示分辨率:300dpi
            显示器则一般用水平和垂直的总图素来表示分辨率: 1024*768
    在windows程序设计中我们采用严格定义:
       分辨率: 每度量单位内的图素数目
       图素大小/图素尺寸: 表示设备水平或垂直显示的总图素
       度量大小/度量尺寸: 以英寸或mm为单位的设备显示区域的大小,即显示的x轴方向的大小或y轴大小
        这样:
                分辨率=图素大小/度量大小
    获取屏幕图素大小:
       1)windows应用程序可以使用SM_CXSCREEN和SM_CYSCREEN参数从GetSystemMetrics得到图素尺寸。
       2)可以利用HORZRES(水平分辨率: 水平图素大小)和VERTRES(垂直分辨率:垂直图素大小)参数
          从GetDeviceCaps中取得同样的值
    关于HORZSIZE和VERTSIZE:
       HORZSIZE:表示以毫米计算的实际屏幕宽度
       VERTSIZE:表示以毫米计算的实际屏幕高度
5.2.3.1
    当我们在改变显示属性: 桌面-》右击——》属性——》外观——》字体大小。
    这里有:字体大小的原因是用于当提高显示器的分辨率例如有640*480——》1024*768时可以显示更大的字体。
    这些字体大小是指系统字体大小:指显示器程序的设定页面卷标中的小字体和大字体。

    在传统的排版中,字体的字母大小由点表示。 1点~= 1/72 英寸。
    理论上;字体的点值是从字体中最高字符顶部到字符底部的距离,其中不包括重音符号。  高字符如: j、p、q、y等。
    例如在10点的字体中字符的点值就是10/72英寸。
       在TEXTMETRIC结构中:
                          字体点值= tmHeight- tmInternalLeading字段。
       tmHeight字段指出文字的连续行在屏幕或打印机上的间隔方式,这也可以用点来测量。
       行距: 两行字体间基准线间的点距离, 12点行距指出文字连续行的基准线间距为12/72英寸。

5.2.3.2 色彩
   当显示黑色图素和白色图素的时候,则每个图素仅需要内存中的一位,彩色显示器的每个图素需要多个位;通常
显示的颜色越多则需要的位数也越多。
   显示器可以显示的不同色彩的数目等于2的位数的乘方数。
 
   Full-color 显示器的分别率是每个图素24位: 8位红色、8位绿色和8为蓝色。 红、绿、蓝为色光三原色,混合
这三种颜色可以生成各种其他的颜色。

   High-color 显示分辨率每个图素16位: 5位红色、6为绿色、5位蓝色, 因为人眼对绿色敏感,所以多一位。

   显示256中颜色是显示卡每个图素需要8位。这些8位值一般由定义实际颜色的调色盘组织。

   显示16种颜色的显示卡每个图素需要4位,这些颜色一般固定为: 暗红/亮红、黑、蓝、青、紫、黄、两种灰色。
  
   通常只有某些特殊的程序需要知道显示卡上的内存是如何组织的。 可以通过GetDeviceCaps函数获取显示卡的储存组织以及
   显卡支持的颜色数目:
        iPlanes=GetDeviceCaps(hdc,PLANES);
   通过:
        iBitsPixel=GetDeviceCaps(hdc,BITSPIXEL); 可以获取每个图素的色彩位数
   大多数的显示设备使用多个色彩平面或每个图素有多个色彩位设计,这两种方式不能同时一起使用。
   这两个函数的返回值一定有一个 == 1 。
   显卡支持的色彩数:
        大约为  iColors=1<<(iPlanes * iBitPixel);
   这个值与用NUMCOLORS参数得到的值可能一样,也可能不一样。
        Exp:
              iColors=GetDeviceCaps(hdc,NUMCOLORS);

   对于256色的显示卡,使用色彩调色盘,这种情况下,以NUMCOLORS参数为参数时,GetDeviceCaps返回的值是windows
   保留的色彩数,值为20, 剩下的236种颜色由windows的调色盘管理其进行设定。对于Highcolor和True-color显示的
   分辨率,当用NUMCOLORS参数调用GetDeviceCaps函数返回值为-1, 表示无法获取所需信息,这时就需要使用PLANES和
   BITSPIXEL值的iColors计算公式。

RGB颜色
   在大多数的GDI函数呼叫中,使用COLORREF值(unsigned int )来表示一种色彩。COLORREF值按照红、绿、蓝的亮度
指定了一种颜色, 通常叫做、RGB颜色。
     31...24   23...16   15....8   7....0
        0        蓝色      绿色      红色
  注意这就是Full-color显示的颜色: D31-D24位为0; D23-D16表示的是蓝色, D15-D8是绿色, D7-D0是红色。理论上
这样采用RGB可以表示2^24 或1600万中色彩。

   这样的一个无符号数常常成为一个RGB色彩。 在windows的头文件WINGDI.H 提供了几种使用RGB色彩值的宏。RGB宏要求
三个参数分别代表:红、绿、蓝的值,然后将其组合为一个无符号整数。
Exp:
    #define RGB(r,g,b)  ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
因此值:
    RGB(255,255,0);是0x0000FFFF或黄色(红色和绿色的合成)。
    当r、g、b全设定为0时,则色彩位黑色,
      r、g、b全为255时,色彩为白色。
可以用GetRValue、GetGValue和GetBValue宏从COLORREF值中抽取原色值。

在16色或者256色的显示卡上,windows可以使用混色来模拟设备能够显示的颜色之外的颜色。混色利用了有多种
色彩的图素组成的图素图案,可以呼叫:
     GetNearestColor来决定于某一色彩最接近的纯色:
Exp:
   crPureColor=GetNearestColor(hdc,crColor);

5.2.4  设备内容属性
    windows使用设备内容来保存控制GDI函数在显示器上是如何操作的各种属性。
Exp:
     windows函数TextOut不需要指定文字的色彩和字体,windows会从设备内容上取得这些信息。

    应用程序在取得一个设备内容的句柄时,windows用默认值设定其所有的属性。
    windows定义了很多设备内容属性,这些属性可以查表获取。

5.2.4.1 保存设备内容
    通常在呼叫GetDC或BeginPaint时,windows会用默认值建立一个新的设备内容,在处理消息时对属性
所作的一切改变在设备内容用ReleaseDC或EndPaint呼叫释放时,都会丢失。如果程序使用非默认的设备内容
属性,则必须在应用程序内部在处理消息取得设备内容句柄时初始化设备内容。
Exp:
    case WM_PAINT:
         hdc=BeginPaint(hwnd,&ps);
         设备内容属性
         绘制窗口显示区域
         EndPaint(hwnd,&ps);
         return 0;

    利用上述的方法虽然可以满足一定的需求,但是有时需要在设备内容被释放后,仍然可以保存设备内容属性所作的更改,
以便于在下次调用GetDC和BeginPaint时属性仍然可以起作用。 这样的话需要:
    在注册窗口类别时将CS_OWNDC位旗标加入到窗口类别的style属性中。
Exp:
    wndclss.style=CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
    这样依据这个窗口类别建立的每个窗口,都将拥有自己的设备内容,并且这些属性一直存在,直到
窗口被删除,如果使用了CS_OWNDC风格,则只需初始化设备内容一次,可以在处理WM_CREATE消息时完成
设备内容的初始化工作:
Exp:
   case WM_CREATE:
        hdc=GetDC(hwnd);
        初始化设备内容
        ReleaseDC(hwnd,hdc);
        return 0;
 这样改变的设备内容属性,一直有效,直到再一次改变,或者窗口删除。
要点:
     1)WM_OWNDC风格只影响GetDC和BeginPaint获取的设备内容,不影响其他函数(如GetWindowDC)获取
的设备内容。
     2)即使使用了WM_OWNDC风格,仍然需要在消息处理return 0之前释放设备内容句柄。
     3)WM_OWNDC需要占用内存,但在图形处理程序中可以提供性能。
5.2.4.2
   有时可能想改变某些设备内容属性,用改变后的属性进行绘图,在绘制完图形后再恢复至绘图前的
设备内容属性。可以通过
Exp:
   case WM_LBUTTONDOWN:
        hdc=GetDC(hwnd);
        i=GetTextColor(hdc);
        SetSystemMetrics(hdc,某些属性);
        绘制图形;
        SetTextColor(hdc, i);
        ReleaseDC(hwnd,hdc);
也可以通过:
Exp:
    idSaved=SaveDC(hdc);
    改变属性
    绘图
    RestoreDC(hdc,idSaved);
可以在呼叫RestroreDC之前呼叫SaveDC多次。
这里还提供了一个更直接的方法:
Exp:
     SaveDC(hdc);
     改变某些属性
     这时还可以呼叫一次SaveDC。
     RestoreDC(hdc,-1); 这个操作会恢复到最近一次保存设备内容属性值的情况。
如果多次呼叫SaveDC,如果想恢复到最初的状态则需要进行多次RestoreDC操作。

下面进行测试的代码,比较简单,只有小部分地方加了注释:

   

/*
*
* 设备内容入门基础实例程序
*
*/

#include <windows.h>
#include <winuser.h>

#define NUMLINES ( (int)(sizeof devcaps/sizeof devcaps[0]))

struct DEVCAPS
{
int iIndex;
TCHAR *szLabel;
TCHAR *szDesc;
};
DEVCAPS devcaps[]=
{
HORZSIZE, TEXT("HORZSIZE"), TEXT("Width in millimeters:"),
VERTSIZE, TEXT("VERTSIZE"), TEXT("Height in millimeters:"),
HORZRES, TEXT("HORZRES"), TEXT("Width in pixels:"),
VERTRES, TEXT("VERTRES"), TEXT("Height in pixels"),
BITSPIXEL,TEXT("BITSPIXEL"), TEXT("Color bits per pixel"),
PLANES, TEXT("PLANES"), TEXT("Number of color planes:"),
NUMBRUSHES,TEXT("NUMBRUSHES"),TEXT("Number of device brushes:"),
NUMPENS,TEXT("NUMPENS"),TEXT("Number of device pens:"),
NUMMARKERS,TEXT("NUMMARKERS"),TEXT("Number of device marks:"),
NUMFONTS,TEXT("NUMFONTS"),TEXT("Number of device fonts"),
NUMCOLORS,TEXT("NUMCOLORS"),TEXT("Number of device colors:"),
PDEVICESIZE,TEXT("PDEVICESIZE"),TEXT("Size of device of structure:"),
ASPECTX,TEXT("ASPECTX"),TEXT("Relative width of pixel:"),
ASPECTY,TEXT("ASPECTY"),TEXT("Relative height of pixel:"),
LOGPIXELSX,TEXT("LOGPIXELSX"),TEXT("Horizontal dots per inch:"),
LOGPIXELSY,TEXT("LOGPIXELSY"),TEXT("Vertical dots per inch:"),
SIZEPALETTE,TEXT("SIZEPALETTE"),TEXT("Reserved palette entries:"),
COLORRES,TEXT("COLORRES"),TEXT("Actual color resolution:")
};

LRESULT CALLBACK WndProc(HWND, UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iShowCmd)
{
static TCHAR szAppName[]=TEXT("Devcaps1");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;

wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=WndProc;
wndclass.lpszClassName=szAppName;
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW | CS_VREDRAW ;

if(!RegisterClass(&wndclass))
{
MessageBox(NULL,"You need WinNT to run this program!",TEXT("Warning"),MB_OK);
return 0;
}

hwnd=CreateWindow(szAppName,
TEXT("GetDevcaps"),
WS_OVERLAPPEDWINDOW | WS_HSCROLL|WS_VSCROLL,
100,
100,
640,
480,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd,iShowCmd);
UpdateWindow(hwnd);

while(GetMessage(&msg,hwnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
static int cxChar,
cyChar,
cxCaps,
cyCaps;
static int i,
j=0;
TCHAR szBuffer[10];

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);
EndPaint(hwnd,&ps);
return 0; //这个程序表示WM_PAINT 这样处理的话,不会对无效区域进行重画。
case WM_LBUTTONDOWN:
hdc=GetDC(hwnd);
for(i=0;i<NUMLINES;i++)
{
j=j+20;
SetTextColor(hdc,RGB(j+5,j-10,j));
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);
}
SetTextColor(hdc,RGB(0,0,0));
ReleaseDC(hwnd,hdc);
return 0;
case WM_RBUTTONDOWN:
hdc=GetDC(hwnd);
TextOut(hdc,0,i*(1+cyChar),TEXT("Test color set function!"),lstrlen("Test color set function!"));
ReleaseDC(hwnd,hdc);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}

你可能感兴趣的:(windows)