![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перенос и отлов панели. [D7]
RUNaum © (2006-05-13 21:59:00)Тривиальная задача стоит. Необходимо мышкой перетащить панель и во время переноса отлавливать ее новые координаты.
С первой частью задачи справился без проблем с помощью кода, который приводится во всех без исключения FAQ'ах:
procedure TForm1.pnZoomMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
const
SC_DragMove = $F012;
begin
ReleaseCapture;
pnZoom.Perform(WM_SysCommand, SC_DragMove, 0);
end;
Но тут встает проблема. Отловить позицию панели я могу лишь в MouseDown'e, до передачи WM_SysCommand. Когда компонент находится в "режиме" переноса я не могу контролировать OnMouseMove :( Посоветуйте, как лучше поступить.
p.s. может и стоит забыть про такой способ drag'a панели...
RUNaum (2006-05-17 16:30:00) [1]большое спасибо ) вроде все как надо ))
REA (2006-05-17 11:00:00) [2]И еще так попробуй:
Procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
Begin
If MouseCapture And (Ofs.X > 0) Then
Begin
SetWindowPos(Panel1.Handle, 0, X - Ofs.X, Y - Ofs.Y, 0, 0,
SWP_NOZORDER Or SWP_NOSENDCHANGING Or SWP_NOSIZE);
End;
End;
Procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
If (Ofs.X > 0) Then
Begin
Ofs.X := -1;
SetWindowPos(Panel1.Handle, 0, X - Ofs.X, Y - Ofs.Y, 0, 0,
SWP_NOZORDER Or SWP_NOSIZE);
End;
End;
REA (2006-05-17 10:31:00) [3]Способ с SC_DRAGMOVE использует функцию windows по перетаскиванию окон. Вероятно при этом отрисовка блокируется средствами Windows, но константа не определена (Magic Number), поэтому есть некоторая вероятность, что в следующих версиях windows это не сработает.
Попробуй поставить Panel1.DoubleBuffered := True;
RUNaum (2006-05-16 17:18:00) [4]В догонку вопрос, который меня всегда волновал.
Если рассматривать вариант с
const
SC_DragMove = $F012;
begin
ReleaseCapture;
pnZoom.Perform(WM_SysCommand, SC_DragMove, 0);
то перерисовка контента панели НЕ заметна глазом )
если мы указываем же ее Left/Top то перерисовка контента заметна. Как при мануальном изменении позиции панели избавиться от этой "ненужной" перерисовки?
RUNaum (2006-05-16 17:02:00) [5]REA (15.05.06 14:42) [11]
Прошу прощение, не заметил поста. Огромное спасибо, именно то что нужно - все работает. C MouseCapture разобрался )
REA (2006-05-16 10:23:00) [6]Ну а мой то работает? Принцип то же что и у Мефисто, но немного короче.
RUNaum (2006-05-16 04:38:00) [7]Мефисто (15.05.06 18:20) [12]
вся проблема в том, что данный пример не работает =) обратите внимание, что что-то в нем точно не так ) первая часть (до обработки панели) примера по сути привязана к форме и срабатывает довольно "забавно", когда начинаешь drag самой формы ) понятное дело что никак иначе она сработать то и не может.
а вариант с панелью работает как и должен. либо в приведенном примере опечатка и вы гдя-то перепутали панель с формой, а я не допонял вашу задумку и не смог найти опечатку (а заниматься комбинаторикой как то грустно =).
Мефисто (2006-05-15 18:20:00) [8]RUNaum © (15.05.06 12:53) [8]
Здрастье приехали :)
>> т .к. приведенные вами задумки вместе просто не совместимы и не имеют смысла.
Можно потробней?
>> я так понимаю, вы привели два разных варианта =) первый "ручной" таксть ) второй "панельный".
Вообще-то все один пример (один вариант).
>> отличное решение, но как отлавливать координаты?
Координаты и отлавливаются в событии формы.
REA (2006-05-15 14:42:00) [9]Как нибудь так:
Procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
MouseCapture := True;
Ofs := Point(X, Y);
End;
Procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
Begin
If MouseCapture And (Ofs.X > 0) Then
Begin
Panel1.Top := Y - Ofs.Y;
Panel1.Left := X - Ofs.X;
End;
End;
Procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
Ofs.X := -1;
End;
RUNaum (2006-05-15 13:19:00) [10]Ааа! Я понял, мне че-то в голову стукнуло что это ReadOnly. ясно. но сути дела не меняет.
Мастера, помогите. Задача простая в доску, я уже двое суток не могу допереть =(
REA (2006-05-15 13:11:00) [11]Это почему же? Очень даже и наоборот. ReleaseCapture и SetCapture можно делать через это свойство.
RUNaum (2006-05-15 12:53:00) [12]Мефисто (14.05.06 21:54) [6]
я так понимаю, вы привели два разных варианта =) первый "ручной" таксть ) второй "панельный". т.к. приведенные вами задумки вместе просто не совместимы и не имеют смысла.
const
SC_DragMove = $F012;
begin
ReleaseCapture;
TWinControl(Sender).Perform(WM_SysCommand, SC_DragMove, 0);
end;
отличное решение, но как отлавливать координаты? в этом режиме я никак не могу ( ни событиями формы, ни событиями панели. уже мысли дуратские о таймере закрадываются, но это ужасно и убого.
REA (15.05.06 10:37) [7]
не понял. MouseCapture - лишь сигнализирует нам о том, что компонент был захвачен мышью, не более. как это может помочь?
REA (2006-05-15 10:37:00) [13]SetCapture - см. MouseCapture
Мефисто (2006-05-14 21:54:00) [14]>> RUNaum © (14.05.06 20:32) [5]
Тогда так :)
У формы:
public
{ Public declarations }
FDrag: Boolean;
FX, FY: Integer;
end;
TForm.OnMouseUp:
begin
if FDrag then
begin
TWinControl(Sender).Left := FX;
TWinControl(Sender).Top := FY;
ReleaseCapture;
FDrag := False;
end;
end;
TForm.OnMouseMove:
begin
if FDrag then
begin
TWinControl(Sender).Left := X - FX;
TWinControl(Sender).Top := Y - FY;
end;
end;
TForm.OnMouseDown:
begin
FDrag := True;
FX := X;
FY := Y;
SetCapture(TWinControl(Sender).Handle);
end;
В событии панели:
TPanel.OnMouseDown:
const
SC_DragMove = $F012;
begin
ReleaseCapture;
TWinControl(Sender).Perform(WM_SysCommand, SC_DragMove, 0);
end;
RUNaum (2006-05-14 20:32:00) [15]Задача стоит, как я уже говорил, тривиальная. Необходимо на форме мышью "плавно" позиционировать панель, постоянно обрабатывая ее текущие координаты.
RUNaum (2006-05-14 20:30:00) [16]Я возможно не совсем корректно понял как работать с D'n'D :)
Но без указания новых координат панели при драге не выйдет ее видимого перемещения.
Если указать:
procedure TMainForm.FormDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Source=Panel1 then
Accept:=True;
end;
то панель не сдвинется с места, не смотря на то что драг "как бы работает".
Мефисто (2006-05-14 18:31:00) [17]Непонимаю, нафиг ты панельке позицию назначаешь при перетаскивании? Какой в этом умысел? Опиши задачу в целом...
RUNaum (2006-05-14 12:59:00) [18]Огромное спасибо )
Есть маленький нюанс.
object Panel1: TPanel
Left = 216
Top = 200
Width = 73
Height = 81
Caption = 'Panel1'
DragMode = dmAutomatic
TabOrder = 3
OnEndDrag = Panel1EndDrag
OnStartDrag = Panel1StartDrag
end
procedure TMainForm.FormDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Source=Panel1 then
begin
Panel1.Left:=X;
Panel1.Top:=Y;
end;
end;
Вот при таком раскладе, Drag'n'drop выполняется как надо, но с некоторой периодичностью панель "застряет" на форме, т.е. движение панели перестает быть плавным и она дергается. С чем это может быть связано?
Мефисто (2006-05-13 22:27:00) [19]DockSite
DragMode
DragKind
UseDockManager
OnDrag... & Ko
OnDock... & Ko
\D7\Demos\Docking