Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.91/22: Рейтинг темы: голосов - 22, средняя оценка - 4.91
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
1

Перемещение объектов по форме

09.07.2015, 15:11. Просмотров 4510. Ответов 17
Метки нет (Все метки)

Доброго времени суток! Подскажите, как реализовать такую задачку:

На форме расположены разные объекты, необходимо в реал тайме иметь возможность передвигать эти объекты мышкой. При этом, должна быть отдельная кнопка, которая будет отвечать за активацию режима редактирования положения объектов.
В режиме редактирования, объекты должны быть как бы заморожены (например Enabled=true).
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.07.2015, 15:11
Ответы с готовыми решениями:

Перемещение объектов на форме мышкой
Здравствуйте. Возникла необходимость перемещать, уже в запущенной программе, объекты...

Перемещение динамических объектов
Есть класс, который наследуется от TImage Сделал ему два обработчика, для того чтобы мог...

перемещение кнопки по форме
Доброго времени суток всем!!!1 обращаюсь к вам за помощью как новичёк=) такая задача - нужно...

Перемещение меток по форме
Builder 6 C++ Необходимо чтобы 1 и 0 ВМЕСТЕ двигались. т.е. они двигаются, но надо сделать так,...

17
1386 / 1071 / 206
Регистрация: 22.03.2015
Сообщений: 6,399
Записей в блоге: 3
09.07.2015, 16:25 2
Drug`n`Drop ? или какое-то другое управление? например активируете мышой, а передвигаете стрелками ?
0
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
09.07.2015, 18:28  [ТС] 3
Почтальон, особо не имеет значения, а какой вариант проще?
0
случайный прохожий
1491 / 972 / 372
Регистрация: 20.07.2013
Сообщений: 2,848
09.07.2015, 20:49 4
Вариант для одного Shape: помести на форму Shape и CheckBox; нажимаем левой кнопкой мыши на объекте Shape и двигаем мышь, объект тоже двигается за курсором, пока кнопка нажата.
Если CheckBox не отмечен, то движения не будет.

cpp:
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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
int x, y;
 
void __fastcall TForm1::Shape1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y)
{
  if (CheckBox1->Checked && Button == mbLeft)
  {
    Tag = 1;
    x = X;
    y = Y;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Shape1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y)
{
  Tag = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Shape1MouseMove(TObject *Sender, TShiftState Shift, int X,
          int Y)
{
  if (Tag)
  {
    Shape1->Left += X - x;
    Shape1->Top += Y - y;
  }
}
//---------------------------------------------------------------------------
h:
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
//---------------------------------------------------------------------------
 
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TShape *Shape1;
    TCheckBox *CheckBox1;
    void __fastcall Shape1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y);
    void __fastcall Shape1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y);
    void __fastcall Shape1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y);
 
private:    // User declarations
public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Если должны двигаться несколько Shape, то нужно при совпадении имени (класса) объекта с искомым (Shape, TShape) двигать объект. Каждому Shape назначить один общий обработчик для нажатия, движения и отпускания кнопки.
Плюс учесть случай возможного пересечения объектов.
Если несколько различного типа объектов надо двигать, то тут сложнее.
1
Миниатюры
Перемещение объектов по форме  
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
10.07.2015, 07:54  [ТС] 5
gunslinger, по отдельности двигать какой то объект не сложно) Примеров находил много ... нужно именно разные объекты двигать. НАпример на форме лежат кнопки, панели, image и пр.. Когда заходим в режим редактирования, все объекты как бы заблокированы (чтобы OnClick не работал и т.п.), при клике на объект, нужно иметь возможность изменять его свойства Left и Top.
0
52 / 52 / 30
Регистрация: 24.02.2014
Сообщений: 220
10.07.2015, 08:08 6
В Delphi есть компоненты ...Disain...
Например, http://www.lmdinnovative.com/p... esignpack/
Можно даже менять размеры
Я в одном из проектов использовал - очень удобно
1
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
10.07.2015, 08:40  [ТС] 7
vaberg, Весь смысл в том, чтобы не использовать сторонние компоненты ) Но за ссылочку спасибо )
0
52 / 52 / 30
Регистрация: 24.02.2014
Сообщений: 220
10.07.2015, 10:46 8
Вариант, когда перетакивание разрешено и на форме три кнопки к1, к2, к3:
Создайте некий контейнер для хранения компонентов
Например, удерживаете клавишу Ctrl щелкаете по к1
проверяете есть ли в контейнере "к1"
если нет - добавляете
если есть - удаляете.
Заносите в него эти три кнопки.
потом мышкой перемещаете любую кнопку и в той же процедуре проверяете содержимое контейнера и перемещаете все элементы, находящиеся в нем.
Клик мышки по любому другому компоненту на форме - очищает контейнер.
0
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
10.07.2015, 12:14  [ТС] 9
Появилась такая идея:
По скольку я заранее знаю, какие объекты может потребоваться перемещать, можно их имена записать например в ListBox или StringGrid, сделать отдельно 4 кнопки со стрелками, задать для них обработчик, в котором будет изменяться то или иное свойство для объекта имя которого выбрано в ListBox.

