Буксировка компонентов в Borland C++ Builder

Буксировка компонентов приложения

Буксировку компонентов будем рассматривать на примере перемещения компонентов TImage. Для рассмотрения методов буксировки компонент, достаточно поместить на форму два компонента TImage и создать рисунок приемлемого размера, поместив его в директорию, где создан проект (по умолчанию Projects), например ris.bmp.

В начало

Буксировка компонентов перерисовкой

Создаем новый проект. Определяем глобально:

int  viX0,viY0;
bool fMove;

Помещаем на форму два элемента TImage и готовим в директории Projects рисунок ris.bmp.

В обработчике события OnCreate(два левых клика на форме) пишем код:

void __fastcall 
TForm1::FormCreate(TObject *Sender)
{
 //Создаем изображение и загружаем
 TImage * Pict = new TImage(Form1);
 Pict->AutoSize = true;
 Pict->Picture->LoadFromFile("ris.bmp");
 //Размеры рисунка
 Image1->Width=Pict->Width/2;
 Image2->Width=Image1->Width;
 Image1->Height=Pict->Height;
 Image2->Height=Pict->Height;
 //Копирование из Pict->Canvas в Image1->ClientRect
 //прямоугольника верх/лево/ширина/высота
 Image1->Canvas->CopyRect(Image1->ClientRect, Pict->Canvas,
        Rect(0,0,Pict->Width / 2,Pict->Height));
 Image2->Canvas->CopyRect(Image2->ClientRect, Pict->Canvas,
        Rect(Pict->Width / 2,0,Pict->Width,Pict->Height));
 delete Pict;
}

В каждом TImage сейчас по половинке изображения - будем их перемещать. Для этого для Image1 создадим три обработчика событий мышки: OnMouseDown, OnMoeseMove и OnMouseUp (два клика на соответствующем окошечке в Events инспектора объектов). Для Image2 перенаправим эти события на Image1, для чего в соответствующем окошечке в Events инспектора объектов для Image2 выберем события для Image1. И напишем коды обработчиков.

void __fastcall 
TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 if(Button != mbLeft) return;
 //Запомнить где
 viX0 = X;
 viY0 = Y;
 //Будем тащить
 fMove = true;
 //Переместить на передний план эту половинку
 ((TControl *)Sender)->BringToFront();
}
//              Д В И Г А Е М
void __fastcall
TForm1::Image1MouseMove(TObject *Sender,
           TShiftState Shift,int X, int Y)
{
 if(fMove)
 {
  //Установить новые границы для того на кого нажали
  ((TImage *)Sender)->
  SetBounds(
            ((TImage *)Sender)->Left + X - viX0,
            ((TImage *)Sender)->Top + Y - viY0,
            ((TImage *)Sender)->Width,
            ((TImage *)Sender)->Height);
 }
}

//         О С Т А Н А В Л И В А Е М С Я
void __fastcall
TForm1::Image1MouseUp(TObject *Sender, 
                     TMouseButton Button,
                     TShiftState Shift, int X, int Y)
{
 fMove = false;
}

Теперь при протаскивании курсора по форме при нажатой левой кнопочки мышки над любым изображением половинка изображения начинает двигаться.

Однако сразу виден и недостаток - изображение мелькает при перетаскивании. Для того чтобы исключить этот недостаток можно использовать метод буксировки контура.

В начало

Буксировка компонентов методом перемещения контура

Можно создать новый проект или модифицировать предыдущий, но лучше с нуля. Итак - создаем новый проект.

Определяем глобально:

int   viX0,viY0;
bool  fMove;
TRect tRec; //Здесь будут координаты контура

Помещаем на форму два элемента TImage и готовим в директории Projects любой рисунок в формате .bmp.

В обработчике события OnCreat(два левых клика на форме) пишем код:

//Для создания формы аналог с методом перерисовки
void __fastcall 
TForm1::FormCreate(TObject *Sender)
{
 //Создаем изображение и загружаем
 TImage * Pict = new TImage(Form1);
 Pict->AutoSize = true;
 Pict->Picture->LoadFromFile("ris.bmp");
 //Размеры рисунка
 Image1->Width=Pict->Width/2;
 Image2->Width=Image1->Width;
 Image1->Height=Pict->Height;
 Image2->Height=Pict->Height;
 //Копирование из Pict->Canvas в Image1->ClientRect
 //прямоугольника верх/лево/ширина/высота
 Image1->Canvas->CopyRect(Image1->ClientRect, Pict->Canvas,
                  Rect(0,0,Pict->Width / 2,Pict->Height));
 Image2->Canvas->CopyRect(Image2->ClientRect, Pict->Canvas,
        Rect(Pict->Width / 2,0,Pict->Width,Pict->Height));
 delete Pict;
}

В каждом TImage сейчас по половинке изображения - будем их соединять. Для этого для Image1 создадим три обработчика собы- тий мышки OnMouseDown, OnMoeseMove и OnMouseUp (два клика на соответствующем окошечке в Events инспектора объектов). Для Image2 перенаправим эти события на Image1, для чего в соответствующем окошечке в Events инспектора объектов для Image2 выберем события для Image1. И напишем коды обработчиков.

//Для нажатия аналог с методом перерисовки кроме одной строчки
//tRec = ((TControl *)Sender)->BoundsRect;
void __fastcall 
TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 if(Button != mbLeft) return;
 //Запомнить где
 viX0 = X;
 viY0 = Y;
 //Будем тащить
 fMove = true;
 //Запоминаем границы
 tRec = ((TControl *)Sender)->BoundsRect;
 //Переместить на передний план эту половинку
 ((TControl *)Sender)->BringToFront();
}
// Д В И Г А Е М,  НО НЕ ИЗОБРАЖЕНИЕ, А 
// ТОЛЬКО КОНТУР ИЗОБРАЖЕНИЯ
void __fastcall
TForm1::Image1MouseMove(TObject *Sender,
           TShiftState Shift,int X, int Y)
{
 //Установить новые границы для контура
 if(fMove)
 {
  Canvas->DrawFocusRect(tRec);
  tRec.left += X - viX0;
  tRec.right += X - viX0;
  tRec.top += Y - viY0;
  tRec.bottom += Y - viY0;
  viX0 = X;
  viY0 = Y;
  Canvas->DrawFocusRect(tRec);
 } 
}

//         О С Т А Н А В Л И В А Е М С Я
void __fastcall
TForm1::Image1MouseUp(TObject *Sender, 
                     TMouseButton Button,
                     TShiftState Shift, int X, int Y)
{
 if(!fMove) return;
 //Стирание последнего изображения контура методом OR
 Canvas->DrawFocusRect(tRec);
 //Если не передумали (не нажали Alt)
 if(!Shift.Contains(ssAlt))
 {
  //Рисуем
  ((TControl *)Sender)->
   SetBounds(
             tRec.Left + X - viX0, 
             tRec.Top + Y - viY0,
             ((TControl *)Sender)->Width,
             ((TControl *)Sender)->Height
            );
  ((TControl *)Sender)->BringToFront();
 }
 fMove = false;
}

Все хорощо, и изображение не мелькает при перетаскивании, но много кода. Чтобы было меньше - можно использовать метод буксировки с использованием встроенных механизмов Drag&Dock.

В начало

Буксировка компонентов методом DRAG&DOCK

Как и в предыдущем параграфе можно создать новый проект или модифицировать предыдущий, но лучше опять начнем с нуля. Итак - создаем новый проект.

Помещаем на форму два элемента TImage и готовим в директории Projects любой рисунок в формате .bmp.

Для формы устанавливаем свойство DockSite=true; - в рузудьтате форма стала контейнером, способным принимать переносимые в этот контейнер компоненты. Свойство Use Dock Manager=false иначе приемом компонент будет управлять диспетчер, а он перетаскиваемому компоненту будет выделять пол окна.

Для Image1 и Image2 устанавливаем свойства DragKind=dkDoc; и DragMode=dmAutomatik;

В обработчике события OnCreat (два левых клика на форме) пишем код в котором функция ManualFloat переводит компонент в режим плавающего окна, а ManualDock размещает компонент в указанном приемнике.

void __fastcall 
TForm1::FormCreate(TObject *Sender)
{
 //Создаем изображение и загружаем
 TImage * Pict = new TImage(Form1);
 Pict->AutoSize = true;
 Pict->Picture->LoadFromFile("ris.bmp");
 //Размеры рисунка
 Image1->Width=Pict->Width/2;
 Image2->Width=Image1->Width;
 Image1->Height=Pict->Height;
 Image2->Height=Pict->Height;
 //Копирование из Pict->Canvas в Image1->ClientRect
 //прямоугольника верх/лево/ширина/высота
 Image1->Canvas->CopyRect(Image1->ClientRect, Pict->Canvas,
                  Rect(0,0,Pict->Width / 2,Pict->Height));
 Image2->Canvas->CopyRect(Image2->ClientRect, Pict->Canvas,
        Rect(Pict->Width / 2,0,Pict->Width,Pict->Height));
 delete Pict;
 Image1->ManualFloat(Rect(
                          Form1->Left+Image1->Left,
                          Form1->Top+Image1->Top,
                          Form1->Left+Image1->Left+Image1->Width,
                          Form1->Top+Image1->Top+Image1->Height
                         )
                     );
 Image1->ManualDock(Form1,NULL,alLeft);
 Image2->ManualFloat(Rect(
                          Form1->Left+Image2->Left,
                          Form1->Top+Image2->Top,
                          Form1->Left+Image2->Left+Image2->Width,
                          Form1->Top+Image2->Top+Image2->Height
                         )
                     );
 Image2->ManualDock(Form1,NULL,alLeft);
}

Компоненты хорошо двигаются и не мельтешат при перетаскивании.

В начало

Буксировка компонентов простым методом

Рассмотрим код:

void __fastcall 
TForm1::Button1MouseMove(TObject *Sender,
         TShiftState Shift, int X, int Y)
{
 const int SC_DRAGMOVE=61458;//0xF012;
 ReleaseCapture();
 ((TControl *)Sender)->Perform(WM_SYSCOMMAND,SC_DRAGMOVE,0);
}

Здесь освобождается курсор мыши и методом Perform посылается источнику события сообщение о буксировке. Таким образом можно таскать многие элементы - в том числе и саму форму за любой элемент - достаточно создать для них обработчик события OnMouseMove с данным кодом.

В начало

На главную подраздела о буксировке

Домой


Сайт управляется системой uCoz