1

Тема: WinApi Робота з вікном

Добрий день. Одним із завдань є змусити вікно рухатися по периметру екрана проти годинникової стрілки після натискання Ентер, за годинниковою при натисканні пробілу і зупитини при Ескейп.
Все це діло реалізовано через таймери: коли потрібно створюється або убивається відповідний таймер,
Ескейп працює безвідмовно. З пробілом ніби все теж нормально, а от при натисканні Ентеру відбувається якесь дикунство: 1. екран може просто зупинитися в кутку, почати розширюватися, втікати за межі екрану, почати рухатися в два рази швидше, продовжити рух ЗА годинниковою стрілкою.
Ось код:

#include <iostream>
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int xWindowSize = GetSystemMetrics(SM_CXSCREEN);        // ширина екрану у пікселях
int yWindowSize = GetSystemMetrics(SM_CYSCREEN);        // висота екрану у пікселях
RECT rcWindow;

int cxWindowClient;        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
int cyWindowClient;        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
int cyWindowTitle;            // висота заголовка
int cyWindowBorder;            // ширина рамки вікна
int cxWindowBorder;            // ширина рамки вікна

enum Direction
{
    left, right, up, down
};

int move = 0;
static int dir = Direction::down;

void changeDirectionToOposite(int &dir)
{
    if (dir == Direction::down)
    {
        dir = Direction::up;
    }
    if (dir == Direction::up)
    {
        dir = Direction::down;
    }
    if (dir == Direction::left)
    {
        dir = Direction::right;
    }
    if (dir == Direction::right)
    {
        dir = Direction::left;
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static wchar_t szAppName[] = L"DemoFig";

    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = szAppName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wc);

    HWND hwnd;
    hwnd = CreateWindow(szAppName, L"Демонстрація таймерів", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    //UpdateWindow(hwnd); 

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;

}//    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) 


LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    const UINT IDTIMER = 23454;
    const UINT IDTIMERSHOW = 21123454;
    const UINT IDTIMER_Reverse = 222;
    const UINT IDTIMER_Clockwise = 111;

    HDC hdc;
    PAINTSTRUCT ps;
    switch (iMsg)
    {

    case WM_CREATE:
        SetTimer(hwnd, IDTIMER, 100, NULL);
        break;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        EndPaint(hwnd, &ps);
        return 0;


    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;


    case WM_TIMER:
    {
        switch (wParam)
        {
        case IDTIMER:
            wchar_t buf[444];
            SYSTEMTIME st;
            //GetSystemTime( &st );
            GetLocalTime(&st);
            wsprintf(buf, L" Сьогодні %02i.%02i.%i.    Зараз %02i:%02i:%02i ", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond);
            SetWindowText(hwnd, buf);
            break;

        case IDTIMER_Reverse: //проти часової стрілки
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (dir == Direction::down) //вниз && rcWindow.bottom != yWindowSize
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.bottom >= yWindowSize)
                {
                    rcWindow.top = yWindowSize - (rcWindow.bottom - rcWindow.top);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::right;
                }
            }
            else if (dir == Direction::right) //вправо && rcWindow.right != xWindowSize
            {
                MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.right >= xWindowSize)
                {
                    rcWindow.left = xWindowSize - (rcWindow.right - rcWindow.left);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::up;
                }
            }
            else if (dir == Direction::up) //вверх && rcWindow.top != 0
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.top <= 0)
                {
                    MoveWindow(hwnd, rcWindow.left, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::left;
                }
            }
            else if (dir == Direction::left) //вліво && rcWindow.left != 0
            {
                MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.left <= 0)
                {
                    MoveWindow(hwnd, 0, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::down;
                }
            }
        }

        case IDTIMER_Clockwise: // за годинниковою стрілкою
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (dir == Direction::down) //вниз && rcWindow.bottom != yWindowSize
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.bottom >= yWindowSize)
                {
                    rcWindow.top = yWindowSize - (rcWindow.bottom - rcWindow.top);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::left;
                }
            }
            else if (dir == Direction::right) //вправо && rcWindow.right != xWindowSize
            {
                MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.right >= xWindowSize)
                {
                    rcWindow.left = xWindowSize - (rcWindow.right - rcWindow.left);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::down;
                }
            }
            else if (dir == Direction::up) //вверх && rcWindow.top != 0
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.top <= 0)
                {
                    MoveWindow(hwnd, rcWindow.left, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::right;
                }
            }
            else if (dir == Direction::left) //вліво && rcWindow.left != 0
            {
                MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.left <= 0)
                {
                    MoveWindow(hwnd, 0, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::up;
                }
            }

        }

        case IDTIMERSHOW:    // показуємо приховане вікно
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
            KillTimer(hwnd, IDTIMERSHOW);
            break;
        }
    }

    break;

