Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 39, средняя оценка - 4.97
Shpion007
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 40
#1

Как сделать "Старт", "Пауза", Стоп"? - C++

26.12.2012, 11:11. Просмотров 5499. Ответов 71
Метки нет (Все метки)

Доброго времени суток,
как сделать так, чтобы при нажатии на кнопку начиналось цикличное действие (рисование например) и продолжалось бы пока не будет нажата другая кнопка. Грубо говоря, как сделать "Старт", "Пауза", Стоп".
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.12.2012, 11:11     Как сделать "Старт", "Пауза", Стоп"?
Посмотрите здесь:
C++ Как отключить автоматическое добавление "_" "@" "number" к имени экстернального метода?
C++ Как сделать так, чтобы scanf в переменную double мог считывать с клавиатуры не только "0,01", но и "0.01"
Как сделать так, чтобы введенное с клавиатуры слово "helllo" в памяти сохранялось в виде "Hello". C++
Как сделать, так чтобы i и j можно было вводить самому "i" И "j" в цикле, есть программа C++
Visual Studio не читает операторы, что начинаются на "glu" ("gluBuild2DMipmaps", "gluPerspective") C++
C++ Через ООП: Дать для числа наименование: "рубль", "рубля", "рублей";
C++ Вывести на экран монитора число с наименованием "год","года", "лет"
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kravam
быдлокодер
1693 / 880 / 44
Регистрация: 04.06.2008
Сообщений: 5,438
07.01.2013, 01:38     Как сделать "Старт", "Пауза", Стоп"? #61
Цитата Сообщение от Avazart Посмотреть сообщение
Ситуация: один поток рисует в одном окне, а другой владеет другим окном
Цитата Сообщение от Avazart Посмотреть сообщение
А GDI -ф-ции обращаются не к разделяемому ресурсу - окну программы, сообщения от которого обрабатываются в оконной процедуре в основном потоке ?
там пьяный что ли? Меня же цитируешь где я говорю о РАЗНЫХ окнах и тут же возражаешь так, будто я говорю об одном окне.

Нет, представь себе. Я говорю о случае, когда, каждый поток владеет собственным окном, следовательно, оно- неразделяемый ресурс. И я даже знаю что ты сейчас скажешь, ты скажешь:
Цитата Сообщение от Avazart Посмотреть сообщение
А GDI -ф-ции обращаются не к разделяемому ресурсу - окну программы, сообщения от которого обрабатываются в оконной процедуре в основном потоке ?
скучно с тобой становится.

++++++++++++++++++++++++++++++++++++++++++++++++++

Цитата Сообщение от Avazart Посмотреть сообщение
Все понятно ...

это типа крест на мне...

++++++++++++++++++++++++++++++++++++++++++++++++++

Цитата Сообщение от Avazart Посмотреть сообщение
Какую консоль ты о чем ? приложение оконное изначально было ( напоминаю если ты об этом уже забыл )
Ну и что? Мало ли что там было изначально?
Я ставлю ДРУГОЙ вопрос- вернее ты его ставишь, а именно- потоки в билдер реализованы круче, нежели в pthread, а когда я предлагаю пободаться- в кусты сразу. Консоль вполне подойдёт. Нет, конечно можно попытаться меня запутать, так тот чел- отправить не знаю куда где лежит какой-то там проект, можно глубокомысленно изречь:
Цитата Сообщение от Avazart Посмотреть сообщение
Тут конечно строк по более но и задумка куда по более вашей ...
Ещё вариант: можно продолжать твердить про четыре строчки кода, как мантру.

Не хошь не надо.
Оставайся со своими четырьмя строчками кода.

Цитата Сообщение от Avazart Посмотреть сообщение
Это даже не интересно ... тут и без TThread обойтись можно ... ( CreateThread() + крит секция )
повторюсь: ну раз неинтересно, и сиди со своими четырьмя строчками кода.
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,386
Записей в блоге: 17
07.01.2013, 02:09     Как сделать "Старт", "Пауза", Стоп"? #62
Цитата Сообщение от kravam Посмотреть сообщение
пободаться- в кусты сразу.
Бодаются бараны, я не таков ...

