Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 5

Автор: scroollocker
Дата сообщения: 23.11.2009 14:34
Здравствуйте, подскжите пожалуйста, как можно Замутить перемещение окошка программы без панельки (на которой, еще есть кнопочки:закрыть, минимизировать.., за которую обычно и перемещают окошко)
Знаю функцию SetWindowPos, но как узнать, на сколько пользователь переташил окно?
Автор: JDEE
Дата сообщения: 23.11.2009 15:21
scroollocker


Цитата:
Здравствуйте, подскжите пожалуйста, как можно Замутить перемещение окошка программы без панельки



Код:
TForm1 = class(TForm)
private
{Для перемещения формы вне заголовка объявляем процедуру}
procedure WMNCHitTest(var M:TWMNCHitTest);message wm_NCHitTest;
public
{ Public declarations }
end;

procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
begin
inherited;
if M.Result = htClient then
M.Result := htCaption;
end;

Автор: scroollocker
Дата сообщения: 23.11.2009 16:16
JDEE
Спасибо огромное! Эх жалко не будут работать события мышки.. А без этого никак нельзя?
Автор: SIgor33
Дата сообщения: 23.11.2009 16:25
NOwlar
спасибо за ссылку я тоже склонился к просмотру Timeout.
Автор: JDEE
Дата сообщения: 23.11.2009 17:18
scroollocker

Цитата:
Эх жалко не будут работать события мышки.. А без этого никак нельзя?


Как то так:

Код:
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
IsDown: Boolean;
MX, MY: Integer;
public
{ Public declarations }
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
IsDown := True;
MX := X;
MY := Y;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if IsDown then
begin
Left := Left + (X - MX);
Top := Top + (Y - MY);
end;
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
IsDown := False;
end;
Автор: AndreusB
Дата сообщения: 23.11.2009 17:45
Если устанавливать Delphi 2010 и Visual Sudio 2008 SP1(.NET 3.5 SP1), то в какой последовательности. Есть зависимости?
Автор: JDEE
Дата сообщения: 23.11.2009 17:50
AndreusB
Ставил сначала дельфу потом студию. Никаких проблем не замечено.

PS: Студию уже 2010 ИМХО имеет смысл ставить. Там много всего вкусного.
Автор: NOwlar
Дата сообщения: 23.11.2009 17:59
JDEE
По-моему, это не будет работать.

scroollocker
попробуй так

Код:
procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
begin
inherited;
if M.Result = htClient then begin
if (nil = ControlAtPos( ScreenToClient( Point( M.XPos, M.YPos )), False, True ))
then M.Result := htCaption;
end;
end;
Автор: psa1974
Дата сообщения: 23.11.2009 18:08
mdid
Вот все от того что не полную инфу сразу привел . Возможны 2 варианта:

1. Твой код по созданию подменю правильный. Пункты меню, в том числе TPopupMenu(Sender).Items[4] создан в режиме разработки. Скорее всего, у тебя в инспекторе объектов для пункта TPopupMenu(Sender).Items[4] прописан обработчик события, который и вызывается.

2. Твой код по созданию подменю не правильный. Собственно пункты меню ты создаешь динамически (в том числе и TPopupMenu(Sender).Items[4]). Возможен случай, когда при folder <>'-1' строкой TMenuItem(Sender).Insert(i,mi); ты собственно и создаешь свой пункт меню TPopupMenu(Sender).Items[4] (и автоматом назначаешь ему обработчик, поскольку тут в цикле он добавляется во все вновь созданные пункты вне зависимости ни от чего). А впоследствии назначаешь этому пункту меню элементы субменю.
Убедиться можно так:

Цитата:

if folder='-1' then
begin
if Assigned(TPopupMenu(Sender).Items[4].OnClick) then
ShowMessage('Таки обработчик назначен ');
TPopupMenu(Sender).Items[4].Insert(i,mi);
end;
else
TMenuItem(Sender).Insert(i,mi);


Я бы написал так:

Цитата:

for I:=0 to ds.DataSet.RecordCount - 1 do
begin
mi:=TMenuItem.Create(self);
mi.Caption:=ds.DataSet.FieldByName('Наименование').AsString;
mi.Tag:=ds.DataSet.FieldByName('ID').AsInteger;
selItem.id_DestGr:=ds.DataSet.FieldByName('ID').AsInteger;
if (folder='-1') or ((folder<>'-1') and (i <> 4)) then { гарантированно назначаем обработчик только подпунктам субменю, формируемым для пункта TPopupMenu(Sender).Items[4], либо другим основным пунктам меню, для которых ты не создаешь субменю. Может условие не совсем точно, но идею ты понял }
mi.OnClick:=ReplaceItem;
if folder='-1' then
TPopupMenu(Sender).Items[4].Insert(i,mi)
else
TMenuItem(Sender).Insert(i,mi);
CreateListFolder(mi,inttostr(mi.Tag));
ds.DataSet.Next;
end;

