【Windows編程】系列第三篇:文本字元輸出

來源:互聯網
上載者:User

標籤:

上一篇我們展示了如何使用Windows SDK建立基本控制項,本篇來討論如何輸出文本字元。

在使用Win32編程時,我們常常要輸出文本到視窗上,Windows所有的文本字元或者圖形輸出都是通過圖形裝置介面(GDI)進行的,Windows的三大核心組件之一的GDI32.dll封裝了所有的文本和映像輸出。

  • GDI基本知識

Windows下要繪圖和輸出文本,都是通過GDI(Graphics Device Interface,圖形裝置介面)完成的,GDI是windows在繪製圖文時的裝置上下文環境,包括畫筆、畫刷、字型、位元影像等多種與繪製有關的對象。裝置環境(DC)在繪製中起至關重要的作用。幾乎所有的繪製(包括圖形和文本)都與裝置環境相關,注意“環境”的意義,就跟我們在畫布上繪畫和寫字一樣,繪製時的畫布是哪個,用的什麼筆,什麼顏色,填充整個畫布時用的什麼刷子等等,這就是我們的繪製時的環境,而Windows繪圖的DC裝置上下文就是一樣的道理。裝置環境控制代碼(HDC)就是用來描述DC的控制代碼,可以說,只要有了這個控制代碼,就具備了在視窗上輸出圖形和文本的條件。你獲得了視窗客戶區的HDC,就可以在視窗客戶區上畫;你獲得了視窗的非客戶區HDC,就可以在它上面畫;你獲得了案頭HDC,就可以直接在案頭上畫……

擷取裝置環境控制代碼的方法有兩種:一是處理WM_PAINT訊息時,通過BeginPaint函數返回。另外一種就是通過GetDC、GetWindowDC的API函數擷取。

  • 通過WM_PAINT訊息擷取DC

Windows在檢測到需要重新繪製或者重新整理視窗時,會主動要求處理WM_PAINT訊息。比如在如下情況下就會主動求處理:

  1. 使用者移動一個視窗,導致原來被蓋住的部分視窗顯示出來。
  2. 使用者調整視窗的大小,並且視窗風格類型設定為CS_HREDRAW和CS_VREDRAW。
  3. 程式調用ScrollWindow或者ScrollDC函數滾動客戶區。
  4. 程式調用InvalidateRect或者InvalidateRgn函數,該函數顯示生產一條WM_PAINT訊息。

我們可以在該訊息中完成圖文繪製,該訊息的處理具有特定的格式,必須在實際繪製前調用BeginPaint,在繪製完成後調用EndPaint函數,也就是說我們需要把所有繪製的功能都放到這兩個函數之間,並且HDC也只能在這之間使用,不能儲存起來在其它地方使用。使用WM_PAINT有一個好處,就是windows會自己計算哪些地區需要更新,也就是說只有真正變化的地方才會更新,這樣更新的代價會降低到最小。

  • 通過API函數擷取HDC

我們還可以通過GetDC、GetWindowDC函數來擷取HDC,但是要注意,通過這個來擷取的HDC,可以儲存起來在其它時候使用,但是要記住一旦視窗有更新,必須想辦法重新繪製,否則就會消失了。最後在使用完畢後需要調用ReleaseDC來釋放,否則會造成資源流失。

  • 建立特定字型

我們平時最常見的文本輸出是不需要自己建立字型的,因為常見的對象都有系統預定義好的。如果想輸出點特殊(非系統預定義的)字型,就需要我們建立並自動選入裝置環境。建立字型主要有CreateFont和CreateFontIndirect,這兩個函數的參數都很多,基本一樣,具體用法看後面的執行個體。

  • 實現文本繪製

有了上面的基礎,我們就可以通過Windows的API來完成文本輸出了,常用的文本輸出函數有TextOut、DrawText、DrawTextExt、ExtTextOut等,這些函數基本都有相似的參數,比如hdc,座標位置,字串。下面TextOut、DrawText、ExtTextOut為例來說明如何在Windows視窗中如何輸出文本,其它請查看MSDN的用法。

