前面看了幾天的書,發現那本書太厚了1600多頁,是我認真看過的最厚的書,看著就累,我不知道作者和翻譯是怎麼堅持下來的,這麼多的文字就那麼寫完了;由於有工作要做,並且與電腦的聯絡不大,自學的時候感到很累,所以學習進度有點慢..........不過這個是我的興趣,學起來雖然感覺累,但也樂在其中...嘿嘿
上次說到了windows程式顯示和更新視窗的WM_PAINT訊息的處理機制,這次接著上次沒有說完的話題繼續瞎扯........
非WM_PAINT訊息期間繪製顯示地區
在應用程式編製過程中,有時不需要繪製顯示地區,而只想獲得一些裝置內容的資訊;或者我們想在非WM_PAINT訊息處理期間繪
制顯示地區的某個地區,這時我們就需要採用另外一種方法了。我們通過下面的方式進行處理:
1、擷取裝置內容控制代碼和釋放裝置內容控制代碼:
我們可以通過下面兩個API函數來擷取裝置內容控制代碼和釋放裝置內容控制代碼:
擷取裝置內容控制代碼: GetDC
原型:
HDC GetDC(HWND);
釋放裝置內容控制代碼: ReleaseDC
原型:
int ReleaseDC(HWMD ,HDC )
2、Tip:
這裡和BeginPaint和EndPaint一樣, GetDC和ReleaseDC函數必須成對的使用,若在某個訊息處理的時使用呼叫GetDC則
必須在同一個訊息處理期間呼叫ReleaseDC函數。
不能在處理A訊息時呼叫GetDC,而在處理B訊息時呼叫ReleaseDC。
3、與BeginPaint的比較
GetDC同樣可以擷取裝置內容控制代碼,但是與BeginPaint不一樣的是:GetDC不會使任何無效地區變為有效;
這個可以理解:
我們知道當產生無效地區的時候,系統會記錄無效地區的形態同時發送一個WM_PAINT訊息,同時在呼叫
BeginPaint函數時會清除WM_PAINT訊息,而GetDC函數不會清除WM_PAINT, 我們知道只要有WM_PAINT訊息,
則會存在無效地區。
GetDC返回的裝置內容控制代碼具有一個剪取矩形,它等於整個顯示地區,這樣就可以在顯示地區的某一部分繪製
而不僅僅是在無效矩形上繪製。
4、如何不調用BeginPaint函數而是整個地區有效,可以呼叫:
ValideteRect(hwnd,NULL);
這樣就可以清除系統投遞到訊息佇列的WM_PAINT訊息。
5、使用GetDC和ReleaseDC
可以呼叫GetDC和ReleaseDC來對鍵盤訊息和滑鼠訊息作出響應, 這樣就可以通過滑鼠或者鍵盤輸入來更新顯
示地區,而不需要等到視窗出現無效地區在對視窗進行繪製。
6、GetDC與GetWindowDC
GetDC返回一個用於在顯示地區進行繪製的裝置內容控制代碼,而GetWindow函數返回一個用於在整個視窗進行繪製的
裝置內容控制代碼。
程式同樣應該處理 WM_NCPAINT 非顯示地區繪製訊息。
視窗繪製的步驟:
1、擷取要被繪製視窗的裝置內容控制代碼
2、調用GDI進行視窗繪製
3、釋放裝置內容控制代碼。
4.5 TextOut函數
TextOut函數用於顯示文字;其文法是:
TextOut(hdc, x, y, psText,iLength);
參數:
hdc: 裝置內容控制代碼,可以是GetDC和BeginPaint函數返回的控制代碼
裝置內容的屬性控制被顯示的字串的特徵
在裝置內容中有一個屬性指定文字的顏色,預設的顏色為黑色,預設裝置內容還定義了白色的字元輸出背景,在
用TextOut函數輸出文字時,就按照這個預設的裝置內容屬性進行文字的輸出顯示。
改文字背景色與視窗類別別定義時裝置的背景不相同,視窗類別別中的背景是一個畫刷,被windows用來擦除顯示地區,不是裝置
內容的一部分。通常為了使windows擦除的視窗顯示地區的背景畫刷與預設文字背景顏色相同,會將wndclass.hbrBackground
畫刷設定成白色畫刷WHITE_BRUSH.
psText: 待顯示的字串, 字串中不能包括ASCII控制字元(如換行、斷行符號、製表和退格),windows會將這些顯示為實心塊。
x,y: x和y是字元顯示時的開始座標位置。x是水平位置,方向向右值增加; y是垂直位置,向下方向值增加。(0,0)是應用程式
顯示地區的左上方。這個座標系成為邏輯座標系。在Windows內部有多種座標映像方式,這些座標映像方式將控制GDI函數指定的邏輯
位置轉換為實際圖素座標的顯示座標。在裝置內容定義,預設方式是MM_TEXT, 其單位與實際單位相同,都是圖素。
裝置內容定義了一個剪裁地區, GetDC擷取的裝置內容控制代碼為整個顯示地區;而BeginPaint取得的裝置內容控制代碼為無效地區。windows
不會在剪裁地區之外的任何位置繪製字串。
系統字型:
裝置內容定義了TextOut顯示文字時windows使用的字型, 預設字型為系統字型,或用windows表標頭檔中的標識符SYSTEM_FONT,
系統字型是windows用在標題列、菜單和對話方塊中顯示字串的預設字型。
字元大小
windows顯示器的圖素最小是640*480。 可以通過呼叫系統函數來擷取各種資訊。
1、 GetSystemMetrics函數取得使用者介面上各類視覺組件大小的資訊,
2、 GetTextMetrics取得字型的大小,GetTextMetrics返回裝置內容中當前選擇的字型的資訊,
因此GetTextMetrics函數需要操作裝置內容控制代碼, 調用這個函數時windows將文字大小不同的值賦值
到TEXTMETRICS結構體中。
TEXTMETRICS結構體共有20個欄位,通常我們需要操作的是前面的幾個欄位
typedef struct tagTEXTMETRIC
{
LONG tmHeght; //tmHeight=tmAscent+tmDescent 表示了在基準線下字元的最大高度
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
LONG tmAveCharWidth;
LONG tmMaxCharWidth;
其他欄位;
}TEXTMETRIC, *PTEXTMETRIC;
leading:即間距指印表機在兩行文字間插入的空間,在TEXTMETRIC結構中,內部間距包括在tmAscent中,並且通常
是重音符號出現的地方。tmInternalLeading欄位可以設定成0,這時重音符的字母會稍稍縮短以列印重音符號。
TEXTMETRICS結構包含有描述字元寬度的兩個欄位:
tmAveCharWidth: 小寫字母加權平均寬度
tmMaxCharWidth: 字型中最寬字元的寬度
這裡要說明的是: windows使用的是非等寬的字型, 例如 W就比i寬。
大寫字母的平均寬度: 大約可以用tmAveCharWidth * 150 % 計算。
上面的欄位值的單位取決於選定的裝置內容映像方式,在預設的情況下,映像方式是MM_TEXT,其以圖素為單位。
通過下面的方式擷取文字的資訊:
HDC hdc;
TEXTMETRIC tm;
hdc= GetDC(hwnd)
GetTxtMetrics(hdc, &tm);
ReleaseDC(hwnd,hdc);
這樣就可以通過tm結構體變數的各個欄位查看當前裝置內容中關於字元的資訊。
格式化文字:
windows啟動後,系統字型的大小就不會發生改變。程式當中可以呼叫一次GetTextMetrics函數,擷取系統字型的資訊就可以一直使用。
通常建議在處理WM_CREATE訊息時進行上述的GetTextMetrics函數呼叫,因為WM_CREATE訊息是視窗訊息處理常式接收的第一個訊息。
可以這樣處理:
在訊息處理常式中定義:
static int cxChar, //儲存系統字元的寬度
cyChar; //儲存系統字元的高度
而在訊息處理時:
case WM_CREATE:
hdc=GetDC(hwnd);
GetTextMetrics(hdc,&tm);
cxChar=tm.tmAvdCharWidth;
cyChar=tm.tmHeight+tm.tmExternalLeading;
Release(hwnd,hdc);
return 0;
格式化字串函數: sprintf和wsprintf(windows下可用)。
wspritnf函數原型:
int wsprintf(char *dest,char *source,...);
Exp:
int iLength;
TCHAR szBuffer[40];
iLength=wsprintf(szBuffer,TEXT("the sum of %i and %i is %i"),iA,iB,iA+iB);
TextOut(hdc,x,y,szBuffer,iLength);
wsprintf函數將格式化完的字串放到一個字串中,並且這個函數返回放入到字串中的字元的個數。
這樣正好符合TextOut函數的使用的兩個參數。
因為函數的調用方式是__stdcall方式,所以可以:
TextOut(hdc,x,y,szBuffer,wsprintf(szBuffer,TEXT("the sum of %i and %i is %i"),iA,iB,iA+iB) )。
擷取系統視覺組件大小資訊:
GetSyetemMetrics函數
GetSystemMetrics函數返回windows中不同視覺組件的大小資訊;標、游標、標題列和捲軸等。這些大小與顯示卡
和驅動程式相關。
其函數原型是:
int WINAPI GetSystemMetrics(int index)
今天瞎掰就暫時到這,這裡說的有點亂, 不過估計理解應該沒有什麼問題....................
下一次估計要說捲軸了, 前幾天看書,沒太看明白, 等看明白後再來瞎掰..........
編製windows的應用程式主要是明白其事件驅動機制以及各個功能的內在機理, 通過那本經典的書可以增強對windows程式的認識, 如果學習有一定的基礎的話,同樣可以學習那本經典核心編程課程, 也是1000+以上的書,估計看完要一陣子......
計劃慢慢的學完這本書,然後在看看羅老師的那本700多頁的書, 估計會對windows的運行機理有個大概的認識吧.......
也許以後轉行到挨踢行業,也許就不轉了.........
誰知道以後的事情呢?