Это не существенно, но чего бы не написать вместо TMenuItem(Sender).Insert(i,mi) TMenuItem(Sender).Add(mi)? Все равно ж i с нуля отсчитывается...
Автор: JDEE
Дата сообщения: 23.11.2009 18:10
NOwlar

Цитата:
По-моему, это не будет работать.


Еще как будет.
Это вариант если нужен клик по самой форме тоже. В вашем варианте клик по форме работать не будет.
Автор: mdid
Дата сообщения: 23.11.2009 18:40
scroollocker

Цитата:

Здравствуйте, подскжите пожалуйста, как можно Замутить перемещение окошка программы без панельки (на которой, еще есть кнопочки:закрыть, минимизировать.., за которую обычно и перемещают окошко)
Знаю функцию SetWindowPos, но как узнать, на сколько пользователь переташил окно?

ложите допустим на форму TImage и в обработке OnMouseDown

Код:
ReleaseCapture;
Perform(WM_SYSCOMMAND, $F012, 0);
Автор: scroollocker
Дата сообщения: 24.11.2009 08:32
mdid
Спасиба!
Автор: mdid
Дата сообщения: 25.11.2009 09:32
блин все равно не выходит

Код:
if folder='-1' then
begin
if Assigned(TPopupMenu(Sender).Items[4].OnClick) then
ShowMessage('Таки обработчик назначен ');
TPopupMenu(Sender).Items[4].Insert(i,mi);
end;
else
TMenuItem(Sender).Insert(i,mi);
Автор: psa1974
Дата сообщения: 25.11.2009 12:22
mdid
Я честно говоря не до конца просёк твой алгоритм - не понятно от чего зависит значение folder и на что оно влияет, и сейчас приглядевшись, заметил один нюанс. Давай разбираться...
1. Из твоего кода

Код: if folder='-1' then
TPopupMenu(Sender).Items[4].Insert(i,mi)
else
TMenuItem(Sender).Insert(i,mi);
Автор: mdid
Дата сообщения: 25.11.2009 12:34
пасиб...та прислать не могу ибо это толстый проект с выбором элементов справочника и групп из удаленной БД...пасиб за пример

блин то ли лыжи не едут то ли...в общем проблема в том что ни add ни insert не возвращают индекс созданного элемента посему при добавлении одного уровня ваш пример работает отлично

Код:
var
MI : TMenuItem;
i : Integer;
begin
TPopupMenu(Sender).Items[4].Clear;
for I:=0 to 3 do
begin
mi:=TMenuItem.Create(self);
mi.Caption:= IntToStr(i);
mi.Tag:=i;
mi.OnClick:=ReplaceItem;
TPopupMenu(Sender).Items[4].Insert(i,mi);
end;
Автор: psa1974
Дата сообщения: 25.11.2009 15:31
mdid
Вот оно что! Оказывается ты делаешь пункт меню, для него подпункт, для этого подпункта еще подпункт, и т.д. Вот де собака порылась!
Поехали дальше
Во-первых для каждого подменю индексы начинаются с нуля.
Во-вторых, пункт подменю принадлежит тому элементу меню/подменю, в куда он вставлен/добавлен и не принадлежит другим пунктам меню.
Следствие:

Цитата:
TPopupMenu(Sender).Items.IndexOf(mi)
возвращает индекс пункта в ОСНОВНОМ меню. Если ты mi вставлял не в корень меню а в какой-то пункт, создавая тем самым подменю, то этот mi в самом меню будет отсутствовать. Но будет присутствовать в подменю...
Бери пример, компильни и посмотри текст, выводимый в метке на форме... Test
Обрати внимание, что перед созданием субменю второго уровня вложенности я у элемента, которому сопоставляю это субменю, удаляю обработчик...
Автор: mdid
Дата сообщения: 25.11.2009 15:57
почти оно..но проблема в том что подменю которое открывается тоже должно быть кликабельным...просто есть вариант что сама ОС делает клик при открытии подменю...хотя тут уже можно в первый пункт подменю вставить что то типа "Выбрать"..в общем спасибо..наверно это лучший вариант в данной ситуации
Автор: psa1974
Дата сообщения: 25.11.2009 16:35
mdid

Цитата:
проблема в том что подменю которое открывается тоже должно быть кликабельным

Не вопрос! Если как у меня в примере основные пункты меню созданы в режиме разработки, и им назначен обработчик, то можно его так написать:

Цитата:
procedure TForm3.N151Click(Sender: TObject);
begin
// этот обработчик прописан в инспекторе объектов для всех основных пунктов N111 N121 N131 N141 N151
if (Sender is TMenuItem) then
if (Sender as TMenuItem).Count = 0 then
бла-бла-бла;
end;

Вместо N151Click можно прописать в инспекторе твой ReplaceItem.

И, кстати, это очень даже НЕПЛОХАЯ мысль - такой обработчик можно назначать всем без разбора пунктам и подпунктам - и всё, что вместо бла-бла-бла, будет работать только для пунктов, не имеющих подпунктов!

