WINDOWS 程序設計教程(6章)_第1頁
WINDOWS 程序設計教程(6章)_第2頁
WINDOWS 程序設計教程(6章)_第3頁
WINDOWS 程序設計教程(6章)_第4頁
WINDOWS 程序設計教程(6章)_第5頁
已閱讀5頁,還剩39頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第6章輸出在多任務環(huán)境下,屏幕,打印機等硬件設備都是許多應用程序共享的,因此,任何一個應用程序都不能任意地進行輸出操作,所有的輸出,如屏幕,打印機,繪圖機等,都必須通過GDI(圖形設備接口(GRAPHISCDEVICEINTERFACE)函數(shù)來完成輸出.本章表面上是討論的字符串輸出,實際上是討論與設備無關的程序設計基礎。本章例舉了三個例程來說明應用程序的輸出。6.1客戶區(qū)的繪制和更新Windows是通過發(fā)送WM_PAINT消息給窗口函數(shù),使得窗口顯示輸出。在初始化階段都要調用函數(shù)UpdateWindow,執(zhí)行這個函數(shù)的結果是Windows向窗口函數(shù)發(fā)送第一個WM_PAINT消息。其他還有很多情況下Windows向窗口函數(shù)發(fā)送WM_PAINT消息,使得被覆蓋的部分客戶區(qū)得以重新繪制。

發(fā)送WM_PAINT的情況P1026.1客戶區(qū)的繪制和更新有效矩形和無效矩形1:Windows內部為每個窗口保存一個「繪圖信息結構」,這個結構包含了包圍無效區(qū)域的最小矩形的坐標以及其它信息,這個矩形就叫做「無效矩形」,有時也稱為「無效區(qū)域」。如果在窗口消息處理程序處理WM_PAINT消息之前顯示區(qū)域中的另一個區(qū)域變?yōu)闊o效,則Windows計算出一個包圍兩個區(qū)域的新的無效區(qū)域(以及一個新的無效矩形),并將這種變化后的信息放在繪制信息結構中。Windows不會將多個WM_PAINT消息都放在消息隊列中。6.1客戶區(qū)的繪制和更新有效矩形和無效矩形2:窗口消息處理程序可以通過呼叫InvalidataRect使顯示區(qū)域無效.3:在處理WM_PAINT消息處理期間,窗口消息處理程序在呼叫了BeginPaint之后,整個顯示區(qū)域即變?yōu)橛行?。程序也可以通過呼叫ValidateRect函數(shù)使顯示區(qū)域內的任意矩形區(qū)域變?yōu)橛行АH绻@呼叫具有令整個無效區(qū)域變?yōu)橛行У男Ч?,則目前隊列中的任何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ū)域,可以在調用InvalidateRect之后調用UpdateWindow,如果客戶區(qū)的任一部分無效,則UpdateWindow將導致Windows用WM_PAINT消息調用窗口過程(如果整個客戶區(qū)有效,則不調用窗口過程)。這一WM_PAINT消息不進入消息隊列,直接由WINDOWS調用窗口過程。窗口過程完成刷新以后立刻退出,WINDOWS將控制返回給程序中UpdateWindow調用之后的語句。6.2GDI簡介所有輸出都要通過GDI函數(shù),當執(zhí)行GDI函數(shù)輸出時,可得到與設備無關的輸出,其實現(xiàn)是源于Windows系統(tǒng)中為每一個設備建立一個數(shù)據(jù)結構,這個結構記錄了設備輸出時的詳細要求,例如,輸出時文字的顏色,線條的寬度,畫圖的坐標,…以及輸出時調用的驅動程序等,這個數(shù)據(jù)結構稱為設備描述表,簡稱DC。Windows系統(tǒng)中使用設備就抽象成使用DC。這種把設備抽象成為DC是實現(xiàn)設備無關性的關鍵。每個輸出用的GDI函數(shù)其第1個參數(shù)就是hdc,hdc是指向DC的指針,GDI函數(shù)通過設備進行輸出就變成通過DC進行輸出。同樣,要輸出都得要考慮在那個窗口上輸出,為此要為每個輸出窗口建立一個數(shù)據(jù)結構--繪圖信息結構(PAINTSTRUCT)注意:取得DC,必須釋放DC且必須寫到同一消息處理分支中例:P1056.2.2獲得hDC代號的方法。1.利用GetDC(hWnd)取得窗口hDC.