Цитата Сообщение от kravam Посмотреть сообщение
скучно с тобой становится.
Скучно писать :
Цитата Сообщение от kravam Посмотреть сообщение
Ну то есть: поток запустился, написал "Hello, word" и отработал.
Есть претензии укажи - ошибки в моем коде, либо напиши свой код как альтернативу с теми же возможностями (или более...)

Цитата Сообщение от kravam Посмотреть сообщение
Я ставлю ДРУГОЙ вопрос- вернее ты его ставишь, а именно- потоки в билдер реализованы круче, нежели в pthread, а когда я предлагаю пободаться- в кусты сразу.
Это твой вывод ... для меня это не вопрос ... для данной задачи (для данного компилятора,операционной системы) TThread лучше подходит...
Но никто не запрещает юзать что угодно и как угодно при этом - но будет много буков, как я уже сказал.

Да собственно спросите ТС какой из предложенных кодов ему больше подходит ... и на этом думаю можно тему закрывать (если нет конечно вопросов по сути)

Цитата Сообщение от kravam Посмотреть сообщение
Я ставлю ДРУГОЙ вопрос
Другая тема ...
Shpion007
0 / 0 / 0
Регистрация: 22.10.2012
Сообщений: 40
07.01.2013, 15:04  [ТС]     Как сделать "Старт", "Пауза", Стоп"? #63
Цитата Сообщение от Avazart Посмотреть сообщение
на этом думаю можно тему закрывать
Вопросы есть, один из способов - это с помощью потока рисовать средствами Апи на канве, всё хорошо, НО тогда встает вопрос: как изменять цвет и толщину пера?

Второй реализованный мною способ - это с помощью таймера рисовать на канве средствами Vcl, здесь же слишком большое время исполнения, т.к одной прорисовки предшествует 1000 шагов расчетов (при шаге таймера 1 миллисекунда - это минимум 1 секунда).

Вы предлагали также другие способы, но реализовать их не удалось, что подскажете, что выбрать?
kravam
быдлокодер
1693 / 880 / 44
Регистрация: 04.06.2008
Сообщений: 5,438
07.01.2013, 18:14     Как сделать "Старт", "Пауза", Стоп"? #64
Ну вот, то, о чём я и говорил. Задержка в 1 секунду не допускается, но она есть. Вот и таймер.
Но и мой способ не подойдёт по этой же самой причине. Если его использовать, тогда управляющий поток должен передать управление рисующему потоку, который точно также будет чего-то расчитывать в течении1-ой секунды, а, поскольку он в это время будет владеть окном, та же задержка в управлении и выйдет. Только реализация ещё труднее.

Что же делать?

Нужен симбиоз решений.
Пусть у тебя рисует всё в таймере- у то есть через 100 миллисекунд к примеру. Это нормально. Но все расчёты пуст делаются в ДРУГОМ потоке.
Ну то есть как-то так:

---в потоке A нажал старт-> создался параллельный поток B (чисто для расчётов, он окно не занимает)

(Теперь по расчётам. Я так понимаю, все данные для расчётов формируются динамически, иначе их просто можно было расчитать до начала отрисовки, а потом махом всё отрисовать. То есть

произошла отрисовка- новые данные
произошла отрисовка- новые данные
произошла отрисовка- новые данные
произошла отрисовка- новые данные

Отсюда вывод: по каждому расчёту поток B должен приостанавливать свою деятельность и ждать, сигнала "произошла отрисовка", после этого генерить новые данные и посылать их потоку A).
---В потоке B делается расчёт и посылается об этом сигнал потоку A; поток B приостанавливает деятельность
---Поток A отрисовывает чё надо и посылает сигнал об этом потоку B
---В потоке B делается расчёт и посылается об этом сигнал потоку A; поток B приостанавливает деятельность
---Поток A отрисовывает чё надо и посылает сигнал об этом потоку B

И так сколько нам надо раз. Можно сделать, чтобы поток B сделал, к примеру 10 расчётов по 1-ой секунде каждый после чего самоубился. Тогда вся работа займёт примерно 1- секунд- то же самое, что и в твоём варианте с той лишь разницей, что в эти 10 секунд окно тормозить не будет .
Можно просто напросто реализовать убиение потока по нажатию кнопки стоп.

Я тебе сразу говорил с кандачка эту задачу не решить.

Не по теме:

