Windows滑鼠鍵盤訊息處理
阿新 • • 發佈:2019-01-02
轉載自
https://www.cnblogs.com/ht-beyond/p/4445439.html
#include <windows.h> #include <tchar.h> //swprintf_s函式所需的標頭檔案 #pragma comment(lib, "winmm.lib") //playSound #pragma comment(lib, "Msimg32.lib") //TransparentBlt #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define WINDOW_TITLE L"Windows滑鼠鍵盤訊息處理" // 環境,記憶體控制代碼 HDC g_hdc = NULL, g_mdc = NULL, g_bufdc = NULL; // 四張方向圖,儲存背景圖的控制代碼, 人物2 HBITMAP g_hSprite[4] = { NULL }, g_hBackGround = NULL, g_hMan = NULL; // 上一次繪圖時間,此次準備繪圖的時間 DWORD g_tPre = 0, g_tNow = 0; // 圖號,人物1橫縱座標,滑鼠座標,滑鼠控制人物2座標 int g_iNum = 0, g_iX = 0, g_iY = 0, g_mouseX = 0, g_mouseY = 0, g_iXnow = 0, g_iYnow = 0; // 人物移動方向,以0,1,2,3代表人物上,下,左,右 int g_iDirection = 0; // 回撥函式,視窗過程函式 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL Game_Init(HWND hwnd); VOID Game_Paint(HWND hwnd); BOOL Game_CleanUp(HWND hwnd); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { WNDCLASSEX wndClass = { 0 }; wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = 0; wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 白色畫刷控制代碼 wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 用一個以空終止的字串,指定選單資源的名字 wndClass.lpszMenuName = NULL; //視窗類的名字 wndClass.lpszClassName = L"Game Develop"; if (!RegisterClassEx(&wndClass)) return -1; // 正式建立視窗 HWND hwnd = CreateWindow(L"Game Develop", WINDOW_TITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true); ShowWindow(hwnd, nShowCmd); UpdateWindow(hwnd); if (!Game_Init(hwnd)) { MessageBox(hwnd, L"資源初始化失敗", L"訊息視窗", 0); return FALSE; } PlaySound(L"music.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP); MSG msg = { 0 }; while (msg.message != WM_QUIT) { // 檢視應用程式訊息佇列,有訊息時將佇列中的訊息派發出去 if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { g_tNow = GetTickCount(); // 重繪 if (g_tNow - g_tPre >= 40) Game_Paint(hwnd); } } // 程式準備結束,登出視窗類 UnregisterClass(L"Game Develop", wndClass.hInstance); return 0; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { //鍵盤訊息 case WM_KEYDOWN: switch (wParam) { //按下Esc鍵 case VK_ESCAPE: DestroyWindow(hwnd); PostQuitMessage(0); break; case VK_UP: g_iY -= 10; g_iDirection = 0; if (g_iY < 0) g_iY = 0; break; case VK_DOWN: g_iY += 10; g_iDirection = 1; if (g_iY > WINDOW_HEIGHT - 135) g_iY = WINDOW_HEIGHT - 135; break; case VK_LEFT: g_iX -= 10; g_iDirection = 2; if (g_iX < 0) g_iX = 0; break; case VK_RIGHT: g_iX += 10; g_iDirection = 3; if (g_iX > WINDOW_WIDTH - 75) g_iX = WINDOW_WIDTH - 75; break; } break; // 單擊滑鼠左鍵訊息 case WM_LBUTTONDOWN: break; // 滑鼠移動訊息 case WM_MOUSEMOVE: // 取得滑鼠X座標 g_mouseX = LOWORD(lParam); if (g_mouseX > WINDOW_WIDTH - 292) g_mouseX = WINDOW_WIDTH - 292; else if (g_mouseX < 0) g_mouseX = 0; // 取得滑鼠Y座標 g_mouseY = HIWORD(lParam); if (g_mouseY > WINDOW_HEIGHT - 190) g_mouseY = WINDOW_HEIGHT - 190; else if (g_mouseY < 0) g_mouseY = 0; break; case WM_DESTROY: Game_CleanUp(hwnd); PostQuitMessage(0); break; //呼叫預設的視窗過程 default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } BOOL Game_Init(HWND hwnd) { HBITMAP bmp; g_hdc = GetDC(hwnd); // 建立一個和hdc相容的記憶體DC g_mdc = CreateCompatibleDC(g_hdc); // hdc相容的緩衝DC g_bufdc = CreateCompatibleDC(g_hdc); bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT); g_iX = 100; g_iY = 350; g_mouseX = 300; g_mouseY = 100; g_iXnow = 300; g_iYnow = 100; g_iDirection = 3; g_iNum = 0; SelectObject(g_mdc, bmp); g_hSprite[0] = (HBITMAP)LoadImage(NULL, L"go1.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE); g_hSprite[1] = (HBITMAP)LoadImage(NULL, L"go2.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE); g_hSprite[2] = (HBITMAP)LoadImage(NULL, L"go3.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE); g_hSprite[3] = (HBITMAP)LoadImage(NULL, L"go4.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE); g_hBackGround = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE); g_hMan = (HBITMAP)LoadImage(NULL, L"man2.bmp", IMAGE_BITMAP, 292, 190, LR_LOADFROMFILE); POINT pt, lt, rb; RECT rect; // 設定游標位置 pt.x = 300; pt.y = 100; // 將指定點或者矩形的使用者座標轉換成螢幕座標 ClientToScreen(hwnd, &pt); SetCursorPos(pt.x, pt.y); // 隱藏滑鼠游標 ShowCursor(false); // 限制滑鼠游標移動區域 // 取得視窗內部矩形 GetClientRect(hwnd, &rect); // 將矩形左上點座標存入lt中 lt.x = rect.left; lt.y = rect.top; // 將矩形右下座標存入rb中 rb.x = rect.right; rb.y = rect.bottom; // 將lt和rb的視窗座標轉換為螢幕座標 ClientToScreen(hwnd, <); ClientToScreen(hwnd, &rb); // 以螢幕座標重新設定矩形區域 rect.left = lt.x; rect.top = lt.y; rect.right = rb.x; rect.bottom = rb.y; // 限制滑鼠游標移動區域 ClipCursor(&rect); Game_Paint(hwnd); return TRUE; } VOID Game_Paint(HWND hwnd) { // 先在mdc中貼上背景圖 SelectObject(g_bufdc, g_hBackGround); // 將源矩形區域直接拷貝到目標矩形區域 BitBlt(g_mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY); // 按照目前的移動方向取出對應人物的連續走動圖,並確定擷取人物圖的寬度與高度 SelectObject(g_bufdc, g_hSprite[g_iDirection]); // 使用AND(與)操作符來將源和目標矩形區域內的顏色合併 BitBlt(g_mdc, g_iX, g_iY, 60, 108, g_bufdc, g_iNum * 60, 108, SRCAND); // 使用布林型的OR(或)操作符將源和目標矩形區域的顏色合併 BitBlt(g_mdc, g_iX, g_iY, 60, 108, g_bufdc, g_iNum * 60, 0, SRCPAINT); // 計算人物2的貼圖座標,設定每次進行貼圖時,其座標(g_iXnow,g_iYnow)會以每20個單位慢慢向滑鼠游標所在的目的點(x,y)接近,直到兩個座標相同為止 if (g_iXnow < g_mouseX) { g_iXnow += 20; if (g_iXnow > g_mouseX) g_iXnow = g_mouseX; } else { g_iXnow -= 20; if (g_iXnow < g_mouseX) g_iXnow = g_mouseX; } if (g_iYnow < g_mouseY) { g_iYnow += 20; if (g_iYnow > g_mouseY) g_iYnow = g_mouseY; } else { g_iYnow -= 20; if (g_iYnow < g_mouseY) g_iYnow = g_mouseY; } // 貼上人物2圖 SelectObject(g_bufdc, g_hMan); // 對指定的源裝置環境中的矩形區域資料進行位塊轉換,並將結果置於目標裝置環境 TransparentBlt(g_mdc, g_iXnow, g_iYnow, 292, 190, g_bufdc, 0, 0, 292, 190, RGB(0, 0, 0)); HFONT hFont; // 建立字型 hFont = CreateFont(20, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("微軟雅黑")); SelectObject(g_mdc, hFont); // 設定文字背景透明 SetBkMode(g_mdc, TRANSPARENT); // 設定文字顏色 SetTextColor(g_mdc, RGB(255, 255, 0)); //在左上角進行文字輸出 wchar_t str[20] = {}; swprintf_s(str, L"滑鼠X座標為%d", g_mouseX); TextOut(g_mdc, 0, 0, str, wcslen(str)); swprintf_s(str, L"滑鼠Y座標為%d", g_mouseY); TextOut(g_mdc, 0, 20, str, wcslen(str)); // 貼上背景圖 BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY); // 記錄此次繪圖時間 g_tPre = GetTickCount(); // go1.bmp有8個人物1動作圖,用來實現人物1運動 g_iNum++; if (g_iNum == 8) g_iNum = 0; } BOOL Game_CleanUp(HWND hwnd) { // 釋放資源物件 DeleteObject(g_hBackGround); for (int i = 0; i<4; i++) { DeleteObject(g_hSprite[i]); } DeleteObject(g_hMan); DeleteDC(g_bufdc); DeleteDC(g_mdc); ReleaseDC(hwnd, g_hdc); return TRUE; }