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


Думаю у всех офисных работников бывает ситуация, когда после вкусненького обеда сильно разморило и хочется вздремнуть. На самом деле, дневной сон очень полезен как для организма, так и для работы, так как очень положительно влияет на продуктивность. Однако по моему опыту, более 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.
}

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


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

Комментарии (10)


  1. dom3d
    21.02.2019 00:02
    +4

    На работе во время обеда 20 минут поспать не преступление.


  1. vassabi
    21.02.2019 00:47
    +1

    пфф, 10+ лет тому назад я работал на одной фирме, где была система, что приходишь на рабочее место — нажимаешь кнопочку «на работе», а перед уходом домой — кнопочку «не на работе».
    Так у нас в отделе автоматизации в свое время был конкурс (хехе, негласный конечно же) на написание своей утилитки для залогина-вылогина: у кого она будет красивее, устойчивее в работе и с более богатым функционалом (учет праздников например)…


    1. Kocmohabt314
      21.02.2019 12:27

      А у меня на первой работе мы должны были отправлять письмо через аутлук о том что пришел на работу… Правда при наличии СКУД и камер наблюдения в коридоре не понимаю зачем это было нужно.


    1. kosmonaFFFt
      21.02.2019 12:55

      Такое ощущение, что я работал там же. Случаем не АС?


  1. KvanTTT
    21.02.2019 01:53

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

    А вы с ним общаться пробовали? Не вижу в этом ничего криминального. У нас может кто-то бы и спал, только вот негде, не на рабочем же месте.


    Кстати, принимать горизонтальное положение после обильного приема пищи может быть не очень то и полезно, особенно людям с рефлюксом, гастритом.


  1. Aracon
    21.02.2019 03:14

    Помнится, ещё в конце 90-х гуляли по рунету и по сборникам на дисках «имитаторы работы», которые сами водили мышкой, открывали и закрывали окна, набирали текст. А ещё в мелких казуальных играх нередкой функцией была «кнопка „начальник“, по нажатию которой игра сворачивалась, или на экране появлялся скриншот Excel (на английском, само собой). От этой статьи прямо повеяло теми временами.


    1. qw1
      21.02.2019 15:17

      Boss Key был не только в играх, но и в браузерах. Например, в Maxthon2 — Alt+`


  1. AKudinov
    21.02.2019 07:06

    Позвольте, а зачем Вам WinProc() и MessageLoop(), если Вы не создаёте никаких окон???


  1. zbestr
    21.02.2019 10:09

    5 скролю странички таким образом в своем расширении для браузера:
    $('html, body').animate( { scrollTop: $(selector).offset().top }, [scroll offset] );


  1. Alexey2005
    22.02.2019 00:11

    А можно просто слепить формочку с меткой «Updating...» и индикатором прогресса, который будет обновляться по таймеру, достигая 100% как раз за 20 мин.