《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)。