Конференция "WinAPI" » WM_LBUTTONDOWN
 
  • dmk © (28.03.17 06:30) [0]
    Всем привет! Обрабатываю сообщение WM_LBUTTONDOWN. Транслирую его для дочернего класса без оконной процедуры. И естественно обработчик после того как послал 1 раз, воторой раз не приходит, пока не вызовешь Application.ProcessMessages.

    А чем еще можно прокрутить очередь сообщений? Dispatch?
    Или надо свой цикл выборки писать? Не хочется VCL :(
  • Игорь Шевченко © (28.03.17 10:16) [1]
    Каша какая-то.

    Причем тут VCL, Application и прочее ?
    У тебя нет исходников VCL и ты не можешь посмотреть, какие функции вызываются тем же методом ProcessMessages ?

    Ты сообщение, кому пришедшее, обрабатываешь ?
  • dmk © (28.03.17 13:44) [2]
    Application - это VCL. Не хочу внедрять в EXE библиотеки VCL. У меня почти чистый WinApi.

    Сообщение посылается из формы дочернему контролу созданному с помощью AllocateHWnd. Оконной процедуры у него нет, поэтому просто транслирую сообщение. Обычный SendMessage. Сообщения принимается нормально. WM_PAINT, WM_MOUSEMOVE транслируются без задержек. Но в случае с WM_LBUTTONDOWN происходит задержка около секунды. Если вставить Application.ProcessMessages в конец трансляции, то сообщения начинают поступать в дочерний контрол по кругу, как в оконной процедуре без задержек. Поэтому я и подумал, что возможно есть какой то способ делать трансляцию без задержек.
  • dmk © (28.03.17 13:47) [3]
    Пробовал свой TranslateMessage/DispatchMessage сделать, но это приводит к зацикливанию. В Application есть TranslateMessageA/TranslateMessageW и с Dispatch тоже самое. Может в этом дело. В общем пока не знаю что делать.
  • Игорь Шевченко © (28.03.17 14:10) [4]
    dmk ©   (28.03.17 13:44) [2]

    Если не трудно, переведи свой пост на русский язык. Я до сих пор не понимаю, что ты имеешь в виду, а вытягивать из тебя информацию мне не надо, в конце концов проблемы у тебя.
  • dmk © (28.03.17 19:03) [5]
    Суть в трасляции. Она выполняется для 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;
  • dmk © (28.03.17 19:13) [6]
    Пробую сделать DispatchMessageW(FMsg) после трансляции, опять EStackOverflow.
    Может как то иначе транслировать сообщения надо?
  • Игорь Шевченко © (28.03.17 21:28) [7]

    > Суть в трасляции. Она выполняется для WM_LBUTTONDOWN с задержкой.


    А зачем она вообще нужна ?

    Как построен цикл выборки сообщений:

    while GetMessage (Msg) do
    begin
     TranslateMessage(Msg);
     DispatchMessage(Msg);
    end;

    Когда твое окно получает WM_MOUSExxx никакой дополнительной трансляции не требуется.
  • dmk © (28.03.17 21:41) [8]
    Проблема в том, что после нажатия сообщение не поступает мгновенно по кругу в трансляцию, а в VCL оно при зажатой кнопке работает нормально. Т.е. если держишь кнопку нажатой, то сообщение поступает постоянно. В этом и загвоздка. У меня из TForm посылается сообщение в TObject. Все сообщения нормально посылаются кроме клавиш мыши. После того как оно обработано нужно его снять из очереди сообщений, чтобы следующий WM_LBUTTONDOWN прошел, а этого не происходит. Получается между кликами по 0,5 секунды где-то. Вот и ищу проблему. GetAsyncState думаю пока выручит, а так надо свою выборку из очереди писать. Фактически свой мини-VCL.
  • Игорь Шевченко © (28.03.17 23:38) [9]
    dmk ©   (28.03.17 21:41) [8]

    Ты б книги какие почитал, Рихтера с Петцольдом - такое ощущение, что путаница в элементарных вещах. Круги, трансляции, мини-VCL - зачем это все ?
  • dmk © (28.03.17 23:38) [10]
    По-моему проблема в TForm. Сообщение WM_LBUTTONDOWN принимается с задержкой именно в TForm. На WinApi такой задержки нет. Все очень шустро.
  • dmk © (29.03.17 00:24) [11]
    Игорь, у меня порядок с пониманием. Думал наскоком сделать  не вышло.
    VCL с WinAPI мешать тяжело. Надо VCL знать изнутри, чего совсем не хочется.
    Ибо мне все навороты VCL не нужны.
  • D7 (29.03.17 00:48) [12]
    С какой такой задержкой? Что значит снять? Обработали его и всё.
    Сделайте что ли мини-проект, без основного кода вашего удивительного класса, а чтоб было видно проблему.
  • D7 (29.03.17 00:55) [13]
    > Получается между кликами по 0,5 секунды где-то.

    Так может у вас не клик, а даблклик? :)
  • D7 (29.03.17 01:18) [14]
    > 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.
  • dmk © (29.03.17 01:19) [15]
    Нет у меня сделано вот так:

    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;
  • D7 (29.03.17 02:44) [16]
    Зачем вам вообще дочерние окна? Вы же хотите всё рисовать сами. Хороший вариант - нарисовать всё на буфере, иметь одно окно которое только и делает что выводит буфер и принимает управление.

    А если создавать дочерние окна (чтоб избавить себя от мороки с определением на что попали курсором) то им не надо руками дублировать сообщения, наоборот они сообщают об своих.

    S_OK ..?
  • dmk © (29.03.17 02:57) [17]
    >S_OK
    Просто константа. Когда пишешь много именованная константа гораздо удобнее для восприятия чем простой ноль. Задекларирована в Windows.Messages.
  • dmk © (29.03.17 02:58) [18]
    А вообще я нашел проблему. WM_NCHITTEST меня спас.
    Там и позиция и клики.
  • dmk © (29.03.17 02:59) [19]
    >S_OK ..?
    Есть еще S_FALSE
 
Конференция "WinAPI" » WM_LBUTTONDOWN
Есть новые Нет новых   [118461   +17][b:0][p:0.001]