Windows的圖形設備接口與Windows繪圖


本次學習目標

理解DC, 映像模式, 坐標系統, 窗口和視口; 學習獲取繪圖工具(畫筆/畫刷)的句柄, 設置顏色, 能定義映像模式; 會使用常用的繪圖函數.

編寫程序: 在屏幕上出現一個圓心沿正弦曲線軌跡移動的實心圓.

 

1. 理解DC, 映像模式, 坐標系統, 窗口和視口;

編寫基本的windows繪圖程序,獲取DC並繪圖,然后改變其映射模式、坐標、窗口和視口原點,觀察圖像輸出的變化,理解DC, 映像模式, 坐標系統, 窗口和視口的工作方式。

程序代碼如下:

#include<windows.h>

#include<stdlib.h>

#include<string.h>

long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam);

BOOL InitWindowsClass(HINSTANCE hInstance);

BOOL InitWindows(HINSTANCE hInstance,int nCmdShow);

 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

    MSG Message;

    if(!InitWindowsClass(hInstance))

        return FALSE;

    if(!InitWindows(hInstance,nCmdShow))

        return FALSE;

    while(GetMessage(&Message,0,0,0))        //消息循環

    {

        TranslateMessage(&Message);

        DispatchMessage(&Message);

    }

    return Message.wParam;

}

 

long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)

{

    HDC hDC;             //定義指向設備上下文的句柄

    HPEN hPen;            //定義指向畫筆的句柄

    PAINTSTRUCT PtStr;     //定義指向包含繪圖信息的結構體變量

    switch(iMessage)     //處理消息

    {

    case WM_PAINT:                             //處理繪圖消息

        hDC=BeginPaint(hWnd,&PtStr);

 

        SetMapMode(hDC,MM_ANISOTROPIC);         //設置映射模式為MM_ANISOTROPIC

 

        hPen=(HPEN)GetStockObject(BLACK_PEN);//設置畫筆為系統預定定義的黑色畫筆

        

        SelectObject(hDC,hPen);             //選擇畫筆

RoundRect(hDC,50,120,200,-200,15,15); //圓角矩形

        Ellipse(hDC,100,50,200,100);          //橢圓

                EndPaint(hWnd,&PtStr);         //結束繪圖

        return 0;

    case WM_DESTROY:                          //結束應用程序

        PostQuitMessage(0);

        return 0;

    default:                                    //其他消息處理程序

            return(DefWindowProc(hWnd,iMessage,wParam,lParam)) ;

        }

}

 

BOOL InitWindows(HINSTANCE hInstance,int nCmdShow)        //初始化窗口

{

    HWND hWnd;

    hWnd=CreateWindow("WinFill",                         //生成窗口

                        "填充示例程序",

                        WS_OVERLAPPEDWINDOW,

                        CW_USEDEFAULT,

                        0,

                        CW_USEDEFAULT,

                        0,

                        NULL,

                        NULL,

                        hInstance,

                        NULL);

    if(!hWnd)

            return FALSE;

        ShowWindow(hWnd,nCmdShow);                    //顯示窗口

        UpdateWindow(hWnd);

        return TRUE;

}

 

BOOL InitWindowsClass(HINSTANCE hInstance)             //定義窗口類

{

        WNDCLASS WndClass;

        WndClass.cbClsExtra=0;

        WndClass.cbWndExtra=0;

        WndClass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH));

        WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);

        WndClass.hIcon=LoadIcon(NULL,"END");

        WndClass.hInstance=hInstance;

        WndClass.lpfnWndProc=WndProc;

        WndClass.lpszClassName="WinFill";

        WndClass.lpszMenuName=NULL;

        WndClass.style=CS_HREDRAW|CS_VREDRAW;

        return RegisterClass(&WndClass);

}

編譯並調試程序,

 

分別改變其映射模式、坐標、窗口和視口原點,觀察圖像輸出的變化

 

2. 獲取繪圖工具(畫筆/畫刷)的句柄, 設置顏色

修改繪圖代碼為:

