《windows程序设计》学习_3.4:实现雷区翻转

  1 #include<windows.h>
  2 #include "resource.h"
  3 
  4 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
  5 
  6 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstace, PSTR szCmdLine, int iCmdShow)
  7 {
  8     static TCHAR szAppName[] = TEXT ("Stick1");
  9     HWND        hwnd;
 10     MSG         msg;
 11     WNDCLASS    wndclass;
 12     
 13     wndclass.style                  = CS_HREDRAW | CS_VREDRAW ;
 14     wndclass.lpfnWndProc            = WndProc;
 15     wndclass.cbClsExtra             = 0;
 16     wndclass.cbWndExtra             = 0;
 17     wndclass.hInstance              = hInstance;
 18     wndclass.hIcon                  = LoadIcon (NULL, IDI_APPLICATION);
 19     wndclass.hCursor                = LoadCursor(NULL, IDC_ARROW);
 20     wndclass.hbrBackground          = (HBRUSH)GetStockObject(WHITE_BRUSH);
 21     wndclass.lpszMenuName           = NULL;
 22     wndclass.lpszClassName          = szAppName;
 23     
 24     if(!RegisterClass(&wndclass))
 25     {
 26         MessageBox(NULL, TEXT ("The Program requires Windows NT!"), szAppName, MB_ICONERROR);
 27         return 0;
 28     }
 29     
 30     hwnd = CreateWindow (szAppName,
 31         TEXT ("Stick 1"),
 32         WS_OVERLAPPEDWINDOW,
 33         CW_USEDEFAULT,
 34         CW_USEDEFAULT,
 35         CW_USEDEFAULT,
 36         CW_USEDEFAULT,
 37         NULL,
 38         NULL,
 39         hInstance,
 40         NULL);
 41     
 42     ShowWindow(hwnd , iCmdShow);
 43     UpdateWindow(hwnd);
 44     
 45     while(GetMessage(&msg, NULL, 0, 0))
 46     {
 47         TranslateMessage(&msg);
 48         DispatchMessage(&msg);
 49     }
 50     return msg.wParam;
 51 }
 52 
 53 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 54 {
 55     static HBITMAP hBitmap;
 56     static int cxClient,cyClient,cxSource,cySource;
 57     //位图类结构,包含位图信息
 58     BITMAP bitmap;
 59     //设备环境表句柄
 60     HDC hdc,hdcMem;
 61     //这条消息的实例句柄,因为只在WM_CREATE消息中获得,所以是创建窗口的实例句柄
 62     HINSTANCE hInstance;
 63     int x,y,mx,my;
 64     //PAINTSTRUCT包含了绘制客户区域的信息,第一个参数就是HDC类
 65     PAINTSTRUCT ps;
 66     
 67     
 68     //控制距离的变量
 69     int dstx = 100;
 70     int dsty = 100;
 71     switch(message)
 72     {
 73         //创建窗口的消息:第一个消息
 74     case WM_CREATE:
 75         //LPCREATESTRUCT是一个指向结构CREATESTRUCT的指针
 76         //对lParam强制类型转换以后指向结构体,结构体中的hInstance
 77         hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
 78         //装载位图:参数为实例句柄,位图,返回值是位图句柄
 79         //虽然也可以用位图名来装载位图,但通常都是用序号
 80         hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE  (IDB_BITMAP1));
 81         //从制定的图形对象中获取信息
 82         //参数为:图形句柄,对象缓冲区大小,对象信息缓冲区
 83         GetObject(hBitmap,sizeof(BITMAP),&bitmap);
 84         //一幅位图的宽
 85         cxSource = bitmap.bmWidth;
 86         ///一幅位图的高:整个位图由16种不同的图形组成,每幅图形为整个位图的16分之1
 87         cySource = bitmap.bmHeight/16;
 88         
 89         return 0;
 90         //改变窗口的大小
 91     case WM_SIZE:
 92         //32位值的高低位代表客户区的长宽
 93       //不同的消息间需要保留,所以用的是static 94 cxClient = LOWORD(lParam); 95 cyClient = HIWORD(lParam); 96 return 0; 97 //绘制窗口消息 98 case WM_PAINT: 99 //BeginPaint?函数准备画图,向PAINTSTRUCT结构中填充信息
100        //参数为:窗口句柄,指向PAINTSTRUCT结构的画图信息,返回值为一个HDC 101 hdc = BeginPaint (hwnd, &ps) ; 102 //创建内存的环境设备,返回值是一个内存设备环境的句柄 103 hdcMem = CreateCompatibleDC(hdc); 104 //将一个对象选择到设备环境中,参数为:设备环境句柄,对象句柄 105 SelectObject(hdcMem,hBitmap); 106 107 108 for(y = dsty; y < cyClient-dsty; y += cySource) 109 { 110 for(x = dstx; x < cxClient-dstx; x += cxSource) 111 { 112 //贴图函数,参数为:目标DC句柄,贴图点的左上坐标的x坐标,贴图点的左上坐标的y坐标,
113              //目标和源的长,目标和源的宽,源DC句柄,源的左上角x坐标,源的左上角y坐标,
114                //光栅操作代码(这里是直接从源矩阵复制到目标矩阵) 115 BitBlt(hdc,x,y,cxSource,cySource,hdcMem,0,0,SRCCOPY); 116 117 } 118 } 119 DeleteDC(hdcMem); 120 //绘制窗口结束 121 EndPaint (hwnd, &ps) ; 122 return 0; 123 case WM_LBUTTONDOWN: 124 //左键会显示雷区被翻开的效果 125 hdc = GetDC(hwnd); 126 hdcMem = CreateCompatibleDC(hdc); 127 SelectObject(hdcMem,hBitmap); 128 129 130 //使得鼠标点到哪,就选择那里的雷区,并画一幅翻开的图片
131        //鼠标点到雷区外,不起作用
132        //鼠标点到雷区里,用这个方块的左上角代替贴图的位置
133        //鼠标位置: 134 mx = (LOWORD(lParam)); 135 my = (HIWORD(lParam)); 136 137 //点到雷区里面才有效,雷区位置:离上下dsty,左右dstx 138 if(mx>dstx && mx<cxClient-dstx && my>dsty && my<cyClient-dsty ) 139 { 140 //将鼠标的位置改为这个点对应雷区的方砖的左上角 141 //结构总是在第一块砖上 142 mx = ((int)(mx-dstx)/cxSource)*cxSource+dstx; 143 my = ((int)(my-dsty)/cySource)*cySource+dsty; 144 //贴图函数,参数为:目标DC句柄,贴图点的左上坐标的x坐标,贴图点的左上坐标的y坐标,
145            //目标和源的长,目标和源的宽,源DC句柄,源的左上角x坐标,源的左上角y坐标,
146            //光栅操作代码(这里是直接从源矩阵复制到目标矩阵) 147 BitBlt(hdc,mx,my,cxSource,cySource,hdcMem,0,cySource*15,SRCCOPY); 148 149 } 150 DeleteDC(hdcMem); 151 ReleaseDC(hwnd,hdc); 152 return 0; 153 //关闭窗口消息 154 case WM_DESTROY:
155 PostQuitMessage(0); 156 return 0; 157 } 158 return DefWindowProc(hwnd, message, wParam, lParam); 159 } 160

左键点击翻砖的实现:

鼠标点一下,将鼠标点的位置换成它属于的方砖的位置,然后贴上另一种方砖即可。位置的转化原理其实很简单,就是利用C语言中int类型数据整除的性质,举个例子:

如果一块方砖的大小为16*16,你鼠标的位置为(30,50),那么它所属的方砖的左上角,肯定是在30/16 =1, 50/16 = 3就是第一列,第三行的那里,具体的像素就是(1*16,3*16)。

原文地址:https://www.cnblogs.com/Hewie/p/3422710.html