IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Builder 6.0
сообщение
Сообщение #1


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Хочу сделать следуюшее...чтобы по определенным клавишам двигалася напиример Button1,
а по другим Button2...написал примерно так


void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg,
bool &Handled)
{
// Memo1->Lines->Add(Msg.wParam);
const nStep = 1;
switch(Msg.wParam)
{
case 40: Button1->Top += nStep;
break;
case 38: Button1->Top -= nStep;
break;
case 37: Button1->Left -= nStep;
break;
case 39: Button1->Left += nStep;
break;

case 83: Button2->Top += nStep;
break;
case 87: Button2->Top -= nStep;
break;
case 65: Button2->Left -= nStep;
break;
case 68: Button2->Left += nStep;
break;

}



Но теперь пока одна кнопка движеться вторая не будет...как реализовать независимое движение?..
может как то через много поточность?..можно для каждой кнопки писать свой поток и в нём ждать нажатия определённой кнопки и его уже орабатывать...но как ето сделать?..

Сообщение отредактировано: Fanat -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Цитата
можно для каждой кнопки писать свой поток и в нём ждать нажатия определённой кнопки и его уже орабатывать...
Угу... Чтобы наконец убедиться, что весь GUI должен всегда работать в одном потоке, иначе проблем не оберешься... Вообще-то можно сделать и так:

typedef struct {
int x, y;
bool b;
} RMove;

RMove moving[2];

void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled)
{
switch(Msg.message) {
case WM_KEYDOWN:
// Ну, ты же понимаешь, что все это можно записать и намного короче,
// добавив одну-единственную функцию, правда? Это - просто пример...
switch(Msg.wParam) {
case 40:
{
moving[0].x = 0; moving[0].y = 1;
Handled = moving[0].b = true; break;
}
case 38:
{
moving[0].x = 0; moving[0].y = -1;
Handled = moving[0].b = true; break;
}
case 37:
{
moving[0].x = -1; moving[0].y = 0;
Handled = moving[0].b = true; break;
}
case 39:
{
moving[0].x = 1; moving[0].y = 0;
Handled = moving[0].b = true; break;
}

case 83:
{
moving[1].x = 0; moving[1].y = 1;
Handled = moving[1].b = true; break;
}
case 87:
{
moving[1].x = 0; moving[1].y = -1;
Handled = moving[1].b = true; break;
}
case 65:
{
moving[1].x = -1; moving[1].y = 0;
Handled = moving[1].b = true; break;
}
case 68:
{
moving[1].x = 1; moving[1].y = 0;
Handled = moving[1].b = true; break;
}
}

break;
case WM_KEYUP:
switch(Msg.wParam) {
case 40: case 38:
case 37: case 39:
{
Handled = true;
moving[0].b = false; break;
}
case 83: case 87:
case 65: case 68:
{
Handled = true;
moving[1].b = false; break;
}
}

break;
}
}


void MoveButton(TButton *button, RMove r) {
const int nStep = 1;
button->Left += nStep * r.x;
button->Top += nStep * r.y;
}


// Таймер установлен на 0,1 секунды...
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if(moving[0].b) {
MoveButton(Button1, moving[0]);
}
if(moving[1].b) {
MoveButton(Button2, moving[1]);
}
}
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Да...так работает..=)

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

А зачем Handled ( - признак обработки события) выставлять в true?..

Цитата

// Ну, ты же понимаешь, что все это можно записать и намного короче,
// добавив одну-единственную функцию, правда? Это - просто пример...


Я как то об этом не задумывался даже... blink.gif Я так понимаю эта функция просто внутри себя будет проверять клавиши, да и кнопку которую двигать ей тоже отправлять надо...и она уже будет двигать ету кнопку...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
Хотелось бы всё таки узнать как сделать через потоки...
Ты действительно этого хочешь? Тогда посмотри присоединенный файл, там описание того, как это можно сделать. Один из способов, скажем так...

Прикрепленный файл  fanat.txt ( 2.08 килобайт ) Кол-во скачиваний: 347