Перемещение объектов по форме
0
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
10.07.2015, 13:08  [ТС] 10
Вопрос! Как описать переменную, которая могла бы принимать свойства от любого компонента ?

Например:

C++
1
2
3
4
[Какой то тип] NameJbj;
 
NameObj->Left = 10;
NameObj->Top = 10;
Возможно ли это ?
0
1386 / 1071 / 206
Регистрация: 22.03.2015
Сообщений: 6,399
Записей в блоге: 3
10.07.2015, 14:02 11
А тип этой переменной каким должен быть ?
0
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
10.07.2015, 14:11  [ТС] 12
Почтальон, дак в этом и вопрос)) Я не уверен, что это возможно даже ...
0
1386 / 1071 / 206
Регистрация: 22.03.2015
Сообщений: 6,399
Записей в блоге: 3
10.07.2015, 14:16 13
Ну тут видимо придется однозначно писать свой класс.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
29948 / 19691 / 7699
Регистрация: 22.10.2011
Сообщений: 34,328
Записей в блоге: 6
10.07.2015, 16:21 14
Не надо ничего писать. Left и Top - свойства, описанные в классе TControl, достаточно сделать
C++
1
2
3
4
TControl *NameObj; // присвоить сюда указатель на нужный компонент, и...
 
NameObj->Left = 10;
NameObj->Top = 10;
1
Техник
314 / 172 / 25
Регистрация: 09.10.2009
Сообщений: 3,095
14.07.2015, 15:09  [ТС] 15
volvo, Я так и хотел сделать, но проблема в том, что не совсем ясно, как переменной NameObj присвоить имя выбранное в StringGrind например.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
29948 / 19691 / 7699
Регистрация: 22.10.2011
Сообщений: 34,328
Записей в блоге: 6
14.07.2015, 15:15 16
C++
1
2
3
4
5
    String s = "Button1"; // сюда занесешь строковое значение из грида
 
    TControl *NameObj = static_cast<TControl*>(FindComponent(s));
    NameObj->Left = 10;
    NameObj->Top = 10;
0
Почетный модератор
Эксперт С++
5836 / 2842 / 390
Регистрация: 01.11.2011
Сообщений: 6,881
15.07.2015, 12:13 17
Давно хотел написать такую хрень.

На форме только таймер один.
.h

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
//---------------------------------------------------------------------------
 
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TTimer *Timer1;
        void __fastcall Timer1Timer(TObject *Sender);
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
 
        void __fastcall BtnMouseMove( TObject *Sender, TShiftState Shift, int X, int Y );
private:    // User declarations
       int CountPanel;
       TPanel **Panels;
 
       TCheckBox *CBFinish;
       TButton *Btn;
public:     // User declarations
        __fastcall TForm1(TComponent* Owner);
 
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

.cpp

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
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
this->DoubleBuffered = false;
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Timer1->Tag = 500;       // Время
Timer1->Interval = 100;
 
randomize();
int SizePanelCoef = 10;
CountPanel = 100;
 
                                                                 ////////
CBFinish = new TCheckBox( this );                                      //
CBFinish->Parent = this;
CBFinish->Width = CBFinish->Height;
CBFinish->Caption = "";
CBFinish->Checked = false;
 
CBFinish->Left = this->Width/2 + this->Width/CountPanel  * random( CountPanel/2 ); // В правой
CBFinish->Top  = this->Height/2 + this->Height/CountPanel * random( CountPanel/2 ); //  половине экрана
                                                                       //
                                                                 ////////
                                                                 ////////
Btn = new TButton( this );                                             //
Btn->Parent = this;
Btn->Width  = 30;
Btn->Height = 20;
Btn->Caption = "8-@";
 
