Форум: "Основная";
Текущий архив: 2004.01.29;
Скачать: [xml.tar.bz2];
ВнизПоложение курсора над компонентом Найти похожие ветки
← →
lhs7fy (2004-01-15 16:14) [0]Доброго времени суток, господа! Подскажите позжалуйста,
как определить, находится ли курсор мыши в данный момент
времени над визуальным компонентом, или нет (Тут речь
идет о тектовом поле TEdit).
← →
Семен Сорокин (2004-01-15 16:19) [1]Mouse.Capture + F1
← →
Тимохов (2004-01-15 16:21) [2]На самом деле немного не понятно. Что значит определить? В какой момент определить? Кем определить?
Немножно подробнее задачу.
← →
alex_*** (2004-01-15 16:26) [3]ControlAtPos
← →
AKul (2004-01-15 16:30) [4]Можно попробовать так:
var P:TPoint;
...
GetCursorPos(P);
P:=<Визуальный компонент>.ScreenToClient(P);
//Дальше проверяем находится ли точка P в прямоугольнике, который описывает <Визуальный компонент>.
//Если да - то курсор над <Визуальный компонент>
Кстати, еще есть такое свойство OnMouseMove - вызывается при перемещении курсора над компонетом.
← →
Тимохов (2004-01-15 16:33) [5]Варинтов много, а что автору нужно добиться так и не понятно.
← →
lhs7fy (2004-01-16 12:07) [6]AKul"у конечно большое спасибо, но я точно так же сделал
сам, а про OnMouseMove мне рассказывать не надо, потому,
что мне нужно определить когда курсора над компонентом уже
не будет, а поскольку я создаю компонент , то добраться до родительского OnMouseMove ни через какие Parent"ы нельзя.
Все равно спасибо!
← →
jack128 (2004-01-16 12:11) [7]
> мне нужно определить когда курсора над компонентом уже
> не будет
cm_mouseleave
← →
Семен Сорокин (2004-01-16 12:19) [8]
var
X, Y: integer; // Needed position in screen coordinates
...
if PointInRect(Point(X, Y), OffsetRect(MyComp.ClientRect, -MyComp.ClientOrigin.X, -MyComp.ClientOrigin.Y)) then
///
только проблема останется в случае custom regions.
← →
vl-chel (2004-01-17 12:22) [9]>lhs7fy
есть сообщение WM_MOUSELEAVE - посылаемое когда мышь покидает компонент в VCL не реализовано
← →
vl-chel (2004-01-17 12:27) [10]>lhs7fy
есть сообщение CM_MOUSELEAVE - посылаемое когда мышь покидает компонент в VCL не реализовано см CM_MOUSEENTER
а к OnMouseMove можно добраться переопределив процедуру MouseMove - проверь она должна быть в protected
← →
Владимир Секретев (2004-01-17 20:01) [11]Пример AKul не плох, но содержит ошибку. Процедуру OnMouseMove надо писать для родительского компонента (ибо, как справедливо отметил lhs7fy, <Визуальный компонент>.OnMouseMove помочь не может), а строку
P:=<Визуальный компонент>.ScreenToClient(P);
Надо писать так:
P:=<Родитель визуального компонента>.ScreenToClient(P);
В следующем примере кнопка DeleteButton меняет свою картинку в зависимости от того, над ней курсор или нет. Проверка Tag <> 0 введена для того, чтобы зря не переисовывать (моргание).
procedure TForm1.ToolBar2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var P:TPoint;
BM : TBitmap;
begin
GetCursorPos(P);
// 1. Delete Button
with DeleteButton do if Tag <> 0 then begin
P := ToolBar2.ScreenToClient(P);
if not ((P.y > DeleteButton.Top) and (P.x > DeleteButton.Left) and
(P.y < DeleteButton.Height+Top) and (P.x < DeleteButton.Width+Left)) then begin
DeleteButton.Tag := 0;
BM := TBitmap.Create;
MainButtons.GetBitmap(0, BM);
DeleteButton.Glyph := BM;
BM.Free;
end;
end; // with DeleteButton do begin
end;
Но вот проблема!
Событие OnMouseMove НЕ ВОЗНИКАЕТ, если мышь достаточно быстро пролетает над панелью (родитель кнопки). Если ведем мышь медленно - все Ok. Если быстро - то не работает.
Приходится направлять события ото всех соседних компонентов и Form1 на ToolBar2MouseMove. ReplaceButton лежит рядом.
procedure TForm1.ReplaceButtonMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
begin
ToolBar2MouseMove(Sender, Shift, X, Y);
end;
Кто знает более красивый способ - поделитесь!
← →
Игорь Шевченко (2004-01-17 22:08) [12]lhs7fy (16.01.04 12:07)
> мне нужно определить когда курсора над компонентом уже
> не будет
C этого надо начинать. SetCapture + F1 + ReleaseCapture + WM_MOUSEMOVE + PtInRect.
Пример для Static но для Edit все тоже самое
procedure TfAbout.Label2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
Control : TStaticText;
begin
Control := Sender as TStaticText;
if (PtInRect(Control.ClientRect, Point(X,Y))) then begin
{ Курсор над контролом }
SetCapture(Control.Handle);
Screen.Cursor := crHandPoint;
Control.Font.Style := Control.Font.Style + [fsUnderline];
end else begin
{ Курсор вне контрола }
Control.Font.Style := Control.Font.Style - [fsUnderline];
ReleaseCapture();
Screen.Cursor := crDefault;
end;
end;
← →
lhs7fy (2004-01-18 14:42) [13]Владимиру Секретеву спасибо, но я всё-таки воспользовался спосо-
бом Игоря Шевченко, потому что он не такой громоздкий, хотя оба
метода вполне рабочие, так что благодарен всем, кто поучаствовал.
Только мне одно интересно, может кто подскажет, как перехватывать
событие wm_mouseleave, а то что-то не получается.
← →
AKul (2004-01-19 10:11) [14]
> Владимир Секретев (17.01.04 20:01) [11]
> Пример AKul не плох, но содержит ошибку. Процедуру OnMouseMove
> надо писать для родительского компонента (ибо, как справедливо
> отметил lhs7fy, <Визуальный компонент>.OnMouseMove помочь
> не может), а строку
>
> P:=<Визуальный компонент>.ScreenToClient(P);
> P:=<Родитель визуального компонента>.ScreenToClient(P);
Уважаемый Владимир Секретев, не подскажете где Вы здесь нашли ошибку? Первоначально вопрос ставился так: "находится ли курсор мыши в данный момент времени над визуальным компонентом, или нет". А с чего Вы взяли, что для того чтобы отловить перемещение курсора над компонетом, необходимо реагировать на событие родительского компонента??? Бред какой-то.
P:=<Визуальный компонент>.ScreenToClient(P); - даст координату внутри компонета и проверить ее принадлежность прямоугольнику типа (0,0,width,height) по-моему не составит труда.
А причем тут
P:=<Родитель визуального компонента>.ScreenToClient(P);
не понятно!
To lhs7fy:
Будь повнимательнее с вопросами!!!
Для тго, чтобы перехватить сообщение WM_MOUSELEAVE - напиши свой класс TMyEdit наследованный от TEdit (TCustomEdit), а в нем и объяви метод обработки этого сообщения, что-то типа:
procedure WMMouseLeave(var MSG:TMessage);message WM_MOUSELEAVE
← →
lhs7fy (2004-01-19 11:07) [15]To AKul:
Можно сделать и так, разницы нет, но париться с лишними процедурами нету охоты. Хотя я и сам так делал, только что-то ничего не получилось, но это неважно.
← →
NAlexey (2004-01-19 11:23) [16]>lhs7fy ©
А с другой стороны, в примере приведенном Игорь Шевченко © (17.01.04 22:08) [12]. Проведи такой эксперемент: Тебе надо было для TEdit? Вот и пробуй для TEdit. Клади на форму вставляй процедуру:
procedure TForm1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
Control : TEdit;
begin
Control := Sender as TEdit;
if (PtInRect(Control.ClientRect, Point(X,Y))) then begin
{ Курсор над контролом }
SetCapture(Control.Handle);
Screen.Cursor := crHandPoint;
Control.Font.Style := Control.Font.Style + [fsUnderline];
end else begin
{ Курсор вне контрола }
Control.Font.Style := Control.Font.Style - [fsUnderline];
ReleaseCapture();
Screen.Cursor := crDefault;
end;
end;
А теперь наводи мышь на Edit и попробуй выделить текст в нем. Вот тебе и SetCapture, ReleaseCapture.
← →
NAlexey (2004-01-19 11:31) [17]>AKul ©
>Для тго, чтобы перехватить сообщение WM_MOUSELEAVE - напиши свой класс
Да не надо никого класса. Просто у формы:
procedure TForm1.CMMouseEnter(var Message: TMessage);
begin
if Message.LParam = Integer(Edit1) then
begin
Screen.Cursor := crHandPoint;
Edit1.Font.Style := Edit1.Font.Style + [fsUnderline];
end;
inherited;
end;
procedure TForm1.CMMouseLeave(var Message: TMessage);
begin
if Message.LParam = Integer(Edit1) then
begin
Edit1.Font.Style := Edit1.Font.Style - [fsUnderline];
Screen.Cursor := crDefault;
end;
inherited;
end;
← →
AKul (2004-01-19 11:41) [18]
> NAlexey © (19.01.04 11:31) [17]
Идея хороша.
Только для lhs7fy © здесь следует добавить,
что
TForm1.CMMouseEnter будет вызываться, когда курсор заходит на форму, т.е. ПОКИДАЕТ TEdit.
CMMouseLeave - наоборот.
← →
NAlexey (2004-01-19 11:48) [19]>AKul © (19.01.04 11:41) [18]
Я думаю что всетаки это не связано с формой. Т.е на Enter будет заходить в контрол, на Leave выходить.
← →
AKul (2004-01-19 11:56) [20]
> NAlexey © (19.01.04 11:48) [19]
> Я думаю что всетаки это не связано с формой. Т.е на Enter
> будет заходить в контрол, на Leave выходить.
Не согласен!
В коде обрабатываются события CM_MOUSEENTER, CM_MOUSELEAVE
- а это события окна формы!!! Поэтому их следует рассматривать относительно формы.
Возможно ты что-то спутал с диалоговым окном, WndProc которого вызывается при возникновении события в дочерних окнах (API)
Можешь проверить мою догадку.
← →
NAlexey (2004-01-19 12:00) [21]>AKul © (19.01.04 11:56) [20]
>Можешь проверить мою догадку.
Проверил, работает как я сказал. На Enter заходит в контрол, на Leave выходит. Как у виннипуха.
← →
AKul (2004-01-19 12:13) [22]NAlexey © (19.01.04 12:00) [21]
Согласен с тобой - код работает правильно.
Я немного не так понял твою идею (точнее лень было внимательно просмотреть на "if Message.LParam = Integer(Edit1)").
Я вел к тому, что перед входом в Edit, сначала все равно вызовется событие CMMouseLeave, только относительно формы! - можешь проверить.
P.S. Sorry, если не так выразился
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.01.29;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.009 c