hPen=(HPEN)GetStockObject(BLACK_PEN);//設置畫筆為系統預定定義的黑色畫筆

        hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH); //采用系統預定義的深灰色畫刷

        SelectObject(hDC,hBrush);             //選擇畫刷

        SelectObject(hDC,hPen);             //選擇畫筆

        RoundRect(hDC,50,120,200,-200,15,15); //圓角矩形

        hBrush=CreateSolidBrush(RGB(220,32,70));

        SelectObject(hDC,hBrush);             //選擇畫刷

        Ellipse(hDC,100,50,200,100);         //橢圓

編譯並調試程序

 

3.在屏幕上繪制一個圓心沿正弦曲線軌跡移動的實心圓

程序源代碼如下:

#include <windows.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#define Pi 3.1415926

 

long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam);                    //消息處理函數聲明.

 

double dfTheta=0,dfRange=100.0;                        //正弦曲線的角度變量.

long i=0,j=0;

long lCentreX=0,lCentreY=0,lRadious=(long)(0.5*dfRange);

                //定義圓心坐標和圓坐標.

POINT lpSin[100];    //定義正弦曲線的點坐標.

 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)            //主函數

{

    MSG Message;            //定義消息變量.

    HWND hWnd;                //定義窗口句柄.

 

    WNDCLASS WndClass;        //定義窗口類.

    WndClass.cbClsExtra=0;        //無窗口類擴展.

    WndClass.cbWndExtra=0;        //無窗口實例擴展.

    WndClass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH));//背景為白色.

    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);    //窗口采用箭頭光標.

    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);    //采用缺省圖標.

    WndClass.hInstance=hInstance;                    //當前應用程序句柄.

    WndClass.lpfnWndProc=WndProc;                    //窗口處理函數.

    WndClass.lpszClassName="SIN";                    //窗口類名稱.

    WndClass.lpszMenuName=NULL;                        //無窗口菜單.

    WndClass.style=0;                                //窗口類型為缺省類型.

 

    if(!RegisterClass(&WndClass))            //注冊窗口.

    {

        MessageBeep(0);

        return FALSE;

    }

    

    hWnd=CreateWindow("SIN",                //窗口類名.

                    "yuan",                    //標題名.

                    WS_OVERLAPPEDWINDOW,    //帶標題欄,最大和最小按鈕的窗口.

                    CW_USEDEFAULT,            //窗口左上角坐標.

                    0,                        

                    CW_USEDEFAULT,            //采用缺省的寬度和高度.

                    0,

                    NULL,                    //無父窗口.

                    NULL,                    //無主菜單.

                    hInstance,                //當前實例句柄.

                    NULL);                    //不要此參數.

    ShowWindow(hWnd,nCmdShow);            //顯示窗口.

    UpdateWindow(hWnd);                    //更新並繪制用戶區.

 

    for(int j=0;j<100;j++)        //生成正弦曲線的點坐標.

    {

        lpSin[j].x=(long)(j*2*Pi/100*60);

        lpSin[j].y=(long)(dfRange*sin(j*2*Pi/100));

    }

    

    while(GetMessage(&Message,0,0,0))

    {

        TranslateMessage(&Message);            //消息循環.

        DispatchMessage(&Message);

    }

    return Message.wParam;

}

 

long WINAPI WndProc(HWND hWnd,

                    UINT iMessage,

                    UINT wParam,

                    LONG lParam)            //消息處理函數.