Btn->OnMouseMove = BtnMouseMove;
 
 
Btn->Left = random( this->Width/2  ); // В левой
Btn->Top  = random( this->Height/2 ); //  половине экрана              //
                                                                 ////////
                                                                 ////////
                                                                       //
Panels = new TPanel*[CountPanel];
for( int i=0; i<CountPanel; i++ )
  {
  Panels[i] = new TPanel( this );
  Panels[i]->Parent = this;
  Panels[i]->Caption = "";
 
  while( true )
    {
/*    Panels[i]->Width  = SizePanelCoef * this->Width  / ( CountPanel/SizePanelCoef + random( CountPanel ) );
    Panels[i]->Height = SizePanelCoef * this->Height / ( CountPanel/SizePanelCoef + random( CountPanel ) );
    Panels[i]->Left = this->Width/CountPanel  * random( CountPanel ) - Panels[i]->Width  + SizePanelCoef;
    Panels[i]->Top  = this->Height/CountPanel * random( CountPanel ) - Panels[i]->Height * 1 + SizePanelCoef;
*/
/*    Panels[i]->Width  = random( this->Width/SizePanelCoef );//CountPanel;
    Panels[i]->Height = random( this->Height/SizePanelCoef );//CountPanel;
    Panels[i]->Left = random( this->Width - Panels[i]->Width*2 );
    Panels[i]->Top  = random( this->Height - Panels[i]->Height*2 );
*/
    Panels[i]->Width  = SizePanelCoef * random( this->Width/CountPanel );  // Вариантов засеивания поля панелями дофига
    Panels[i]->Height = SizePanelCoef * random( this->Height/CountPanel );
    Panels[i]->Left = random( this->Width - Panels[i]->Width*2 );
    Panels[i]->Top  = random( this->Height - Panels[i]->Height*2 );
    if( !(
        ( Btn->Left <= Panels[i]->Left+Panels[i]->Width &&
          Btn->Left+Btn->Width >= Panels[i]->Left )
        ||
        ( CBFinish->Left <= Panels[i]->Left+Panels[i]->Width &&
          CBFinish->Left+CBFinish->Width >= Panels[i]->Left )
        )
      )
      break;
 
    }
  }                                                                    //
                                                                 ////////
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
delete []Panels;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
static const int StepPx = 5;
static int Sign = -1;
static int Counter = 0;
 
if( !( Counter++ % 5 ) )
  Sign *= -1;
 
Timer1->Tag-=10;
this->Caption = Timer1->Tag;
 
if( Btn->Left <= CBFinish->Left &&                    // Если окажется внутри кнопки
    Btn->Top  <= CBFinish->Top  &&
    Btn->Left+Btn->Width >= CBFinish->Left+CBFinish->Width &&
    Btn->Top+Btn->Height >= CBFinish->Top+CBFinish->Height )
  {
  Timer1->Enabled = false;
  CBFinish->Checked = true;
  Application->MessageBoxA( "You wings", "Error", MB_OK );
  }
 
if( Timer1->Tag == 0 )
  {
  Timer1->Enabled = false;
  Application->MessageBoxA( "You lays", "Correct" );
  }
 
bool MayISwell = true;
for( int i=0; i<CountPanel; i++ )
  {
  if( (
        ( Btn->Top <= Panels[i]->Top+Panels[i]->Height &&
          Btn->Top+Btn->Height >= Panels[i]->Top )
        &&
        (
        ( Btn->Left+Btn->Width >= Panels[i]->Left  &&
          Btn->Left+Btn->Width <= Panels[i]->Left+Panels[i]->Width )
 
        ||
        ( Btn->Left >= Panels[i]->Left  &&
          Btn->Left <= Panels[i]->Left+Panels[i]->Width )
        )
      )
    &&
      ( ( Btn->Left <= Panels[i]->Left+Panels[i]->Width &&
          Btn->Left+Btn->Width >= Panels[i]->Left )
        &&
        (
        ( Btn->Top+Btn->Height >= Panels[i]->Top &&
          Btn->Top+Btn->Height <= Panels[i]->Top+Panels[i]->Height )
        ||
        ( Btn->Top >= Panels[i]->Top &&
          Btn->Top <= Panels[i]->Top+Panels[i]->Height )
        )
      )
    )
    {
    MayISwell = false;
    break;
    }
  }