#pragma region MOVE
    case WM_KEYDOWN:
    {
        switch (wParam)
        {
        case L'Q':        // ставить вікно у лівий верхній кут
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE);
            break;

        case L'Z':        // ставить вікно у правий нижній кут
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            int dy = cyWindowClient + cyWindowBorder + cyWindowTitle - rcWindow.bottom;        // на скільки зсунути донизу

            OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
        }
        break;

        case L'H':        // Згортає вікно 
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_HIDEWINDOW);
            SetTimer(hwnd, IDTIMERSHOW, 3000, NULL);
            break;

        case L'R':        // Розгортає вікно 
        {
            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна
            SetWindowPos(hwnd, NULL, 0, 0, cxWindowClient + cxWindowBorder * 2, cyWindowClient + cyWindowBorder + cyWindowTitle, SWP_SHOWWINDOW);
        }

        case VK_LEFT:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (rcWindow.left != 0)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left - 20, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left - 1, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_RIGHT:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна


            if (rcWindow.right != xWindowSize)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left + 20, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left + 1, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_UP:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            //int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            //int dy = 0;        // на скільки зсунути донизу

            //OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            if (rcWindow.top != 0)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 20, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 1, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_DOWN:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            //int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            //int dy = 0;        // на скільки зсунути донизу

            //OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            if (rcWindow.bottom != yWindowSize)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 20, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 1, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

#pragma endregion

        case VK_RETURN: // при натисканні Ентер
        {
            KillTimer(hwnd, IDTIMER_Clockwise); // вбиваємо таймер за годинниковою
            changeDirectionToOposite(dir); // змінюємо напрямок на протилежний
            SetTimer(hwnd, IDTIMER_Reverse, 100, NULL); // запускаємо таймер проти годинникової стрілки по клавіші ENTER
            break;
        }

        case VK_SPACE:  // при натисканні пробілу Space bar
        {
            KillTimer(hwnd, IDTIMER_Reverse);
            changeDirectionToOposite(dir);
            SetTimer(hwnd, IDTIMER_Clockwise, 100, NULL);// запускаємо таймер за годинниковою стрілкою
            break;
        }

        case VK_ESCAPE: // при натисканні Escape
        {
            KillTimer(hwnd, IDTIMER_Reverse);
            KillTimer(hwnd, IDTIMER_Clockwise);
            dir = Direction::down;
            break;
        }
        break;

        }

    }
    break;

    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
} // LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) 

звернути увагу, думаю, треба на case VK_RETURN:, case IDTIMER_Reverse:

2

Re: WinApi Робота з вікном

Перевірте case-и, кожен має закінчуватися break-ом.

Подякували: boshik1983, ostap34PHP2

3

Re: WinApi Робота з вікном

Точно. Саме очевидне випустив.
Виникло, по ходу справи, ще одне питання:
якщо запущено цикл по годинниковій і при цьому натиснути Ентер (вмикає реверс), то вікно не відразу змінює напрямок, а спочатку доходить до краю екрана, а вже тоді починає рух в протилежному напрямку. З чим це пов*язано?

Подякували: ostap34PHP1

4

Re: WinApi Робота з вікном

Що ви встигли змінити у коді? Викладіть свіжу версію.

