在第三章我們已經使用設備環境句柄在窗口客戶區繪圖了。在圖形輸出設備(比如屏幕或者打印機)上繪制圖形,必須首先獲取設備環境,即DC的句柄。當 Windows把這個句柄交給你的程序,Windows同時也就給予你使用這個設備的權限。接著,在GDI函數中將這個句柄作為一個參數,告訴 Windows在哪個設備上進行繪圖。
本節必須掌握的知識點:
獲取設備環境句柄
獲取設備環境信息
第22練:獲取設備環境信息
設備環境包含許多決定GDI函數如何工作的屬性。這些屬性使得GDI函數只需要提供少量的參數(如起始坐標),而不需要提供 Windows在設備上顯示對象時需要的所有信息。例如,當你調用 TextOut函數時,僅需要在函數中指定設備環境句柄、起始坐標、文本以及文本的長度,不需要指定字體、文本的顏色、文本背景的顏色或者字符間距。所有這些屬性都是設備環境的一部分。當你想改變這些屬性時,可以調用函數來執行,之后調用的TextOut函數就會使用新的設備環境的屬性。
■在WM_PAINT消息中獲取
在處理 WM_PAINT消息時使用 BeginPaint函數和 EndPaint函數:
hdc=BeginPaint (hwnd, &ps) ;
其他行程式
EndPaint (hwnd, &ps) ;
■在其他消息中獲取
hdc=GetDC (hwnd) ;
其他行程式
ReleaseDC (hwnd, hdc) ;
EndPaint函數組合與GetDC函數組合的主要差別是:
EndPaint函數獲取無效區域的設備環境句柄。
GetDC函數返回的是整個窗口客戶區的設備環境句柄。并且GetDC和 ReleaseDC函數并不使任何客戶區的無效區域變為有效。
■獲取屏幕設備環境句柄
hdc=CreateDC (pszDriver, pszDevice, pszOutput, pData) ;
其他行程式
DeleteDC (hdc) ;
例如,可以通過調用下面的函數獲取當前整個屏幕的設備環境句柄:
hdc=CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;
此外,我們還將在第十三章使用CreateDC函數獲取打印機設備環境句柄。
■獲取內存設備環境句柄
hdcMem=CreateCompatibleDC (hdc) ;
其他行程式
DeleteDC (hdcMem) ;
可以把一個位圖選入內存設備環境,并且調用GDl函數繪制這個位圖。我將在第十四章介紹這些技術。
■獲取整個窗口設備環境句柄
hdc=GetWindowDC (hwnd) ;
其他行程式
ReleaseDC (hwnd, hdc) ;
這里的設備環境除了包括客戶區,還包含窗口標題欄、菜單、滾動條和客戶區的外框。應用程序很少使用 GetWindowDC函數。如果你想嘗試使用它,則還應當捕獲WM_NCPAINT( nonclient paint,非客戶區繪制)消息,Windows使用這個消息在窗口的非客戶區繪圖。
■獲取圖元文件設備環境句柄
hdcMeta=CreateMetaFile (pszFilename) ;
其他行程式
hmf=CloseMetaFile (hdcMeta) ;
在圖元文件設備環境有效時,使用 hdcMeta所做的任何GDI調用都不會被直接顯示出來,它們都會變成圖元文件的一部分。當你調用 CloseMetaFile時,圖元文件設備環境句柄變為無效,該函數返回一個圖元文件句柄(hmf)。我將在第十七章討論圖元文件。
設備環境通常指的是物理的顯示設備,如視頻顯示器或者打印機。經常需要獲取這些設備的某些信息,包括顯示器的大小(以像素或者物理尺寸的方式)和它的色彩能力。這些信息可以通過調用 GetDeviceCaps(意思為獲取設備的能力)函數來獲取。
iValue=GetDeviceCaps (hdc, iIndex) ;
其中,參數 iIndex是定義在 WINGDL.H頭文件中的29個標識符之一。例如,當 iIndex的值為 HORZRES時, GetDeviceCaps函數以像素為單位返回設備的寬度;使用ⅤERTRES參數值會以像素為單位返回設備的高度。如果hdc是一個屏幕設備環境的句柄,這里所獲取的信息和從 GetSystemMetrics函數獲取的信息是一樣的。如果hdc是一個打印機設備環境,那么 GetDevice Caps將以像素為單位返回打印機顯示區域的高度和寬度。
還可以使用 GetDeviceCaps函數來確定設備處理各種類型圖形的能力。通常這對于視頻顯示器并不重要,但是對于打印機卻非常重要。例如,大多數的繪圖儀不能繪制位圖圖像,通過調用 GetDeviceCaps函數可以讓你提前知道這一情況。我們將在接下來的實例中演示GetDeviceCaps函數的使用方法。
/*------------------------------------
022. 編程達人win32 API每日一練
第22個例子DEVCAPS1.C:獲取顯示器設備環境信息
GetDeviceCaps函數
(c) www.bcdaren.com, 2020
-------------------------------------------*/
#include <windows.h>
#define NUMLINES ((int)(sizeof devcaps / sizeof devcaps[0])) //行數
struct
{
int iIndex; //索引
TCHAR *szLable; //系統信息
TCHAR *szDesc; //描述
}
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 raster lines:"),
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 markers:"),
NUMFONTS, TEXT("NUMFONTS"), TEXT("Number of device fonts:"),
NUMCOLORS, TEXT("NUMCOLORS"), TEXT("Number of device colors:"),
PDEVICESIZE, TEXT("PDEVICESIZE"), TEXT("Size of devicestructure:"),
ASPECTX, TEXT("ASPECTX"), TEXT("Relative width of pixel:"),
ASPECTY, TEXT("ASPECTY"), TEXT("Relative height of pixel:"),
ASPECTXY, TEXT("ASPECTXY"), TEXT("Relative diagonal of pixel:"),
LOGPIXELSX, TEXT("LOGPIXELSX"), TEXT("Horizontal dots per inch:"),
LOGPIXELSY, TEXT("LOGPIXELSY"), TEXT("Vertical dots per inch:"),
SIZEPALETTE, TEXT("SIZEPALETTE"), TEXT("Number of palette entries:"),
NUMRESERVED, TEXT("NUMRESERVED"), 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,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[]=TEXT ("DEVCAPS1.C") ;
…(略)
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar;
HDC hdc ;
int i;
PAINTSTRUCT ps ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc=GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar=tm.tmAveCharWidth ; //字符平均寬度
//平均字符寬度cxCaps設為cxChar的1.5倍。1表示變寬字體
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].szLable,
lstrlen(devcaps[i].szLable));
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);
}
/****************************
GetDeviceCaps功能檢索指定設備的設備特定的信息
int GetDeviceCaps(
HDC hdc, //設備環境句柄
int index //設備環境信息索引
);
返回值指定所需項目的值。
********************************
類似的API:
GetSystemMetrics函數:檢索指定的系統指標或系統配置設置。
int GetSystemMetrics(int nIndex //要檢索的系統指標或配置設置);
*/
運行結果:
圖4-1 獲取顯示設備信息
總結
DEVCAPS1.C的代碼實現非常簡單,定義了一個顯示設備信息的結構數組,然后在WM_PAINT消息中循環輸出GetDeviceCaps(hdc,devcaps[i].iIndex)));獲取的顯示設備信息。
微軟這兩天的發布會適逢國慶假期,關心的人可能會少很多,除了推出Surface Pro 6之外,對廣大Windows用戶最重要的消息就是Windows 10十月更新開始推送了,由于微軟智能化分批推送策略所致,并非所有人都會在第一時間收到通知,沒收到的等下就是了。對游戲玩家來說,這次的10月更新還有個驚喜,那就是Windwos 10正式支持微軟的DXR光線追蹤技術了,想玩戰地5、古墓麗影等支持光線追蹤的游戲玩家更要升級了。
微軟的DirectX RayTracing(簡稱DXR)在今年的GDC大會上正式宣布,它包括4項全新的DirectX 12 API:Acceleration Structure(加速結構)、DispatchRays(調度光),同時還有一系列的HLSL著色器,最后是Raytracing Pipeline State(光線追蹤管線)。
雖然看上去很復雜,但是DirectX Raytracing并不需要額外的、全新的DirectX 12 Engine,這是微軟團隊有意為之的,目的就是就讓目前能夠良好支持DirectX 12的顯卡都能支持好DirectX Raytracing,所以目前支持DirectX12良好的Unreal、Unity、Frostbite都可以很到位的直接支持。
早前升級過Windows 10秋季創意者更新的玩家已經可以通過開發者模式體驗DXR,現在推送的Windows 10十月更新則是正式支持DXR了,每個玩家都可以體驗到光線追蹤技術了,前提是你有支持DXR光線追蹤的硬件及游戲,前一個條件目前只有圖靈顯卡,而DXR光線追蹤游戲已經有戰地5、古墓麗影及Metro Exodus,不過現在這些游戲要么沒上市,要么還沒實裝光線追蹤技術,還要等等。
Windows 10十月更新已經在太平洋時間10月2日下午2點之后開放,沒收到升級通知的耐心等下,這是微軟分批推送所致,等等就會有了,Windows 10不會放過你們的更新的!