Цитата
А зачем Handled ( - признак обработки события) выставлять в true?..
Затем, что если ты этого не сделаешь, и у тебя на форме будет, например, Edit, и фокус будет на нем, то этот Edit будет заполняться символами, которые ты вводишь (нажимая клавишу). А если ничего из текстовых контролов не будет - то программа будет пищать. А установкой Handled = true ты говоришь обработчику ApplicationMessage, что это событие уже обработано, дальше по цепочке его передавать не надо...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Цитата(volvo @ 1.02.2008 1:29) *

Ты действительно этого хочешь? Тогда посмотри присоединенный файл, там описание того, как это можно сделать. Один из способов, скажем так...

Прикрепленный файл  fanat.txt ( 2.08 килобайт ) Кол-во скачиваний: 347


Затем, что если ты этого не сделаешь, и у тебя на форме будет, например, Edit, и фокус будет на нем, то этот Edit будет заполняться символами, которые ты вводишь (нажимая клавишу). А если ничего из текстовых контролов не будет - то программа будет пищать. А установкой Handled = true ты говоришь обработчику ApplicationMessage, что это событие уже обработано, дальше по цепочке его передавать не надо...


Да...интересно..я вроде во всём разобрался...

И я так понимаю Sleep(100); чтобы мы успели нажать какую либо кнопку...но при етом слишком скорость маленькая...а при Sleep(10) у меня в конце концов всё таки зависало =(...
А вообще при отключения Sleep кнопки почему то движуться с разными скоростями и зависает быстро..=(
Не мог бы ты привести пример ещё какого либо способа...

(не обязательно на счёт данной задачи...я могу разобраться и сам попрбовать сделать..=)...в общем как тебе удобней...)

Сообщение отредактировано: Fanat -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
а при Sleep(10) у меня в конце концов всё таки зависало =(...
Поменял в Execute() условие выхода на
  ...
}
while(!Terminated);

(как я мог написать там Suspended - не понимаю wacko.gif ), гонял программу минут 20 со Sleep(5) и nStep = 2: скорости движения одинаковые, зависаний никаких не обнаружено. Я надеюсь, ты в OnDestroy формы прописал завершение потоков?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Цитата(volvo @ 1.02.2008 12:24) *

Поменял в Execute() условие выхода на
  ...
}
while(!Terminated);

(как я мог написать там Suspended - не понимаю wacko.gif ), гонял программу минут 20 со Sleep(5) и nStep = 2: скорости движения одинаковые, зависаний никаких не обнаружено. Я надеюсь, ты в OnDestroy формы прописал завершение потоков?


Да..так лучше...
Теперь написал...они же и так сами должны завершаться при завершении приложения?..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Должны... Но их должна завершить система, а это требует дополнительного времени, будет подвисать при выходе. А если ты напишешь
for(int i = num_threads - 1; i >= 0; i--) {
thr[i] -> Terminate();
}
, то дело пойдет быстрее...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Цитата(volvo @ 1.02.2008 12:47) *

Должны... Но их должна завершить система, а это требует дополнительного времени, будет подвисать при выходе. А если ты напишешь
for(int i = num_threads - 1; i >= 0; i--) {
thr[i] -> Terminate();
}
, то дело пойдет быстрее...


Понятно...А как отловить нажатие двух кнопок сразу?..хочу добавить движение по диагоналям...
А какой компонент лучше использовать для движения?...хочу написать что то вроде Ice hockey, так что это могут быть и TPanel и просто прямоугольник нарисованый...

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Цитата
А как отловить нажатие двух кнопок сразу?..хочу добавить движение по диагоналям...
Ну, например, вот так:
const int dirLt = 0;
const int dirRg = 1;
const int dirUp = 2;
const int dirDn = 3;

// Делаем множество направлений
typedef Set<int, dirLt, dirDn> TDir;

class TMyThread : public TThread
{
private:
TButton *btn;
TDir FState;
protected:
void __fastcall Execute();
public:
__property TDir GetState = {read = FState, nodefault};
__fastcall bool SetState(TDir& state) {
FState = state;
if(state.Empty())
{
Suspend();
}
else
{
Resume();
}
return true;
}

__fastcall TMyThread(TButton *button, bool CreateSuspended):
TThread(CreateSuspended)
{
btn = button;
}
};

