亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Windows編程基礎 - 文本顯示

2019-11-17 05:18:31
字體:
來源:轉載
供稿:網友

  前一章所介紹的程序只創建了一個的窗口,但是除了窗口的標題欄中顯示的窗口名之外,并未用它顯示其它信息。應用程序可以在窗口的用戶區內顯示文本和圖形信息。本章僅討論文本行的顯示。通過本章的程序實例,我們將介紹幾個用于文本輸出的Windows函數以及有效和無效矩形區的概念。同時介紹有關設備對象和字體尺寸的基本概念。這里,我們還將介紹幾個重要的Windows消息。應用程序可以利用這些消息進行程序的初始化和終止處理,以及完成應用程序的任務等。

2.1、顯示信息
  下面的程序從用戶區的左上角開始顯示“Hello,Welcome to Windows”。

  // 2-1.c 顯示信息
  #include <windows.h>

  LRESULT CALLBACK WndPRoc(HWND, UINT, WPARAM, LPARAM);

  int PASCAL WinMain(
    HINSTANCE hInstance,   // 應用程序的實例句柄
    HINSTANCE hPrevInstance, // 該應用程序前一個實例的句柄
    LPSTR lpszCmdLine,    // 命令行參數串
    int nCmdShow )      // 程序在初始化時如何顯示窗口
  {
     char szAppName[] = "DispText";
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    if (!hPrevInstance) {
      // 該實例是程序的第一個實例,注冊窗口類
      wndclass.style = CS_VREDRAW CS_HREDRAW;
      wndclass.lpfnWndProc = WndProc;
      wndclass.cbClsExtra = 0;
      wndclass.cbWndExtra = 0;
      wndclass.hInstance = hInstance;
      wndclass.hIcon = LoadIcon(hInstance, IDI_application);
      wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
      wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
      wndclass.lpszMenuName = NULL;
      wndclass.lpszClassName = szAppName;

      if (!RegisterClass(&wndclass))
        // 假如注冊失敗
        return FALSE;
    }

    // 對每個實例,創建一個窗口對象
    hwnd = CreateWindow(
      szAppName,
      "Display Text",
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT,
      CW_USEDEFAULT, CW_USEDEFAULT,
      NULL,
      NULL,
      hInstance,
      NULL );

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

    return msg.wParam;
  }

  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    char msg[] = "Hello, Welcome to Windows!";
    PAINTSTRUCT ps;
    HDC hDC;

    switch(message)
    {
      case WM_PAINT:
        hDC = BeginPaint(hwnd, &ps);
        TextOut (hDC, 0, 0, msg, sizeof(msg) - 1);
        EndPaint(hwnd, &ps);
        return 0;

      case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
  }

  我們首先介紹這個程序中使用的Windows數據類型,然后介紹和這幾個類型有的Windows函數,最后介紹消息WM_PAINT的含義。
  HDC是在Windows.h中定義的一個數據類型,類似于HWND,它是用于標識一個設備對象的句柄;許多繪圖函數需要這個句柄,這些繪圖函數在這個句柄標識的對象上繪圖。
  PAINTSTRUCT結構類型的變量所包含的信息可被用來重新繪制窗口的用戶區域,下面的定義中只給出應用程序關心的幾個域,其它未列出的域是供Windows系統使用的。

  typedef struct tagPAINTSTRUCT {
    HDC hdc;   // 標識顯示設備對象的句柄
    BOOL fErase; // 若為非零。說明用戶背景已被重畫過,否則未被重畫
    RECT rcPaint; // 指定要求重畫(著色)的矩形區域的左上角和右下角坐標
    //......
  } PAINTSTRUCT;

  其中,類型RECT的說明為:

  typedef struct tagRECT {
    int left;  // 矩形左上角的X坐標值
    int top;   // 矩形左上角的Y坐標值
    int right;  // 矩形右上角的X坐標值
    int bottom; // 矩形右上角的Y坐標值
  } RECT;

  函數BeginPaint()使用一個窗口句柄和一個指向PAINTSTRUCT類型的變量的指針為參數,它除了填充該指針所指向的變量的各域以外,同時向Windows借用一個顯示設備用于繪制用戶區。該函數返回這個設備對象的句柄,有了該句柄,應用程序就可以隨意繪制用戶區。函數EndPaint()與函數BeginPaint()所使用的參數一樣,它必須與函數BeginPaint()配對使用,并且必須同時都用在WM_PAINT消息內。函數EndPaint()有兩個作用。其一是歸還BeginPaint()所借用的顯示設備對象。Windows治理著五個公用的顯示設備對象,供給用程序在顯示設備上進行文本和圖形輸出所用。當一個窗口對象要繪制它的用戶區時,它必須首先向Windows借用一個顯示設備對象。由于公用的顯示設備對象有限,因此,窗口對象在繪制完它的用戶區之后,必須及時歸還它所借用的設備對象,以不影響其它對象使用公用顯示設備對象。一般的原則是:在從窗口函數中返回之前,應歸還所借用的顯示設備對象。EndPaint()函數的第二個作用是消除應用程序消息隊列中的WM_PAINT消息,關于WM_PAINT消息,我們放在后面單獨討論。
  函數TextOut()使用BeginPaint()所借用的顯示設備對象,在用戶區中顯示一條消息。表2-1給出該函數的使用說明。

  表2-1 TextOut 函數
