Шаг 16 - Функции Windows [MoveWindow, GetWindowRect]

Я всегда думаю, что вместо подробных объяснений лучше привести пример и потом откомментировать его.

Как пример использования функций можно привести программку, управляющую кнопкой Пуск. Ее форма:

gif/16_1.gif (3142 b)

А вот код:

void* StartHandle=NULL;
TRect WinRect;
int left=0,width=0,height=0,top=0;
bool mousedown=false;
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MoveWindow(StartHandle,CSpinEdit1->Value,
          CSpinEdit2->Value,width,height,true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Timer1->Enabled=!Timer1->Enabled;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
if(Timer2->Enabled)Timer2->Enabled=false;
else Timer2->Enabled=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if (left>Screen->Width) {left=1;return;};
left+=5;
MoveWindow(StartHandle,left,8,width,height,true);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer2Timer(TObject *Sender)
{
GetWindowRect(StartHandle,&WinRect);
if ((Mouse->CursorPos.x>WinRect.left)
                &&
    (Mouse->CursorPos.x<WinRect.right)
                &&
    (Mouse->CursorPos.y>WinRect.top)
                &&
    (Mouse->CursorPos.y<WinRect.bottom))
  {
   left+=10;
   if(left>Screen->Width-5) left=0;
   MoveWindow(StartHandle,left,8,width,height,true);
  };
}
//-----Следующие три обработчика позволяют определить дескриптор Пуска
void __fastcall TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
mousedown=true;
SetCaptureControl(Image1);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
if(mousedown)
        ::SetCursor(LoadCursorFromFile("cursor.cur"));
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
StartHandle=WindowFromPoint(Mouse->CursorPos);
SendMessage(StartHandle,WM_SETFOCUS,0,0);
::SetCursor(LoadCursor(HInstance,IDC_ARROW));
mousedown=false;
ReleaseCapture();
GetWindowRect(StartHandle,&WinRect);
width=WinRect.Width();
height=WinRect.Height();
Button1->Enabled=true;
Button2->Enabled=true;
Button3->Enabled=true;
}
//---------------------------------------------------------------------------

Из новых компонентов на форме использован TTimer gif/16_2.gif (126 b) с палитры System. Обработчик события OnTimer() вызывается каждые Interval миллисекунд. В листинге обработчики представлены как Timer1Timer и Timer2Timer. Таймер можно отключить свойством Enabled.

Непонятный момент здесь только один - откуда я взял StartHandle? Во время работы программы пользователь перетаскивает инструмент на кнопку Пуск. Функция WindowFromPoint позволяет достать дескриптор окна по точке. Чтобы инструмент, изображенный на форме компонентом TImage, мог получать все "мышиные" сообщения, используется функция SetCaptureControl. Потом нужно применять ReleaseCapture(), для освобождения захвата.

Для разнообразия во время перетаскивания инструмента курсор меняется на нарисованный мной. Если Вам это не надо, вычеркните.

А так - функция GetWindowRect возвращает по дескриптору структуру TRect окна, содержащую его координаты и размеры. Функция MoveWindow перемещает соответствующее окно. Последний параметр отвечает за перерисовку. Общая логика кнопки "Побегаем" такова - по таймеру вызывается обработчик, передвигающий кнопку. Если кнопка выходит за пределы окна, то кнопка выходит с другого края. Логика "Поймай" - опять-таки по интервалу вызывается обработчик, который проверяет, находится ли курсор над кнопкой и при необходимости сдвигающий ее. Я думаю, объяснять "Передвинуть" уже не надо ;).


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Аванесов Самвел.