if( MayISwell )
  {
  Btn->Width  += Sign * StepPx;
  Btn->Height += Sign * StepPx;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnMouseMove( TObject *Sender, TShiftState Shift, int X, int Y )
{
static TRect BtnRect, PanelRect;
 
#define ROUNDBORD -0 // Зазор
if( Shift.Contains( ssLeft ) )
  {
  BtnRect.Left   = Btn->Left + X + 1; // Единичка чтоб
  BtnRect.Top    = Btn->Top  + Y + 1; //  скрыть рамочку
  BtnRect.Right  = Btn->Left + X + Btn->Width;
  BtnRect.Bottom = Btn->Top  + Y + Btn->Height;
 
  for( int i=0; i<CountPanel; ++i ) // Пересеклось ли
    {
    PanelRect.Left   = Panels[i]->Left;
    PanelRect.Top    = Panels[i]->Top;
    PanelRect.Right  = Panels[i]->Left + Panels[i]->Width;
    PanelRect.Bottom = Panels[i]->Top  + Panels[i]->Height;
 
    if( ( BtnRect.Top <= PanelRect.Bottom &&
          BtnRect.Bottom >= PanelRect.Top )
        &&
        (
        ( BtnRect.Right + ROUNDBORD >= PanelRect.Left  &&
          BtnRect.Right + ROUNDBORD <= PanelRect.Right )
 
        ||
        ( BtnRect.Left - ROUNDBORD >= PanelRect.Left  &&
          BtnRect.Left - ROUNDBORD <= PanelRect.Right )
        )
        ||
        ( BtnRect.Left - ROUNDBORD <= 0 ||
          BtnRect.Right + ROUNDBORD >= this->Width )
      )
      X = 0;
    if( ( BtnRect.Left <= PanelRect.Right &&
          BtnRect.Right >= PanelRect.Left )
        &&
        (
        ( BtnRect.Bottom + ROUNDBORD >= PanelRect.Top &&
          BtnRect.Bottom + ROUNDBORD <= PanelRect.Bottom )
        ||
        ( BtnRect.Top - ROUNDBORD >= PanelRect.Top &&
          BtnRect.Top - ROUNDBORD <= PanelRect.Bottom )
        )
        ||
        ( BtnRect.Top - ROUNDBORD <= 0 ||
          BtnRect.Bottom + ROUNDBORD + 30 >= this->Height )
      )
      Y = 0;
    }
 
  Btn->Left += X;
  Btn->Top  += Y;
 
  Mouse->CursorPos = ClientToScreen( TPoint( Btn->Left, Btn->Top ) );
  //Sleep( 20 );
 
    SendMessage( Btn->Handle, WM_LBUTTONUP, 0, 0 ); // Чтобы при перемещении пульсировала
    Sleep( 10 );
    Application->ProcessMessages(); // Фарш
    SendMessage( Btn->Handle, WM_LBUTTONDOWN, 0, 0 );
 
  this->Update();
  }
}
//---------------------------------------------------------------------------

Что надо делать - догадайтесь.

P.S. Все на коленке и работает очень худо.
0
Миниатюры
Перемещение объектов по форме  
4029 / 2319 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
18.07.2015, 22:52 18
SatanaXIII, есть пять секунд дотащить вырывающуюся кнопку до чека, прыгая по панелям. И ни фига я не запускал код, а предпочел сломать голову об эти монументально неочевидные if'ы.

Не по теме:

Где-то у меня завалялась злая программка-приколюха, дергающая мышь рандомно во времени и интенсивности. Позволила мне убедить более одного товарища, что мыши его пришел каюк... ну, шутки ради, естессно.))



A little bit of a pickle though.
smth->Left + smth->Width is better looking as smth->BoundsRect.Right. Same goes for smth->BoundsRect.Bottom. Easier to read anyway.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.07.2015, 22:52

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Медленное перемещение image по форме
Добрый день всем! Подскажите как програмно задать медленное перемещение image по форме. Поиск...

Перемещение множества Image по форме
пишу игру шашки. все шашки бросаю на компоненты image. Для перемещения Image нужно прописывать...

Перемещение объекта по форме по таймеру
Как сделать визуализацию? Чтобы допустим перемещался какой-то элемент на форме по времени.

Рандомное перемещение объектов по форме
Имеется форма, на ней, скажем, 6 зарезервированных областей координатной плоскости (кстати,как...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

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