用 途該函數用當前選擇的字體繪制一字符串。其中參數x和y是串中第一個字符左上角的坐標。原 型BOOL TextOut(   HDC hDC 設備對象的句柄  int x,串起始點的邏輯x坐標值(相對于用戶區左上角)   int y,串起始點的邏輯y坐標值(相對于用戶區左上角)   LPSTR lpString, 所要繪制的字符串  int nCount 所要繪制的字符個數); 返回值返回非零,則串被繪制,否則沒有被繪制。注:關于邏輯坐標的含義在第三章討論。

 2.2、繪制和重畫用戶區
  你試著運行上節給出的程序。當該應用程序的窗口出現在屏幕上時,觀察窗口中顯示的信息。然后使用鼠標(或鍵盤)移動該窗口;將窗口隱藏在其它窗口后面,再讓它顯現出來;使窗口以最小化方式顯示,再恢復為原窗口大小。在對該窗口對象進行上述操作之后,觀察用戶區顯示的信息有什么變化。
  上述操作并沒有改變(也未破壞)用戶區中顯示的信息,為什么呢?要回答這個問題,必須首先明白消息WM_PAINT的作用。
  Windows是一種消息驅動的系統。通過把消息郵寄到應用程序的隊列中(甚至于直接發送到有關的窗口對象上),Windows通知應用程序所發生的各種有關事件。當Windows認為(由于窗口用戶區的某些部分顯示的內容受到破壞)需要窗口對象重新繪制用戶區時,Windows就在應用程序的消息隊列中放置一條WM_PAINT消息,窗口對象在接受到WM_PAINT消息之后,就重新繪制它的用戶區中所顯示的內容。
  在前面一章我們曾介紹了Windows應用程序的面向對象的特點,面向對象的方法將對象視為能作出動作。因此,當一個對象(例如Windows)需要另一個對象作某件事時,就向它發送相應的消息,讓它動作起來。繪制對象的用戶區是對象自己的事,所以,當一個對象的用戶區需要重繪時,Windows就向這個對象發送WM_PAINT消息。Windows知道在什么情況下需要窗口對象重繪其用戶區。

