![]() |
1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!
![]() ![]() |
![]() |
Fanat |
![]()
Сообщение
#1
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Хочу сделать следуюшее...чтобы по определенным клавишам двигалася напиример 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 - 31.01.2008 17:41 |
volvo |
![]()
Сообщение
#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]);
}
}
|
Fanat |
![]()
Сообщение
#3
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Да...так работает..=)
Хотелось бы всё таки узнать как сделать через потоки... мне непонятно к в потоке узнать что нажата клавиша?.. А зачем Handled ( - признак обработки события) выставлять в true?.. Цитата // Ну, ты же понимаешь, что все это можно записать и намного короче, // добавив одну-единственную функцию, правда? Это - просто пример... Я как то об этом не задумывался даже... ![]() |
volvo |
![]()
Сообщение
#4
|
Гость ![]() |
Цитата Хотелось бы всё таки узнать как сделать через потоки... Ты действительно этого хочешь? Тогда посмотри присоединенный файл, там описание того, как это можно сделать. Один из способов, скажем так...![]() Цитата А зачем Handled ( - признак обработки события) выставлять в true?.. Затем, что если ты этого не сделаешь, и у тебя на форме будет, например, Edit, и фокус будет на нем, то этот Edit будет заполняться символами, которые ты вводишь (нажимая клавишу). А если ничего из текстовых контролов не будет - то программа будет пищать. А установкой Handled = true ты говоришь обработчику ApplicationMessage, что это событие уже обработано, дальше по цепочке его передавать не надо... |
Fanat |
![]()
Сообщение
#5
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Ты действительно этого хочешь? Тогда посмотри присоединенный файл, там описание того, как это можно сделать. Один из способов, скажем так... ![]() Затем, что если ты этого не сделаешь, и у тебя на форме будет, например, Edit, и фокус будет на нем, то этот Edit будет заполняться символами, которые ты вводишь (нажимая клавишу). А если ничего из текстовых контролов не будет - то программа будет пищать. А установкой Handled = true ты говоришь обработчику ApplicationMessage, что это событие уже обработано, дальше по цепочке его передавать не надо... Да...интересно..я вроде во всём разобрался... И я так понимаю Sleep(100); чтобы мы успели нажать какую либо кнопку...но при етом слишком скорость маленькая...а при Sleep(10) у меня в конце концов всё таки зависало =(... А вообще при отключения Sleep кнопки почему то движуться с разными скоростями и зависает быстро..=( Не мог бы ты привести пример ещё какого либо способа... (не обязательно на счёт данной задачи...я могу разобраться и сам попрбовать сделать..=)...в общем как тебе удобней...) Сообщение отредактировано: Fanat - 1.02.2008 11:54 |
volvo |
![]()
Сообщение
#6
|
Гость ![]() |
Цитата а при Sleep(10) у меня в конце концов всё таки зависало =(... Поменял в Execute() условие выхода на ...
}
while(!Terminated);
(как я мог написать там Suspended - не понимаю ![]() |
Fanat |
![]()
Сообщение
#7
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Поменял в Execute() условие выхода на ...
}
while(!Terminated);
(как я мог написать там Suspended - не понимаю ![]() Да..так лучше... Теперь написал...они же и так сами должны завершаться при завершении приложения?.. |
volvo |
![]()
Сообщение
#8
|
Гость ![]() |
Должны... Но их должна завершить система, а это требует дополнительного времени, будет подвисать при выходе. А если ты напишешь
for(int i = num_threads - 1; i >= 0; i--) {
thr[i] -> Terminate();
}
, то дело пойдет быстрее... |
Fanat |
![]()
Сообщение
#9
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Должны... Но их должна завершить система, а это требует дополнительного времени, будет подвисать при выходе. А если ты напишешь for(int i = num_threads - 1; i >= 0; i--) {
thr[i] -> Terminate();
}
, то дело пойдет быстрее...Понятно...А как отловить нажатие двух кнопок сразу?..хочу добавить движение по диагоналям... А какой компонент лучше использовать для движения?...хочу написать что то вроде Ice hockey, так что это могут быть и TPanel и просто прямоугольник нарисованый... |
volvo |
![]()
Сообщение
#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;
}
}
"... И всего делов..." (С) "И.В. меняет профессию"![]() |
Fanat |
![]()
Сообщение
#11
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
А что значит строчка
__property TDir GetState = {read = FState, nodefault};
Это мы свойства добавляем?..синтаксис не понятен..=( И:
thr[thread_n]->GetState << dir
<< это что значит?.. |
volvo |
![]()
Сообщение
#12
|
Гость ![]() |
Цитата Это мы свойства добавляем? Угу... Именно свойства. А что непонятно? Описываешь свойство (имя и тип), и указываешь что для чтения обращение к свойству аналогично обращению к FState. Поскольку нет write=, то это свойство только для чтения. И не является свойством "по умолчанию".Цитата << это что значит?.. для типа Set перегружены операторы << (через него реализовано добавление элемента в множество) и >> (извлечение элемента из множества, если он там присутствует) |
Fanat |
![]()
Сообщение
#13
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Угу... Именно свойства. А что непонятно? Описываешь свойство (имя и тип), и указываешь что для чтения обращение к свойству аналогично обращению к FState. Поскольку нет write=, то это свойство только для чтения. И не является свойством "по умолчанию". Вроде разобрался...а почему используется свойство?...можно так
TDir GetState() {return FState;};
Через свойство лучше чем то?.. Цитата для типа Set перегружены операторы << (через него реализовано добавление элемента в множество) и >> (извлечение элемента из множества, если он там присутствует) Понял... |
volvo |
![]()
Сообщение
#14
|
Гость ![]() |
Цитата можно так Можно. Только тогда придется делать:TDir GetState() {return FState;};
Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState() >> dir // <--- вызов функции GetState
);
, правда? А не боишься, что у тебя будет постоянно создаваться новая копия множества, и ты потом получишь тормоза при выходе из программы? А при работе с __property ты работаешь с одной и той же переменной... |
Fanat |
![]()
Сообщение
#15
|
![]() Fanat ![]() ![]() ![]() Группа: Пользователи Сообщений: 261 Пол: Мужской Реальное имя: Сергей Репутация: ![]() ![]() ![]() |
Можно. Только тогда придется делать: Handled = thr[thread_n]->SetState(
thr[thread_n]->GetState() >> dir // <--- вызов функции GetState
);
, правда? Ну это понятно... Цитата А не боишься, что у тебя будет постоянно создаваться новая копия множества, и ты потом получишь тормоза при выходе из программы? А при работе с __property ты работаешь с одной и той же переменной... Я так понимаю что они создаються при возвращении значения...но разве эта копия будет существовать до самого выхода из программы?..они не будут удаляться при выходе за '}' ?.. Согласен, что твой вариант работать все равно будет лучше... ![]() |
![]() ![]() |
![]() |
Текстовая версия | 18.07.2025 1:35 |