-
Всем привет! Обрабатываю сообщение WM_LBUTTONDOWN. Транслирую его для дочернего класса без оконной процедуры. И естественно обработчик после того как послал 1 раз, воторой раз не приходит, пока не вызовешь Application.ProcessMessages.
А чем еще можно прокрутить очередь сообщений? Dispatch?
Или надо свой цикл выборки писать? Не хочется VCL :(
-
Каша какая-то.
Причем тут VCL, Application и прочее ?
У тебя нет исходников VCL и ты не можешь посмотреть, какие функции вызываются тем же методом ProcessMessages ?
Ты сообщение, кому пришедшее, обрабатываешь ?
-
Application - это VCL. Не хочу внедрять в EXE библиотеки VCL. У меня почти чистый WinApi.
Сообщение посылается из формы дочернему контролу созданному с помощью AllocateHWnd. Оконной процедуры у него нет, поэтому просто транслирую сообщение. Обычный SendMessage. Сообщения принимается нормально. WM_PAINT, WM_MOUSEMOVE транслируются без задержек. Но в случае с WM_LBUTTONDOWN происходит задержка около секунды. Если вставить Application.ProcessMessages в конец трансляции, то сообщения начинают поступать в дочерний контрол по кругу, как в оконной процедуре без задержек. Поэтому я и подумал, что возможно есть какой то способ делать трансляцию без задержек.
-
Пробовал свой TranslateMessage/DispatchMessage сделать, но это приводит к зацикливанию. В Application есть TranslateMessageA/TranslateMessageW и с Dispatch тоже самое. Может в этом дело. В общем пока не знаю что делать.
-
dmk © (28.03.17 13:44) [2]
Если не трудно, переведи свой пост на русский язык. Я до сих пор не понимаю, что ты имеешь в виду, а вытягивать из тебя информацию мне не надо, в конце концов проблемы у тебя.
-
Суть в трасляции. Она выполняется для WM_LBUTTONDOWN с задержкой.
Есть форма, в ней есть оконная процедура. Она транслирует дочернему контролу TWindow64 сообщения. TWindow64 их принимает и обрабатывает. Например, что-нибудь рисует. Видно ниже в процедуре OnMessage. Так вот в случае с WM_LBUTTONDOWN происходит задержка выборки сообщения из общей очереди. Пока не нажмешь еще раз мышкой - сообщение не транслируется, т.к. то ли считается не обработанным, то ли еще по какой-то причине.
procedure TImageForm.WndProc(var Message: TMessage);
var
Msg: dword;
begin
inherited;
Msg := Message.Msg;
case Msg of
WM_MOUSEMOVE: TranslateMessage(Message);
WM_LBUTTONDOWN: TranslateMessage(Message);
WM_LBUTTONUP: TranslateMessage(Message);
WM_RBUTTONDOWN: TranslateMessage(Message);
WM_RBUTTONUP: TranslateMessage(Message);
WM_PAINT: TranslateMessage(Message);
WM_NCPAINT: TranslateMessage(Message);
end;
end;
procedure TWindow64.OnMessage(var Message: TMessage);
begin
case Message.Msg of
WM_MOUSEMOVE: WMMouseMove(TWMMouse(Message));
WM_LBUTTONDOWN: WMLButtonDown(TWMMouse(Message));
WM_LBUTTONUP: WMLButtonUp(TWMMouse(Message));
WM_PAINT: WMPaint(TWMPaint(Message));
WM_NCPAINT: WMNCPaint(TWMNCPaint(Message));
end;//case
end;
-
Пробую сделать DispatchMessageW(FMsg) после трансляции, опять EStackOverflow.
Может как то иначе транслировать сообщения надо?
-
> Суть в трасляции. Она выполняется для WM_LBUTTONDOWN с задержкой.
А зачем она вообще нужна ?
Как построен цикл выборки сообщений:
while GetMessage (Msg) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Когда твое окно получает WM_MOUSExxx никакой дополнительной трансляции не требуется.
-
Проблема в том, что после нажатия сообщение не поступает мгновенно по кругу в трансляцию, а в VCL оно при зажатой кнопке работает нормально. Т.е. если держишь кнопку нажатой, то сообщение поступает постоянно. В этом и загвоздка. У меня из TForm посылается сообщение в TObject. Все сообщения нормально посылаются кроме клавиш мыши. После того как оно обработано нужно его снять из очереди сообщений, чтобы следующий WM_LBUTTONDOWN прошел, а этого не происходит. Получается между кликами по 0,5 секунды где-то. Вот и ищу проблему. GetAsyncState думаю пока выручит, а так надо свою выборку из очереди писать. Фактически свой мини-VCL.
-
dmk © (28.03.17 21:41) [8]
Ты б книги какие почитал, Рихтера с Петцольдом - такое ощущение, что путаница в элементарных вещах. Круги, трансляции, мини-VCL - зачем это все ?
-
По-моему проблема в TForm. Сообщение WM_LBUTTONDOWN принимается с задержкой именно в TForm. На WinApi такой задержки нет. Все очень шустро.
-
Игорь, у меня порядок с пониманием. Думал наскоком сделать не вышло.
VCL с WinAPI мешать тяжело. Надо VCL знать изнутри, чего совсем не хочется.
Ибо мне все навороты VCL не нужны.
-
С какой такой задержкой? Что значит снять? Обработали его и всё.
Сделайте что ли мини-проект, без основного кода вашего удивительного класса, а чтоб было видно проблему.
-
> Получается между кликами по 0,5 секунды где-то.
Так может у вас не клик, а даблклик? :)
-
> procedure TImageForm.WndProc(var Message: TMessage);
> ...
эм... Зачем многоступенчатый case-то? Как бы внутри WndProc можно просто:
TranslateMessage(Message);
без case, у вас в OnMessage уже есть такой же case, либо хотя бы так:
case Msg of
WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_PAINT, WM_NCPAINT:
TranslateMessage(Message);
А вообще есть смысл вызывать эти всякие WMMouseMove(TWMMouse(Message));
и прочие в самом WndProc.
-
Нет у меня сделано вот так:
procedure TImageForm.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_MOUSEMOVE: MessageToChild(Message);
WM_LBUTTONDOWN: MessageToChild(Message);
WM_LBUTTONUP: MessageToChild(Message);
WM_PAINT: MessageToChild(Message);
end;
inherited WndProc(Message);
end;
//Транслирует сообщения элементам класса TWindow64
procedure TImageForm.MessageToChild(var Msg: TMessage);
var
i: integer;
Wnd: HWND;
Wnds: array[0..1] of HWND;
begin
if FRulesEnabled and InState(VS_INITED) then
begin
Wnds[0] := FHScroll.Handle;
Wnds[1] := FVScroll.Handle;
Caption := IntToStr(Msg.Msg);
for i := Low(Wnds) to High(Wnds) do
begin
Wnd := Wnds[i];
SendMessage(Wnd, Msg.Msg, Msg.WParam, Msg.LParam);
end;
Msg.Result := S_OK;
end;//if InState
end;
-
Зачем вам вообще дочерние окна? Вы же хотите всё рисовать сами. Хороший вариант - нарисовать всё на буфере, иметь одно окно которое только и делает что выводит буфер и принимает управление.
А если создавать дочерние окна (чтоб избавить себя от мороки с определением на что попали курсором) то им не надо руками дублировать сообщения, наоборот они сообщают об своих.
S_OK ..?
-
>S_OK
Просто константа. Когда пишешь много именованная константа гораздо удобнее для восприятия чем простой ноль. Задекларирована в Windows.Messages.
-
А вообще я нашел проблему. WM_NCHITTEST меня спас.
Там и позиция и клики.
-
>S_OK ..?
Есть еще S_FALSE
-
Я знаю, просто в MSDN написано конкретно и буквально "должна возвращать ноль" или "должна возвращать единицу", а не подобную константу. И разные сообщения после обработки должны возвращать не обязательно только ноль.
Тем более вроде ж не давалось гарантий что S_OK всегда и во всех версиях WindowsAPI будет равна нулю. Это как передавать в функцию SetWindowPos() параметр MK_MBUTTON вместо SWP_NOACTIVATE, махая руками мол - ну и чего, значения-то у них равны...
-
>во всех версиях WindowsAPI будет равна нулю
Константу можно перегрузить в зависимости от версии.