跟我一起玩Win32開發(10):繪圖(C)

來源:互聯網
上載者:User

今天我們來欣賞一下用於填充圖形的函數,當然我不會逐個去介紹,因為我們參考MSDN直接套參數就可以了。

SetDCBrushColor函數有必要扯一下,它的聲明如下:

  COLORREF SetDCBrushColor(    __in  HDC hdc,    __in  COLORREF crColor  );

第二個參數,通過RGB宏產生COLORREF傳進去就可以了,比如這樣:

SetDCBrushColor(ps.hdc,RGB(211,254,41));

但是,如果只是調用這個函數,你會發現在繪圖的時候,畫刷的顏色還是沒有變化,因為我們還沒有將HBRUSH的預設畫刷DC_BRUSH選到DC中去。所以,在調用SetDCBrushColor之前,要把預設的畫刷先放到裝置上下文,預設畫刷可以通過GetStockObject(DC_BRUSH)獲得。

SelectObject(ps.hdc,GetStockObject(DC_BRUSH));

 

接下來我們可以嘗試填充幾個圖形試試,如矩形、橢圓、餅圖等。

case WM_PAINT:{BeginPaint(hwnd,&ps);SelectObject(ps.hdc,GetStockObject(DC_BRUSH));SetDCBrushColor(ps.hdc,RGB(0,0,255));Rectangle(ps.hdc,20,18,68,50);SetDCBrushColor(ps.hdc,RGB(220,32,70));Rectangle(ps.hdc,125,100,230,300);SetDCBrushColor(ps.hdc,RGB(30,235,12));Ellipse(ps.hdc,270,80,390,223);SetDCBrushColor(ps.hdc,RGB(35,160,242));Chord(ps.hdc,185,260,420,480,190,260,405,479);SetDCBrushColor(ps.hdc,RGB(211,254,41));Pie(ps.hdc,35,320,300,600,56,470,60,360);EndPaint(hwnd,&ps);}return 0;

每一次調用SetDCBrushColor都會改變畫刷的顏色,所以,比如你希望繪製藍色的矩形,在調用Rectangle之前就要調用SetDCBrushColor修改畫刷顏色,然後再畫矩形。我們可以看看上面代碼的最終效果。

 

下面,我們做一個人類曆史上最簡單的畫圖程式。

我們為程式提供幾種可選的線條風格,通過菜單來選擇,如實線,虛線等,滑鼠按下左鍵後開始,滑鼠左鍵彈起就完成一條直線的繪製。為了簡化,我們把相應菜單的ID設定的值與CreatePen中的線型的宏的值一致。

這樣一來,選擇了哪個菜單就直接用這個菜單的ID來建立畫筆,就省去了許多代碼。

 

在響應WM_CREATE訊息時,建立菜單。