5

Re: WinApi Робота з вікном

Поставив 2 брейка після  case IDTIMER_Reverse: та case IDTIMER_Clockwise:

#include <iostream>
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int xWindowSize = GetSystemMetrics(SM_CXSCREEN);        // ширина екрану у пікселях
int yWindowSize = GetSystemMetrics(SM_CYSCREEN);        // висота екрану у пікселях
RECT rcWindow;

int cxWindowClient;        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
int cyWindowClient;        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
int cyWindowTitle;            // висота заголовка
int cyWindowBorder;            // ширина рамки вікна
int cxWindowBorder;            // ширина рамки вікна

enum Direction
{
    left, right, up, down
};

int move = 0;
static int dir = Direction::down;

void changeDirectionToOposite(int &dir)
{
    if (dir == Direction::down)
    {
        dir = Direction::up;
    }
    if (dir == Direction::up)
    {
        dir = Direction::down;
    }
    if (dir == Direction::left)
    {
        dir = Direction::right;
    }
    if (dir == Direction::right)
    {
        dir = Direction::left;
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static wchar_t szAppName[] = L"DemoFig";

    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = szAppName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wc);

    HWND hwnd;
    hwnd = CreateWindow(szAppName, L"Демонстрація таймерів", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    //UpdateWindow(hwnd); 

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;

}//    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) 


LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    const UINT IDTIMER = 23454;
    const UINT IDTIMERSHOW = 21123454;
    const UINT IDTIMER_Reverse = 222;
    const UINT IDTIMER_Clockwise = 111;

    HDC hdc;
    PAINTSTRUCT ps;
    switch (iMsg)
    {

    case WM_CREATE:
        SetTimer(hwnd, IDTIMER, 100, NULL);
        break;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        EndPaint(hwnd, &ps);
        return 0;


    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;


    case WM_TIMER:
    {
        switch (wParam)
        {
        case IDTIMER:
            wchar_t buf[444];
            SYSTEMTIME st;
            //GetSystemTime( &st );
            GetLocalTime(&st);
            wsprintf(buf, L" Сьогодні %02i.%02i.%i.    Зараз %02i:%02i:%02i ", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond);
            SetWindowText(hwnd, buf);
            break;

        case IDTIMER_Reverse: //проти часової стрілки
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (dir == Direction::down) //вниз && rcWindow.bottom != yWindowSize
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.bottom >= yWindowSize)
                {
                    rcWindow.top = yWindowSize - (rcWindow.bottom - rcWindow.top);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::right;
                }
            }
            else if (dir == Direction::right) //вправо && rcWindow.right != xWindowSize
            {
                MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.right >= xWindowSize)
                {
                    rcWindow.left = xWindowSize - (rcWindow.right - rcWindow.left);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::up;
                }
            }
            else if (dir == Direction::up) //вверх && rcWindow.top != 0
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.top <= 0)
                {
                    MoveWindow(hwnd, rcWindow.left, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::left;
                }
            }
            else if (dir == Direction::left) //вліво && rcWindow.left != 0
            {
                MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.left <= 0)
                {
                    MoveWindow(hwnd, 0, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::down;
                }
            }
            break;
        }

        case IDTIMER_Clockwise: // за годинниковою стрілкою
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (dir == Direction::down) //вниз && rcWindow.bottom != yWindowSize
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.bottom >= yWindowSize)
                {
                    rcWindow.top = yWindowSize - (rcWindow.bottom - rcWindow.top);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::left;
                }
            }
            else if (dir == Direction::right) //вправо && rcWindow.right != xWindowSize
            {
                MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.right >= xWindowSize)
                {
                    rcWindow.left = xWindowSize - (rcWindow.right - rcWindow.left);
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::down;
                }
            }
            else if (dir == Direction::up) //вверх && rcWindow.top != 0
            {
                MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.top <= 0)
                {
                    MoveWindow(hwnd, rcWindow.left, 0, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::right;
                }
            }
            else if (dir == Direction::left) //вліво && rcWindow.left != 0
            {
                MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                if (rcWindow.left <= 0)
                {
                    MoveWindow(hwnd, 0, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                    dir = Direction::up;
                }
            }
            break;
        }

        case IDTIMERSHOW:    // показуємо приховане вікно
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
            KillTimer(hwnd, IDTIMERSHOW);
            break;
        }
    }

    break;

#pragma region MOVE
    case WM_KEYDOWN:
    {
        switch (wParam)
        {
        case L'Q':        // ставить вікно у лівий верхній кут
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE);
            break;

        case L'Z':        // ставить вікно у правий нижній кут
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            int dy = cyWindowClient + cyWindowBorder + cyWindowTitle - rcWindow.bottom;        // на скільки зсунути донизу

            OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
        }
        break;

        case L'H':        // Згортає вікно 
            SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_HIDEWINDOW);
            SetTimer(hwnd, IDTIMERSHOW, 3000, NULL);
            break;

        case L'R':        // Розгортає вікно 
        {
            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна
            SetWindowPos(hwnd, NULL, 0, 0, cxWindowClient + cxWindowBorder * 2, cyWindowClient + cyWindowBorder + cyWindowTitle, SWP_SHOWWINDOW);
        }

        case VK_LEFT:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            if (rcWindow.left != 0)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left - 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left - 20, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left - 1, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_RIGHT:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна


            if (rcWindow.right != xWindowSize)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left + 10, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left + 20, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left + 1, rcWindow.top, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_UP:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            //int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            //int dy = 0;        // на скільки зсунути донизу

            //OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            if (rcWindow.top != 0)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 20, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top - 1, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

        case VK_DOWN:
        {
            GetWindowRect(hwnd, &rcWindow);    // отримує положення і розміри вікна

            cxWindowClient = GetSystemMetrics(SM_CXFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowClient = GetSystemMetrics(SM_CYFULLSCREEN);        // розмір клієнтської зони вікна у повноекранному режимі у пікселях
            cyWindowTitle = GetSystemMetrics(SM_CYCAPTION);            // висота заголовка
            cyWindowBorder = GetSystemMetrics(SM_CYBORDER);            // ширина рамки вікна
            cxWindowBorder = GetSystemMetrics(SM_CXBORDER);            // ширина рамки вікна

            //int dx = cxWindowClient + cxWindowBorder - rcWindow.right;                        // на скільки змістити праворуч
            //int dy = 0;        // на скільки зсунути донизу

            //OffsetRect(&rcWindow, dx, dy);

            //SetWindowPos( hwnd, NULL, rcWindow.left, rcWindow.top, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW );
            if (rcWindow.bottom != yWindowSize)
            {
                if (GetAsyncKeyState(VK_SHIFT))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 10, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else if (GetAsyncKeyState(VK_CONTROL))
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 20, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
                else
                {
                    MoveWindow(hwnd, rcWindow.left, rcWindow.top + 1, rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
                }
            }
            break;
        }

#pragma endregion

        case VK_RETURN: // при натисканні Ентер
        {
            KillTimer(hwnd, IDTIMER_Clockwise); // вбиваємо таймер за годинниковою
            changeDirectionToOposite(dir); // змінюємо напрямок на протилежний
            SetTimer(hwnd, IDTIMER_Reverse, 100, NULL); // запускаємо таймер проти годинникової стрілки по клавіші ENTER
            break;
        }

        case VK_SPACE:  // при натисканні пробілу Space bar
        {
            KillTimer(hwnd, IDTIMER_Reverse);
            changeDirectionToOposite(dir);
            SetTimer(hwnd, IDTIMER_Clockwise, 100, NULL);// запускаємо таймер за годинниковою стрілкою
            break;
        }

        case VK_ESCAPE: // при натисканні Escape
        {
            KillTimer(hwnd, IDTIMER_Reverse);
            KillTimer(hwnd, IDTIMER_Clockwise);
            dir = Direction::down;
            break;
        }
        break;

        }

    }
    break;

    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
} // LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)