Если же и основные пункты меню создаются динамически, то поступаешь так же, как я в примере для второго субменю, т.е. считай что субменю первого уровня моего примера - это твое меню. Само собой, это только пример, будут нюансы, но все реализуемо

Цитата:
есть вариант что сама ОС делает клик при открытии подменю

Неа, делать ОС больше нечего Опять же ссылаюсь на свой пример - у меня не происходит клика на подпунктах, у которых есть свои подпункты. Так что - не делает она ничего! Она делает только то, что ты ей расскажешь делать.
Автор: Tualan
Дата сообщения: 26.11.2009 11:04
Такой вот вопрос...
Если во время выполнения кода конструктора объекта возникает исключительная ситуация (Exception) и выполнение кода прерывается, выделяется ли под объект память ?
Автор: grimoor
Дата сообщения: 26.11.2009 11:05
Ошибка в конструкторе приводит к автоматическому вызову деструктора.
Автор: Tualan
Дата сообщения: 26.11.2009 11:08
А в деструкторе нужно проверять какие объекты создались, а какие нет?
Автор: data man
Дата сообщения: 26.11.2009 11:14
grimoor
Tualan
Для чата есть ПМ.
Это и про ваше обсуждение по компонентам.
Автор: Tualan
Дата сообщения: 26.11.2009 14:31
data man
Извините пожалуйста, я думал тема будет интересна не только мне
Автор: ShIvADeSt
Дата сообщения: 27.11.2009 03:27
data man

Цитата:
Для чата есть ПМ.
Это и про ваше обсуждение по компонентам.

В данном случае Вы не правы тут у многих чат идет, главное чтобы в оффтоп и флуд не ушли.
Tualan
grimoor
продолжайте самообразовываться.
Автор: Kursist
Дата сообщения: 27.11.2009 09:21
Есть собственный класс, объекты которого создаются динамически

TapButton=class(TapRegion)
private
FOnMouseUpEvent: TNotifyEvent;
FOnMouseClickEvent: TNotifyEvent;
....
public
....
procedure MouseUp(X,Y:Integer);
procedure MouseClick(X,Y:Integer);
property OnMouseUp: TNotifyEvent read FOnMouseUpEvent write FOnMouseUpEvent;
property OnMouseClick: TNotifyEvent read FOnMouseClickEvent write FOnMouseClickEvent;
....

На форме, в событии OnClick есть такой код:
if (TapList.Items(index) is TapButton) then
(TapList.Items(index) as TapButton).MouseClick(mX,mY);

в процедуре TapButton.MouseClick(X, Y: Integer);
естественно, есть такой код:
if assigned(FOnMouseClickEvent) then FOnMouseClickEvent(self);

Объекты типа TapButton создаются по мере надобности из файла.
В течение работы программы объекты будут многократно удаляться и загружаться=создаваться новые.

Подскажите, как правильнее присваивать процедуру типа TNotifyEvent?
Например, такая процедура, в теле которой есть программный код:

index:=TapList.Add; {создаем в списке объект класса TapButton}
if (TapList.Items(index) is TapButton) then
(TapList.Items(index) as TapButton).OnMouseClick:=...(тут - откуда взять процедуру для присваивания?);

Спасибо.
Автор: ppkp
Дата сообщения: 27.11.2009 15:36
Kursist

Цитата:
(TapList.Items(index) as TapButton).OnMouseClick:=...(тут - откуда взять процедуру для присваивания?);


В разделе private объявляете
procedure MyMouseClick(X,Y:Integer);

В секции implementation пишите свой обработчик событий
procedure MyForm.MyMouseClick(X,Y:Integer);
begin
........
end;
И потом
(TapList.Items(index) as TapButton).OnMouseClick:=MyMouseClick;
Автор: MrZeRo
Дата сообщения: 27.11.2009 15:38
удалено
Автор: Kursist
Дата сообщения: 27.11.2009 16:46
Спасибо за ответы.

1. Только что решил проблему иным способом (если кому интересно):
создал метод
function TapButton.MouseClick(X, Y: Integer):Boolean;
Там проверяется был ли клик (координаты мыши) в области TRect объекта.
А на форме пишу - если произошел клик - то сделать всё что хочу. И не надо использовать TNotifyEvent.

2. На тему TNotifyEvent нашел инфу:
"Обработчики событий нельзя сделать просто процедурами — они обязательно должны быть чьими-то методами.Но их можно "отдать" какому-либо другому объекту. Более того, для этих целей можно описать и создать специальный объект. Его единственное предназначение — быть носителем методов, которые затем делегируются другим объектам."
http://delphi-masters.ru/one/11926.htm


Автор: data man
Дата сообщения: 27.11.2009 16:57
Kursist

Цитата:
Обработчики событий нельзя сделать просто процедурами — они обязательно должны быть чьими-то методами


Не совсем так. К примеру эта статья и её обсуждение О назначении пользовательского TNotifyEvent
Автор: V1s1ter
Дата сообщения: 27.11.2009 18:27
Kursist
Вам ppkp все правильно подсказал, возможно Вы его не правильно поняли.

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Clipper 5


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.