case WM_CREATE:{// 建立菜單HMENU menubar = CreateMenu();HMENU menuPop = CreatePopupMenu();AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_SOLID,L"實線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASH,L"虛線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DOT,L"點線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASHDOT,L"點虛線");AppendMenu(menubar, MF_STRING | MF_POPUP, (UINT_PTR)menuPop, L"選擇線型");SetMenu(hwnd, menubar);}return 0;

 

現在我們來想一下,繪製直線的大概思路。

1、滑鼠左鍵按下,記錄線條的起點。

2、滑鼠左鍵彈起時,記錄線條的終點,並畫出整條線。

3、當視窗發生重繪時,前面畫的所有線條被清除,要希望保留前面畫的線條,就要響應WM_PAINT訊息,把所有線條重新畫一次。

4、由於我們會在視窗上畫出多條線,程式需要定義一個結構體用來儲存線條的起點、終點和所使用的線型。

5、正因為需要儲存多條線的資料,故可以把每一條線的相關資料放到一個vector中。

 

根據上面的分析,完成程式的代碼如下:

#include <Windows.h>#include <WindowsX.h>#include <vector>using namespace std;typedef struct tagData{int ptBeginX, ptBeginY;//起點int ptEndX, ptEndY;//終點int penStyle;//畫筆的線型} PAINTDATA;LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hThisApp,HINSTANCE hPrevApp,LPSTR lpsCmd,int nShow){WNDCLASS wc = {};wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));wc.hInstance = hThisApp;wc.lpfnWndProc = WindowProc;wc.lpszClassName = L"My";wc.style = CS_HREDRAW | CS_VREDRAW;RegisterClass(&wc);HWND hwnd = CreateWindow(L"My",L"應用程式",WS_OVERLAPPEDWINDOW,50,20,600,480,NULL,NULL,hThisApp,NULL);if(hwnd == NULL)return -1;ShowWindow(hwnd, nShow);UpdateWindow(hwnd);MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){static vector<PAINTDATA> datas;static int penStyle = PS_SOLID;static PAINTDATA *pCurrentData = NULL;//指向當前PAINTDATA的指標switch(msg){case WM_CREATE:{// 建立菜單HMENU menubar = CreateMenu();HMENU menuPop = CreatePopupMenu();AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_SOLID,L"實線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASH,L"虛線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DOT,L"點線");AppendMenu(menuPop,MF_STRING,(UINT_PTR)PS_DASHDOT,L"點虛線");AppendMenu(menubar, MF_STRING | MF_POPUP, (UINT_PTR)menuPop, L"選擇線型");SetMenu(hwnd, menubar);}return 0;case WM_COMMAND:{//為選中的菜單加上單選標記HMENU mnbar = GetMenu(hwnd);HMENU hmnPop = GetSubMenu(mnbar, 0);CheckMenuRadioItem(hmnPop, PS_SOLID, PS_DASHDOT, LOWORD(wParam), MF_BYCOMMAND);//記錄使用者選擇的線型penStyle = (int)LOWORD(wParam);}return 0;case WM_LBUTTONDOWN:{pCurrentData = new PAINTDATA;//擷取起點pCurrentData ->penStyle = penStyle;pCurrentData->ptBeginX = GET_X_LPARAM(lParam);pCurrentData->ptBeginY = GET_Y_LPARAM(lParam);}return 0;case WM_LBUTTONUP:{if(pCurrentData != NULL){//擷取終點pCurrentData->ptEndX = GET_X_LPARAM(lParam);pCurrentData->ptEndY = GET_Y_LPARAM(lParam);//畫出線條HDC hdc = GetDC(hwnd);HPEN pen = CreatePen(pCurrentData->penStyle,1,RGB(0,255,0));HPEN oldpen = (HPEN)SelectObject(hdc,pen);MoveToEx(hdc,pCurrentData->ptBeginX,pCurrentData->ptBeginY,NULL);LineTo(hdc,pCurrentData->ptEndX,pCurrentData->ptEndY);SelectObject(hdc,oldpen);DeleteObject(pen);ReleaseDC(hwnd,hdc);//把當前資料添加到vector中datas.push_back(*pCurrentData);}}return 0;case WM_PAINT:{PAINTSTRUCT ps;BeginPaint(hwnd,&ps);//將所有線條重新畫一遍vector<PAINTDATA>::const_iterator item;for(item = datas.begin(); item != datas.end(); item++){HPEN pen = CreatePen(item->penStyle, 1, RGB(0,255,0));SelectObject(ps.hdc, pen);MoveToEx(ps.hdc, item->ptBeginX, item->ptBeginY, NULL);LineTo(ps.hdc, item->ptEndX, item->ptEndY);DeleteObject(pen);}EndPaint(hwnd,&ps);}return 0;case WM_DESTROY:PostQuitMessage(0);return 0;default:return DefWindowProc(hwnd,msg,wParam,lParam);}return 0;}

 

結構體PAINTDATA用來儲存每一條線的起點座標、終點座標、線型。為了避免在跳出WindowProc後所有資料被回收,可以使用static關鍵字來聲明變數,這樣這些變數的生命週期就與整個應用程式相同了。

運行程式後,在菜單中選擇一種線型,然後在視窗上畫線,效果。

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.