2.3、有效和無效矩形區
  當Windows通知窗口對象重繪用戶區時,并非整個用戶區都要重繪。例如,當一個覆蓋了窗口用戶區域的對話框消失時,只有被對話框覆蓋的用戶區需要重新繪制(被對話框覆蓋的其它區域,例如標題欄、滾動杠等重繪問題由函數DefWindowProc負責。Windows向窗口對象發送WM_NCPAINT消息;窗口對象將這個消息交給DefWindowProc函數進行缺省處理;DefWindowProc繪制窗口對象的非用戶區)。這個需要重繪的區域稱為“無效矩形區”。如圖2-1所示。在任何情況下,Windows通知窗口對象需要重繪的區域總是一個矩形區域。在用戶區中出現的一個無效矩形提示Windows在應用程序的消息隊列中放置WM_PAINT消息,窗口對象僅在其用戶區無效接收到WM_PAINT消息。

Windows編程基礎 - 文本顯示(圖一)圖2-1 窗口用戶區的無效矩形區
  各種排隊的消息首先在應用程序的消息隊列中按優先級排隊,WM_PAINT有最低的優先別,它總是在隊列中的其它消息都被處理完之后才被處理。因此,在應用程序處理其他消息時,有可能又出現新的無效矩形,這樣Windows又要向消息隊列中放置WM_PAINT消息。
  但是,Windows只為每個窗口對象保留一條WM_PAINT消息和一個“繪制信息結果” — PAINTSTRUCT,這個結構內包含有無效矩形區的坐標。當一個窗口對象出現新的無效矩形區時,Windows在向應用程序的消息隊列中放置WM_PAINT消息之前,它首先檢查在消息隊列中是否已存在一條預備發送給該窗口對象的WM_PAINT消息。若該消息存在,Windows將這兩條WM_PAINT消息合并為一條WM_PAINT消息。該消息的“繪制信息結構”的無效矩形區將包含原來的兩個WM_PAINT消息的無效矩形區。
  在窗口對象處理WM_PAINT消息時,通過函數BeginPaint可以獲得無效矩形區的坐標。在其他情況下,只能通過調用函數GetUpdateRect()獲得無效矩形區的坐標(見表2-2)

  表2-2 GetUpdateRect 函數
用 途檢索無效矩形區的坐標,假如該矩為空,則所有坐標值為零。原 型GetUpdateRect(   HWND hWnd, 和用戶區相關聯的窗口對象的句柄  LPRECT lpRect, 指向類型為RECT的變量的指針,該變量用于保存所獲得的無效矩形區的坐標(相對于用戶區左上角的坐標)   BOOL bErase所要繪制的字符個數); 返回值假如更新區不空,返回非零,否則返回零。
  無效矩形也是一個裁剪矩形,也就是說,Windows限制應用程序只能在這個區域中繪圖。當使用PAINSTRUCT結構中的顯示設備對象繪圖時,Windows將裁剪掉在rcPaint域所標識的矩形之外所繪的圖。
  應用程序可以使用函數InvalidateRect()產生一個的無效矩形。表2-3給出了函數InvalidateRect()和函數ValidateRect()的使用說明。

  表2-3-1 InvalidateRect() 函數
用 途將該函數所指定的一個矩形作為無效矩形區加到窗口的無效矩形區上。原 型VOID InvalidateRect(   HWND hWnd, 和無效矩形區相關聯的窗口的句柄  LPRECT lpRect, 指向RECT類型的變量的指針,該變量定義的矩形被加到無效矩形區上,假如該指針為NULL,則整個用戶區變為無效矩形區   BOOL bErase是(非零)否(零)擦除lpRect所標識的區域的內容); 注 釋當該函數被調用時,它生成一條WM_PAINT消息,該消息所附帶的無效矩形區由lpRect指定。Windows將該消息和應用程序信息隊列中已存在的一條WM_PAINT消息合并。
  表2-3-2 ValidateRect() 函數
