繪圖(VC_Win32)


目錄

GUI作圖概述
描繪圖形
位圖
文本輸出
設置畫刷/畫筆/字體
MFC 資源句柄的獲得與釋放

(本章節中例子都是用 VS2005 編譯調試的)


GUI作圖概述

作圖步驟

  • 獲得設備描述表資源句柄
  • 繪圖操作
  • 釋放設備描述表資源句柄

流程圖如下:

獲取/釋放設備資源描述表

  • 獲取設備資源描述表:   BeginPaint / GetDC
  • 釋放設備資源描述表:  EndPaint / ReleaseDC

BeginPaint / GetDC 兩種方式的區別:

             BeginPaint             GetDC            
使用環境         只用於圖形刷新時獲取設備環境   使用較為廣泛
操作區域         無效區              特定窗口的客戶區或者整個窗口
釋放設備環境所用函數   EndPaint ()            ReleaseDC ()

代碼示例:

在 WM_PAINT 添加 BeginPaint 事件,在 WM_LBUTTONDOWN 添加 GetDC 事件.

BeginPaint 使用:

//獲得資源DC
hdc=BeginPaint(hwnd,&ps);
//獲得窗口大小
GetClientRect(hwnd,&rect);
//繪制文本
DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
    DT_SINGLELINE | DT_CENTER | DT_VCENTER);
//釋放資源DC
EndPaint(hwnd,&ps);

 GetDC 使用: 

//獲得設備資源描述表
hdc = GetDC(hwnd);
//繪制帶圓角矩形
RoundRect(hdc,10,10,110,60,10,10);
//釋放設備資源描述表
ReleaseDC(hwnd,hdc);

程序源碼

運行結果:

單擊鼠標右鍵和重繪窗口時

在單擊鼠標右鍵后

繪圖操作分類

  • 描繪圖形
  • 位圖
  • 文本輸出

與設備描述表相關函數


描繪圖形

常用繪圖函數:

  • 畫貝塞爾曲線:
  • 畫點:  SetPixel
  • 畫矩形:  Rectangle
  • 畫帶圓角的矩形:  RoundRect
      函數原型:  BOOL RoundRect( HDC hdc, int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nWidth,int nHeight);
      參數說明:
            
  • 畫橢圓:  Ellipse
  • 畫橢圓的一部分(即畫一個弦):  Chord
  • 畫一個扇形區並用當前畫刷填充:  Pie
  • 畫橢圓弧線:   Arc
      函數原型:  BOOL Arc(HDC hdc,int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc);
      參數說明:

            
  • 畫橢圓弧線:   ArcTo
  • 畫正圓弧線:  AngleArc
      函數原型:   BOOL AngleArc(HDC hdc,int X,int Y,DWORD dwRadius,FLOAT eStartAngle,FLOAT eSweepAngle);
      參數說明:

          
  • 畫一系列相連的直線:
  • 畫線條:
    • 設置畫筆起始位置:  MoveToEx
    • 設置畫筆終止位置:  LineTo

位圖

步驟:

  • 建立位圖資源
  • 載入/創建位圖資源
  • 獲取設備內存
  • 選入內存設備
  • 貼圖

流程圖如下所示:

代碼示例:

.rc 內容(位圖資源):

IDB_BITMAP1             BITMAP                  "8c8a09f1gw1ds3qh4vtcyj.bmp"

位圖(8c8a09f1gw1ds3qh4vtcyj.bmp 尺寸信息:440*622):

在鼠標左鍵單擊事件中添加貼圖操作:

加載位圖:

hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));

創建兼容 DC 並將位圖選入兼容 DC 中:

hcmdc = CreateCompatibleDC(hdc);
SelectObject(hcmdc,hBmp);

 獲得窗口大小(被顯示的區域),獲得位圖信息(要顯示的區域)

//獲取窗口大小
GetClientRect(hwnd,&rect);
//獲取位圖信息(在 StretchBlt 時候有用到,而 BitBlt 沒有)
GetObject(hBmp, sizeof(BITMAP), &bmp);

 顯示位圖:

//顯示方式一,  按原圖比例顯示
BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY);

