Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.12.2008, 18:01   #1
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию Перемещение через сообщение

Здраствуйте глубоко уважаемые жильци форума. Перейду сразу к делу.
Имею на форме объект допустим Panel1.
есть задача перемещать ее по форме но необходимо организовать привязку к сетке.
В идеальном варианте хотелось бы получить примерно тоже самое что в самой системе Delphi когда создаются объекты на форме.
Пользуюсь процедурой Perform отправляя сообщение объекту таким образом
panel1.Perform(WM_SYSCOMMAND, $F012 ,0);
Дык вот как всетаки сделать привязку к сетке? Может есть какоенибудь другое хорошее решение?
devi409 вне форума Ответить с цитированием
Старый 17.12.2008, 18:07   #2
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

В обработчике сообщения этой панели выранивай полученные координаты и приближай их к ближайшему узлу сетки. Если не хочешь писать класс потомок TPanel, то перед передачей координат выравнивай их.
rpy3uH вне форума Ответить с цитированием
Старый 17.12.2008, 18:10   #3
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию

Извените, а поподробней можно? как вызвать обработчик сообщений... вернее в каком месте и как?
devi409 вне форума Ответить с цитированием
Старый 17.12.2008, 18:53   #4
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

panel1.Perform(...); - это и есть вызов обработчика сообщений.
в каком имеено именно месте ты передаёшь сообщение чтобы твоя панелька переместилась? давай сюда код

Последний раз редактировалось rpy3uH; 17.12.2008 в 18:56.
rpy3uH вне форума Ответить с цитированием
Старый 17.12.2008, 21:55   #5
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию

да код обычный
Код:
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
panel1.Perform(WM_SYSCOMMAND, $F012 ,0);
end;
При нажатии на панель тут же посылается сообщение на перемещение.
При желании можно использовать событие OnClick
Проблема в том как это сообщение отловить отредактировать и обратно послать.

Еще возможно вы меня не поняли. Необходимо привязать к сетке не после перетаскивания а во время перетаскивания.

Последний раз редактировалось rpy3uH; 18.12.2008 в 08:54.
devi409 вне форума Ответить с цитированием
Старый 18.12.2008, 08:58   #6
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

во-первых, посмотри описание сообщения
http://msdn.microsoft.com/en-us/libr...60(VS.85).aspx
и указывай в параметре WParam одну из констант, которые там указаны.

во-вторых, для перемещения контролов используй функцию SetWindowPos

в-третьих, зачем извращаться через API функции когда у конпонента есть свойства Top, Left, Width, Height ?

Последний раз редактировалось rpy3uH; 18.12.2008 в 09:01.
rpy3uH вне форума Ответить с цитированием
Старый 18.12.2008, 16:39   #7
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию

и так. начну все с начала
я делаю редактор объектов. объекты создаются удаляются перемещаются и изменяются в размерах. по полной аналогии как в среде разработки delphi мы вытаскиваем объекты и располагаем на форме. Создавать удалять перемещать и изменять размер я умею. Остается только наложить сетку. чтобы перемещение и изменение размера проходило скачкообразно. Процедура выравнивания по сетке должна выравнивать объекты не после того как перемести а во время перемещения объекта. Основной алгоритм таков.
1. Нажимаю на объект OnMouseDown
2. Перетаскиваю объет OnMouseMove
2.1 Выравниваю объект по сетке
3. Отпускаю кнопку мыши OnMouseUp

Вот впринципе и все.
Можно все это делать с помощью "Top, Left, Width, Height" Но придется обрабатывать три события OnMouseDown, OnMouseMove, OnMouseUp. Вводить дополнительные переменные типа Draw:boolean - перетаскивание активно X,Y:integer - координаты начала передвижения. получится что то типа этого:

Код:
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Draw := true;
Per.X := x;
Per.Y := Y;
end;

procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
if Draw then
  begin
    panel1.Left := Setka(panel1.Left - (Per.x - x));
    panel1.Top := Setka(panel1.Top - (Per.y - y));
  end; 
