diff --git a/Lab_1/Lab_1/Lab_1.cpp b/Lab_1/Lab_1/Lab_1.cpp index 2b9b658..ab2405b 100644 --- a/Lab_1/Lab_1/Lab_1.cpp +++ b/Lab_1/Lab_1/Lab_1.cpp @@ -1,43 +1,31 @@ -#include -#include +#include #include "resource.h" -#define _USE_MATH_DEFINES -#include +#pragma comment(lib, "msimg32.lib") -#define WM_LOAD_SPRITE WM_USER -#define WM_UPDATE_SPRITE (WM_USER + 1) -#define WM_LOAD_DEFAULT_SPRITE (WM_USER + 2) +#define WM_UPDATE_SPRITE (WM_USER) +#define WM_LOAD_DEFAULT_SPRITE (WM_USER + 1) +#define BACKGROUND_COLOR COLOR_WINDOW constexpr auto WINDOW_NAME = "Lab_1"; constexpr auto SPRITE_STEP = 10; -constexpr auto SPRITE_DEGREE_ROTATE_STEP = 15; constexpr auto VK_W = 0x57; constexpr auto VK_A = 0x41; constexpr auto VK_S = 0x53; constexpr auto VK_D = 0x44; -constexpr auto VK_Q = 0x51; -constexpr auto VK_E = 0x45; - -constexpr auto VK_L = 0x4c; - ATOM RegisterWindowClass(HINSTANCE); BOOL InitWindowInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +HINSTANCE _hInstance; + bool PostLoadDefaultSpriteMessage(HWND hWnd, HINSTANCE hInstance) { return PostMessage(hWnd, WM_LOAD_DEFAULT_SPRITE, NULL, (LPARAM)hInstance); } -bool PostLoadSpriteMessage(HWND hWnd) -{ - return PostMessage(hWnd, WM_LOAD_SPRITE, NULL, NULL); -} - - bool PostUpdateSpriteMessage(HWND hWnd) { return PostMessage(hWnd, WM_UPDATE_SPRITE, NULL, NULL); @@ -149,89 +137,7 @@ COORD CreateLeftSteps() return steps; } -XFORM GetMovementXform(COORD coordinates) -{ - XFORM xForm; - xForm.eM11 = 1; - xForm.eM12 = 0; - xForm.eM21 = 0; - xForm.eM22 = 1; - xForm.eDx = coordinates.X; - xForm.eDy = coordinates.Y; - - return xForm; -} - -XFORM GetRotationXform(short degreeAngle) -{ - XFORM xForm; - FLOAT radAngle = (FLOAT)(M_PI * degreeAngle / 180); - FLOAT angleSin = sin(radAngle); - FLOAT angleCos = cos(radAngle); - - xForm.eM11 = angleCos; - xForm.eM12 = angleSin; - xForm.eM21 = -angleSin; - xForm.eM22 = angleCos; - xForm.eDx = 0; - xForm.eDy = 0; - - return xForm; -} - -LRESULT LoadSprite(HWND hWnd, HBITMAP& sprite) -{ - char fileName[MAX_PATH] = { NULL }; - - OPENFILENAME openFileName; - openFileName.lStructSize = sizeof(OPENFILENAME); - openFileName.hwndOwner = hWnd; - openFileName.hInstance = NULL; - openFileName.lpstrFilter = "Images\0*.bmp;*.gif;*.jpeg;*.png;\0\0"; - openFileName.lpstrCustomFilter = NULL; - openFileName.nFilterIndex = 1; - openFileName.lpstrFile = fileName; - openFileName.nMaxFile = sizeof(fileName); - openFileName.lpstrFileTitle = NULL; - openFileName.lpstrInitialDir = NULL; - openFileName.lpstrTitle = "Select sprite"; - openFileName.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; - openFileName.lpstrDefExt = NULL; - - if (GetOpenFileName(&openFileName)) - { - int fileNameLength = MultiByteToWideChar(CP_ACP, 0, fileName, -1, NULL, 0); - WCHAR* wideCharFileName = new WCHAR[MultiByteToWideChar(CP_ACP, 0, fileName, -1, NULL, 0)]; - MultiByteToWideChar(CP_ACP, 0, fileName, -1, wideCharFileName, fileNameLength); - - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - ULONG_PTR gdiplusToken; - GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); - - Gdiplus::Bitmap* sourceImage = Gdiplus::Bitmap::FromFile(wideCharFileName); - HBITMAP hBitmap; - Gdiplus::Color imageBackgroundColor; - imageBackgroundColor.SetFromCOLORREF(GetSysColor(COLOR_WINDOW)); - Gdiplus::Status bitmapStatus = sourceImage->GetHBITMAP(imageBackgroundColor, &hBitmap); - - Gdiplus::GdiplusShutdown(gdiplusToken); - - if (bitmapStatus != Gdiplus::Ok) - return -1; - - SIZE windowSize = GetClientWindowSize(hWnd), spriteSize = GetSpriteSize(hBitmap); - if ((windowSize.cx < spriteSize.cx) || (windowSize.cy < spriteSize.cy)) - return -2; - - sprite = hBitmap; - - return 0; - } - - return 1; -} - -bool PutSpriteOnWindow(HWND hWnd, HBITMAP sprite, COORD coordinates, short angle) +bool PutSpriteOnWindow(HWND hWnd, HBITMAP sprite, COORD coordinates) { HDC windowDC = GetDC(hWnd); HDC spriteDC = CreateCompatibleDC(windowDC); @@ -239,47 +145,31 @@ bool PutSpriteOnWindow(HWND hWnd, HBITMAP sprite, COORD coordinates, short angle HGDIOBJ oldObject = SelectObject(spriteDC, sprite); SIZE bitmapSize = GetSpriteSize(sprite); - XFORM xForm; - int graphicsMode = SetGraphicsMode(windowDC, GM_ADVANCED); - - xForm = GetMovementXform(coordinates); - SetWorldTransform(windowDC, &xForm); - - COORD transformationCenter; - transformationCenter.X = (SHORT)(-(coordinates.X + bitmapSize.cx / 2)); - transformationCenter.Y = (SHORT)(-(coordinates.Y + bitmapSize.cy / 2)); - xForm = GetMovementXform(transformationCenter); - ModifyWorldTransform(windowDC, &xForm, MWT_RIGHTMULTIPLY); - - xForm = GetRotationXform(angle); - ModifyWorldTransform(windowDC, &xForm, MWT_RIGHTMULTIPLY); - - transformationCenter.X = -transformationCenter.X; - transformationCenter.Y = -transformationCenter.Y; - xForm = GetMovementXform(transformationCenter); - ModifyWorldTransform(windowDC, &xForm, MWT_RIGHTMULTIPLY); - - bool result = BitBlt(windowDC, 0, 0, bitmapSize.cx, bitmapSize.cy, spriteDC, 0, 0, SRCCOPY); - ModifyWorldTransform(windowDC, NULL, MWT_IDENTITY); - SetGraphicsMode(windowDC, graphicsMode); - - SelectObject(spriteDC, oldObject); + bool result = TransparentBlt(windowDC, // дескриптор приемного DC + coordinates.X, // x-коорд. верхнего левого угла приемника + coordinates.Y, // y-коорд. верхнего левого угла приемника + bitmapSize.cx, // ширина приемного прямоугольника + bitmapSize.cy, // высота приемного прямоугольника + spriteDC, // дескриптор источника DC + 0, // x-коорд. верхнего левого угла источника + 0, // y-коорд. верхнего левого угла источника + bitmapSize.cx, // ширина источника прямоугольника + bitmapSize.cy, // высота источника прямоугольника + RGB(255, 255, 255)); // цвет который делается прозрачным + DeleteDC(spriteDC); ReleaseDC(hWnd, windowDC); return result; } -int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR cmdLine, int cmdShowMode) +int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR cmdLine, _In_ int showMode) { - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(cmdLine); - MSG msg; RegisterWindowClass(hInstance); - if (!InitWindowInstance(hInstance, cmdShowMode)) + if (!InitWindowInstance(hInstance, showMode)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) @@ -303,7 +193,7 @@ ATOM RegisterWindowClass(HINSTANCE hInstance) windowClassEx.hInstance = hInstance; windowClassEx.hIcon = LoadIcon(0, IDI_WINLOGO);; windowClassEx.hCursor = LoadCursor(0, IDC_ARROW); - windowClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW); + windowClassEx.hbrBackground = (HBRUSH)(BACKGROUND_COLOR); windowClassEx.lpszMenuName = 0; windowClassEx.lpszClassName = WINDOW_NAME; windowClassEx.hIconSm = 0; @@ -311,22 +201,30 @@ ATOM RegisterWindowClass(HINSTANCE hInstance) return RegisterClassEx(&windowClassEx); } -BOOL InitWindowInstance(HINSTANCE hInstance, int cmdShowMode) +BOOL InitWindowInstance(HINSTANCE hInstance, int showMode) { HWND hWnd; - hWnd = CreateWindow(WINDOW_NAME, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); + hWnd = CreateWindow(WINDOW_NAME, // Указатель на зарегистрированное имя класса. + WINDOW_NAME, // Указатель на имя окна. + WS_OVERLAPPEDWINDOW, // Стиль окна. + CW_USEDEFAULT, // Горизонтальная позиция окна. + CW_USEDEFAULT, // Вертикальная позиция окна. + CW_USEDEFAULT, // Ширина окна. + CW_USEDEFAULT, // Высота окна. + NULL, // Дескриптор родительского или окна владельца. + NULL, // Дескриптор меню или ID дочернего окна. + hInstance, // Дескриптор экземпляра приложения. + NULL); // Указатель на данные создания окна. if (!hWnd) return FALSE; - ShowWindow(hWnd, cmdShowMode); - UpdateWindow(hWnd); + ShowWindow(hWnd, showMode); // Load default sprite. PostLoadDefaultSpriteMessage(hWnd, hInstance); - + return TRUE; } @@ -334,7 +232,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HBITMAP sprite = NULL; static COORD spritePosition = { 0, 0 }; - static short angle = 0; switch (message) { @@ -342,29 +239,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if ((sprite = LoadBitmap((HINSTANCE)lParam, MAKEINTRESOURCE(IDB_SPRITE))) != NULL) PostUpdateSpriteMessage(hWnd); break; - case WM_LOAD_SPRITE: - switch (LoadSprite(hWnd, sprite)) - { - case 0: - spritePosition = { 0, 0 }; - angle = 0; - PostUpdateSpriteMessage(hWnd); - break; - case -1: - MessageBox(hWnd, "An unknown error occurred while loading the sprite.", - "Unknown error", MB_OK | MB_ICONERROR); - break; - case -2: - MessageBox(hWnd, "The sprite does not fit into the window.", - "Large sprite size", MB_OK | MB_ICONERROR); - break; - default: - break; - } - break; case WM_UPDATE_SPRITE: - FillWindowWithColor(hWnd, GetSysColor(COLOR_WINDOW)); - PutSpriteOnWindow(hWnd, sprite, spritePosition, angle); + FillWindowWithColor(hWnd, GetSysColor(BACKGROUND_COLOR)); + PutSpriteOnWindow(hWnd, sprite, spritePosition); break; case WM_KEYDOWN: switch (wParam) @@ -389,17 +266,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) spritePosition = CreateNewSpritePosition(spritePosition, CreateLeftSteps(), hWnd, sprite); PostUpdateSpriteMessage(hWnd); break; - case VK_Q: - angle -= SPRITE_DEGREE_ROTATE_STEP; - PostUpdateSpriteMessage(hWnd); - break; - case VK_E: - angle += SPRITE_DEGREE_ROTATE_STEP; - PostUpdateSpriteMessage(hWnd); - break; - case VK_L: - PostLoadSpriteMessage(hWnd); - break; default: break; } @@ -432,8 +298,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } } break; - case WM_ERASEBKGND: - return 1; case WM_SIZE: PostUpdateSpriteMessage(hWnd); return DefWindowProc(hWnd, message, wParam, lParam); @@ -445,4 +309,4 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } return 0; -} +} \ No newline at end of file diff --git a/Lab_1/Lab_1/resource.h b/Lab_1/Lab_1/resource.h index 47f81d8..4594e3b 100644 --- a/Lab_1/Lab_1/resource.h +++ b/Lab_1/Lab_1/resource.h @@ -2,13 +2,14 @@ // Microsoft Visual C++ generated include file. // Used by Lab_1.rc // -#define IDB_SPRITE 101 + +#define IDB_SPRITE 107 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_RESOURCE_VALUE 108 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/Lab_1/Lab_1/sprite.bmp b/Lab_1/Lab_1/sprite.bmp index 6e6fb38..43a64e6 100644 Binary files a/Lab_1/Lab_1/sprite.bmp and b/Lab_1/Lab_1/sprite.bmp differ