看看这个简单的程序(还需要改进)
#include<windows.h> #include<windowsx.h> #define DIVISIONS 5 LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state ) { static TCHAR szAppName[]=TEXT("leidemingzi"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDI_ERROR); wndclass.hInstance=hInstance; wndclass.lpfnWndProc=WindowProc; wndclass.lpszClassName=szAppName; wndclass.lpszMenuName=NULL; wndclass.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("the program require window NT"),TEXT("just tip"),MB_ICONERROR); return 0; } hwnd=CreateWindow( szAppName, // registered class name TEXT("this is title"), // window name WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // horizontal position of window CW_USEDEFAULT, // vertical position of window CW_USEDEFAULT, // window width CW_USEDEFAULT, // window height NULL, // handle to parent or owner window NULL, // menu handle or child identifier hInstance, // handle to application instance NULL // window-creation data ); ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void DrawBoxOutLine(HWND hwnd,POINT ptBeg,POINT ptEnd)//定义个画矩形的函数 { HDC hdc; hdc=GetDC(hwnd); SetROP2(hdc,R2_NOT);//设置画笔 SelectObject(hdc,GetStockObject(NULL_BRUSH));//不使用画刷 Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);//画矩形 ReleaseDC(hwnd,hdc); } LRESULT CALLBACK WindowProc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { static BOOL fBlocking,fValidBox; static POINT ptBeg,ptEnd,ptBoxBeg,ptBoxEnd; HDC hdc; PAINTSTRUCT ps; switch(uMsg) { case WM_LBUTTONDOWN: ptBeg.x=ptEnd.x=GET_X_LPARAM(lParam);//获取开始坐标 ptBeg.y=ptEnd.y=GET_Y_LPARAM(lParam); DrawBoxOutLine(hwnd,ptBeg,ptEnd);//画矩形,其实不要这句也行 SetCursor(LoadCursor(NULL,IDC_CROSS));//把鼠标设置成为十字形状 fBlocking=TRUE;//设标志为真 return 0; case WM_MOUSEMOVE: if(fBlocking)//判断是否按下鼠标左键 { SetCursor(LoadCursor(NULL,IDC_CROSS));//设置鼠标为十字形状 DrawBoxOutLine(hwnd,ptBeg,ptEnd);//画矩形 ptEnd.x=GET_X_LPARAM(lParam);//不断的获取移动后的坐标(矩形的右下方坐标) ptEnd.y=GET_Y_LPARAM(lParam); DrawBoxOutLine(hwnd,ptBeg,ptEnd);//不断的画矩形 } return 0; case WM_LBUTTONUP: if(fBlocking)//判断是否先有按下鼠标 { DrawBoxOutLine(hwnd,ptBeg,ptEnd);//画出矩形 ptBoxBeg=ptBeg; ptBoxEnd.x=GET_X_LPARAM(lParam);//获取终点坐标 ptBoxEnd.y=GET_Y_LPARAM(lParam); SetCursor(LoadCursor(NULL,IDC_ARROW));//设置鼠标为正常状态 fBlocking=FALSE;//设置标志为假 fValidBox=TRUE; InvalidateRect(hwnd,NULL,TRUE);//使矩形区域无效,触发WM_PAINT事件 } return 0; case WM_CHAR: if(fBlocking & (wParam=='\x1B'))//是否为ESC键 { 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,uMsg,wParam,lParam); }
在客户区可以任意画矩形,然后自动用黑色画刷去填充,但是鼠标不能超过窗口边界,否则,你自己调试吧
下面这个是改进版的:只在上面的函数增加了三行.
使用了SetCapture和ReleaseCapture函数
#include <windows.h> #include <windowsx.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("BlokOut2") ; 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 ("Mouse Button & Capture 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 ; } void DrawBoxOutline (HWND hwnd, POINT ptBeg, POINT ptEnd) { HDC hdc ; hdc = GetDC (hwnd) ; SetROP2 (hdc, R2_NOT) ; SelectObject (hdc, GetStockObject (NULL_BRUSH)) ; Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ; ReleaseDC (hwnd, hdc) ; } 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 = GET_X_LPARAM (lParam) ; ptBeg.y = ptEnd.y = GET_Y_LPARAM (lParam) ; DrawBoxOutline (hwnd, ptBeg, ptEnd) ; SetCapture (hwnd) ;//新增加的 SetCursor (LoadCursor (NULL, IDC_CROSS)) ; fBlocking = TRUE ; return 0 ; case WM_MOUSEMOVE : if (fBlocking) { SetCursor (LoadCursor (NULL, IDC_CROSS)) ; DrawBoxOutline (hwnd, ptBeg, ptEnd) ; ptEnd.x = GET_X_LPARAM (lParam) ; ptEnd.y = GET_Y_LPARAM (lParam) ; DrawBoxOutline (hwnd, ptBeg, ptEnd) ; } return 0 ; case WM_LBUTTONUP : if (fBlocking) { DrawBoxOutline (hwnd, ptBeg, ptEnd) ; ptBoxBeg = ptBeg ; ptBoxEnd.x = GET_X_LPARAM (lParam) ; ptBoxEnd.y = GET_Y_LPARAM (lParam) ; ReleaseCapture () ;//新增加的 SetCursor (LoadCursor (NULL, IDC_ARROW)) ; fBlocking = FALSE ; fValidBox = TRUE ; InvalidateRect (hwnd, NULL, TRUE) ; } return 0 ; case WM_CHAR : if (fBlocking & (wParam == '\x1B')) // i.e., Escape { DrawBoxOutline (hwnd, ptBeg, ptEnd) ; ReleaseCapture () ;//新增加的 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) ; }
可以处理鼠标超过边界的问题了: