windows程序设计读书笔记四

前面的程序碰到刷新时碰到闪烁问题,百度一搜,一堆关于双缓冲解决闪烁的文章。

具体实施方案为:

1、建立一个内存DC

       hdcMem = CreateCompatibleDC(hdc);

此时,内存DC的显示表面是单色、1个像素宽、1个像素高。即显示表面仅仅1位。

2、CreateCompatibleBitmap创建一个与设备兼容的位图,

::GetClientRect(hwnd, &rc);

        hBitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left, rc.bottom-rc.top);

3、把画布对象选入内存DC

      SelectObject(hdcMem, hBitmap);

4、将内存DC中的图一次性丢给DC,或则将DC中的图丢给内存DC

      BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);

      BitBlt(hdcMem, 0, 0, cxClient, cyClient, hdc, 0, 0, SRCCOPY);

在用本方法改进前面的CAD程序碰到的问题

1、初始化时 ,将当前hdc内容丢给内存DC,BitBlt语句的位置。

       a、放在WM_CREATE消息中,里面的内容是黑色的;

       b、只有放置在WM_SIZE或WM_PAINT消息内,内容才和DC一样是白色(注意hdc的释放及申请);

       从上述两点,可以看出,创建窗口时,windows系统并没有绘制窗口。跟踪发现,CreateWindow执行完毕,窗口并未绘制,而是在后面的ShowWindow时窗口完成了绘制,此刻后进入了WM_SIZE消息,所以此时hdc内是有内容的,同理WM_PAINT发生在后面,hdc也是有内容。

2、刚开始改动时,延续了前面程序的做法,所有更新都在WM_PAINT中进行,无法避免闪烁。后面将绘制过程在响应消息内完成,就好了。

/*--------------------------------------------------
 利用BitBlt来刷新
  --------------------------------------------------*/
 
#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 ("MyCAD") ;
     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 ("MyCAD"),
                          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];
	 static HBITMAP hBitmap, hBitmapTmp;
	 static HDC    hdcMem, hdcMemTmp;
	 static RECT rc;
	 static BOOL flagCreate;
	 static BOOL flagClicked;
	 line lineTmp;
     HDC          hdc;
     PAINTSTRUCT  ps ;
	 static POINT aptStart = {0,0}, aptEnd = { 0,0 }, aptCurrent;
	 static BOOL fdraw = 0;
     switch (message)
     {
	 case WM_CREATE:
		 flagCreate = TRUE;
		 hdc = GetDC(hwnd);		 
		 ::GetClientRect(hwnd, &rc);
		 hdcMem = CreateCompatibleDC(hdc);
		 hBitmap = CreateCompatibleBitmap(hdc, rc.right-rc.left, rc.bottom-rc.top);
		 hdcMemTmp = CreateCompatibleDC(hdc);
		 hBitmapTmp = CreateCompatibleBitmap(hdc, rc.right - rc.left, rc.bottom - rc.top);
		 
		 SelectObject(hdcMem, hBitmap);
		 SelectObject(hdcMemTmp, hBitmapTmp);
		 SelectObject(hdcMemTmp, hPen[1]);
		 hPen[0] = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
		 hPen[1] = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
		 hPen[2] = CreatePen(PS_DASH, 1, RGB(0, 0, 0));
		 //此时hdc内没有内容,将得到全黑图像
		 //BitBlt(hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);
		 //BitBlt(hdcMemTmp, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);
		 ReleaseDC(hwnd, hdc);
		 return 0;
	 case WM_SIZE:
		 cxClient = LOWORD(lParam);
		 cyClient = HIWORD(lParam);
		 //此时hdc内有内容,可以正常使用
		 //hdc = GetDC(hwnd);
		 //BitBlt(hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);
		 //BitBlt(hdcMemTmp, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);
		 //ReleaseDC(hwnd, hdc);
		 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++;
		 }
		 else
		 {
			 aptStart = aptEnd;
			 SetPixel(hdcMem, aptStart.x, aptStart.y, 0);
			 fdraw = 1;
			 return 0;
		 }	
		 MoveToEx(hdcMem, aptStart.x, aptStart.y, NULL);
		 LineTo(hdcMem, aptEnd.x, aptEnd.y);
		 hdc = GetDC(hwnd);
		 BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMemTmp, 0, 0, SRCCOPY);
		 ReleaseDC(hwnd, hdc);
		 aptStart = aptEnd;
		 if (!lines_scaled.empty())
			 lines_scaled.clear();
		 lines_scaled = lines;
		
         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);				 
			 BitBlt(hdcMemTmp, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
			 MoveToEx(hdcMemTmp, aptStart.x, aptStart.y, NULL);
			 LineTo(hdcMemTmp, aptEnd.x, aptEnd.y);
			 hdc = GetDC(hwnd);
			 BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMemTmp, 0, 0, SRCCOPY);
			 ReleaseDC(hwnd, hdc);					
		 }		
		 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);
		 }
		 BitBlt(hdcMem, 0, 0, cxClient, cyClient, hdc, 0, 0, SRCCOPY);
		 BitBlt(hdcMemTmp, 0, 0, cxClient, cyClient, hdc, 0, 0, SRCCOPY);
		 return 0;
     case WM_PAINT:		
		 hdc = BeginPaint (hwnd, &ps) ;		  
		 if (flagCreate)
		 {
			BitBlt(hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);
			BitBlt(hdcMemTmp, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0, SRCCOPY);		 
			flagCreate = FALSE;
			return 0;
		  }		
		  BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
          EndPaint (hwnd, &ps) ;		  
		  return 0;
               
     case WM_DESTROY:
          PostQuitMessage (0) ;
		  DeleteObject(hPen[0]);
		  DeleteObject(hPen[1]);
		  DeleteObject(hPen[2]);
		  DeleteDC(hdcMem);
		  DeleteObject(hBitmap);
		  DeleteDC(hdcMemTmp);
		  DeleteObject(hBitmapTmp);
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值