hdc=GetDC(hwnd);

注意:GetDC不會使任何無效區(qū)域變?yōu)橛行?,可以使用validateRect(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繪圖信息結構(PAINTSTRUCT)繪圖信息結構(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;定義變量,程序調用BeginPaint時,返回值是hDC,Windows會把它填入PAINTSTRUCT中。用戶程序只使用畫圖信息結構的前三個條款,其他條款由Windows操作系統(tǒng)內部使用。hdc條款是BeginPaint的返回值。fErase被標志為FALSE(0),這意味著Windows已經(jīng)擦除了無效矩形的背景。rcPaint

是一個結構指針,指向RECT結構,RECT結構記錄著畫圖區(qū)域坐標,無效矩形的邊界。6.2.3繪圖信息結構(PAINTSTRUCT)在調用BeginPaint後PAINTSTRUCT結構的fErase條款將成為TRUE(非零)

PAINTSTRUCT結構的rcPaint條款是RECT類型的結構,RECT結構定義了一個無效矩形的邊界坐標6.2.3繪圖信息結構(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ū)內輸出字符串的開始地址,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類型的結構typedef

struct

tagTEXTMETRIC{ LONGtmHeight; LONGtmAscent; LONGtmDescent; LONGtmInternalLeading; LONGtmExternalLeading; LONGtmAveCharWidth;LONGtmMaxCharWidth;

其他結構條款}TEXTMETRIC系統(tǒng)定義的TEXTMETRICS的結構如下: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結構中。BOOLGetTextExtentPoint32(

HDChdc,

LPCTSTRlpszString,//指定的字符串

int

nLength, //字符串中的字符數(shù)

LPSIZElpSize

//返回字符串寬度及高度的SIZE數(shù)據(jù)結構的地址)SIZE數(shù)據(jù)結構的定義typedefstructtagSIZE{LONGcx;

LONGcy;

}SIZE;例如,X軸起始坐標為cx0,后續(xù)文本起始坐標cx1為:

cx1=cx0+size.cx;

GetTextExtentPoint32(hDC,

Text,

lstrlen(Text),

size)

(2)確定換行時文本坐標字符的高度與行間隔均存儲在tm指向的TEXTMETRIC結構中,換行時Y軸上文本的起始坐標cy為:

cy=tm.tmHeight+tm.tmExternalLeading;通過計算當前行文本字符的高度與行間隔之和,即可得到換行時文本的起始坐標6.5.3格式化文字下面是取得系統(tǒng)字體的字符寬度和高度的WM_CREATE程序碼:caseWM_CREATE:hdc=GetDC(hwnd);//取得窗口的DCGetTextMetrics(hdc,&tm);//通過DC取得字體的尺寸信息存入tm結構cxChar=tm.tmAveCharWidth;//從tm結構中得到平均寬度cyChar=tm.tmHeight+tm.tmExternalLeading;//從tm結構中有關參數(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;//定義指向包含繪圖信息的結構體變量

staticchar*textbuf[]= {

"ThisistheFirstline",

"Thisisthesecondline",

"Thisisthethirdline",

"Thisisthefourthline",

"Thisisthefifthline",

"Thisisthesixthline"

};輸出的文本內容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: //結束應用程序

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; //存放字體各種屬性的結構體變量5.PAINTSTRUCTPtStr; //指向包含繪圖信息的結構體變量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; //結束繪圖22. caseWM_DESTROY://結束應用程序

PostQuitMessage(0); return0;23. default: return(DefWindowProc(hWnd,iMessage,wParam,lParam));}}6.6字體顯示的綜合使用SYSMETS1.c

視覺元件信息表struct

{

int Index;//索引

TCHAR* szLabel;//指向寬字符的指針

TCHAR* szDesc;//指向寬字符的指針}sysmetrics;//這是定義的結構名,sysmetrics[]//此結構數(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)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論