看看这个简单的程序(还需要改进)
#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) ;
}
可以处理鼠标超过边界的问题了:

本文介绍了一个改进的程序,允许用户在客户区任意画矩形,并在释放鼠标按钮时自动填充矩形。通过使用SetCapture和ReleaseCapture函数解决了鼠标超出窗口边界的限制。
3714

被折叠的 条评论
为什么被折叠?



