diff --git a/Lab_1/Lab_1/Lab_1.cpp b/Lab_1/Lab_1/Lab_1.cpp index 0431bbb..4197831 100644 --- a/Lab_1/Lab_1/Lab_1.cpp +++ b/Lab_1/Lab_1/Lab_1.cpp @@ -1,4 +1,11 @@ #include +#define _USE_MATH_DEFINES +#include + +#include "resource.h" + +#define WM_UPDATE_SPRITE (WM_USER + 1) +#define WM_LOAD_DEFAULT_SPRITE (WM_USER + 2) constexpr auto WINDOW_NAME = "Lab_1"; @@ -6,6 +13,97 @@ ATOM RegisterWindowClass(HINSTANCE); BOOL InitWindowInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +bool PostLoadDefaultSpriteMessage(HWND hWnd, HINSTANCE hInstance) +{ + return PostMessage(hWnd, WM_LOAD_DEFAULT_SPRITE, NULL, (LPARAM)hInstance); +} + +bool PostUpdateSpriteMessage(HWND hWnd) +{ + return PostMessage(hWnd, WM_UPDATE_SPRITE, NULL, NULL); +} + +SIZE GetSpriteSize(HBITMAP hBitmap) +{ + BITMAP sprite; + GetObject(hBitmap, sizeof(BITMAP), &sprite); + + SIZE spriteSize; + spriteSize.cx = sprite.bmWidth; + spriteSize.cy = sprite.bmHeight; + + return spriteSize; +} + +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; +} + +bool PutSpriteOnWindow(HWND hWnd, HBITMAP sprite, COORD coordinates, short angle) +{ + HDC windowDC = GetDC(hWnd); + HDC spriteDC = CreateCompatibleDC(windowDC); + + 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); + DeleteDC(spriteDC); + ReleaseDC(hWnd, windowDC); + + return result; +} + int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR cmdLine, int cmdShowMode) { UNREFERENCED_PARAMETER(hPrevInstance); @@ -60,13 +158,32 @@ BOOL InitWindowInstance(HINSTANCE hInstance, int cmdShowMode) ShowWindow(hWnd, cmdShowMode); UpdateWindow(hWnd); + // Load default sprite. + PostLoadDefaultSpriteMessage(hWnd, hInstance); + return TRUE; } 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) { + case WM_LOAD_DEFAULT_SPRITE: + if ((sprite = LoadBitmap((HINSTANCE)lParam, MAKEINTRESOURCE(IDB_SPRITE))) != NULL) + { + PostUpdateSpriteMessage(hWnd); + } + break; + case WM_UPDATE_SPRITE: + PutSpriteOnWindow(hWnd, sprite, spritePosition, angle); + break; + case WM_SIZE: + PostUpdateSpriteMessage(hWnd); + return DefWindowProc(hWnd, message, wParam, lParam); case WM_DESTROY: PostQuitMessage(0); return 0; diff --git a/Lab_1/Lab_1/Lab_1.rc b/Lab_1/Lab_1/Lab_1.rc new file mode 100644 index 0000000..b0b820c --- /dev/null +++ b/Lab_1/Lab_1/Lab_1.rc @@ -0,0 +1,69 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_SPRITE BITMAP "sprite.bmp" + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Lab_1/Lab_1/Lab_1.vcxproj b/Lab_1/Lab_1/Lab_1.vcxproj index 6bd1f26..053e416 100644 --- a/Lab_1/Lab_1/Lab_1.vcxproj +++ b/Lab_1/Lab_1/Lab_1.vcxproj @@ -141,6 +141,15 @@ + + + + + + + + + diff --git a/Lab_1/Lab_1/Lab_1.vcxproj.filters b/Lab_1/Lab_1/Lab_1.vcxproj.filters index 2954ba3..2cf59e0 100644 --- a/Lab_1/Lab_1/Lab_1.vcxproj.filters +++ b/Lab_1/Lab_1/Lab_1.vcxproj.filters @@ -19,4 +19,19 @@ Source Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + \ No newline at end of file diff --git a/Lab_1/Lab_1/resource.h b/Lab_1/Lab_1/resource.h new file mode 100644 index 0000000..47f81d8 --- /dev/null +++ b/Lab_1/Lab_1/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Lab_1.rc +// +#define IDB_SPRITE 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Lab_1/Lab_1/sprite.bmp b/Lab_1/Lab_1/sprite.bmp new file mode 100644 index 0000000..6e6fb38 Binary files /dev/null and b/Lab_1/Lab_1/sprite.bmp differ