用 途使無效矩形區有效。原 型VOID ValidateRect(   HWND hWnd, 窗口句柄  LPRECT lpRect, 指向RECT類型的變量的指針,無效矩形區將不再包含由該變量所指定的矩形區域,假如其值為NULL,則整個用戶區有效 ); 注 釋函數BeginPaint()自動使整個用戶區有效。

  進行裁剪操作是費時間的,為了提高程序的運行效率,當用戶區顯示的內容不很復雜時(或可以很有效地重畫整個用戶區時),可以在調用BeginPaint()函數之前調用InvalidateRect函數使整個用戶區無效,然后,應用程序在整個用戶區上進行繪制。
  由于WM_PAINT消息的優先級很低,這樣,由于窗口對象不能及時收到WM_PAINT消息而影響用戶對屏幕對象的視覺感覺。為彌補這個缺陷,程序員可以考慮使用函數UpdateWindows(),它在應用程序的消息隊列中存在WM_PAINT消息的情況下,強使Windows立即向窗口對象發送WM_PAINT消息。例如,前面幾個示例程序的WinMain函數中,我們多次使用了這個函數。這樣,程序一啟動,用戶可以很快在屏幕上看到窗口。
  EndPaint不僅歸還顯示設備對象,同時,它還清除應用程序的消息隊列中的WM_PAINT消息。當使用函數ValidateRect使用窗口對象不存在任何無效的矩形區域時,ValidateRect函數同樣也清除消息隊列中的WM_PAINT消息。