end;

procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if Draw then
  begin
    Draw := false;
      panel1.Left := Setka(panel1.Left - (Per.x - x));
      panel1.Top := Setka(panel1.Top - (Per.y - y));
  end;
end;
Где функция Setka выравнивает переменную к сетке.
Код:
Function Setka(X:integer):integer;
Begin
  X:=(X div Setk)*Setk; // Setk - шаг сетки
  Setka:=X;
end;
аж три процедуры и одна функция. Только дял перемещения нужно 3 процедуры. Можно сделать все намного проще прописав в обработчике OnMouseDown такую весчь:

Код:
procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
panel1.Perform(WM_SYSCOMMAND, $F012 ,0); // $F012 помоему и есть SC_MOVE
end;
Единственная процедура для перемещения объекта panel1 но без выравнивания по сетке.
Преимущества:
1. Малый код
2. Полностью заменят выше описаннвй функции. Ничем не отличается от них.
3. Используется стандартная функция перемещения объектов любого типа.
4. Автоматически назначает граници перемещения мыши (к примеру только в пределах формы, в способе с тремя функциями это нужно делать по другому)
5. Если необходимо изменить объект то ему стоит послать тоже самое сообщение только с параметром
$F001 - для изменения только левой границы
$F002 - для изменения только правой границы
$F003 - для изменения только верхней границы
$F004 - для изменения левой и верхней границы
$F005 - для изменения правой и верхней границы
$F006 - для изменения только нижней границы
$F007 - для изменения правой и нижней границы
$F008 - для изменения правой и нижней границы

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

Последний раз редактировалось rpy3uH; 18.12.2008 в 17:55.
devi409 вне форума Ответить с цитированием
Старый 18.12.2008, 18:02   #8
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

ещё раз повторяю: не надо извращаться и использовать цифры вместо буквенных констант. Ибо зачем люди мучались и описывали все эти константы в заголовочных файлах?
и вот объявления констант SC_***
Цитата:
#define SC_SIZE 0xF000
#define SC_MOVE 0xF010
#define SC_MINIMIZE 0xF020
#define SC_MAXIMIZE 0xF030
#define SC_NEXTWINDOW 0xF040
#define SC_PREVWINDOW 0xF050
#define SC_CLOSE 0xF060
#define SC_VSCROLL 0xF070
#define SC_HSCROLL 0xF080
#define SC_MOUSEMENU 0xF090
#define SC_KEYMENU 0xF100
#define SC_ARRANGE 0xF110
#define SC_RESTORE 0xF120
#define SC_TASKLIST 0xF130
#define SC_SCREENSAVE 0xF140
#define SC_HOTKEY 0xF150
rpy3uH вне форума Ответить с цитированием
Старый 18.12.2008, 18:43   #9
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию

хорошо буду использовать буквенные константы если конечно покажите мне константу на код $F001 или $F002 ...
Ну и опять возвращаясь к проблеме. Никто ничего посоветовать не может?
devi409 вне форума Ответить с цитированием
Старый 18.12.2008, 19:18   #10
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

по документации, младшие 4 бита этих значений использовать нельзя, они используются системой внутренне. И по идее мы не должны отправлять это сообщение, это сообщение отправляет система.

По теме, создай свой класс, например TMyPanel = class (TPanel) в нём обрабатывай сообщение перемещения WM_MOVE
функцию в классе объявляй вот так:
procedure myproc(var Msg:TMessage); message WM_MOVE;
и изменяй в нём полученные координаты, можно попробовать другие сообщения...

Последний раз редактировалось rpy3uH; 18.12.2008 в 19:41.
rpy3uH вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
SSL через WinSock или через что? Jolyk Win Api 2 07.06.2008 17:37
Icq сообщение Marsik Помощь студентам 2 10.04.2008 04:22
Звуковое сообщение. Небесный Паскаль, Turbo Pascal, PascalABC.NET 13 17.10.2007 12:24