LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { static BOOL fBlocking,fValidBox; static POINT ptBeg,ptEnd,ptBoxBeg,ptBoxEnd; HDC hdc; PAINTSTRUCT ps; switch(message) { case WM_LBUTTONDOWN: ptBeg.x=ptEnd.x=LOWORD(lParam); ptBeg.y=ptEnd.y=HIWORD(lParam); DrawBoxOutline(hwnd,ptBeg,ptEnd); //设置光标为IDC_CROSS,表示正在画矩形 SetCursor(LoadCursor(NULL,IDC_CROSS)); //标志,TRUE表示正在画 fBlocking=TRUE; return 0; case WM_MOUSEMOVE: if(fBlocking) { //当鼠标移动时,设置光标为IDC_CROSS SetCursor(LoadCursor(NULL,IDC_CROSS)); //当下面这一行注释点时,移动鼠标会出现下面图片的效果 DrawBoxOutline(hwnd,ptBeg,ptEnd); ptEnd.x=LOWORD(lParam); ptEnd.y=HIWORD(lParam); //下面这一行也是会出现下面图片的效果 DrawBoxOutline(hwnd,ptBeg,ptEnd); } return 0; case WM_LBUTTONUP: if(fBlocking) { DrawBoxOutline(hwnd,ptBeg,ptEnd); //用来保存最终的矩形 ptBoxBeg=ptBeg; ptBoxEnd.x=LOWORD(lParam); ptBoxEnd.y=HIWORD(lParam); //光标还原 SetCursor(LoadCursor(NULL,IDC_ARROW)); fBlocking=FALSE; fValidBox=TRUE; //下面后调用WM_PAINT InvalidateRect(hwnd,NULL,TRUE); } return 0; case WM_CHAR: //x1b是esc,实现效果,当正在画时,点一个esc会取消 if(fBlocking & (wParam=='\x1B')) { DrawBoxOutline(hwnd,ptBeg,ptEnd); SetCursor(LoadCursor(NULL,IDC_ARROW)); fBlocking=FALSE; } return 0; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); //这个是用来画鼠标松开时最终的矩形 if(fValidBox) { SelectObject(hdc,GetStockObject(BLACK_BRUSH)); Rectangle(hdc,ptBoxBeg.x,ptBoxBeg.y,ptBoxEnd.x,ptBoxEnd.y); } //这个是实现鼠标点下左键后,移动时候的效果,但是鼠标移动时没有调用这个,我认识无用 /*if(fBlocking) { SetROP2(hdc,R2_NOT); SelectObject(hdc,GetStockObject(NULL_BRUSH)); Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y); }*/ EndPaint(hwnd,&ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); }
上面代码有两个问题还没有搞清楚:
25---30行中有两个DrawBoxOutline,我试着去掉任何一个,但是效果都会变成下图这样。
我想应该跟WM_MOUSEMOVE有关,不能做到时时的来相应。
66-----72行的代码让我去掉了,我认识没有用,因为在WM_MOUSEMOVE中没有调用WM_PAINT,那段代码应该不会被执行。