今天学习做一个简单的画直线应用。
基本根据这篇博客完成的。
1、思路
主要处理集中在WindowProc函数,WM_LBUTTONDOWN和WM_LBUTTONUP消息
首先定义一个结构体,用于存放画线时每根线的起点和终点坐标,以及线的类型(实线、虚线、点线等)
当窗口重绘时需要把之前的直线也画出来,因此需要保存之前画过的直线的信息以重绘直线,可以用一个vector保存
每次按下鼠标左键开始画一根线,该点坐标作为该直线的起点坐标,松开左键时表示该直线画完,松开时的坐标作为该直线的终点坐标。使用弹出式菜单来选择线型,还可以加入颜色、线粗的菜单,但是我这里没有加。
以前做opengl的作业时还有实现过右键点击某直线删除该直线,可以遍历vector判断点击的坐标在哪条直线上然后删除该直线信息。这里没有实现
2、代码
struct PAINTDATA {
int BeginX, BeignY;
int EndX, EndY;
int penStyle;
};
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
) {
PAINTSTRUCT ps;
HDC hdc;
static vector<PAINTDATA> datas;
static int penStyle = PS_DOT;
static PAINTDATA *pCurrentData = NULL;
switch (uMsg)
{
//选择线型
case WM_COMMAND:
{
HMENU mnbar = GetMenu(hwnd);
HMENU hmnPop = GetSubMenu(mnbar, 0);
CheckMenuRadioItem(hmnPop, ID_SOLIDLINE, ID_DASHDOT, LOWORD(wParam), MF_BYCOMMAND);
penStyle = (int)LOWORD(wParam);
}
break;
//开始画线
case WM_LBUTTONDOWN:
{
pCurrentData = new PAINTDATA;
pCurrentData->penStyle = penStyle;
pCurrentData->BeginX = GET_X_LPARAM(lParam);
pCurrentData->BeignY = GET_Y_LPARAM(lParam);
}
break;
//结束画线
case WM_LBUTTONUP:
{
if (pCurrentData != NULL) {
pCurrentData->EndX = GET_X_LPARAM(lParam);
pCurrentData->EndY = GET_Y_LPARAM(lParam);
HDC hdc = GetDC(hwnd);
HPEN pen = CreatePen(pCurrentData->penStyle, 1, RGB(0, 200, 0));
HPEN oldpen = (HPEN)SelectObject(hdc, pen);
MoveToEx(hdc, pCurrentData->BeginX, pCurrentData->BeignY, NULL);
LineTo(hdc, pCurrentData->EndX, pCurrentData->EndY);
//加入工具
SelectObject(hdc, oldpen);
//释放资源
DeleteObject(pen);
ReleaseDC(hwnd, hdc);
//保存直线信息
datas.push_back(*pCurrentData);
}
}
break;
//重绘窗口,比如最小化窗口后还原
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
vector<PAINTDATA>::const_iterator it;
for (it = datas.begin(); it != datas.end(); it++) {
HPEN pen = CreatePen(it->penStyle, 1, RGB(0, 200, 0));
SelectObject(ps.hdc, pen);
MoveToEx(ps.hdc, it->BeginX, it->BeignY, NULL);
LineTo(ps.hdc, it->EndX, it->EndY);
DeleteObject(pen);
}
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
break;
}
return 0;
}
3、运行结果