2.4、格式化顯示信息
  本節介紹另一個繪制字符的函數DrawText(),表2-4給出了該函數的使用說明。

  // 2-4-1.c
  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    HDC hDC;
    PAINTSTRUCT ps;
    RECT rect;

    switch(message)
    {
      case WM_PAINT:
        hDC = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        DrawText(hDC, "Hello, Welcome to Windows!", -1,
             &rect, DT_SINGLELINE DT_CENTER DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0L;

      case WM_DESTROY:
        PostQuitMessage(0);
        return 0L;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
  }

  該程序在用戶區的中心顯示一條信息,用戶試著移動屏幕上窗口的位置,或改變窗口的大小,信息始終顯示在中心位置。該程序有助于你更好地理解WM_PAINT消息的作用。
  程序中使用了函數GetClientRect(),它將用戶區的坐標(左上角和右下角,其中左上角坐標總為(0,0),而右下角坐標是相對于用戶區左上角坐標)拷貝到第二個指針參數所向的RECT類型的變量。 三層交換技術 交換機與路由器密碼恢復 交換機的選購 路由器設置專題 路由故障處理手冊 數字化校園網解決方案

  表2-4 DrawText 函數
用 途該函數在lpRect參數指定的矩形中格式化文本。原 型int DrawText(   HDC hDC 設備對象句柄  LPSTR lpString, 指向要繪制的字符串  int nCount 要繪制的字符個數。若其為-1,則lpString必須指向以空字符(即‘/0’)結尾的字符串  LPRECT lpRect 指向一個RECT類型的變量,在該變量所指定矩形內進行文本的格式化(矩形以邏輯坐標表示,見第三章)  Word wFormat以下列常量使用“位或”運算得到的值(表2-4-1));  返回值返回本文的高度。
  表2-4-1 wFormat 值 類型說明DT_BOTTOM與DT_SINGLELINE組合使用,指定底對齊DT_CENTER文本水平居中DT_VCENTER垂直對中文本(與DT_SINGLELINE組合使用)DT_LEFT文本左對齊DT_RIGHT文本右對齊DT_TOP頂對齊(與DT_SINGLELINE組合使用)DT_SINGLELINE繪制在一行中。回車換行符不打斷該行
  上面的程序有一個小問題,窗口對象每當收到WM_PAINT消息時都要調用函數GetClientRect()來獲得用戶區的大小。這樣,對程序的效率有些影響,因為窗口對象在大多數情況下收到WM_PAINT消息時,用戶區的大?。ɑ蛘f整個窗口的大?。┎]有改變,例如,在窗口被對話框覆蓋的情況下等。
  每當窗口的大小發生變化時,Windows都要向窗口對象直接發送一條WM_SIZE消息(不通過應用程序的消息隊列),消息的lParam參數的低位字中含有用戶區的寬度,而高位字中含有用戶區的高度,并使用設備單位(像素)表示(有關設備單位的內容在第三章介紹)。在Windows.h中定義的宏LOWORD和HIWORD可用來分離參數lParam的高位字和低位字。下面是使用WM_SIZE消息重新設計的程序。

  // 2-4-2.c
  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    HDC hDC;
    PAINTSTRUCT ps;
    static RECT rect;

    switch(message)
    {
      case WM_SIZE:
        rect.right = LOWORD(lParam);
        rect.bottom = HIWORD(lParam);
        return 0L;

      case WM_PAINT:
        hDC = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        DrawText(hDC, "Hello, Welcome to Windows!", -1,
             &rect, DT_SINGLELINE DT_CENTER DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0L;

      case WM_DESTROY:
        PostQuitMessage(0);
        return 0L;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
  }

  注重,由于處理消息WM_SIZE的代碼所預備的數據是提供其它消息(WM_PAINT)使用的,它們只有在窗口函數再次被進入時才能被使用,因此,變量rect被說明為靜態變量。當在不同的消息之間共享一些數據時,必須注重使用靜態生存期的變量。
  當調用ShowWindow()函數時(例如,第一章中程序中的主函數),Windows也要使用WM_SIZE消息調用窗口函數,因為這時窗口第一次被顯現出來。

2.5、字體的大小與多行信息顯示
  雖然DrawText()函數也可以顯示多行信息,但在顯示多行信息時, 經常使用的是函數TextOut()。為了顯示多行信息,我們必須了解顯示設備對象度量字體尺寸的方法,因此,本節先介紹這方面的內容。在本節給出的程序示例中,我們還要介紹WM_CREATE消息和借用顯示設備對象的另一種方法。
  字樣是一種基本的字符圖案,具有特定的的襯線和筆劃寬度,而字體指的是具有相同字樣和尺寸的字符集。字體的尺寸用點來度量,點是印刷業中使用的度量字體的最小度量單位,每一英寸大約有72個點。有關字體的更具體的內容在以后章節介紹。
  應用程序可以使用Windows提供的不同字體,也可以使用在應用程序的可執行文件中定義和包含的專用字體。本節僅介紹應用程序如何獲得有關字體尺寸方面的信息。使用TextOut函數顯示多行文本時,需要確定字體字符的大小,以便根據字符的高度和寬度在用戶區中顯示多行文本。根據字符的高度可以在文本的相繼行之間留出空距,而根據字符的寬度在文本的各列之間留出空距。
  結構類型TEXTMETRIC描述了與一種字體有關的基本信息,它的各域所給出的字體大小以邏輯單位表示(關于邏輯單位的介紹參見下一章)。該結構類型包含有許多域,圖2-2給出了與字體垂直尺寸有關的五個域的定義。

Windows編程基礎 - 文本顯示(圖二)圖2-1 TEXTMETRIC結構類型中定義垂直尺寸字體的域
  tmInternalLeading的值是答應在一個字符上加上重音號的空隙量,tmExternalLeading的值是字體的設計者推薦的空隙量,在顯示多行文本時程序員可以拒絕使用這個空隙量。
  在TEXTMETRIC結構類型中,有兩個域用來定義字符的寬度:tmAveCharWidth表示字體字符的平均寬度,tmMaxCharWidth表示字體最寬的字符的寬度。Windows中使用兩種類型的字體,一類是固定寬度的字體,固定寬度的字體的每個字符的寬度是一樣的,這樣tmAveCharWidth和tmMaxCharWidth兩值相等;另一類是可變寬度的字體,對于這類字體,每個字符占用的寬度不一樣。例如, 字符“w”和“i”的寬度就不同,使用可變寬度的字體可以繪制緊湊的文本。
  可以使用函數GetTextExtent計算出一個特定的文本行的寬度和高度,使用函數GetTextMetrics可以得到字符的有關尺寸,這兩個函數的說明見表2-5。

  表2-5-1 GetTextExtent 函數
用 途該函數使用設備對象當前使用的字體計算一個文本行寬度和高度(邏輯單位),在計算時不考慮當前裁剪區。原 型DWORD GetTextExtent(   HDC hDC 設備對象句柄  LPSTR lpString, 指向一個字符串  int nCount 所要計算字符數。);  返回值返回字符串的尺寸,高度在高位字上,寬度在低位字上。
  表2-5-2 GetTextMetrics 函數
用 途返回設備對象當前所使用的字體字符的有關尺寸。原 型DWORD GetTextMetrics(   HDC hDC 設備對象句柄  LPTEXTMETRIC lpMetric, 指向TEXTMETRIC類型的變量的指針,有關尺寸被放入該變量中。);  返回值若調用成功,返回非零,否則返回零。

  三層交換技術 交換機與路由器密碼恢復 交換機的選購 路由器設置專題 路由故障處理手冊 數字化校園網解決方案  下面的程序使用所介紹的這些知識在用戶區中顯示多行文本。
  
  // 2-5.c
  #include <windows.h>
  #include <stdio.h>

  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

  int PASCAL WinMain(
    HINSTANCE hInstance,   // 應用程序的實例句柄
    HINSTANCE hPrevInstance, // 該應用程序前一個實例的句柄
    LPSTR lpszCmdLine,    // 命令行參數串
    int nCmdShow )      // 程序在初始化時如何顯示窗口
  {
     char szAppName[] = "DispText";
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    if (!hPrevInstance) {
      // 該實例是程序的第一個實例,注冊窗口類
      wndclass.style = CS_VREDRAW CS_HREDRAW;
      wndclass.lpfnWndProc = WndProc;
      wndclass.cbClsExtra = 0;
      wndclass.cbWndExtra = 0;
      wndclass.hInstance = hInstance;
      wndclass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
      wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
      wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
      wndclass.lpszMenuName = NULL;
      wndclass.lpszClassName = szAppName;

      if (!RegisterClass(&wndclass))
        // 假如注冊失敗
        return FALSE;
    }

    // 對每個實例,創建一個窗口對象
    hwnd = CreateWindow(
      szAppName,
      "Display Text",
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT,
      CW_USEDEFAULT, CW_USEDEFAULT,
      NULL,
      NULL,
      hInstance,
      NULL );

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while( GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

    return msg.wParam;
  }

  LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  {
    static int xChar, yChar;
    char szBuffer[256];
    int line;
    HDC hDC;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
    FILE *fp;

    switch(message)
    {
      case WM_CREATE:
        hDC = GetDC(hwnd);
        GetTextMetric(hDC, &tm);
        xChar = tm.tmAveCharWidth;
        yChar = tm.tmHeight + tm.tmExternalLeading;
        ReleaseDC(hwnd, hDC);
        return 0L;

      case WM_PAINT:
        hDC = BeginPaint(hwnd, &ps);
        line = 0;
        if((fp = fopen("disptext.cpp", "r")) != NULL)
        {
          while(!feof(fp)) {
            int i = 0;
            char ch;
            while((ch = fgetc(fp)) != '/n' && ch != EOF)
              szBuffer[i++] = (char)ch;
            TextOut(hDC, xChar, line*yChar, szBuffer, i);
            line++;
          }
          fclose(fp);
        }
        EndPaint(hwnd, &ps);
        return 0L;

      case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
  }

  該程序運行后,在用戶區中將顯示本程序的部分內容。
  當窗口對象被第一次創建時(調用函數CreateWindow()),Windows向窗口對象發送消息WM_CREAT,這是窗口對象接收的第一個(對應用程序有意義的)消息,我們一般使用這條消息進行與本窗口對象有關的初始化工作。例如,在本程序示例中,我們用于計算字符的寬度和高度(包括了空隙量)。由于使用函數GetTextMetric()需要一個設備對象句柄,我們使用函數GetDC()從Windows那里借用一個公用顯示對象。
  Windows只有有限的五個公用的顯示設備對象供正在運行的所有的應用程序使用,這些顯示設備對象是Windows的一個寶貴的資源,當一個窗口對象不再使用通過函數GetDC()借用的顯示設備對象時,應使用函數ReleaseDC()將它歸還給Windows,否則,其它窗口對象將由于不能借用到顯示設備對象而不能繪制它的用戶區。因此,函數GetDC()和ReleaseDC()要配合使用,當窗口對象使用GetDC借用了一個顯示設備對象之后,在從窗口函數返回之前,應使用ReleaseDC函數歸還所借用的顯示設備對象。
  函數GetDC/ReleaseDC用于在處理非WM_PAINT消息其間需要顯示設備對象進行繪制時。在處理WM_PAINT消息其間應使用函數BeginPaint/EndPaint,因為使用GetDC/ReleaseDC不能清除應用程序的消息隊列中的WM_PAINT消息。假如WM_PAINT消息不能被清除,則窗口對象會不斷地接收到WM_PAINT消息。
  設備對象總定義有一個裁剪區,使用函數GetDC()得到的設備對象將整個用戶區作為裁剪區,因此,使用該設備對象所做的繪圖不會出現在用戶區之外。

2.6、小結
  本章介紹了在用戶區中顯示信息的有關問題,同時介紹了消息WM_CREATE、WM_SIZE和WM_PAINT的意義和用途。WM_CREATE是在建立窗口對象時Windows發送給窗口對象的第一條對應用程序有意義的消息,我們可以利用這條消息進行程序的初始化工作。窗口對象接收到最后一條對應用程序有意義的消息是WM_DESTROY消息,我們可以使用這條消息完成一些程序終止之前的清除工作,例如釋放內存對象等。根據應用程序的使用要求,利用其它消息完成一些別的處理工作,例如響應用戶的輸入操作和命令等。
  WM_PAINT消息是一條非常重要的消息,它的作用是通知窗口對象用戶區顯示的內容已被破壞,需要重繪。雖然在處理任何消息時都可以繪制用戶區,但將用戶區的繪制工作集中于處理WM_PAINT消息的程序段中是合理的,這可以保證用戶區中總顯示出合適的內容。學習Windows程序設計,重要的內容之一是把握Windows函數的功用和使用方法,但更重要的是把握一條消息是怎么樣產生的,窗口對象利用這條消息能做什么工作。

  Windows編程基礎 - 文本顯示(圖三) 本章節附帶的例程(4KB)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲 日韩 国产第一| 久久精品一本久久99精品| 精品呦交小u女在线| 亚洲一区二区国产| 精品国产欧美成人夜夜嗨| 欧美精品videos| 午夜精品一区二区三区视频免费看| 久久欧美在线电影| 久久精品国产电影| 日韩中文字幕免费看| 久久影视电视剧凤归四时歌| 这里只有精品在线播放| 黑人精品xxx一区| 国产精品一区二区三区成人| 美女精品久久久| 91网站在线免费观看| 久久精品视频播放| 国产精品91视频| 92国产精品视频| 日韩国产欧美精品一区二区三区| 中文字幕亚洲精品| 国产精品久久久久久久av电影| 国外成人性视频| 久久99青青精品免费观看| 国产99视频在线观看| 国产欧美亚洲精品| 亚洲国产精品热久久| 欧美有码在线观看视频| 欧美色道久久88综合亚洲精品| 性色av一区二区三区免费| 欧美多人爱爱视频网站| 国产精品美女视频网站| 国产主播欧美精品| 2019中文字幕免费视频| 国产噜噜噜噜噜久久久久久久久| 高跟丝袜一区二区三区| 欧美日韩国产精品一区| 国产在线久久久| 97在线视频免费播放| 热久久这里只有精品| 国产91网红主播在线观看| 亚洲黄色有码视频| 亚洲激情在线视频| 欧美精品一区在线播放| 国产在线精品一区免费香蕉| 欧美午夜视频一区二区| 日本精品中文字幕| 欧美日韩国产va另类| 九九综合九九综合| 俺也去精品视频在线观看| 国产成人精品日本亚洲| 精品一区二区三区四区| 亚洲久久久久久久久久久| 欧美激情性做爰免费视频| 久久偷看各类女兵18女厕嘘嘘| 日本成人在线视频网址| 久久精品视频亚洲| 久久成人精品视频| 欧美激情aaaa| 91香蕉国产在线观看| 久久久成人精品视频| 91色p视频在线| 成人黄色av网站| 久久不射电影网| 亚洲天堂网在线观看| 久久综合免费视频| 日韩在线视频免费观看| 亚洲性无码av在线| 久久久精品中文字幕| 国产va免费精品高清在线| 成人激情视频在线播放| 91精品国产成人www| www.午夜精品| 亚洲欧美视频在线| 久久精品91久久久久久再现| 5278欧美一区二区三区| 欧美超级免费视 在线| 欧美午夜片在线免费观看| 国产成人中文字幕| 日韩精品在线观| 国产91精品黑色丝袜高跟鞋| 欧美性猛交xxxx黑人猛交| 91精品视频专区| 欧美在线视频免费观看| 亚洲成人黄色网址| 日韩成人性视频| 欧美性猛交xxxxx水多| 日韩动漫免费观看电视剧高清| 亚洲成人网久久久| 懂色aⅴ精品一区二区三区蜜月| 欧美日韩精品在线观看| 精品久久久久国产| 中文字幕综合一区| 国产精品国产三级国产专播精品人| 色婷婷综合久久久久中文字幕1| 国产va免费精品高清在线观看| 日韩成人在线视频观看| 亚洲色图色老头| 国模视频一区二区| 91视频免费网站| 欧美成人免费全部观看天天性色| 日韩电影第一页| 亚洲天堂av女优| 亚洲国产精品中文| 国产91在线高潮白浆在线观看| 热久久美女精品天天吊色| 九九久久久久久久久激情| 日韩在线观看免费全| 91成人天堂久久成人| 成人伊人精品色xxxx视频| www日韩中文字幕在线看| 亚洲第一色中文字幕| 亚洲欧美日韩直播| 亚洲欧美在线磁力| 69久久夜色精品国产69| 亚洲电影av在线| 91av在线免费观看视频| 亚洲午夜精品久久久久久性色| 5566成人精品视频免费| 国产精品中文字幕久久久| 最近中文字幕2019免费| 国产精品com| 欧美成人小视频| 亚州欧美日韩中文视频| 国外成人在线播放| 超碰91人人草人人干| 久久99精品国产99久久6尤物| 亚洲福利精品在线| 国产精品视频26uuu| 久久777国产线看观看精品| 久久久久亚洲精品国产| 国模精品视频一区二区三区| 欧美成人免费网| 精品久久中文字幕久久av| 麻豆国产精品va在线观看不卡| 亚洲精品久久久久中文字幕二区| 亚洲视频自拍偷拍| 九九久久国产精品| 国产精品久久婷婷六月丁香| 国产成人精品久久二区二区91| 国产一区二区三区日韩欧美| 91国产精品电影| 一区二区亚洲精品国产| 国产精品久久久久aaaa九色| 精品美女国产在线| 亚洲精品国产电影| 成人黄色生活片| 高清一区二区三区四区五区| 欧美乱大交xxxxx| 91精品国产91久久久久久不卡| 亚洲色图综合久久| 国产成人jvid在线播放| 国模私拍一区二区三区| 91老司机精品视频| 久久在线免费观看视频| 亚洲性日韩精品一区二区| 午夜欧美不卡精品aaaaa| 欧美日韩日本国产| 欧美黄色成人网| 综合国产在线视频| 亚洲人成亚洲人成在线观看| 91久久在线观看| 欧美精品videosex极品1| 国产精品第一视频|