我們都知道在 console 版的 c++ 中,我們要將文字顯示在螢幕上
可以使用 cout << 將文字顯示在螢幕上,而進到視窗版的 c++ 又要如何處理呢?
今天就來聊聊兩個函式 DrawText() 和 TextOut()


int DrawText(
  HDC     hdc,
  LPCTSTR lpchText,
  int     cchText,
  LPRECT  lprc,
  UINT    format
);

 

 

  HDC     hdc,       輸出標的指引碼
  LPCTSTR lpchText,  字串,指標
  int     cchText,   字串的長度,如果字串是以零字碼結尾,此值必須為-1 
  LPRECT  lprc,      要書寫文字所在的矩形範圍,指標
  UINT    format     排置方式旗標

 

這個 format 可選擇的選項太多了,請自行上微軟官網看一看
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext

 

到目前為止,我比較不用 DrawText() 這個函式,個人喜歡 TextOut()
或許是...我也還是新手,還沒找到讓他發揮的空間吧 

 

DrawText 還有一個擴充版函式 DrawTextEx 也請自行上微軟官網一趟,瞧個仔細


再來就是 TextOut()

BOOL TextOutA(
  HDC    hdc,         輸出標的指引碼
  int    x,           起始點之X座標
  int    y,           起始點之Y座標
  LPCSTR lpString,    字串,指標 
  int    c            字串長度(不接受零字碼結尾之字串)
);

想不到微軟官網稱為 TextOutA ,好吧!多個 A 就多個 A

TextOut也有一個擴充版函式 ExTextOut() 以及跳格輸出文字 TabbedTextOut()


好了,我們就稍微瞄一下程式碼,在一些程式碼要配合修改的地方就稍微修改一下,

在 LRESULT CALLBACK WndProc() 內增加一下宣告和字串

RECT rect;
RECT 是微軟設定好的矩形結構,我們就跟著宣告一個 rect 來給 DrawText() 函數中使用

TCHAR szstr[] = "最美麗的風景從這裡開始...DrawText(  )";
TCHAR szstr2[] = "最堅定的美麗風景在這裡...TextOut(  )";

static UINT dwformat = 0; 
就是這個 dwformat 有一大堆選項,你可以在宣告這裡改變一下成非0數值看看他的變化,


在 case WM_PAINT: 內就套套函式 DrawText() TextOut()

記得 case IDM_Bottom: 也改一下

dwformat = DT_SINGLELINE | DT_BOTTOM;   這個參數是可以搭配使用的

 

InvalidateRect(hwnd, NULL, TRUE);
由於WM_PAINT訊息的優先權很低,而且我們無法預期視窗何時有空可以處理這個訊息,這種情況下,
如果有特定的需要,必須馬上更新顯示內容,而不想讓WM_PAINT訊息一直被動的留在訊息佇列裡等待處理,
可以透過 InvalidateRect()函式指定視窗的某個範圍為無效區域之後接著呼叫 UpdateWindow()函式,
強制更新視窗的畫面,這種情況系統會直接要求視窗程序立刻處理WM_PAINT訊息而不是僅放在訊息佇列裡排隊等待     
           

 


。,、'﹕︰﹔﹖﹑•!?!﹪%*﹡﹢ 我是可愛的分隔線  〈〉『』〖〗[]《》〔〕  「」【】﹁﹃︻﹂﹄︼

 

resource.rc


#define IDM_Demo1       1001      //  設定選單識別碼 
#define IDM_Bottom        1002    /////  配合修改一下

DODO MENU 
{
    POPUP "檔案 "
    {
      MENUITEM "&開新檔案", IDM_Demo1  
      
            // 請自行增加其他功能 例如: MENUITEM "&開啟舊檔", IDM_Demo11 
           // 所有想歸類在 "檔案 " 底下的功能選項都寫在這邊 
    }
    POPUP "編輯"
    {
 
     MENUITEM "&文字置底", IDM_Bottom  ///// 配合修改一下
       
           //  你還可以增加任何你要的功能..如:畫兩條線... 
    }
}

 

。,、'﹕︰﹔﹖﹑•!?!﹪%*﹡﹢ 我是可愛的分隔線  〈〉『』〖〗[]《》〔〕  「」【】﹁﹃︻﹂﹄︼

 

 

main.cpp

 

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#define IDM_Demo1      1001      
#define IDM_Bottom       1002    //


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


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
char szAppName[] = "HelloWin";
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof(WNDCLASSEX) ;
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 = GetSysColorBrush(COLOR_3DFACE);   //3DFACE);
wndclass.lpszMenuName = "DODO";  
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = 0 ;

RegisterClassEx (&wndclass);


hwnd = CreateWindowEx (
0,
szAppName, 
"Graph 繪製圖形",
WS_OVERLAPPEDWINDOW, 

0,0,800,500, 
NULL, 
NULL, 
hInstance, 
NULL) ; 


ShowWindow (hwnd, iCmdShow) ;
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)
{
  PAINTSTRUCT ps;                     // 若改用這樣則不會閃爍 //*

  RECT rect;
  TCHAR szstr[] = "最美麗的風景從這裡開始...DrawText(  )";
  TCHAR szstr2[] = "最堅定的美麗風景在這裡...TextOut(  )";
  static UINT dwformat = 0;

   
switch (message)
{
HDC hdc;
 
case WM_PAINT:
     
//    hdc = GetDC(hwnd);
    hdc = BeginPaint(hwnd,&ps);      // 若改用這樣則不會閃爍 //*
    

//   SetRect(&rect, 32,32,280,64);    // 選擇一 自己決定顯示位置 
    GetClientRect(hwnd, &rect);      // 選擇二 dwformatd 控制顯示位置 
                                                       // 二選一   看你要註標掉哪一個 
    DrawText(hdc, szstr, -1, &rect, dwformat);    // 第三個參數 -1   你也可以試試直接給字數
    
     TextOutA(hdc, 50, 50, szstr2, 36);  // 可以直接計算字數...中文字要算2 
     TextOut(hdc, 80, 80, szstr2, sizeof(szstr2)-1); // 記得 sizeof(szstr2) 要 -1 

//    ReleaseDC(hwnd,hdc);

     EndPaint(hwnd,&ps);                // 若改用這樣則不會閃爍 //*
    return 0;

case WM_CREATE:
     return 0 ;
    
case WM_COMMAND:                        
        switch(LOWORD(wParam))
    { 
            case IDM_Demo1:
                 
              break;
            

             case IDM_Bottom:   //
                     {    
                  
                dwformat =     DT_SINGLELINE | DT_BOTTOM;
                InvalidateRect(hwnd, NULL, TRUE);

                
                 }  
                break;
      } 
       
       return 0 ;

case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}


return DefWindowProc (hwnd, message, wParam, lParam) ;
}

 

 

 

 

 

 

 

 

延伸閱讀

 

[伊蒙 dev c++] 視窗程式學習筆記

 

[做中學 dev c++] dev c++

.

 

 

 

 

 

 

 

 

arrow
arrow

    伊蒙‧普羅客 發表在 痞客邦 留言(0) 人氣()