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

📄 7. 鼠标.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
                 return 0 ;
        
           }
        
           hwnd = CreateWindow ( szAppName, TEXT ("Checker2 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 BOOL   fState[DIVISIONS][DIVISIONS] ;
        
           static int            cxBlock, cyBlock ;
        
           HDC                                  hdc ;
        
           int                                  x, y ;
        
           PAINTSTRUCT                   ps ;
        
           POINT                                point ;
        
           RECT                                 rect ;
        
   
        
           switch (message)
        
           {
        
           case   WM_SIZE :
        
                  cxBlock = LOWORD (lParam) / DIVISIONS ;
        
                  cyBlock = HIWORD (lParam) / DIVISIONS ;
        
                  return 0 ;
        
        
        
           case   WM_SETFOCUS :
        
                  ShowCursor (TRUE) ;
        
                  return 0 ;
        
        
        
           case   WM_KILLFOCUS :
        
                  ShowCursor (FALSE) ;
        
                  return 0 ;
        
        
        
           case   WM_KEYDOWN :
        
                  GetCursorPos (&point) ;
        
                  ScreenToClient (hwnd, &point) ;
        
                 x = max (0, min (DIVISIONS - 1, point.x / cxBlock)) ;
        
                  y = max (0, min (DIVISIONS - 1, point.y / cyBlock)) ;
        
        
        
                  switch (wParam)
        
                  {
        
                          case VK_UP :
        
                                                 y-- ;
        
                                                 break ;
        
             
        
                          case   VK_DOWN :
        
                                                 y++ ;
        
                                                 break ;
        
             
        
                          case   VK_LEFT :
        
                                                 x-- ;
        
                                                 break ;
        
             
        
                         case   VK_RIGHT :
        
                                                 x++ ;
        
                                                 break ;
        
             
        
                          case   VK_HOME :
        
                                                x = y = 0 ;
        
                                                 break ;
        
             
        
                          case   VK_END :
        
                                                 x = y = DIVISIONS - 1 ;
        
                                                 break ;
        
             
        
                          case   VK_RETURN :
        
                          case   VK_SPACE :
        
                                                 SendMessage (hwnd, WM_LBUTTONDOWN, MK_LBUTTON,
        
                                  MAKELONG (x * cxBlock, y * cyBlock)) ;
        
                                                break ;
        
                  }
        
                   x = (x + DIVISIONS) % DIVISIONS ;
        
                          y = (y + DIVISIONS) % DIVISIONS ;
        
        
        
                          point.x = x * cxBlock + cxBlock / 2 ;
        
                          point.y = y * cyBlock + cyBlock / 2 ;
        
        
        
                          ClientToScreen (hwnd, &point) ;
        
                          SetCursorPos (point.x, point.y) ;
        
                          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) ;
        
}
        
CHECKER2中的WM_KEYDOWN的处理方式决定光标的位置(用GetCursorPos),把屏幕坐标转换为显示区域坐标(用ScreenToClient),并用矩形方块的宽度和高度来除这个坐标。这会产生指示矩形位置的x和y值(5×5数组)。当按下一个键时,鼠标光标可能在或不在显示区域中,所以x和y必须经过min和max宏处理以保证它们的范围是0到4之间。

对方向键,CHECKER2近似地增加或减少x和y。如果是Enter键或Spacebar键,那么CHECKER2使用SendMessage把WM_LBUTTONDOWN消息发送给它自身。这种技术类似于在第六章SYSMETS程序中把键盘接口加到窗口滚动条时所使用的方法。WM_KEYDOWN的处理方式是通过计算指向矩形中心的显示区域坐标,再用ClientToScreen转换成屏幕坐标,然后用SetCursorPos设定光标位置来实作的。

将子窗口用于命中测试


有些程序(例如,Windows的「画图」程序),把显示区域划分为几个小的逻辑区域。「画图」程序在其左边有一个由图示组成的工具菜单区,在底部有颜色菜单区。在这两个区做命中测试的时候,「画图」必须在使用者选中菜单项之前记住菜单的位置。

不过,也可能不需要这么做。实际上,画风经由使用子窗口简化了菜单的绘制和命中测试。子窗口把整个矩形区域划分为几个更小的矩形区,每个子窗口有自己的窗口句柄、窗口消息处理程序和显示区域,每个窗口消息处理程序接收只适用于它的子窗口的鼠标消息。鼠标消息中的lParam参数含有相当于该子窗口显示区域左上角的坐标,而不是其父窗口(那是「画图」的主应用程序窗口)显示区域左上角的坐标。

以这种方式使用子窗口有助于程序的结构化和模块化。如果子窗口使用不同的窗口类别,那么每个子窗口都有它自己的窗口消息处理程序。不同的窗口也可以定义不同的背景颜色和不同的内定光标。在第九章中,我将看到「子窗口控件」-滚动条、按钮和编辑方块等预先定义的子窗口。现在,我们说明在CHECKER程序中是如何使用子窗口的。

CHECKER中的子窗口


程序7-4所示的CHECKER3程序,这一版本建立了25个处理鼠标单击的子窗口。它没有键盘接口,但是可以按本章后面的CHECKER4程序范例的方法添加。

程序7-4 CHECKER3 
        
CHECKER3.C
        
/*---------------------------------------------------------------------------
        
  CHECKER3.C --   Mouse Hit-Test Demo Program No. 3
        
                                                 (c) Charles Petzold, 1998
        
----------------------------------------------------------------------------*/
        
#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 ;

⌨️ 快捷键说明

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