#include <windows.h>#include <tchar.h>static TCHAR szAppName[] = TEXT("Textout");static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){     HWND     hWnd;     MSG      msg;     WNDCLASS wndclass;     wndclass.style         = CS_HREDRAW | CS_VREDRAW;     wndclass.lpfnWndProc   = WndProc;     wndclass.cbClsExtra    = 0;     wndclass.cbWndExtra    = 0;     wndclass.hInstance     = hInstance;     wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);     wndclass.lpszMenuName  = NULL;     wndclass.lpszClassName = szAppName;     if (!RegisterClass(&wndclass))     {          MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);          return 0;     }          hWnd = CreateWindow(szAppName,            // window class name                          szAppName,           // window caption                          WS_OVERLAPPEDWINDOW, // window style                          CW_USEDEFAULT,       // initial x position                          CW_USEDEFAULT,       // initial y position                          400,                 // initial x size                          300,                 // initial y size                          NULL,                // parent window handle                          NULL,                // window menu handle                          hInstance,           // program instance handle                          NULL);               // creation parameters          ShowWindow(hWnd, iCmdShow);     UpdateWindow(hWnd);          while (GetMessage(&msg, NULL, 0, 0))     {          TranslateMessage(&msg);          DispatchMessage(&msg);     }     return msg.wParam;}static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){HDC         hDC;PAINTSTRUCT ps;switch (message){case WM_CREATE:return 0;case WM_PAINT:{RECT rect = {10, 30, 100, 50};TCHAR str[] = TEXT("English and 中文");hDC = BeginPaint(hWnd, &ps);TextOut(hDC, 10, 10, str, _tcslen(str));SetTextColor(hDC, RGB(255,0,0));DrawText(hDC, str, -1, &rect, DT_LEFT|DT_VCENTER);SetTextColor(hDC, RGB(0,255,0));INT dx[] = {8,8,8,8,16,8,8,8,16,8,8,8,10};ExtTextOut(hDC, 10, 50, 0, &rect, str, _tcslen(str), dx);SetTextColor(hDC, RGB(0,0,255));rect.right = 110;rect.top = 70;rect.bottom = 82;ExtTextOut(hDC, 10, rect.top, ETO_CLIPPED, &rect, str, _tcslen(str), dx);HFONT hFont = CreateFont(96,         // nHeight, 所建立字型的字元高度0,           // nWidth,       字型的字元平均寬度200,          // nEscapement,  字元輸出方向與水平向右的方向所成角度,以0.1度為單位0,             // nOrientation, 字元與基準的角度,以0.1度為單位FW_BOLD,        // nWeight,      字元顏色的深淺度TRUE,            // bItalic,      斜體屬性標誌(FALSE:正常字型,TRUE:斜體)FALSE,            // bUnderline,   底線屬性標誌(FALSE:無底線,TRUE:有底線)FALSE,             // cStrikeOut,   刪除線屬性標誌(FALSE:無刪除線,TRUE:有刪除線)ANSI_CHARSET,       // nCharSet,        字元集標識0:ANSI字元集,1:系統預設字元集OUT_DEFAULT_PRECIS,  // nOutPrecision,   輸出精度CLIP_DEFAULT_PRECIS, // nClipPrecision,  剪下精度DEFAULT_QUALITY,      // nQuality,        輸出品質DEFAULT_PITCH|FF_SWISS, // nPitchAndFamily, 字元間距TEXT("Arial"));          // lpszFacename,    現有系統TrueType字型名稱HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);SetBkMode(hDC, TRANSPARENT);SetTextColor(hDC, RGB(0x00, 0xFF, 0xFF));TextOut(hDC, 0, 150, TEXT("建立Font"), 6);DeleteObject(hFont);EndPaint(hWnd, &ps);}return 0;case WM_DESTROY:PostQuitMessage(0);return 0 ;}return DefWindowProc (hWnd, message, wParam, lParam);}

 

程式運行,點擊滑鼠左鍵後效果如下:

程式中的DrawText、ExtTextOut能設定文本輸出的矩形範圍,超出部分是看不見的,從運行結果我們也可以看出有兩行顯示不全,就是由於設定的顯示範圍小的緣故。

另外ExtTextOut函數還可以設定字元的間距,運行結果的第三行就是這種自己設定間距不一樣的結果。

本程式還用CreateFont函數建立了一個斜體、右上排列的文本串。通過上例,我們把常用的文本輸出作為執行個體展示給大家,只要好好對照執行個體代碼,在結合MSDN的說明,再加上本系列的第一篇的Windows編程基本架構,一定可以掌握好Windows編程的基本文本輸出。

 

關注公眾平台:程式員互動聯盟(coder_online),你可以第一時間擷取原創技術文章,和(java/C/C++/Android/Windows/Linux)技術大牛做朋友,線上交流編程經驗,擷取編程基礎知識,解決編程問題。程式員互動聯盟,開發人員自己的家。

轉載請註明出處,謝謝合作!

【Windows編程】系列第三篇:文本字元輸出

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.