VC++ 用MOVETtoEX和Lineto繪製連貫流暢線條

BUKE_GUIGUI發表於2018-04-27

之前學VC++嘗試了使用setpixel函式畫線,結果畫出來的線斷斷續續,一點都不連貫,那麼怎麼使其畫出連貫流暢的線條呢?

效果圖:


對比setpixel()


先來看程式碼:

#include<Windows.h>
#include<tchar.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOLEAN InitWindowsClass(HINSTANCE, int);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!InitWindowsClass(hInstance, nCmdShow))
{
MessageBox(NULL, _T("建立視窗失敗!"), _T("建立視窗"), NULL);
return 1;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}




LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static bool  isDrawPoint = 0;
static int x = 0, y = 0;
static int x1 = 0, y1 = 0;
x = LOWORD(lParam);
y = HIWORD(lParam);
switch (message)
{
case WM_LBUTTONDOWN:
isDrawPoint = true;
x1 = x;
y1 = y;


InvalidateRect(hWnd, NULL, false);
break;
case WM_LBUTTONUP:

isDrawPoint = false;
InvalidateRect(hWnd, NULL, false);
break;
case WM_RBUTTONDOWN:
InvalidateRect(hWnd, NULL, true);
break;
case WM_MOUSEMOVE:
if (isDrawPoint)
{
hdc = GetDC(hWnd);
x = LOWORD(lParam);
y = HIWORD(lParam);
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x, y);
x1 = x;
y1 = y;
ReleaseDC(hWnd,hdc);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);




EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOLEAN InitWindowsClass(HINSTANCE hInstance, int nCmdShow)
{
WNDCLASSEX wndclass;
HWND hWnd;


wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor(hInstance, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszClassName = _T("視窗1");
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wndclass))
return FALSE;


hWnd = CreateWindow(_T("視窗1"), _T("滑鼠畫線示例"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;

}


核心程式碼:

 case WM_MOUSEMOVE:
if (isDrawPoint)
{
hdc = GetDC(hWnd);
x = LOWORD(lParam);
y = HIWORD(lParam);
MoveToEx(hdc, x1, y1, NULL);
LineTo(hdc, x, y);
x1 = x;
y1 = y;
ReleaseDC(hWnd,hdc);
}
break;

我也是初學VC++,第一次知道可以不用再paint中畫圖,直接在move中畫圖即可。

這裡使用類似動態跟蹤的功能,先定下滑鼠左鍵按下的初始點,在move到滑鼠指標現在的位置,接著將lineto的滑鼠座標賦值給初始點,就這樣迴圈往復即可實現不斷的連線。


之所以setpixel函式會出現斷斷續續,我認為可能是由於每一次的重新整理速率跟不上滑鼠位置變化率,當滑鼠飛快在使用者區滑動時,setpixel未能及時捕獲到每一個時刻的座標位點。


但同樣可以定義一個point陣列,例如point[100]={0,0}存放setpixel的值,再加一個判斷條件,當抬起滑鼠時,將陣列裡的元素統統連線,這樣也可以實現畫流暢線條。


如有疑問歡迎交流

相關文章