版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第6章輸出在多任務環(huán)境下,屏幕,打印機等硬件設備都是許多應用程序共享的,因此,任何一個應用程序都不能任意地進行輸出操作,所有的輸出,如屏幕,打印機,繪圖機等,都必須通過GDI(圖形設備接口(GRAPHISCDEVICEINTERFACE)函數(shù)來完成輸出.本章表面上是討論的字符串輸出,實際上是討論與設備無關(guān)的程序設計基礎。本章例舉了三個例程來說明應用程序的輸出。6.1客戶區(qū)的繪制和更新Windows是通過發(fā)送WM_PAINT消息給窗口函數(shù),使得窗口顯示輸出。在初始化階段都要調(diào)用函數(shù)UpdateWindow,執(zhí)行這個函數(shù)的結(jié)果是Windows向窗口函數(shù)發(fā)送第一個WM_PAINT消息。其他還有很多情況下Windows向窗口函數(shù)發(fā)送WM_PAINT消息,使得被覆蓋的部分客戶區(qū)得以重新繪制。
發(fā)送WM_PAINT的情況P1026.1客戶區(qū)的繪制和更新有效矩形和無效矩形1:Windows內(nèi)部為每個窗口保存一個「繪圖信息結(jié)構(gòu)」,這個結(jié)構(gòu)包含了包圍無效區(qū)域的最小矩形的坐標以及其它信息,這個矩形就叫做「無效矩形」,有時也稱為「無效區(qū)域」。如果在窗口消息處理程序處理WM_PAINT消息之前顯示區(qū)域中的另一個區(qū)域變?yōu)闊o效,則Windows計算出一個包圍兩個區(qū)域的新的無效區(qū)域(以及一個新的無效矩形),并將這種變化后的信息放在繪制信息結(jié)構(gòu)中。Windows不會將多個WM_PAINT消息都放在消息隊列中。6.1客戶區(qū)的繪制和更新有效矩形和無效矩形2:窗口消息處理程序可以通過呼叫InvalidataRect使顯示區(qū)域無效.3:在處理WM_PAINT消息處理期間,窗口消息處理程序在呼叫了BeginPaint之后,整個顯示區(qū)域即變?yōu)橛行А3绦蛞部梢酝ㄟ^呼叫ValidateRect函數(shù)使顯示區(qū)域內(nèi)的任意矩形區(qū)域變?yōu)橛行?。如果這呼叫具有令整個無效區(qū)域變?yōu)橛行У男Ч瑒t目前隊列中的任何WM_PAINT消息都將被刪除。6.1客戶區(qū)的繪制和更新InvalidateRect只是增加重繪區(qū)域,在下次WM_PAINT的時候才生效,InvalidateRect函數(shù)中的參數(shù)TRUE表示系統(tǒng)會在你畫之前用背景色將所選區(qū)域覆蓋一次,默認背景色為白色,可以通過設置BRUSH來改變背景色。InvalidateRect(hWnd,&rect,TRUE);向hWnd窗體發(fā)出WM_PAINT的消息,強制客戶區(qū)域重繪制,rect是你指定要刷新的區(qū)域,此區(qū)域外的客戶區(qū)域不被重繪,這樣防止客戶區(qū)域的一個局部的改動,而導致整個客戶區(qū)域重繪而導致閃爍,如果最后的參數(shù)為TRUE,則還向窗體發(fā)送WM_ERASEBKGND消息,使背景重繪,當然在客戶區(qū)域重繪之前。UpdateWindow只向窗體發(fā)送WM_PAINT消息,在發(fā)送之前判斷GetUpdateRect(hWnd,NULL,TRUE)看有無可繪制的客戶區(qū)域,如果沒有,則不發(fā)送WM_PAINT。如果希望立即刷新無效區(qū)域,可以在調(diào)用InvalidateRect之后調(diào)用UpdateWindow,如果客戶區(qū)的任一部分無效,則UpdateWindow將導致Windows用WM_PAINT消息調(diào)用窗口過程(如果整個客戶區(qū)有效,則不調(diào)用窗口過程)。這一WM_PAINT消息不進入消息隊列,直接由WINDOWS調(diào)用窗口過程。窗口過程完成刷新以后立刻退出,WINDOWS將控制返回給程序中UpdateWindow調(diào)用之后的語句。6.2GDI簡介所有輸出都要通過GDI函數(shù),當執(zhí)行GDI函數(shù)輸出時,可得到與設備無關(guān)的輸出,其實現(xiàn)是源于Windows系統(tǒng)中為每一個設備建立一個數(shù)據(jù)結(jié)構(gòu),這個結(jié)構(gòu)記錄了設備輸出時的詳細要求,例如,輸出時文字的顏色,線條的寬度,畫圖的坐標,…以及輸出時調(diào)用的驅(qū)動程序等,這個數(shù)據(jù)結(jié)構(gòu)稱為設備描述表,簡稱DC。Windows系統(tǒng)中使用設備就抽象成使用DC。這種把設備抽象成為DC是實現(xiàn)設備無關(guān)性的關(guān)鍵。每個輸出用的GDI函數(shù)其第1個參數(shù)就是hdc,hdc是指向DC的指針,GDI函數(shù)通過設備進行輸出就變成通過DC進行輸出。同樣,要輸出都得要考慮在那個窗口上輸出,為此要為每個輸出窗口建立一個數(shù)據(jù)結(jié)構(gòu)--繪圖信息結(jié)構(gòu)(PAINTSTRUCT)注意:取得DC,必須釋放DC且必須寫到同一消息處理分支中例:P1056.2.2獲得hDC代號的方法。1.利用GetDC(hWnd)取得窗口hDC.
hdc=GetDC(hwnd);
注意:GetDC不會使任何無效區(qū)域變?yōu)橛行В梢允褂胿alidateRect(hwnd,NULL)使整個客戶區(qū)有效。
ReleaseDC(hWnd,hdc);
2.處理WM_PAINT消息期間用
BeginPaint獲得hDC的方法。
PAINTSTRUCTps
;
hdc=BeginPaint(hwnd,&ps);
TextOut(hdc,0,0,“Hello,Windows!”,15);
EndPaint(hwnd,&ps);
.
6.2.3繪圖信息結(jié)構(gòu)(PAINTSTRUCT)繪圖信息結(jié)構(gòu)(PAINTSTRUCT)typedef
struct
tagPAINTSTRUCT{ HDC hdc;//輸出設備的設備描述表代號
BOOL fErase;//畫圖區(qū)域的背景要否擦去
RECT rcPaint;//畫圖區(qū)域坐標,無效矩形的邊界,
BOOL fRestore;//操作系統(tǒng)用
BOOL fIncUpdate;//操作系統(tǒng)用
BYTE rgbReserved[32];//操作系統(tǒng)用}PAINTSTRUCT;通過PAINTSTRUCTps;定義變量,程序調(diào)用BeginPaint時,返回值是hDC,Windows會把它填入PAINTSTRUCT中。用戶程序只使用畫圖信息結(jié)構(gòu)的前三個條款,其他條款由Windows操作系統(tǒng)內(nèi)部使用。hdc條款是BeginPaint的返回值。fErase被標志為FALSE(0),這意味著Windows已經(jīng)擦除了無效矩形的背景。rcPaint
是一個結(jié)構(gòu)指針,指向RECT結(jié)構(gòu),RECT結(jié)構(gòu)記錄著畫圖區(qū)域坐標,無效矩形的邊界。6.2.3繪圖信息結(jié)構(gòu)(PAINTSTRUCT)在調(diào)用BeginPaint後PAINTSTRUCT結(jié)構(gòu)的fErase條款將成為TRUE(非零)
PAINTSTRUCT結(jié)構(gòu)的rcPaint條款是RECT類型的結(jié)構(gòu),RECT結(jié)構(gòu)定義了一個無效矩形的邊界坐標6.2.3繪圖信息結(jié)構(gòu)(PAINTSTRUCT)BOOLInvalidateRect(HWNDhWnd,//handleofwindowwithchangedupdateregionCONSTRECT*lpRect,//addressofrectanglecoordinatesBOOLbErase//erase-backgroundflag);
其中InvalidateRect(hwnd,NULL,true);重畫時將擦除背景。InvalidateRect(hwnd,NULL,false);重畫時不擦除背景6.3TextOut函數(shù)。TextOut是在屏幕上顯示文字的最常用的GDI函數(shù)。語法是:TextOut(hdc,x,y,psText,iLength)hdc--屏幕也是設備。
1.hDC就是屏幕的設備描述表代號
2.x,y是客戶區(qū)內(nèi)輸出字符串的開始地址,x是水平地址,y是垂直地址,
3.psText參數(shù)是指向需要在窗口顯示的字符串的指針,
4.iLength是輸出字符串中字符的個數(shù)6.4重畫區(qū)域的設定WM_PAINT窗口消息并非只來源于Windows系統(tǒng),它們可以使用InvalidateRect或InvalidateRgn函數(shù)直接產(chǎn)生并送消息隊列。一般是先設定一個重畫區(qū),然后再用它們中的一個送WM_PAINT消息到消息隊列,再排隊進入窗口函數(shù)并在這個分支中進行重畫。InvalidateRect設定的重畫區(qū)是矩形,InvalidateRgn函數(shù)設定的重畫區(qū)為不規(guī)則區(qū)域。6.4重畫區(qū)域的設定InvalidateRect函數(shù)(MSDN)6.5系統(tǒng)字體字體的基本概念等寬字體和變寬字體6.5.1系統(tǒng)字體字體參數(shù)存貯在TEXTMETRIC類型的結(jié)構(gòu)typedef
struct
tagTEXTMETRIC{ LONGtmHeight; LONGtmAscent; LONGtmDescent; LONGtmInternalLeading; LONGtmExternalLeading; LONGtmAveCharWidth;LONGtmMaxCharWidth;
其他結(jié)構(gòu)條款}TEXTMETRIC系統(tǒng)定義的TEXTMETRICS的結(jié)構(gòu)如下:typedefstructtagTEXTMETRIC
{ //tmLONGtmHeight; //字符高度LONGtmAscent; //字符基線以上高度LONGtmDescent; //字符基線以下高度LONGtmInternalLeading; //tmHeight制訂的字符高度頂部的控件LONGtmExternalLeading; //行與行之間的間隔LONGtmAveCharWidth; //平均字符寬度LONGtmMaxCharWidth; //最大字符寬度LONGtmWeight; //字符的粗細度LONGtmOverhang; //合成字體間附加的寬度LONGtmDigitizedAspectX; //為輸出設備設計的X軸尺寸LONGtmDigitizedAspectY; //為輸出設備設計的Y軸尺寸BCHARtmFirstChar; //字體中第一個字符值BCHARtmLastChar; //字體中最后一個字符值BCHARtmDefaultChar; //代替不在字體中字符的字符BCHARtmBreakChar; //作為分割符的字符BYTEtmItalic; //非0則表示字體為斜體BYTEtmUnderlined; //非0則表示字體有下劃線BYTEtmStruckOut; //非0則表示字符為刪除字體BYTEtmPitchAndFamily; //字體間距和字體族BYTEtmCharSet; //字符集}TEXTMETRIC6.5.2系統(tǒng)字體用五個參數(shù)表示字體尺寸格式化文本(1)確定后續(xù)文本坐標換行時確定下一行文本的坐標需要格式化處理的情況在文本行中確定后續(xù)文本的坐標確定后續(xù)文本的坐標,應先獲取當前的字符串的寬度,
該工作由GetTextExtentPoint32函數(shù)完成,并把它存儲于一個SIZE結(jié)構(gòu)中。BOOLGetTextExtentPoint32(
HDChdc,
LPCTSTRlpszString,//指定的字符串
int
nLength, //字符串中的字符數(shù)
LPSIZElpSize
//返回字符串寬度及高度的SIZE數(shù)據(jù)結(jié)構(gòu)的地址)SIZE數(shù)據(jù)結(jié)構(gòu)的定義typedefstructtagSIZE{LONGcx;
LONGcy;
}SIZE;例如,X軸起始坐標為cx0,后續(xù)文本起始坐標cx1為:
cx1=cx0+size.cx;
GetTextExtentPoint32(hDC,
Text,
lstrlen(Text),
size)
(2)確定換行時文本坐標字符的高度與行間隔均存儲在tm指向的TEXTMETRIC結(jié)構(gòu)中,換行時Y軸上文本的起始坐標cy為:
cy=tm.tmHeight+tm.tmExternalLeading;通過計算當前行文本字符的高度與行間隔之和,即可得到換行時文本的起始坐標6.5.3格式化文字下面是取得系統(tǒng)字體的字符寬度和高度的WM_CREATE程序碼:caseWM_CREATE:hdc=GetDC(hwnd);//取得窗口的DCGetTextMetrics(hdc,&tm);//通過DC取得字體的尺寸信息存入tm結(jié)構(gòu)cxChar=tm.tmAveCharWidth;//從tm結(jié)構(gòu)中得到平均寬度cyChar=tm.tmHeight+tm.tmExternalLeading;//從tm結(jié)構(gòu)中有關(guān)參數(shù)祘出總高度ReleaseDC(hwnd,hdc);//釋放DC return0;6.5.3格式化文字int
iLength;//定義變量存放長度TCHARszBuffer[40];//寬字符數(shù)組,存放sprintf-wsprintf的格式化輸出程序如下:iLength=wsprintf(szBuffer,TEXT("Thesumof%iand%iis%i"),
iA,iB,iA+iB);//TEXT把字符串輸出,wsprintf將它存進szbufferTextOut(hdc,x,y,szBuffer,iLength);文本操作實例【例】在用戶窗口上輸出幾行字符串,當窗口接收到WM_PAINT消息后,顯示的文本每次都被重新刷新。#include<windows.h>#include<stdlib.h>#include<string.h>longWINAPIWndProc(
HWNDhWnd,
UINTiMessage,
UINTwParam,
LONGlParam
);BOOLInitWindowsClass(HINSTANCE
hInstance);BOOLInitWindows(HINSTANCE
hInstance,int
nCmdShow);//主函數(shù)intWINAPIWinMain(
HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPSTRlpCmdLine,
intnCmdShow){
MSGMessage;
if(!InitWindowsClass(hInstance)) returnFALSE;
if(!InitWindows(hInstance,nCmdShow))returnFALSE;
while(GetMessage(&Message,0,0,0))//消息循環(huán)
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
returnMessage.wParam;}//消息處理函數(shù)longWINAPIWndProc(HWND
hWnd,UINT
iMessage,UINT
wParam,LONG
lParam){
staticlongnXChar,nYChar;
HDChDC;//定義指向設備上下文的句柄
shortx;
TEXTMETRICtm;
shortLnCount=6;
PAINTSTRUCTPtStr;//定義指向包含繪圖信息的結(jié)構(gòu)體變量
staticchar*textbuf[]= {
"ThisistheFirstline",
"Thisisthesecondline",
"Thisisthethirdline",
"Thisisthefourthline",
"Thisisthefifthline",
"Thisisthesixthline"
};輸出的文本內(nèi)容switch(iMessage)//處理消息
{caseWM_CREATE: //處理窗口創(chuàng)建消息
hDC=GetDC(hWnd); //獲取當前設備表句柄
GetTextMetrics(hDC,&tm); //獲取字體信息
nXChar=tm.tmAveCharWidth; //獲取字符寬度
nYChar=tm.tmHeight+tm.tmExternalLeading;
ReleaseDC(hWnd,hDC); //釋放當前設備句柄
return0;
caseWM_PAINT: //處理重畫消息
hDC=BeginPaint(hWnd,&PtStr); //開始繪畫
for(x=0;x<LnCount;x=x+1) //輸出文本
TextOut(hDC,nXChar,nYChar*(1+x),textbuf[x],lstrlen(textbuf[x]));
EndPaint(hWnd,&PtStr); return0;
caseWM_DESTROY: //結(jié)束應用程序
PostQuitMessage(0); return0;default: //其他消息處理程序
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}}BOOLInitWindowsClass(HINSTANCE
hInstance) //初始化窗口類{
WNDCLASSWndClass; …………;
WndClass.style=CS_HREDRAW|CS_VREDRAW;
returnRegisterClass(&WndClass);}BOOLInitWindows(HINSTANCE
hInstance,int
nCmdShow)//初始化窗口{
HWNDhWnd;
hWnd=CreateWindow("WinText",//生成窗口
"文本顯示示例程序", WS_OVERLAPPEDWINDOW, …….; NULL);
if(!hWnd) returnFALSE;
ShowWindow(hWnd,nCmdShow); //顯示窗口
UpdateWindow(hWnd);
returnTRUE;}【例】將一首四句的古詩從右到左豎排輸出。要求窗口每次接收到WM_PAINT消息時都刷新顯示的文本。
#include<windows.h>#include<stdlib.h>#include<string.h>longWINAPIWndProc(HWND
hWnd,UINT
iMessage,UINT
wParam,LONG
lParam);BOOLInitWindowsClass(HINSTANCE
hInstance);BOOLInitWindows(HINSTANCE
hInstance,int
nCmdShow);
//主函數(shù)intWINAPIWinMain(HINSTANCE
hInstance,HINSTANCEhPrevInstance, LPSTRlpCmdLine,int
nCmdShow){ MSGMessage;
if(!InitWindowsClass(hInstance)) returnFALSE;
if(!InitWindows(hInstance,nCmdShow)) returnFALSE; while(GetMessage(&Message,0,0,0)) //消息循環(huán)
{TranslateMessage(&Message);
DispatchMessage(&Message); } returnMessage.wParam;}longWINAPIWndProc(HWND
hWnd,UINT
iMessage,UINTwParam,LONGlParam)1.{staticlongnXChar,nCaps,nYChar;2.int
pointx,pointy,i,j;3.HDChDC; //定義指向設備環(huán)境的句柄 4.TEXTMETRICtm; //存放字體各種屬性的結(jié)構(gòu)體變量5.PAINTSTRUCTPtStr; //指向包含繪圖信息的結(jié)構(gòu)體變量6.staticchar*textbuf[4]={{"故人西辭黃鶴樓"},{"煙花三月下?lián)P州"}, {"孤帆遠影碧空盡"},{"唯見長江天際流"}};7.switch(iMessage) //處理消息8.{ caseWM_CREATE: //處理窗口創(chuàng)建消息9. hDC=GetDC(hWnd); //獲取當前設備表句柄10. GetTextMetrics(hDC,&tm); //獲取字體信息11. nXChar=tm.tmAveCharWidth; //獲取字符寬度12.nYChar=tm.tmHeight+tm.tmExternalLeading; //字符高度13. nCaps=(tm.tmPitchAndFamily&1?3:2)*nXChar/2; //字間距14. ReleaseDC(hWnd,hDC);return0; //釋放當前設備句柄15. caseWM_PAINT: //處理重畫消息16. hDC=BeginPaint(hWnd,&PtStr); //開始繪圖17. for(i=4;i>0;i--)18. {for(j=0;j<7;j++) //輸出文本19.
{pointx=100+i*nXChar*5; pointy=50+j*(nYChar+nCaps);20.
TextOut(hDC,pointx,pointy,textbuf[4-i]+j*2,2);}}21.EndPaint(hWnd,&PtStr);return0; //結(jié)束繪圖22. caseWM_DESTROY://結(jié)束應用程序
PostQuitMessage(0); return0;23. default: return(DefWindowProc(hWnd,iMessage,wParam,lParam));}}6.6字體顯示的綜合使用SYSMETS1.c
視覺元件信息表struct
{
int Index;//索引
TCHAR* szLabel;//指向?qū)捵址闹羔?/p>
TCHAR* szDesc;//指向?qū)捵址闹羔榼sysmetrics;//這是定義的結(jié)構(gòu)名,sysmetrics[]//此結(jié)構(gòu)數(shù)組用作視覺元件信息表P1156.7SYSMETS1.c
SYSMETS1.c程序例子:6\SYSMETS1.c6.7SYSMETS1.cSYSMETS1.c窗口函數(shù)的分析。
SYSMETS1.c程序存在問題。6.8滾動條的使用滾動條的范圍和地址6.8滾動條的使用滾動條的范圍BOOLSetScrollRange(HWND
hWnd,//handletowindowwithscrollbarint
nBar,//scrollbarflagint
nMinPos,//minimumscrolling positionint
nMaxPos,//maximumscrollingpositionBOOL
bRedraw//redrawflag);
nBar:SB_HORZSetstherangeofawindow'sstandardhorizontalscrollbar.SB_VERTSetstherangeofawindow'sstandardverticalscrollbar.SetScrollRange()6.8滾動條的使用滾動條的地址int
SetScrollPos(HWND
hWnd,//handletowindowwithscrollbarint
nBar,//scrollbarflagint
nPos,//newpositionofscrollboxBOOL
bRedraw//redrawflag);
GetScrollPos()6.8滾動條的使用如果設置滾動范圍為0到46.8滾動條的使用滾動條消息WM_VSCROLL(供上下移動)和WM_HSCROLL(供左右移動)消息。通知碼的解釋(MSDN中WM_VSCROLL)P123-124(注意)6.8滾動條的使用在SYSMETS1.C中加入滾動功能
(例子\6\SYSMETS2.C.doc)
6.8滾動條的使用
WM_VSCROLL消息分支中更新客戶區(qū)的方法。6.9建立更好的滾動在使用滾動條功能時,如果要設置它的范圍和位置可以用以前的函數(shù),例如:SetScrollRange()、
SetScrollPos()、GetScrollRange(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 喉感覺麻痹的健康宣教
- 電力系統(tǒng)分析課件孟祥萍
- 黑素細胞痣的臨床護理
- 小兒蕁麻疹的臨床護理
- 先天性耳廓畸形的健康宣教
- 哺乳期乳頭皸裂的健康宣教
- 《單片機原理及應用 》課件-第4章
- 《第一章》課件-第五章技術(shù)體驗 - 智能交互
- 皮膚良性腫瘤的臨床護理
- 隆突性皮膚纖維肉瘤的臨床護理
- O型密封圈壓縮量計算
- 云南省昆明市盤龍區(qū)2023-2024學年部編版九年級歷史上學期期末質(zhì)量監(jiān)測試題(含答案)
- 公交公司點鈔管理制度
- 華師大版七年級上冊數(shù)學期末考試試卷含答案
- 呆滯料與超期物料處理流程
- 2019年4月自考00015英語二真題及答案含解析
- 重癥患者中心靜脈導管管理專家共識解讀
- 長輸管道犧牲陽極法陰極保護施工方案
- 保函(履約、投標、付款、質(zhì)量等保函參考格式)
- 北京東城區(qū)北京匯文中學2023-2024學年高二物理第一學期期末復習檢測模擬試題含解析
- 《流程分析與改善》課件
評論
0/150
提交評論