我想上一篇提到了畫一條線,那麼今天就繼續聊聊繪線的函數吧。
本來接著是想畫一個圓,可是找來找去就是找不到畫圓的函數,只有畫橢圓的函數,
好吧,就來變通一下下。
畫橢圓的函數:
Ellipse(HDC hdc, int nLeftRect, int nTopRect, int RightRect, int nBottomRect)
只要我們把這個矩形參數設成正方形,那麼他所畫出來的橢圓形就變成圓形了,哇!太好了。
當然啦,把這矩形參數設成長方形的時候,畫出來的就是橢圓形了。
看似達到我想要的目的了,可是當我再畫一直線進入到這圓形的內部時卻產生畫面閃爍的問題,
同樣的,畫兩個圓有交集的部份也一樣會發生閃爍的問題,這…可就不是我想要的答案。
為了證實我的想法,再來一個矩形的函數試試吧!
畫矩形的函數:
Rectangle(HDC hdc, int nLeftRect, int nTopRect, int RightRect, int nBottomRect)
鏘鏘~
結果和畫橢圓形的時候一樣。雖然我並不知道其內部的處理方式為如何,但…或許是畫封閉式的圖形
都會有這個情形吧。如果我的假設推斷是正確的,那……只能找畫非封閉圖形函數了。
(((我要一個圓啦)))
那就畫弧線的函數吧!也許畫兩個半圓的弧線就可以湊成一個圓了,聰明吧~【挑眉】
再想想,何不試試把起點當成終點,看看會是怎樣的結果,反正試又不用錢。
弧線的函數:
Arc(HDC hdc, int nLeftRect, int nTopRect, int RightRect, int nBottomRect,
int nXStartArc, int nYStartArc, int nXEndArc, nYEndArc)
只要把nXEndArc﹦nXStartArc,nYEndArc﹦nYStartArc,賓果!!!
因為畫了一條線,就想要畫一個圓。為了要畫一個圓,測試了橢圓、矩形、弧線函數,
當然也讓大腦燃燒了一下下,對於自學者的我來說,好玩。
沒動到resource.rc,就不重貼resource.rc了。
➻➼➸➳➺➻➴➵➶▶♕♖♗♘♙♚♛ 我是可愛的分隔線 ➻➼➸➳➺➻➴➵➶▶♕♖♗♘♙♚♛
main.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define IDM_Demo1 1001
#define IDM_Line 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);
wndclass.lpszMenuName = "DODO";
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = 0 ;
RegisterClassEx (&wndclass);
hwnd = CreateWindowEx (
0,
szAppName,
"Graph 繪製圖形", // 純好玩.. 改一下
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
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)
{
switch (message)
{
HDC hdc;
case WM_PAINT:
hdc = GetDC(hwnd);
MoveToEx(hdc,80,80,NULL);
LineTo(hdc,180,80); // 重疊部份就會閃爍
///// 增加這段程式碼 ↓↓↓↓↓↓↓
Ellipse (hdc,100,100,200,200);
Ellipse (hdc,250,200,350,250); // 沒重疊到就不會閃爍
Arc (hdc,260,260,300,300,120,60,120,60);
Rectangle(hdc,10,10,150,150);
///// 增加這段程式碼 ↑↑↑↑↑↑↑
ReleaseDC(hwnd,hdc);
return 0;
case WM_CREATE:
return 0 ;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_Demo1:
break;
case IDM_Line:
{ hdc = GetDC(hwnd);
MoveToEx(hdc,20,20,NULL);
LineTo(hdc,150,20);
ReleaseDC(hwnd,hdc);
}
break;
}
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
➻➼➸➳➺➻➴➵➶▶♕♖♗♘♙♚♛ 我是可愛的分隔線 ➻➼➸➳➺➻➴➵➶▶♕♖♗♘♙♚♛
2020-12-26 補記
經過幾天的思考,想想或許還有些什麼吧。
再小小修改了一下程碼,居然有不同的結果,我們一起來瞧瞧。
case WM_PAINT:
// hdc = GetDC(hwnd);
hdc = BeginPaint(hwnd,&ps); // 若改用這樣則不會閃爍 //*
MoveToEx(hdc,80,80,NULL);
LineTo(hdc,180,80); // 重疊部份就會閃爍
///// 增加這段程式碼 ↓↓↓↓↓↓↓
Ellipse (hdc,100,100,200,200); // 這是取正方形範圍來畫圓
Ellipse (hdc,250,200,350,250); // 沒重疊到就不會閃爍
Arc (hdc,260,260,300,300,120,60,120,60);
Rectangle(hdc,10,10,150,150);
///// 增加這段程式碼 ↑↑↑↑↑↑↑
// ReleaseDC(hwnd,hdc);
EndPaint(hwnd,&ps); // 若改用這樣則不會閃爍 //*
return 0;
發覺Ellipse()和Rectangle()就是畫它所圈起來的整個範圍,不只是畫框框線條,
而Arc()和LineTo()就只是畫線條而已。
另一方面,hdc = GetDC(hwnd) 會自動的一直重繪,所以才會不斷的閃爍,
而 hdc = BeginPaint(hwnd,&ps),並不會一直的重繪,只有在改變視窗大小
的時候,才重繪一次,所以就不閃爍了,各位可以自行試試。
.
延伸閱讀