windows程序设计读书笔记之练习一

版权声明:本文为博主原创文章,转载注明出处。 https://blog.csdn.net/pengjc2001/article/details/56268144

看完第5章,突然想写一个类cad的程序,先做简单功能描述及可能用到的函数

1、画直线,线宽、线形可以设置,鼠标左键开始绘图,鼠标移动时,跟踪鼠标绘制直线,再次左键,直线绘制完毕,同时开始绘制下一直线,右键结束直线绘制。线形线宽在开始绘图时设置。

2、鼠标滚动,放大 缩小, 放大的中心区为鼠标位置。

问题1的解决过程,有意思的地方是,直线的末端跟随鼠标调整直线的位置。在这鼠标移动的事件中,不停的绘制 起点 到 终点(当前鼠标坐标)的直线,

a、那么问题来了,鼠标前一位置画出的直线怎么办?  解决之道, 要么处理当前 WM_MOUSEMOVE 消息时, 用背景色绘制 前面一条直线(相当于把前面那条直线擦除),再绘制当前直线。

b、问题又来了,如果前一条直线与已绘制的直线有交点时, 那么擦除前一条直线时,同时把已绘制的直线上的那个交点也擦除了。这种状态在windows绘图软件中也是存在的。后画上的直线会把前面的直线覆盖掉。

如果要解决上面的问题,目前能想到的解决方案是,把图形的绘制丢给WM_PAINT,它的每次更新都是当前图像的最新状态。 但是问题又来了,随着图元的增加,WM_PAINT会越来越慢。


在对问题2的探索过程中,发现如果真的要实现类cad功能的话,得放弃GDI了 转向矢量图寻找解决方案。

1、记录当前鼠标点坐标,

2、放大后点坐标 = 相对坐标X放大系数 + 鼠标当前坐标。

注意:

滚轮的滚动使Windows产生的WM_MOUSEWHEEL消息,参数lParam包含鼠标的位置信息,但是,这些坐标是相对于屏幕左上角的坐标,而不是客户区的坐标。

所以,程序里使用的坐标是有WM_MOUSEMOVE消息中得到的。


 
#include <windows.h>
#include <windowsx.h>
#include <vector>
using std::vector;

vector<POINT> pt;

enum LineStyle {HeavyLine, LightLine, DashLine};

struct line
{
	POINT ptStart;
	POINT ptEnd;
	enum LineStyle  lineStyel;
};

