现在的位置: 首页 > 综合 > 正文

鼠标(2)

2013年08月22日 ⁄ 综合 ⁄ 共 6170字 ⁄ 字号 评论关闭

Windows的GetKeyState函数能够返回鼠标按钮或Shift等键的状态,当GetKeyState函数返回一个负值时,表示已经按下了鼠标按钮或相应的Shift或Ctrl键。

在没有按下鼠标时,不能使用GetKeyState函数。

在鼠标事件的时候,有时候,需要对参数wParam和MK_XX进行位与运算

if(wParam & MK_SHIFT)
{
    if(wParam  &  MK_CONTROL)
    {
        按下Shift+Ctrl
    }
     else{
        按下Shift键
    }
}
else
{
    if(wParam & MK_CONTROL)
    {
        按下Ctrl键
    }
     else
    {
       Shift和Ctrl键都没有按下
    }
}

又如:

case WM_LBUTTONDOWN:
     if(!(wParam & MK_SHIFT))
     {
        这里处理左键;
     }
      return 0;

下面常用的虚拟键代码:

VK_LBUTTON
VK_RBUTTON
VK_MBUTTON
VK_SHIFT
VK_CONTROL
VK_LMENU
VK_RMENU

看看非客户区鼠标消息

窗口的非客户区包括标题栏,菜单和窗口滚动条。

鼠标按钮产生的消息如下所示:

按钮 按下 释放 第二次按下按钮
左键 WM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
中键 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
右键 WN_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

 

利用下面两个函数,可以将屏幕坐标和客户区坐标进行互换

ScreenToClient(hwnd,&pt);
ClientToScreen(hwnd,&pt);

击中测试消息:

HTCLIENT 客户区
HTNOWHERE 不在任何窗口
HTTRANSPARENT 被另一个窗口覆盖的窗口
HTERROR 使函数DefWindowProc产生一个警示声

 

下面这个代码,可以让你的窗口叫天天不应,叫地地不灵

case WM_NCHITTEST:
         return (LRESULT)HTNOWHERE;

此时,无论鼠标位于窗口任何位置,包括系统菜单图标,调整大小和关闭按钮,鼠标按钮操作都将失效。

 

一个简单的程序,该程序将客户区划分成25个矩形,构成5X5的数组,如果在其中一个矩形内单击鼠标,就用X形填充该矩形,再次单击,则X形消失;

#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"),szAppName,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;

}

LRESULT CALLBACK WindowProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static BOOL fState[DIVISIONS][DIVISIONS];
	static int cxBlock,cyBlock;
	int x,y;
	RECT rect;

	switch(uMsg)
	{
	
	case WM_SIZE:
		cxBlock=LOWORD(lParam)/DIVISIONS;//横竖都分成五份
		cyBlock=HIWORD(lParam)/DIVISIONS;
		return 0;
		
	case WM_LBUTTONDOWN:
		x=GET_X_LPARAM(lParam)/cxBlock;
		y=GET_Y_LPARAM(lParam)/cyBlock;

		if(x<DIVISIONS && y<DIVISIONS)
		{
			fState[x][y]^=1;//异或,如果已经显示了X,再点击,则X消失,如果没有X显示,则点击会显示X

			rect.left=x*cxBlock; //标记该被点击的矩形区域,为后面“显示”和“消失”固定一个范围
			rect.top=y*cyBlock;
			rect.right=(x+1)*cxBlock;
			rect.bottom=(y+1)*cyBlock;

			InvalidateRect(hwnd,&rect,FALSE);
		}else{
			MessageBeep(0);
		}
		return 0;



	case WM_PAINT:
		hdc=BeginPaint(hwnd,&ps);
		
		for(x=0;x<DIVISIONS;++x)
		{
			for(y=0;y<DIVISIONS;++y)
			{
				Rectangle(hdc,x*cxBlock,y*cyBlock,(x+1)*cxBlock,(y+1)*cyBlock);

				if(fState[x][y])//画“X”
				{
					MoveToEx(hdc,x*cxBlock,y*cyBlock,NULL);
					LineTo(hdc,(x+1)*cxBlock,(y+1)*cyBlock);

					MoveToEx(hdc,x*cxBlock,(y+1)*cyBlock,NULL);
					LineTo(hdc,(x+1)*cxBlock,y*cyBlock);
				}
			}
		}
		EndPaint(hwnd,&ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

运行结果如下:

 

 可以用子窗口完成相同的功能:

#include <windows.h>

#define DIVISIONS 5

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

TCHAR szChildClass[] = TEXT ("Checker3_Child") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("Checker3") ;
     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 ;
     }
     
     wndclass.lpfnWndProc   = ChildWndProc ;
     wndclass.cbWndExtra    = sizeof (long) ;
     wndclass.hIcon         = NULL ;
     wndclass.lpszClassName = szChildClass ;
     
     RegisterClass (&wndclass) ;
     
     hwnd = CreateWindow (szAppName, TEXT ("Checker3 Mouse Hit-Test 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 HWND hwndChild[DIVISIONS][DIVISIONS] ;
     int         cxBlock, cyBlock, x, y ;
     
     switch (message)
     {
     case WM_CREATE :
          for (x = 0 ; x < DIVISIONS ; x++)
               for (y = 0 ; y < DIVISIONS ; y++)
                    hwndChild[x][y] = CreateWindow (szChildClass, NULL,
                              WS_CHILDWINDOW | WS_VISIBLE,
                              0, 0, 0, 0,
                              hwnd, (HMENU) (y << 8 | x),
                              (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
                              NULL) ;
          return 0 ;
               
     case WM_SIZE :
          cxBlock = LOWORD (lParam) / DIVISIONS ;
          cyBlock = HIWORD (lParam) / DIVISIONS ;
          
          for (x = 0 ; x < DIVISIONS ; x++)
                for (y = 0 ; y < DIVISIONS ; y++)
                    MoveWindow (hwndChild[x][y],
                                x * cxBlock, y * cyBlock,
                                cxBlock, cyBlock, TRUE) ;
          return 0 ;
               
     case WM_LBUTTONDOWN :
          MessageBeep (0) ;
          return 0 ;
          
     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT message, 
                               WPARAM wParam, LPARAM lParam)
{
     HDC         hdc ;
     PAINTSTRUCT ps ;
     RECT        rect ;
     
     switch (message)
     {
     case WM_CREATE :
          SetWindowLong (hwnd, 0, 0) ;       // on/off flag
          return 0 ;
          
     case WM_LBUTTONDOWN :
          SetWindowLong (hwnd, 0, 1 ^ GetWindowLong (hwnd, 0)) ;
          InvalidateRect (hwnd, NULL, FALSE) ;
          return 0 ;
          
     case WM_PAINT :
          hdc = BeginPaint (hwnd, &ps) ;
          
          GetClientRect (hwnd, &rect) ;
          Rectangle (hdc, 0, 0, rect.right, rect.bottom) ;
          
          if (GetWindowLong (hwnd, 0))
          {
               MoveToEx (hdc, 0,          0, NULL) ;
               LineTo   (hdc, rect.right, rect.bottom) ;
               MoveToEx (hdc, 0,          rect.bottom, NULL) ;
               LineTo   (hdc, rect.right, 0) ;
          }
          
          EndPaint (hwnd, &ps) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

 

 

抱歉!评论已关闭.