А в билдере, как я понял, надо только подумать и синхронизацию прописывать не надо, всё само пропишется.



И напоследок ты спросишь- а где тут таймер? Как видишь, обошлись без него. Ведь для чего он нам нужен был? Чтобы циклично выполнялись какие-то действия (перерисовка). Но тут таймером может с успехом служить поток B- всякий раз по окончании расчётов он посылает сигнал об этом потоку A; так что не будем плодить лишние сущности.

Щас изобразим. Сразу говорю- кнопки пауза не будет, кроме того. Данные потоку B передаваться не будут. Передача динамически формирующихся данных- это отдельная тема. Вместо этого будет например семафор какой-нибудь (тоже вид данных своего рода),
то есть так:

поток B расчитал- сбросил флаг
поток A отрисовал- установил флаг


Считай что флаг это и есть данные
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,386
Записей в блоге: 17
07.01.2013, 19:10     Как сделать "Старт", "Пауза", Стоп"? #65
Цитата Сообщение от Shpion007 Посмотреть сообщение
Вопросы есть, один из способов - это с помощью потока рисовать средствами Апи на канве, всё хорошо, НО тогда встает вопрос: как изменять цвет и толщину пера?
Ну я уже говорил что это опасно -раз, неудобно - два,в этом нет необходимости так как решение предусмотрено VCL - три.
(о рисование можно найти в любом справочнике по WinApi ( работа GDI ) )

Собственно в коде который я предлагал для потоков можно увидеть как я выставляю толщину пера с помощью VCL

Цитата Сообщение от Shpion007 Посмотреть сообщение
Второй реализованный мною способ - это с помощью таймера рисовать на канве средствами Vcl, здесь же слишком большое время исполнения, т.к одной прорисовки предшествует 1000 шагов расчетов (при шаге таймера 1 миллисекунда - это минимум 1 секунда).
Ну говорил об этом расчетов много - таймер не подойдет, решать надо в потоке....

Более того в VCL таймер работает адекватно с интервалом ~300 мс ( меньше выставить нельзя- не сработает ).
Если это слишком надо то нужно реализовывать таймер на основе WinApi ( что собственно несложно и пример этого есть в одной из книг Архангельского, которые указывал раньше)

Цитата Сообщение от Shpion007 Посмотреть сообщение
Вы предлагали также другие способы, но реализовать их не удалось....
Что именно ? Что не удалось ?
Я же выкладывал готовый проект...

Цитата Сообщение от Shpion007 Посмотреть сообщение
что подскажете, что выбрать?
Моё мнение тоже TThread c синхронизацией ...

Да и переформулируй задание по конкретнее, а то благодаря некоторым уже и непонятно что именно нужно тебе ....



Добавлено через 3 минуты
Цитата Сообщение от kravam Посмотреть сообщение
Нужен симбиоз решений.
Это идиотизм, пЫрдонте...
Цитата Сообщение от kravam Посмотреть сообщение
Я тебе сразу говорил с кандачка эту задачу не решить.
Да да... тебе не решить...
kravam
быдлокодер
1693 / 880 / 44
Регистрация: 04.06.2008
Сообщений: 5,438
19.01.2013, 16:38     Как сделать "Старт", "Пауза", Стоп"? #66
Цитата Сообщение от Avazart Посмотреть сообщение
Это идиотизм, пЫрдонте...
мели, Емеля.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include <windows.h>
#include <pthread.h> 
#include <stdio.h> 
#include<semaphore.h>
 
//лепим своё сообщение
#define WM_OUR  WM_USER+100
#define zaderzhka  1000
 
 
#define ButtonID 1
#define ButtonID_ 2
 
 
//оконная процедура
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//функция потока
void *task2(void *X);
 
//ЭТО для объявления потоков всё
void* status; 
pthread_t ThreadA; // Объявляем потоки. 
bool flag= false;
 
//это семафор будет
sem_t sem;
 
 
 
char ClassName       []= "SimpleWinClass";
char AppName         []= "Our First Window";
char ButtonClassName []= "button";
char ButtonText      []= "Пуск";
char ButtonText_     []= "Стоп";
char* OurText          = (char*)"Win32 assembly is great and easy!";
 
HINSTANCE hInstance;
LPSTR CommandLine;
HWND hwndButton;
HWND hwndEdit;
char buffer [512];
 
//Длина OurText
int dlina_OurText;                                      //+
                                      //+
                                      //+
                                      //+
                                      //+
                                      //+
//Главная функция, создаёт окно
int WINAPI WinMain (HINSTANCE hInst,
                    HINSTANCE hPrevInst,
                    LPSTR CmdLine,
                    int CmdShow)
 
{
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 
 dlina_OurText= strlen (OurText);
 
 
 
 hInstance= hInst;
 CommandLine= CmdLine;
 //структуры
 WNDCLASSEX wc;
 MSG msg;
 HWND hwnd;
 
 //инициализация;
 wc.cbSize= sizeof (WNDCLASSEX);
 wc.style= CS_HREDRAW | CS_VREDRAW;
 wc.lpfnWndProc= WndProc;
 wc.cbClsExtra= 0;
 wc.cbWndExtra= 0;
 wc.hInstance= hInst;
 wc.hbrBackground= (HBRUSH)(COLOR_BTNFACE+1);
 wc.lpszMenuName= NULL;
 wc.lpszClassName= ClassName;
 wc.hIcon= LoadIcon (NULL,IDI_APPLICATION);
 wc.hIconSm= wc.hIcon;
 wc.hCursor= LoadCursor (NULL,IDC_ARROW);
 
 
 RegisterClassEx (&wc);
 
 hwnd= CreateWindowEx (WS_EX_CLIENTEDGE, ClassName,AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,500, 500,NULL,NULL,\
           hInst,NULL);
 
 ShowWindow (hwnd,SW_SHOWNORMAL);
 UpdateWindow (hwnd);
 
 
 
 while (true) {
   if (!GetMessage (&msg,NULL,0,0))
     break;
    TranslateMessage (&msg);
    DispatchMessage  (&msg);
 }
 return msg.wParam;
}
                                      //+
                                      //+
                                      //+
                                      //+
                                      //+
                                      //+
 