//顯示方式二,  拉伸式顯示
StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

程序源碼

運行結果:

  • 在未點擊鼠標右鍵時候:

  • 點擊鼠標左鍵(用 BitBlt 方法):

  • 點擊鼠標左鍵(用 StretchBlt 方法):


文本輸出

文本輸出操作

  • 文字輸出:  TextOut
  • 顯示字符串:  DrawText

有關文本操作:

  • 獲取文字信息:  GetTextMetrics
  • 格式化文字:  GetTextExtentPoint32
  • 設置字體顏色和背景顏色:
    • 字體:  SetTextColor
    • 背景:  SetBkColor

設置畫刷/畫筆/字體

相關結構體:

字體結構體

TEXTMETRIC

作用:  記錄基本的字體信息

結構體定義(MSDN 鏈接):

View Code
typedef struct tagTEXTMETRIC {
  LONG  tmHeight; // Specifies the height (ascent descent) of characters.
  LONG  tmAscent; // Specifies the ascent (units above the base line) of characters.
  LONG  tmDescent; // Specifies the descent (units below the base line) of characters.
  LONG  tmInternalLeading; // Specifies the amount of leading (space) inside the bounds set by the tmHeight member. 
  LONG  tmExternalLeading; // Specifies the amount of extra leading (space) that the application adds between rows. 
  LONG  tmAveCharWidth; // Specifies the average width of characters in the font.
  LONG  tmMaxCharWidth; // Specifies the width of the widest character in the font.
  LONG  tmWeight; // Specifies the weight of the font.
  LONG  tmOverhang; // Specifies the extra width per string that may be added to some synthesized fonts
  LONG  tmDigitizedAspectX; // Specifies the horizontal aspect of the device for which the font was designed.
  LONG  tmDigitizedAspectY; // Specifies the vertical aspect of the device for which the font was designed. 
  TCHAR tmFirstChar; // Specifies the value of the first character defined in the font.
  TCHAR tmLastChar; // Specifies the value of the last character defined in the font.
  TCHAR tmDefaultChar; // Specifies the value of the character to be substituted for characters not in the font.
  TCHAR tmBreakChar; // Specifies the value of the character that will be used to define word breaks for text justification.
  BYTE  tmItalic; // Specifies an italic font if it is nonzero.
  BYTE  tmUnderlined; // Specifies an underlined font if it is nonzero.
  BYTE  tmStruckOut; // Specifies a strikeout font if it is nonzero.
  BYTE  tmPitchAndFamily; // Specifies information about the pitch, the technology, and the family of a physical font.
  BYTE  tmCharSet; // Specifies the character set of the font. 
} TEXTMETRIC, *PTEXTMETRIC;

 圖示:

步驟:

  • 創建資源句柄
  • 創建自定義資源/調用系統資源
  • 將資源選入系統

如下圖所示:

代碼示例:

在窗口重畫的時候添加創建新畫筆操作:

創建新畫筆,並將畫筆選入設備描述表中

pen = CreatePen(PS_DOT,3,RGB(255,100,100));
SelectObject(hdc,pen);

為了區別創建畫筆前和創建畫筆后的作圖的區別

在創建畫筆前繪制一條直線:

//rect 為記錄窗口大小的 RECT 結構體
MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);

在創建畫筆后繪制一條直線:

MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);

程序源碼

運行結果:


程序源碼

View Code
#include<windows.h>
#include"resource.h"

HINSTANCE hinstance;

LRESULT CALLBACK textprom(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);