const int num_threads = 2;
TMyThread *thr[num_threads];


void __fastcall TMyThread::Execute()
{
const int nStep = 2;

do {

int dx = 0, dy = 0;
for(int dir = dirLt; dir <= dirDn; dir++) {
// если текущее направление присутствует во множестве
if(FState.Contains(dir)) {
// то высчитываем, куда двигаться...
switch(dir) {
case dirLt: dx = -nStep; break;
case dirRg: dx = +nStep; break;
case dirUp: dy = -nStep; break;
case dirDn: dy = +nStep; break;
}

}
}

btn->Left += dx; btn->Top += dy;
Sleep(5);
}
while(!Terminated);
}

// ...

int key_pressed(unsigned int key, int& dir)
{
unsigned codes[num_threads][4] = {
{37, 39, 38, 40}, {65, 68, 87, 83}
};

for(int i = 0; i < num_threads; i++) {
for(int j = 0; j < 4; j++) {
if(codes[i][j] == key) {
dir = j; return i;
}
}
}
return -1;
}


void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled)
{
int thread_n, dir;

switch(Msg.message) {
case WM_KEYDOWN:
if((thread_n = key_pressed(Msg.wParam, dir)) >= 0) {
Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState << dir // добавляем направление во множество
);
}
break;
case WM_KEYUP:
if((thread_n = key_pressed(Msg.wParam, dir)) >= 0) {
Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState >> dir // "изымаем" направление ...
);
}
break;
}
}
"... И всего делов..." (С) "И.В. меняет профессию"
smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


А что значит строчка

__property TDir GetState = {read = FState, nodefault};


Это мы свойства добавляем?..синтаксис не понятен..=(
И:

thr[thread_n]->GetState << dir


<< это что значит?..

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Цитата
Это мы свойства добавляем?
Угу... Именно свойства. А что непонятно? Описываешь свойство (имя и тип), и указываешь что для чтения обращение к свойству аналогично обращению к FState. Поскольку нет write=, то это свойство только для чтения. И не является свойством "по умолчанию".

Цитата
<< это что значит?..
для типа Set перегружены операторы << (через него реализовано добавление элемента в множество) и >> (извлечение элемента из множества, если он там присутствует)
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Цитата(volvo @ 2.02.2008 4:22) *

Угу... Именно свойства. А что непонятно? Описываешь свойство (имя и тип), и указываешь что для чтения обращение к свойству аналогично обращению к FState. Поскольку нет write=, то это свойство только для чтения. И не является свойством "по умолчанию".


Вроде разобрался...а почему используется свойство?...можно так

TDir GetState() {return FState;};


Через свойство лучше чем то?..

Цитата

для типа Set перегружены операторы << (через него реализовано добавление элемента в множество) и >> (извлечение элемента из множества, если он там присутствует)

Понял...

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Цитата
можно так
TDir GetState() {return FState;};

Можно. Только тогда придется делать:
				Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState() >> dir // <--- вызов функции GetState
);

, правда? А не боишься, что у тебя будет постоянно создаваться новая копия множества, и ты потом получишь тормоза при выходе из программы? А при работе с __property ты работаешь с одной и той же переменной...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Fanat
***

Группа: Пользователи
Сообщений: 261
Пол: Мужской
Реальное имя: Сергей

Репутация: -  5  +


Цитата(volvo @ 2.02.2008 13:41) *

Можно. Только тогда придется делать:
				Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState() >> dir // <--- вызов функции GetState
);

, правда?

Ну это понятно...

Цитата

А не боишься, что у тебя будет постоянно создаваться новая копия множества, и ты потом получишь тормоза при выходе из программы? А при работе с __property ты работаешь с одной и той же переменной...


Я так понимаю что они создаються при возвращении значения...но разве эта копия будет существовать до самого выхода из программы?..они не будут удаляться при выходе за '}' ?..
Согласен, что твой вариант работать все равно будет лучше... good.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 1.12.2020 20:08
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name