//+++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++
//Оконная процедура                              
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   static int i= 0;
   HDC hdc;
   PAINTSTRUCT ps;
   RECT rect;
  if (uMsg==WM_DESTROY) 
      PostQuitMessage (0);
  else if (uMsg==WM_CREATE) {
      //И две кнопки
      hwndButton= CreateWindowEx (0, ButtonClassName,ButtonText,\
      WS_CHILD + WS_VISIBLE + BS_DEFPUSHBUTTON,\
      75,70,140,25,hWnd,(HMENU)ButtonID,hInstance,NULL);
 
 
      hwndButton= CreateWindowEx (0, ButtonClassName,ButtonText_,\
      WS_CHILD + WS_VISIBLE + BS_DEFPUSHBUTTON,\
      75,100,140,25,hWnd,(HMENU)ButtonID_,hInstance,NULL);
  }
  else if (uMsg==WM_PAINT) {
      hdc= BeginPaint (hWnd, &ps);
      GetClientRect (hWnd, &rect);
      DrawText (hdc, OurText ,-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
      EndPaint (hWnd, &ps);
      //Отрисовали? Теперь устанавливаем семафор в единицу,
      //типа послали новые данные для вычисляемого потока
      sem_post(&sem);
  }
  else if (uMsg==WM_COMMAND) {
      WPARAM eax= wParam%0xffff;
      if (lParam) {
            if (eax==ButtonID) {
                eax= wParam/0Xffff;
                if (eax==BN_CLICKED) {
                   //Если нажимаем на вехнюю кнопку, то               
                   //создаём отдельный поток                          
                   //Создаём один раз, для этого используем флаг flag 
                   //когда поток аннулируется можно снова создат будет
                   if (!flag) {
                    
                    //Семафор инициализируем НУЛЁМ, всё, как положено:
                    sem_init(&sem, 0, 0);
                    
                    pthread_create(&ThreadA,NULL,task2, (void*)hWnd); 
                    flag= true;
                   }
                }
            }
            else if (eax==ButtonID_) {
                eax= wParam/0Xffff;
                if (eax==BN_CLICKED) {
                  //Убиваем на хрен поток, который пишет всякую херь
                  //но только если он создан                        
                  if (flag)
                  pthread_cancel(ThreadA); 
                }
            }
      }
  }
  else 
      return DefWindowProc (hWnd,uMsg,wParam,lParam );      
  return 0;
}
 
 
 
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Функция- дестуктор потока, выполняется при его анулировании
void routine  (void* x) {
 printf ("всё, я спёкся");
 flag= false;
}
 
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                   //Функция потока
void *task2(void *X) { 
 
 int x;
 void* arg= &x;
 pthread_cleanup_push (&routine, arg); 
 int OldState,OldType; 
// // Разрешено аннулирование асинхронного типа. 
 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &OldState); 
 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS,&OldType); 
 
 //Вот твой вечный цикл                         
 //ОН работает пока другой поток (родительский) 
 //не убьёт этот поток (дочерний)               
 //иначе будет рабтать вечно                    
 //Тут типа вычисления                          
 while (true) {
  printf ("Я, поток-тормоз, делаю расчёты %d секунд, но окна не занимаю!", zaderzhka/1000);
  printf ("шевели окно как тебе угодно\n");
  Sleep (zaderzhka);
 
  
  //Првоначально я не думал разбиратться здесь со строкой OurText,
  //а думал это делать всякий раз при обработке OurText,          
  //но передумал                                                  
  //Грамотно это будет зделать здесь                              
  //Это и будет перерасчётом данных                               
  OurText++;
  if (!(*OurText))
   OurText-= dlina_OurText;
  
  //Так, а тут поток заканчивает свои расчёты и посылает об этом сигнал окну
  //просто задействуем функцию                                              
  InvalidateRect ((HWND)X, NULL, true);
  
  //ждём на семафоре, когда он станет равным 1 
  sem_wait(&sem);
 
 }
 
 
 pthread_cleanup_pop (false); 
 
 return NULL; 
}
компилить с опциями:
-lpthread -lgdi32
mary_19
0 / 0 / 0
Регистрация: 04.03.2014
Сообщений: 25
27.11.2016, 21:37     Как сделать "Старт", "Пауза", Стоп"? #67
Но если не использовать сторонних библиотек, то как можно реализовать старт, паузу и выход из консольной программы?
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,386
Записей в блоге: 17
27.11.2016, 22:07     Как сделать "Старт", "Пауза", Стоп"? #68
mary_19, Вы о чем? О каких сторонних библиотеках речь?
mary_19
0 / 0 / 0
Регистрация: 04.03.2014
Сообщений: 25
28.11.2016, 23:34     Как сделать "Старт", "Пауза", Стоп"? #69
Ну есть же чисто С++ - ные библиотеки как заголовочный файл iostream включён в стандартную библиотеку C++. А вот Boost это как не стандартная библиотека.

Вопрос не по теме, кто-то может знает, что такое log state-переходов и как это оформить в формате .txt
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,386
Записей в блоге: 17
28.11.2016, 23:36     Как сделать "Старт", "Пауза", Стоп"? #70
Вы про потоки? Есть std::thread в > С++11
mary_19
0 / 0 / 0
Регистрация: 04.03.2014
Сообщений: 25
29.11.2016, 00:01     Как сделать "Старт", "Пауза", Стоп"? #71
Я с многопоточностью ещё не знакомилась, не могу сказать)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.11.2016, 00:07     Как сделать "Старт", "Пауза", Стоп"?
Еще ссылки по теме:
На C++ в строке после символа - "+" поставить символ "*" и посчитать сколько "+" C++
Определить, какая из точек "В" или "С" расположены ближе к точке "А". C++
C++ Добавить к возрасту человека указание "год", "года", "лет"
C++ Как сделать execl("my", "arg", argv)?
Создайте вектор, хранящий десять строковых значений "zero", "one", ..., "nine" C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Avazart
Эксперт С++
7115 / 5292 / 273
Регистрация: 10.12.2010
Сообщений: 23,386
Записей в блоге: 17
29.11.2016, 00:07     Как сделать "Старт", "Пауза", Стоп"? #72
Цитата Сообщение от mary_19 Посмотреть сообщение
Я с многопоточностью ещё не знакомилась, не могу сказать)
А читать умеете вообще? - Читайте тему с начала...
А затем задайте себе вопрос "о чем это я?"
Yandex
Объявления
29.11.2016, 00:07     Как сделать "Старт", "Пауза", Стоп"?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru