Pull to refresh

Имитатор чтения статей

Reading time5 min
Views5.4K

Добрый день уважаемые. Хотелось бы поделиться своей историей и маленьким лайфхаком.


Думаю у всех офисных работников бывает ситуация, когда после вкусненького обеда сильно разморило и хочется вздремнуть. На самом деле, дневной сон очень полезен как для организма, так и для работы, так как очень положительно влияет на продуктивность. Однако по моему опыту, более 20 минут — явный перебор. Этого достаточно чтобы организм привел себя в норму. И спустя буквально минуту, в течение которой очень хочется продолжить спать, организм просыпается, чувствуется бодрость и прилив сил.


С другой стороны, многие предпочитают выпить чашечку кофе. И хоть кажется, что это помогает, на самом деле организм не восстанавливает свои ресурсы, а только больше теряет. Да и вредно это.


В целом понятно, о чем идет речь, правда? однако вполне закономерно возникает вопрос, как это провернуть в офисе. И ведь все дело в том, что большинство начальников такое не одобряет. Да и диван есть далеко не везде. Да и вряд ли вы позволите себе на нем прикорнуть, если дорожите своим рабочим местом.


Однако мне повезло, у меня кресло может очень сильно откинуться назад, и я могу в целом выглядеть работающим, просто задумавшимся. И все бы ничего, если бы не одно но.


Абсолютно статичная картинка на мониторах выдает меня с потрохами!


Я как то поделился этой проблемой с другом, и он в шутку предложил сделать имитатор работы.
Идея мне очень понравилась, однако реализовать полноценный имитатор работы — это что вообще такое должно быть? оно что, и работать за меня смогло бы? В общем понятно, что создать такое было бы крайне затруднительно. Но можно было бы упростить задачу.


По роду деятельности я простой С++ программист, а посему очень часто ползаю по интернету и читаю различные статьи. Без этого никак, все это понимают.


Если понаблюдать за человеком, который читает длинную и сложную статью, можно заметить, что он периодически прокручивает статью то вверх, то вниз. И вот это то я и решил реализовать.
Спустя буквально час серфинга в интернете, путем объединения материала трех статей (статьи по скрытному приложению без окна, по перехвату событий клавиатуры и статьи по имитации событий от мышки) была реализована простецкая программа, которой я и хотел бы поделиться с людьми.


Идея простая в своей основе: случайные события прокрутки колесика мышки. То есть просто выбираешь статью подлиннее и посложнее по текущей задаче, включаешь имитатор, и засыпаешь себе спокойно. Программа не видна в диспетчере задач (или я просто слепой и не нашел ее там), с помощью комбинации клавиш Ctrl + пробел ставится на паузу, и возобновляет свое выполнение, а по нажатии стрелочки вниз она закрывается. Программу можно увидеть через консоль, с помощью команды tasklist, и при необходимости так можно выяснить ее PID, чтобы закрыть ее через taskkill.


Код программы я сам не до конца понимаю, поэтому комментариев его не будет.


Собственно, сам код:


#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <string.h>
#include <windows.h>

HHOOK hKeyboardHook;
#define X 500
#define Y 500
#define SCREEN_WIDTH 1920
#define SCREEN_HEIGHT 1080
bool bQuit = false;
bool bPause = false;

__declspec(dllexport) LRESULT CALLBACK KeyboardEvent(int nCode, WPARAM wParam, LPARAM lParam)
{
    DWORD SHIFT_key = 0;
    DWORD CTRL_key = 0;
    DWORD ALT_key = 0;

    if ((nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN)))
    {
        KBDLLHOOKSTRUCT hooked_key = *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = { 0 };

        int i = GetKeyNameText(dwMsg, (lpszKeyName + 1), 0xFF) + 1;

        int key = hooked_key.vkCode;

        SHIFT_key = GetAsyncKeyState(VK_SHIFT);
        CTRL_key = GetAsyncKeyState(VK_CONTROL);
        ALT_key = GetAsyncKeyState(VK_MENU);

        //printf("Keycode = %c\n", key);
        if (key == VK_DOWN)
        {
            bQuit = true;
            PostQuitMessage(0);
        }
        if (CTRL_key != 0 && key == ' ')
        {
            bPause = !bPause;
        }

        //if (key >= 'A' && key <= 'Z')
        //{

        //  if (GetAsyncKeyState(VK_SHIFT) >= 0) key += 32;

        //  /*********************************************
        //  ***   Hotkey scope                         ***
        //  ***   do stuff here                        ***
        //  **********************************************/

        //  if (CTRL_key != 0 && key == 'y')
        //  {
        //      MessageBox(NULL, "CTRL-y was pressed\nLaunch your app here", "H O T K E Y", MB_OK);
        //      CTRL_key = 0;

        //      //do stuff here

        //  }

        //  if (CTRL_key != 0 && key == 'q')
        //  {
        //      MessageBox(NULL, "Shutting down", "H O T K E Y", MB_OK);
        //      bQuit = true;
        //      PostQuitMessage(0);
        //  }
        //  

        //  SHIFT_key = 0;
        //  CTRL_key = 0;
        //  ALT_key = 0;

        //}

    }
    return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

void MessageLoop()
{
    MSG message;
    while (GetMessage(&message, NULL, 0, 0))
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
}

DWORD WINAPI my_HotKey(LPVOID lpParm)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR)lpParm);
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardEvent, hInstance, NULL);
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

void MouseSetup(INPUT *buffer)
{
    buffer->type = INPUT_MOUSE;
    buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
    buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
    buffer->mi.mouseData = 0;
    buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
    buffer->mi.time = 0;
    buffer->mi.dwExtraInfo = 0;
}

void MouseMoveAbsolute(INPUT *buffer, int x, int y)
{
    buffer->mi.dx = (x * (0xFFFF / SCREEN_WIDTH));
    buffer->mi.dy = (y * (0xFFFF / SCREEN_HEIGHT));
    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);

    SendInput(1, buffer, sizeof(INPUT));
}

void MouseClick(INPUT *buffer)
{
    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN);
    SendInput(1, buffer, sizeof(INPUT));

    Sleep(10);

    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP);
    SendInput(1, buffer, sizeof(INPUT));
}
void MouseWheel(INPUT *buffer, bool bUp)
{
    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_WHEEL);
    if(bUp)
        buffer->mi.mouseData = 120;
    else
        buffer->mi.mouseData = -120;
    SendInput(1, buffer, sizeof(INPUT));
}

/* declare window procedure for this application. */
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR szArgs, int nCmdShow)
{
    HANDLE hThread;
    DWORD dwThread;
    hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)my_HotKey, (LPVOID)szArgs[0], NULL, &dwThread);

    INPUT buffer[1];
    int probability = 3; //   probability / 1000
    int pr = probability;
    int repeat = 0;
    while (!bQuit)
    {
        if (bPause)
        {
            continue;
            Sleep(100);
        }
        MouseSetup(buffer);
        int p = rand() % 1000;
        if (p < pr)
        {
            if(p >= (pr + 1) / 2)
                MouseWheel(buffer, true);
            else
                MouseWheel(buffer, false);
            pr-=100;
            if (pr < probability)
                pr = probability;
        }
        else
        {
            pr++;
        }
        Sleep(100);
    }
    if (hThread) return WaitForSingleObject(hThread, INFINITE);
    return 0;
    //MSG Msg; // save window messages here.
    //       /* Run the message pump. It will run until GetMessage() returns 0 */
    //while (GetMessage(&Msg, NULL, 0, 0))
    //{
    //  TranslateMessage(&Msg); // Translate virtual-key messages to character messages
    //  DispatchMessage(&Msg); // Send message to WindowProcedure
    //}
    //return Msg.wParam;

    return 0;
}

/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WinProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
    case VK_ESCAPE:
    {
        MessageBox(NULL, "You hit escape, quitting now.", "Message", 0);
        PostQuitMessage(0);
        break;
    }

    // handle non-trapped messages.
    default:return DefWindowProc(hWnd, Message, wParam, lParam);
    }

    return 0; // this indicates a message was trapped.
}

Код не очищен от лишних комментариев и прочего мусора по той простой причине, что кому то для понимания может пригодиться. К сожалению не могу приложить исполняемый файл для ленивых.


Хотелось бы отметить, что использовать эту программу я не рекомендую никому, да и сам ей пользоваться не рискну. Ведь если вы просто задремали на рабочем месте, это можно объяснить, сославшись на плохое самочувствие, или долгое отсутствие отпуска, или еще что — либо. А если кто — нибудь поймет, что вы пытаетесь его обмануть, это будет уже плохо, обидно и неприятно. И вряд ли положительно скажется на вашей карьере.

Tags:
Hubs:
+6
Comments21

Articles

Change theme settings