int WINAPI WinMain(  HINSTANCE hInstance,  // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,      // pointer to command line
  int nCmdShow          // show state of window
)
{
    WNDCLASS wndclass;
    HWND hwnd;
    MSG msg;

    //設計窗口類
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
    wndclass.hInstance=hInstance;
    wndclass.lpfnWndProc=textprom;
    wndclass.lpszClassName="text";
    wndclass.lpszMenuName=NULL;
    wndclass.style=CS_HREDRAW | CS_VREDRAW;
    
    //注冊窗口類
    if(!RegisterClass(&wndclass))
    {
        MessageBox(NULL,"create windows error!","error",MB_OK | MB_ICONSTOP);
    }

    //創建無菜單資源的窗口窗口
    hwnd=CreateWindow("text","hellow world",WS_DLGFRAME | WS_MINIMIZEBOX | WS_SYSMENU,0,0,500,300,NULL,NULL,hInstance,NULL);


    //顯示更新窗口
    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);

    hinstance = hInstance;

    //消息循環
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK textprom(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
)
{
    HDC hdc,hcmdc;
    PAINTSTRUCT ps;
    RECT rect;
    HBITMAP hBmp;
    SIZE   size;
    BITMAP bmp;
    HPEN pen;

    switch(uMsg)
    {
    //重繪事件
    case WM_PAINT:
        hdc=BeginPaint(hwnd,&ps);
        //顯示文本
        GetClientRect(hwnd,&rect);
        DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
            DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        //畫筆
        MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL);
        LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);
        pen = CreatePen(PS_DOT,3,RGB(255,100,100));
        SelectObject(hdc,pen);
        MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL);
        LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);
        EndPaint(hwnd,&ps);
        break;
    //繪制圓角矩形
    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        RoundRect(hdc,10,10,110,60,10,10);
        ReleaseDC(hwnd,hdc);
        break;
    //貼圖
    case WM_RBUTTONDOWN:
        hdc = GetDC(hwnd);
        hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));
        hcmdc = CreateCompatibleDC(hdc);
        SelectObject(hcmdc,hBmp);    
        GetClientRect(hwnd,&rect);
        GetObject(hBmp, sizeof(BITMAP), &bmp);
        StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
        //BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY);
        ReleaseDC(hwnd,hdc);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

MFC 資源句柄的獲得與釋放

繪圖是選用GDI資源的說明

在程序中,當構造函數構造一個GDI對象后,該對象並不會立刻生效,必須選入設備描述表,它才會在以后的操作中生效,利用SelectObject函數可以實現把GDI對象選入設備描述表中,並且返回指向先前GDI設備對象的指針,一般情況下,在完成繪圖操作后,都要利用SelectObject函數吧先前的GDI對象選入設備表,以便使恢復到先前狀態

GDI繪圖對象(CPen,CFont.CBitmap,CBrush)都派生於CGdiObject類對象,都有一個m_hObject記錄與對應資源聯系的關系,當其對象與對應的資源調用CreateXXXX建立聯系后若想把對象關聯上新的資源時候,必須先對舊的資源釋放才能和新的資源建立上聯系,可以用CGdiObject對象的DeleteObject函數去切斷與舊資源的聯系,並釋放舊的資源

相關函數

獲得資源設備表

函數原型

CDC* GetDC();

返回值:  如果調用成功,則返回CWnd客戶區的設備環境;否則,返回NULL。這個指針可能是臨時的,不能被保存以供將來使用

說明:   這個函數獲得一個指針,指向一個客戶區的公用的、屬於類的或者私有的設備環境,依賴於為CWnd指定的類風格。對於公用的設備環境,GetDC每次獲得設備環境時都給它賦予缺省值。對於屬於類的或者私有的設備環境,GetDC保持原來的屬性不變。在隨后的圖形設備接口(GDI)函數中可以使用設備環境以在客戶區中繪圖

釋放資源設備表

函數原型

int ReleaseDC( CDC* pDC );

參數說明:   pDC 標識了要釋放的設備環境
返回值:    如果成功,則返回非零值;否則返回0
說明:     釋放設備環境,以供其它應用程序使用。ReleaseDC成員函數的效果依賴於設備環境的

CPainDC與CCleintDC的區別

  • CPaintDC
    • CPaintDC繼承於CDC
    • 在構造函數中調用BeginPaint
    • 在析構函數調用EndPaint函數
    • 用於相應WM_PAINT消息的函數中
  • CClientDC
    • CClientDC繼承於CDC
    • 在析構函數中調用GetDC
    • 在析構函數中調用ReleaseDC
    • 用於非WM_PAINT消息的GDI繪圖函數中

獲得設備資源描述表實現步驟


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM