zoukankan      html  css  js  c++  java
  • 第七章 鼠标(CHECKER2)

    CHECKER2程序包含一个键盘接口,内容与CHECKER1完全相同。利用←、→、↑、↓四个方向键可以在25个矩形之间移动鼠标指针。Home键把鼠标指针移动到左上角的矩形;End键使鼠标指针落到右下角的矩形。空格键和回车键都可以切换X形标记。

      1 /*---------------------------------------------
      2 CHECKER2.C -- Mouse Hit-Test Demo Program No.2
      3               (c) Charles Petzold, 1998
      4 ---------------------------------------------*/
      5 
      6 #include <Windows.h>
      7 
      8 #define DIVISIONS 5
      9 
     10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
     11 
     12 int WINAPI WinMain( __in HINSTANCE hInstance
     13                     , __in_opt HINSTANCE hPrevInstance
     14                     , __in LPSTR lpCmdLine
     15                     , __in int nShowCmd )
     16 {
     17     static TCHAR szAppName[] = TEXT("Checker2");
     18     HWND hwnd;
     19     MSG msg;
     20     WNDCLASS wndclass;
     21 
     22     wndclass.style = CS_HREDRAW | CS_VREDRAW;
     23     wndclass.lpfnWndProc = WndProc;
     24     wndclass.cbClsExtra = 0;
     25     wndclass.cbWndExtra = 0;
     26     wndclass.hInstance = hInstance;
     27     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
     28     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
     29     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
     30     wndclass.lpszMenuName = NULL;
     31     wndclass.lpszClassName = szAppName;
     32 
     33     if (!RegisterClass(&wndclass))
     34     {
     35         MessageBox(NULL, TEXT("Program requires Windows NT!")
     36             , szAppName, MB_ICONERROR);
     37         return 0;
     38     }
     39 
     40     hwnd = CreateWindow(szAppName, TEXT("Checker2 Mouse Hit-Test Demo")
     41         , WS_OVERLAPPEDWINDOW
     42         , CW_USEDEFAULT, CW_USEDEFAULT
     43         , CW_USEDEFAULT, CW_USEDEFAULT
     44         , NULL, NULL, hInstance, NULL);
     45 
     46     ShowWindow(hwnd, nShowCmd);
     47     UpdateWindow(hwnd);
     48 
     49     while (GetMessage(&msg, NULL, 0, 0))
     50     {
     51         TranslateMessage(&msg);
     52         DispatchMessage(&msg);
     53     }
     54 
     55     return msg.wParam;
     56 }
     57 
     58 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     59 {
     60     static BOOL fState[DIVISIONS][DIVISIONS];
     61     static int cxBlock, cyBlock;
     62     HDC hdc;
     63     int x, y;
     64     PAINTSTRUCT ps;
     65     POINT point;
     66     RECT rect;
     67 
     68     switch (message)
     69     {
     70     case WM_SIZE:
     71         cxBlock = LOWORD(lParam) / DIVISIONS;
     72         cyBlock = HIWORD(lParam) / DIVISIONS;
     73         return 0;
     74 
     75     case WM_SETFOCUS:
     76         ShowCursor(TRUE);
     77         return 0;
     78 
     79     case WM_KILLFOCUS:
     80         ShowCursor(FALSE);
     81         return 0;
     82 
     83     case WM_KEYDOWN:
     84         GetCursorPos(&point);
     85         ScreenToClient(hwnd, &point);
     86 
     87         x = max(0, min(DIVISIONS - 1, point.x / cxBlock));
     88         y = max(0, min(DIVISIONS - 1, point.y / cyBlock));
     89 
     90         switch (wParam)
     91         {
     92         case VK_UP:
     93             --y;
     94             break;
     95 
     96         case VK_DOWN:
     97             ++y;
     98             break;
     99 
    100         case VK_LEFT:
    101             --x;
    102             break;
    103 
    104         case VK_RIGHT:
    105             ++x;
    106             break;
    107 
    108         case VK_HOME:
    109             x = y = 0;
    110             break;
    111 
    112         case VK_END:
    113             x = y = DIVISIONS - 1;
    114             break;
    115 
    116         case VK_RETURN:
    117         case VK_SPACE:
    118             SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(x * cxBlock, y * cyBlock));
    119             break;
    120         }
    121 
    122         x = (x + DIVISIONS) % DIVISIONS;
    123         y = (y + DIVISIONS) % DIVISIONS;
    124 
    125         point.x = x * cxBlock + cxBlock / 2;
    126         point.y = y * cyBlock + cyBlock / 2;
    127 
    128         ClientToScreen(hwnd, &point);
    129         SetCursorPos(point.x, point.y);
    130         return 0;
    131 
    132     case WM_LBUTTONDOWN:
    133         x = LOWORD(lParam) / cxBlock;
    134         y = HIWORD(lParam) / cyBlock;
    135 
    136         if (x < DIVISIONS && y < DIVISIONS)
    137         {
    138             fState[x][y] ^= 1;
    139 
    140             rect.left = x * cxBlock;
    141             rect.top = y * cyBlock;
    142             rect.right = (x + 1) * cxBlock;
    143             rect.bottom = (y + 1) * cyBlock;
    144 
    145             InvalidateRect(hwnd, &rect, FALSE);
    146         }
    147         else
    148             MessageBeep(0);
    149         return 0;
    150 
    151     case WM_PAINT:
    152         hdc = BeginPaint(hwnd, &ps);
    153 
    154         for (x = 0; x < DIVISIONS; ++x)
    155             for (y = 0; y < DIVISIONS; ++y)
    156             {
    157                 Rectangle(hdc, x * cxBlock, y * cyBlock
    158                     , (x + 1) * cxBlock, (y + 1) * cyBlock);
    159                 
    160                 if (fState[x][y])
    161                 {
    162                     MoveToEx(hdc, x * cxBlock, y * cyBlock, NULL);
    163                     LineTo(hdc, (x + 1) * cxBlock, (y + 1) * cyBlock);
    164                     MoveToEx(hdc, x * cxBlock, (y + 1) * cyBlock, NULL);
    165                     LineTo(hdc, (x + 1) * cxBlock, y * cyBlock);
    166                 }
    167             }
    168 
    169         EndPaint(hwnd, &ps);
    170         return 0;
    171 
    172     case WM_DESTROY:
    173         PostQuitMessage(0);
    174         return 0;
    175     }
    176 
    177     return DefWindowProc(hwnd, message, wParam, lParam);
    178 }
    CHECKER2.C

    在CHECKER2程序中,处理WM_KEYDOWN时利用GetCursorPos判断指针的位置,并利用ScreenToClient将屏幕坐标转换成客户区坐标,然后将坐标值除以矩形块的宽和高,得到x和y。这些x和y的值表示了矩形在5*5数组中的位置。当按下某个键时,鼠标指针可能在客户区也可能不在客户区内,因此x和y必须包含在min和max的宏处理中,保证它们的范围处于0和4之间。

    对于方向键,CHECKER2程序相应的增加或减少x和y的值。若按下回车键或空格键,CHECKER2程序调用SendMessage给自己发送一个WM_LBUTTONDOWN消息。最后,WM_KEYDOWN处理逻辑计算得到指向矩形中心的客户区坐标,并调用ClientToScreen将其转换成屏幕坐标,最后调用SetCursorPos设置指针的位置。

  • 相关阅读:
    python种的builtin函数详解第三篇 C
    python中的buildin函数详解(第一篇) C
    python中的formatter的详细用法 C
    python中的builtin函数详解第二篇 C
    python中函数的默认参数陷阱问题 C
    介绍C++11标准的变长参数模板
    猜数字
    父类和子类
    矩形的面积
    水果类
  • 原文地址:https://www.cnblogs.com/web1013/p/9013520.html
Copyright © 2011-2022 走看看