{

    HDC hDC;                //定義設備環境句柄.

    HBRUSH hBrush;            //定義畫刷句柄

    HPEN hPen;                //定義畫筆句柄

    PAINTSTRUCT PtStr;        //定義包含繪圖信息的結構體變量

 

    switch(iMessage)

    {

    case WM_PAINT:                            //處理繪圖消息.

        hDC=BeginPaint(hWnd,&PtStr);        //獲得設備環境指針.

        SetWindowOrgEx(hDC,-200,-200,NULL);    //設置原點坐標為(-200,-200).

 

        Polyline(hDC,lpSin,100);                //繪制正弦曲線.

 

        hPen=(HPEN)GetStockObject(BLACK_PEN);//設置畫筆為系統預定定義的黑色畫筆

        hBrush=(HBRUSH)GetStockObject(DKGRAY_BRUSH); //采用系統預定義的深灰色畫刷

        SelectObject(hDC,hBrush);    //選入畫刷.

        SelectObject(hDC,hPen);        //選入畫筆.

        lCentreX=lpSin[i].x;        //圓心x坐標.

        lCentreY=lpSin[i].y;        //圓心y坐標.

        Ellipse(hDC,lCentreX-lRadious,lCentreY-lRadious,

            lCentreX+lRadious,lCentreY+lRadious);    //畫圓.

 

        i++;

        if(i>=100)

            i=0;

      

        DeleteObject(hPen);        //刪除畫筆.

        DeleteObject(hBrush);    //刪除畫刷.

        EndPaint(hWnd,&PtStr);    //刪除設備環境指針.

        Sleep(100);                //停0.1秒.

        if(i<100) InvalidateRect(hWnd,NULL,1);    //刷新用戶區.

        return 0;

    case WM_DESTROY:    //關閉窗口.

        PostQuitMessage(0);

        return 0;

    default:

        return(DefWindowProc(hWnd,iMessage,wParam,lParam));

    }

 

}

編譯並調試程序,

 

1.DC, 映像模式, 坐標系統, 窗口和視口程序運行結果

初始圖像:

改變映射模式為MM_LOMETRIC后:

Y向上,X向右,將一個邏輯單位映射為0.1毫米

 

恢復映射模式為MM_ANISOTROPIC並設置setWindowExtEx(hDC,2,2,0);后:

圖形相對於之前縮小

 

設置SetViewportExtEx(hDC,2,2,0);后

SetViewportExtEx(hDC,2,2,0);與setWindowExtEx(hDC,2,2,0);比例設置的映射比例相同,圖像大小與初始一樣。

此時圖像上面部分不可見,設置SetViewportOrgEx(hDC,300,300,0);將視口原點往右下移動,此時圖像輸出為:

圖像隨視口往右下移動,此時可以看見整個圖像。

同樣再上一步步驟中視口原點不變,改變窗口原點SetWindowOrgEx(hDC,-300,-300,0);此時圖像輸出與上圖相同。

 

現在,恢復窗口與視口原點並設置SetViewportExtEx(hDC,1,-1,0);此時圖像輸出為:

圖像繞X翻轉180°。此時為了能夠讓圖像完全顯示,依舊需要將視口原點往下移動即    SetViewportOrgEx(hDC,0,300,0);此時輸出如圖:

或者移動窗口原點SetWindowOrgEx(hDC,0,300,0);此時輸出和上圖相同

 

設置SetWindowExtEx(hDC,1,-1,0);與設置SetViewportExtEx(hDC,1,-1,0)的情況相同。

 

2. 獲取繪圖工具(畫筆/畫刷)的句柄, 設置顏色的運行結果

3.在屏幕上繪制一個圓心沿正弦曲線軌跡移動的實心圓運行結果

總結:

DC, 映像模式, 坐標系統, 窗口和視口;

不同映射模式的邏輯單位映射成的設備單位不同,ANISOTROPIC與ISOTROPIC模式可以通過SetWindowExtEx與SetViewportExtEx函數來確定,其余的為固定尺寸。

不同映射模式的坐標系設定也不同,ANISOTROPIC與ISOTROPIC模式可以通過SetWindowExtEx與SetViewportExtEx函數來確定,其余的有自己固定方向。其中ISOTROPIC模式X軸與Y軸單位比例固定為1:1。

注意在改變視口與窗口原點使圖像能夠全部顯示時,分清窗口在邏輯坐標系中移動的方向和視口在設備坐標系移動的方向!

窗口與視口的映射關系具體可以參考:從窗口到視口的映射.pdf

 

獲取繪圖工具(畫筆/畫刷)的句柄並設置顏色;

可以直接調用函數GetStockObject獲取Windows系統提供的8種畫刷,也可以調用函數CreateSolidBrush或CreateHatchBrush來創建具有指定顏色的單色畫刷或具有指定陰影圖案和顏色的畫刷。

創建好的畫刷記得選入設備環境,不再使用后記得刪除。


免責聲明!

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



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