vector<line> lines;
vector<line> lines_scaled;


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("DrawLines") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     
     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 = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Connect-the-Points Mouse Demo"),
                          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)
{
     static int		iCount =0;
	 static int		cxClient, cyClient;	 
	 static float	scaleratio = 1;
	 static HPEN	hPen[3];
	 line lineTmp;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 static POINT aptStart = {0,0}, aptEnd = { 0,0 }, aptCurrent;
	 static BOOL fdraw = 0;
     switch (message)
     {
	 case WM_CREATE:
		 hPen[0] = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
		 hPen[1] = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
		 hPen[2] = CreatePen(PS_DASH, 1, RGB(0, 0, 0));
		 return 0;
	 case WM_SIZE:
		 cxClient = LOWORD(lParam);
		 cyClient = HIWORD(lParam);
		 return 0;
     case WM_LBUTTONDOWN:

		 
		 aptEnd.x = GET_X_LPARAM(lParam);
		 aptEnd.y = GET_Y_LPARAM(lParam);
	
		 if (fdraw != 0)
		 {			
			 lineTmp.ptStart = aptStart;
			 lineTmp.ptEnd = aptEnd;
			 lineTmp.lineStyel = HeavyLine;
			 lines.push_back(lineTmp);
			 iCount++;
		 }
		 aptStart = aptEnd;
		 fdraw = 1;

		 InvalidateRect(hwnd, NULL, TRUE);
         return 0 ;

	 case WM_RBUTTONDOWN:
		 fdraw = 0;
		 InvalidateRect(hwnd, NULL, TRUE);
		 return 0;

     case WM_MOUSEMOVE:
		 if (fdraw)
		 {
			 aptEnd.x = GET_X_LPARAM(lParam);
			 aptEnd.y = GET_Y_LPARAM(lParam);		
			 InvalidateRect(hwnd,NULL,TRUE);
		 }          
		 aptCurrent.x= GET_X_LPARAM(lParam);
		 aptCurrent.y = GET_Y_LPARAM(lParam);
          return 0 ;  

	 case WM_MOUSEWHEEL:
		 if (!lines_scaled.empty())
		 {
			 if ((short)HIWORD(wParam)>0)
			 {
				 scaleratio = 1.25;
			 }
			 else
			 {
				 scaleratio = 0.8;
				
			 }
			 for (int i = 0;i < (int)lines_scaled.size();i++)
			 {
				 lines_scaled[i].ptStart.x = scaleratio*(lines_scaled[i].ptStart.x - aptCurrent.x) + aptCurrent.x;
				 lines_scaled[i].ptStart.y = scaleratio*(lines_scaled[i].ptStart.y - aptCurrent.y) + aptCurrent.y;
				 lines_scaled[i].ptEnd.x = scaleratio*(lines_scaled[i].ptEnd.x - aptCurrent.x) + aptCurrent.x;
				 lines_scaled[i].ptEnd.y = scaleratio*(lines_scaled[i].ptEnd.y - aptCurrent.y) + aptCurrent.y;
			 }
			 hdc = GetDC(hwnd);
			 Rectangle(hdc,0,0, cxClient, cyClient);
			 for (int i = 0; i < (int)lines_scaled.size(); i++)
			 {
				 MoveToEx(hdc, lines_scaled[i].ptStart.x, lines_scaled[i].ptStart.y, NULL);
				 LineTo(hdc, lines_scaled[i].ptEnd.x, lines_scaled[i].ptEnd.y);
			 }
			 ReleaseDC(hwnd, hdc);
		 }
		 return 0;
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          
          SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          ShowCursor (TRUE) ;
		  if (iCount == 0 && fdraw)
		  {
			  SetPixel(hdc, aptStart.x, aptStart.y, 0);
			  MoveToEx(hdc, aptStart.x, aptStart.y, NULL);
			  LineTo(hdc, aptEnd.x, aptEnd.y);
		  }			  
		  else if (iCount != 0 && !fdraw)
		  {
			  for (int i = 0; i < iCount; i++)
			  {
				  MoveToEx(hdc, lines[i].ptStart.x, lines[i].ptStart.y, NULL);
				  LineTo(hdc, lines[i].ptEnd.x, lines[i].ptEnd.y);
			  }
		  }
		  else if (iCount != 0 && fdraw)
		  {
			  for (int i = 0; i < iCount; i++)
			  {
				  MoveToEx(hdc, lines[i].ptStart.x, lines[i].ptStart.y, NULL);
				  LineTo(hdc, lines[i].ptEnd.x, lines[i].ptEnd.y);
			  }
			  MoveToEx(hdc, aptStart.x, aptStart.y, NULL);
			  LineTo(hdc, aptEnd.x, aptEnd.y);
		  } 
		 
          ShowCursor (FALSE) ;
          SetCursor (LoadCursor (NULL, IDC_ARROW)) ;               
          EndPaint (hwnd, &ps) ;
		  if (!lines_scaled.empty())
			  lines_scaled.clear();
		  lines_scaled = lines;
          return 0 ;
               
     case WM_DESTROY:
          PostQuitMessage (0) ;
		  DeleteObject(hPen[0]);
		  DeleteObject(hPen[1]);
		  DeleteObject(hPen[2]);
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


猜你喜欢

转载自blog.csdn.net/pengjc2001/article/details/56268144
今日推荐