⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 7. 鼠标.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
        
#include <windows.h>
        
#define DIVISIONS 5
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR  szCmdLine, int iCmdShow)
        
{      static TCHAR      szAppName[] = TEXT ("Checker1") ;
        
           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 ("Checker1 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,LPARAMlParam)
        
{
        
           static BOOL   fState[DIVISIONS][DIVISIONS] ;
        
           static int            cxBlock, cyBlock ;
        
           HDC                                  hdc ;
        
           int                                  x, y ;
        
           PAINTSTRUCT           ps ;
        
          RECT                                 rect ;
        
   
        
           switch (message)
        
    {
        
           case   WM_SIZE :
        
                  cxBlock = LOWORD (lParam) / DIVISIONS ;
        
                  cyBlock = HIWORD (lParam) / DIVISIONS ;
        
                  return 0 ;
        
        
        
           case WM_LBUTTONDOWN :
        
                  x = LOWORD (lParam) / cxBlock ;
        
                  y = HIWORD (lParam) / cyBlock ;
        
        
        
                  if (x < DIVISIONS && y < DIVISIONS)
        
                  {
        
                                         fState [x][y] ^= 1 ;
        
                                         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])
        
                          {
        
                          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, message, wParam, lParam) ;
        
}
        
图7-3是CHECKER1的显示。程序画的25个矩形的宽度和高度均相同。这些宽度和高度保存在cxBlock和cyBlock中,当显示区域大小发生改变时,将重新对这些值进行计算。WM_LBUTTONDOWN处理过程使用鼠标坐标来确定在哪个矩形中按下了键,它在fState数组中标志目前矩形的状态,并使该矩形区域失效,从而产生WM_PAINT消息。


 



图7-3 CHECKER1的屏幕显示
 

如果显示区域的宽度和高度不能被5整除,那么在显示区域的左边和下边将有一小条区域不能被矩形所覆盖。对于错误情况,CHECKER1通过呼叫MessageBeep响应此区域中的鼠标按键操作。

当CHECKER1收到WM_PAINT消息时,它通过GDI的Rectangle函数来重新绘制显示区域。如果设定了fState值,那么CHECKER1将使用MoveToEx和LineTo函数来绘制两条直线。在处理WM_PAINT期间,CHECKER1在重新绘制之前并不检查每个矩形区域的有效性,尽管它可以这样做。检查有效性的一种方法是在循环中为每个矩形块建立RECT结构(使用与WM_LBUTTONDOWN处理程序中相同的公式),并使用IntersectRect函数检查它是否与无效矩形(ps.rcPaint)相交。

使用键盘仿真鼠标


CHECKER1只能在装有鼠标情况下才可执行。下面我们在程序中加入键盘接口,就如同第六章中对SYSMETS程序所做的那样。不过,即使在一个使用鼠标光标作为指向用途的程序中加入键盘接口,我们还是必须处理鼠标光标的移动和显示问题。

即使没有安装鼠标,Windows仍然可以显示一个鼠标光标。Windows为这个光标保存了一个「显示计数」。如果安装了鼠标,显示计数会被初始化为0;否则,显示计数会被初始化为-1。只有在显示计数非负时才显示鼠标光标。要增加显示计数,您可以呼叫:

ShowCursor (TRUE) ;
        
要减少显示计数,可以呼叫:

ShowCursor (FALSE) ;
        
您在使用ShowCursor之前,不需要确定是否安装了鼠标。如果您想显示鼠标光标,而不管鼠标存在与否,那么只需呼叫ShowCursor来增加显示计数。增加一次显示计数之后,如果没有安装鼠标则减少它以隐藏光标,如果安装了鼠标,则保留其显示。

即使没有安装鼠标,Windows也保留了鼠标目前的位置。如果没有安装鼠标,而您又显示鼠标光标,光标就可能出现在显示器的任意位置,直到您确实移动了它。要获得光标的位置,可以呼叫:

GetCursorPos (&pt) ;
        
其中pt是POINT结构。函数使用鼠标的x和y坐标来填入POINT字段。要设定光标位置,可以使用:

SetCursorPos (x, y) ;
        
在这两种情况下,x和y都是屏幕坐标,而不是显示区域坐标(这是很明显的,因为这些函数没有要求hwnd参数)。前面已经提到过,呼叫ScreenToClient和ClientToScreen就能做到屏幕坐标与客户坐标的相互转换。

如果您在处理鼠标消息并转换显示区域坐标时呼叫GetCursorPos ,这些坐标可能与鼠标消息的lParam参数中的坐标稍微有些不同。从GetCursorPos传回的坐标表示鼠标目前的位置。lParam中的坐标则是产生消息时鼠标的位置。

您或许想写一个键盘处理程序:使用键盘方向键来移动鼠标光标,使用Spacebar和Enter键来仿真鼠标按键。您肯定不希望每次按键只是将鼠标光标移动一个图素,如果这样做,当要把鼠标光标从显示器的一边移动到另一边时,会使用者在很长一段时间内都要按住同一个方向键。

如果您需要实作鼠标光标的键盘接口,并保持光标的精确定位能力,那么您可以采用下面的方式来处理按键消息:当按下方向键时,一开始鼠标光标移动较慢,但随后会加快。您也许还记得WM_KEYDOWN消息中的lParam参数标志着按键消息是否是重复活动的结果,这就是此参数的一个重要应用。

在CHECKER中加入键盘接口


程序7-3所示的CHECKER2程序,除了包括键盘接口外,和CHECKER1是一样的,您可以使用左、右、上和下方向键在25个矩形之间移动光标。Home键把光标移动到矩形的左上角, End键把光标移动到矩形的右下角。Spacebar和Enter键都能切换X标记。

程序7-3 CHECKER2 
        
CHECKER2.C
        
/*----------------------------------------------------------------------------
        
  CHECKER2.C --   Mouse Hit-Test Demo Program No. 2
        
                                          (c) Charles Petzold, 1998
        
----------------------------------------------------------------------------*/
        
#include <windows.h>
        

#define DIVISIONS 5
        

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

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                          PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR szAppName[] = TEXT ("Checker2") ;
        
           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) ;
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -