1 Востаннє редагувалося Raikoho (07.12.2018 15:10:00)

Тема: Дуже потрібна допомога з завершенням простнької програми (зациклення)

І так, я написав програму для постійного кляцання мишкою з деяким інтервалом при натисканні клавіші АЛЬТ. З цим проблем немає, все працює, от тільки я не можу зробити наступний алгоритм: при повторному натисканні клавіші АЛЬТ - приморозити програму (зупинити клацання але не виходити з програми), і після цього, якщо ще раз натиснути АЛЬТ після цієї ж призупинки, - щоб постійне кляцання відновилось. Тобто необхідно зробити зациклення. Ось мій код спроби.

#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
void StartPressed(int t,int b){
    b++;
    int c=b%10;
while((!GetAsyncKeyState(VK_MENU)) && (c == 0))
    {
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        Sleep(t);
        }
    StartPressed(t,b);
}

int main()
{
    int t;
    cin>>t;
    int a;
    cin>>a;
    int b=2;
Sleep(a);
bool AutoBhop = true;
StartPressed(t, b);

}

2

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

це вам треба toggle зробити, це коли при кожному натисканню Alt значення деякої змінної змінюється на протилежний, та змінна може мати тип boolean. Тоді нехай початкове значення буде false, і при кожному натисканні буде відбуватися ось таке

variable = !variable;

тобто, якщо було false, то тепер буде true, а якщо було true, то буде false.

Ну а в циклі перевіряєте, якщо та змінна == true, тоді натискаємо кнопку, а якщо ні, то нічого не робимо

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

3 Востаннє редагувалося Raikoho (07.12.2018 15:26:31)

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

FakiNyan написав:

це вам треба toggle зробити, це коли при кожному натисканню Alt значення деякої змінної змінюється на протилежний, та змінна може мати тип boolean. Тоді нехай початкове значення буде false, і при кожному натисканні буде відбуватися ось таке

variable = !variable;

тобто, якщо було false, то тепер буде true, а якщо було true, то буде false.

Ну а в циклі перевіряєте, якщо та змінна == true, тоді натискаємо кнопку, а якщо ні, то нічого не робимо

Я робив щось подібне. Як результат - нічого не виходить(. Ну і як можна перезамінювати булеву змінну, якщо там цикл while? Походи не вийде так. Програма зазвичай взагалі крашиться. Ось код:

#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
void StartPressed(int t,bool AutoBhop){
while((GetAsyncKeyState(VK_MENU)) && (AutoBhop == false))
    {
        cout<<"hi ";
        if (AutoBhop == true)
            {AutoBhop =false;}
        else
            {AutoBhop =true;}
    }
while((!GetAsyncKeyState(VK_MENU)) && (AutoBhop == true))
    {
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        Sleep(t);
        }
    StartPressed(t,AutoBhop);
}

int main()
{
    int t;
    cout<<"Interval/Periodic clicking: (100=0.1 sec; 1000 = 1 sec; 10000 = 10 sec)"<<endl;
    cin>>t;
    int a;
    cout<<"How many seconds do you need to prepare clicking? (1000 = 1 sec)"<<endl;
    cin>>a;
    int b=0;
 //ShowWindow(NULL, SW_HIDE);
Sleep(a);
bool AutoBhop = false;
StartPressed(t, AutoBhop);

}

4

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

а перший варіянт коду працює нормально?

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

5

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

FakiNyan написав:

а перший варіянт коду працює нормально?

Там якогось дива цикання працює постійно)). Дивно, правда? Гляньте моє 2 повідомлення з кодом. Там є істина, я це відчуваю, тільки от треба шось підкорегувати...

6

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

1. Вирівняйте код, його читати боляче.
2. Позбудьтеся сміття, яке ви зараз не використовуйте. Що таке a, b і c? Вони тут потрібні? А AutoBhop?
3. Замініть рекурсію на цикл.
4. Прочитайте в MSDN, що робить GetAsyncKeyState.

Подякували: Raikoho, leofun012

7

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

koala написав:

1. Вирівняйте код, його читати боляче.
2. Позбудьтеся сміття, яке ви зараз не використовуйте. Що таке a, b і c? Вони тут потрібні? А AutoBhop?
3. Замініть рекурсію на цикл.
4. Прочитайте в MSDN, що робить GetAsyncKeyState.

а,б і с - вони використовувалися в мому 1-му способі, який, на жаль, не запрацював. Ідея була така: якщо змінна б стає парною, то вмикати цикл з кляцанням, якщо ні - то нічого не робити.

AutoBhop - логічна змінна в 2-му способі. Вона потрібна.
На рахунок GetAsyncKeyState - я читав. До речі, цикл while(!GetAsyncKeyState) спрацьовує до тих пір, поки я не нажму цю клавішу. Так що з цим все норм

8

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.

The return value is zero for the following cases:

The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.

може воно постійно повертає нуль, від того і спрацьовує?

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

9 Востаннє редагувалося Raikoho (07.12.2018 16:09:59)

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

FakiNyan написав:

If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.

The return value is zero for the following cases:

The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.

може воно постійно повертає нуль, від того і спрацьовує?


Можливо, але я пробував взагалі стерти верхній цикл і міняти логічну змінну просто після всіх дій до виклику цієї функції знову. Результат - краш. Точніше, починається кляцання, робить норм, потім ще раз альт = краш) Ось код:

#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
void StartPressed(int t,bool AutoBhop){
while((!GetAsyncKeyState(VK_MENU)) && (AutoBhop == true))
    {
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        Sleep(t);
        }
        if (AutoBhop == true)
            {AutoBhop =false;}
        else
            {AutoBhop =true;}
    StartPressed(t,AutoBhop);
}

int main()
{
    int t;
    cout<<"Interval/Periodic clicking: (100=0.1 sec; 1000 = 1 sec; 10000 = 10 sec)"<<endl;
    cin>>t;
    int a;
    cout<<"How many seconds do you need to prepare clicking? (1000 = 1 sec)"<<endl;
    cin>>a;
    int b=0;
 //ShowWindow(NULL, SW_HIDE);
Sleep(a);
bool AutoBhop = true;
StartPressed(t, AutoBhop);

}

10 Востаннє редагувалося koala (07.12.2018 16:15:32)

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

Для початку:

void f()
{
   smth;
   f();
}

еквівалентно (крім витрат стеку)

void f()
{
   while(true){
       smth;
   }
}

через це воно у вас і крашиться - стек вичерпується; а

        if (AutoBhop == true)
            {AutoBhop =false;}
        else
            {AutoBhop =true;}

еквівалентно (окрім швидкості та довжини коду)

AutoBhop = !AutoBhop;

Тепер давайте розбиратися, що відбувається в першому коді.
1. Alt не натиснено і не натискалося, GetAsyncKeyState повертає 0, цикл крутиться.
2. Ви натискаєте Alt, GetAsyncKeyState повертає 0xA001, стається перехід знову в f(), оскільки Alt натиснено (ви фізично не зможете натиснути так коротко, щоб встигнути за один прохід) - знову 0xA001 і так кілька тисяч разів.
3.  Ви відпускаєте Alt, тоді буде повернуто 0x1, після чого 0 і цикл поновиться. Хоча, може, 0x1 і не буде.
А тепер - що вам треба, як я розумію:

в циклі
{
  доки не натиснули Alt в циклі
  {
    якщо треба, клацаємо мишкою    
  }
  забуваємо, що Alt було натиснуто
}

Ніби все правильно? Тепер кодом:

bool do_clicks = true;
while(true)//умову можете поміняти, якщо треба якось виходити
{

  while(!GetAsyncKeyState(VK_MENU))
  {
        if(do_clicks){
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        }
        Sleep(t);
  }
  while(GetAsyncKeyState(VK_MENU))//чекаємо, доки не відпустять
  {
        Sleep(t);
  //якщо не робити Sleep на якийсь короткий проміжок, цей процеc відбиратиме в системи одне ядро на дурний цикл
  };
  //Alt відпустили, тепер GetAsyncKeyState повертає 0, можна починати цикл наново
  do_clicks = !do_clicks;
}

Так працює?

Подякували: Arete, Raikoho2

11

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

А взагалі якщо пишете під Windows - обробляйте WM_KEYUP і буде вам щастя :)

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

12 Востаннє редагувалося Raikoho (07.12.2018 16:26:00)

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

Ніби все правильно? Тепер кодом:

bool do_clicks = true;
while(true)//умову можете поміняти, якщо треба якось виходити
{

  while(!GetAsyncKeyState(VK_MENU))
  {
        if(do_clicks){
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
        }
        Sleep(t);
  }
  while(GetAsyncKeyState(VK_MENU))//чекаємо, доки не відпустять
  {
        Sleep(t);
  //якщо не робити Sleep на якийсь короткий проміжок, цей процеc відбиратиме в системи одне ядро на дурний цикл
  };
  //Alt відпустили, тепер GetAsyncKeyState повертає 0, можна починати цикл наново
  do_clicks = !do_clicks;
}

Так працює?

Працює, тільки bool do_clicks = true не можна встановлювати в рекурсивній функції, інакше немає сенсу в do_clicks = !do_clicks;. Отож, я її переніс в мейнову фукцію і звідти вернув перше значеня. Тепер все працює, дуже дякую за код))

13

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

koala написав:

А взагалі якщо пишете під Windows - обробляйте WM_KEYUP і буде вам щастя :)

Що за WM_KEYUP? Типу ті ж натискання клавіш?

14

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

Ще раз: вам не потрібна рекурсія, хіба я незрозуміло написав?
Так, це події. WinMain - TranslateMessage - DispatchMessage - WindowProc, всі справи. Тоді можна не в циклі чекати, а лише реагувати на натискання.

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

15

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

koala написав:

Ще раз: вам не потрібна рекурсія, хіба я незрозуміло написав?
Так, це події. WinMain - TranslateMessage - DispatchMessage - WindowProc, всі справи. Тоді можна не в циклі чекати, а лише реагувати на натискання.

Тобто все це можна записати в одному блоці мейн, наприклад?

16 Востаннє редагувалося Raikoho (07.12.2018 17:00:48)

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

koala написав:

Ще раз: вам не потрібна рекурсія, хіба я незрозуміло написав?
Так, це події. WinMain - TranslateMessage - DispatchMessage - WindowProc, всі справи. Тоді можна не в циклі чекати, а лише реагувати на натискання.

І справді, все працює і без рекурсї. Хоча дивно, що як і з рекурсією, так і без, - забирає стабільно 680 кб оперативної пам'яті.

17

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

Тому що розмір стеку прописаний компілятором жорстко; закінчиться стек - програма падає, а не запитує новий.

Подякували: FakiNyan, Arete, Raikoho, leofun014

18

Re: Дуже потрібна допомога з завершенням простнької програми (зациклення)

koala написав:

Тому що розмір стеку прописаний компілятором жорстко; закінчиться стек - програма падає, а не запитує новий.

супер. Дуже дякую за відгуки