Перейти к содержанию
Fire Monkey от А до Я

kami

Пользователи
  • Постов

    643
  • Зарегистрирован

  • Посещение

  • Победитель дней

    41

Сообщения, опубликованные kami

  1. 19 минут назад, neo сказал:

    без первых двух никак не получится

    Т.е. прочитать, что они делают - это излишне? Бессмысленные действия, результат выполнения которых уже известен изначально.

    19 минут назад, neo сказал:

    а с другими флагами не получается

    И всё остальное - тоже проигнорировано...

    Удачи.

  2. Form1.Edit1.Text:=Form1.Edit1.Text+ch;

    Вам еще в прошлом топике сказали - не нужно так делать. Обработчик хука должен максимально быстро вернуть управление. Любая обработка должна проводиться постфактум, асинхронно. Здесь вы без тени сомнения работаете с визуальными компонентами, вызов которых может и должен производиться только из главного потока вашего процесса. Откуда такая уверенность, что коллбак хука будет вызван именно в этом потоке?

    В вашем коде первые две строки бессмысленны, почитайте их описание в https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-mapvirtualkeyw , чтобы понять - почему.
    Читаем ремарки (часто ремарки - это самое главное ) для GetKeyboardState: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getkeyboardstate и выясняем, что она привязана к вызывающему потоку. А LL - хуки вызываются как минимум в контексте установившего их процесса, скорее всего (лень читать доку) - в контексте установившего хук потока. Потому и не отрабатывает, что GetKeyboardState для получения нужного эффекта должен вызываться в контексте чужого потока в чужом процессе. Чтобы отвязаться - следует использовать (как следует из тех же ремарков по ссылке выше) GetAsyncKeyState.

  3. 6 часов назад, neo сказал:

    всё криво тогда работает

    Исчерпывающее описание проблемы.

    6 часов назад, neo сказал:

    там в любом случае должна быть небольшая синхронизации тк нужно дожидаться ответа от idHTTP

    Вам сама операционная система говорит - нельзя так делать, вы тормозите ВСЁ что только можно, в результате ваш хук признается вредоносным и исключается из цепочки. Но вы упорный...

    Ждите ответа. Но в своем коде, а не в хуке. А в свой код передавайте данные асинхронно, через тот же postMessage

  4. PeekMessage - бессмысленно и даже вредно с флагом PM_REMOVE. Убрать.

    SendMessage - эта функция отправляет данные окну и дожидается, пока окно их обработает. А хук ждать не должен, его задача - максимально быстро отработать. Заменить на PostMessage.

    длл здесь не нужна. LL-хуки работают из любого места. Просто перенести весь код в exe.

     

  5. 16 минут назад, gonzales сказал:

    создавать TCPServer и слушать порт

    Не надо TCPServerов на клиентах. Ничего хорошего из этого не выйдет, как минимум потому что белые IP есть у 1% пользователей сотовой связи, к остальным будет не подключиться извне.

    TCP соединение позволяет обеспечить двусторонний обмен. Любой из корреспондентов (и клиент и сервер) в любой момент времени вправе отправить в соединение данные. На стороне TCP сервера для этого нужно отправить данные в конкретное соединение с конкретным клиентом, а на клиентской - и выбирать ничего не надо, у TCP-клиента только одно соединение.

  6. WebSockets обеспечивает обратную связь "сервер-клиент", в отличие от обычного http, где идет клиент-сервер.

    Увы, насколько я знаю - это доступно только на Indy (буду очень рад, если ошибаюсь), а (далее всё очень субъективно) с индейцами у меня как-то не сложилось...

  7. 11 часов назад, ddr 2 сказал:

    нужно учитывать и контролировать, что бы поток не завершился раньше, чем все "сообщения" будут обработаны основным потоком? 

    Это зависит от того, какого эффекта надо добиться.
    Если queue вызываете из не-анонимного потока кодом вида Self.Queue(myProcedure) - то при уничтожении потока всё что он отдал в очередь на выполнение в главный поток, будет уничтожено. Без выполнения.
    Если вызывать как TThread.Queue(nil, myProcedure) - то не будет уничтожено. Но в этом случае, само собой, нельзя обращаться к полям и методам этого потока. Если требуется обращение только к полям - заведите локальные переменные и работайте с ними. Например, так:

    procedure TmyThread.Execute;
    var
      SomeValue, SomeAnotherValue: string;
    begin
      .....
      SomeValue:=Self.FInternalValue; // Self пишу только для понимания, что Fxxx - это поле в экземпляре потока
      SomeAnotherValue:=Self.FInternalAnotherValue;
      TThread.Queue(nil, procedure
        begin
          ShowMessage(SomeValue + SomeAnotherValue); // эти переменные доживут до выполнения анонимки даже если потока уже не будет.
        end;
      );

     

  8. 1 час назад, Иван Р сказал:

    Это весь код больше ничего нет

    Тут нет кода, выполняемого в доп.потоке.
    Метод Synchronize делает следующее: "приостановить выполнение себя (т.е. доп.потока), переключиться в основной поток, выполнить там действие и после этого вернуться в себя (в доп.поток)".
    Ввиду того, что в коде доп.потока есть только synchronize - то единственное, что поток делает - ждёт, пока выполнится его действие в основном потоке.

    То есть - является абсолютно бессмысленным.

  9. 5 часов назад, ddr 2 сказал:

    в чем ошибка?

    Поставьте бряк внутри метода

    _ReciveMessage

    и удивитесь - в каком потоке он вызывается.

    Ну или напишите
    if TThread.Current.ThreadID<>MainThreadID then // мог слегка ошибиться с наименованиями переменных - пишу по памяти, но вроде это они и есть.
      Алярма!!! (тут что-нибудь сигнализирующее что всё неправильно).

    Включая режим буквоедства: смените названия на ReceiveMessage и PackedNumber. Глаз цепляется :)

  10. Опять пошли в какие-то обходные маневры...
    Решение для винды:

    uses
      FMX.Platform.Win,
      Winapi.Windows;
    
    procedure TForm5.FormCreate(Sender: TObject); // Form5 - это окно-"всплывашка". Не забываем выставить в инспекторе объектов stayOnTop, стиль border-а и т.п.
    var
      myHWND: THandle;
      ExStyle: NativeInt;
    begin
      myHWND:=  WindowHandleToPlatform(Handle).Wnd;
      Winapi.Windows.SetParent(myHWND, 0); 
      ExStyle := GetWindowLong(myHWND, GWL_EXSTYLE);
      SetWindowLong(myHWND, GWL_EXSTYLE, ExStyle or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE); 

    Возможно, этот код будет актуальнее смотреться в OnShow, а не в onCreate.

  11. 14 минут назад, Brovin Yaroslav сказал:

    А есть вообще понимание:

    У меня - нет.
    Емнип, Owner-ом для всех наброшенных на форму компонентов выступает сама форма. Вне зависимости от уровня вложенности визуальных компонентов.
    Для невизуальных объектов овнер нужен, если они покладены на форму в дизайн-тайме. Parent-а у невизуального объекта нет, а правило "не ты создал - не тебе удалять" выполняться должно.

    Это из того, что на поверхности. А какие реальные причины заставили иметь не только парента, но и овнера, да еще и для дизайн-тайм... Возможно, действительно без них никак.

    Давайте только без привлечения ARC "ничего удалять не надо, если и владелец и родитель удалятся, ссылки на объект закончатся и он самоуничтожится".

  12. 7 часов назад, FREEFAR сказал:

    Предполагай по сути вопроса. А не отвлекаясь на офТоп. Или там в Питере культуре особо не учат? Или тебя ранило походу где-то, чем-то, как-то.
    Всем успел накидать я смотрю

    Понаехавших - нет, не учат. Раненых особенно. Тебе эпитеты тоже подобрать? По сути вопроса?

    Как ты говоришь "накидывание" возникло от того, что для решения не самого сложного вопроса здесь озвучены (в том числе -тобой)  рекомендации и выводы, от которых потом сложно не удивляться - откуда столько говнокода в экосистеме Делфи?
    Да вот отсюда, из таких топиков на форумах, которые неокрепшие (да и окрепшие) умы впитывают и несут потом в массы. Удивительно, что еще не затронули "уникальное имя нужно, потому что по нему потом будем искать этот компонент"...

  13. 6 минут назад, FREEFAR сказал:

    Откуда узнал про религию дядя?

    Предположил на основании твоего вывода " не будет ошибки дублирования? по моему будет ", который проверяется и опровергается за 2 минуты.
    В результате вместо того, чтобы понять откуда ноги растут у ошибки дублирования имен - вы имеете костыли типа "по этой причине именовали := 'frame_'+i.toString; "

  14. 56 минут назад, slav_z сказал:

    это работа Owner а не Parent.

    Уничтожение и в VCL и в FMX идет именно Parent-ом. Owner получал уведомления (FreeNotification / RemoveFreeNotifications) и убирал высвобожденные ссылки из своего списка на уничтожение. Потом уничтожал свое.
    Это дефолтное поведение, сложившееся издавна, оно же без изменений перекочевало в FMX, единственное - находятся методы FreeNotification / RemoveFreeNotifications в разных классах.

    1 час назад, slav_z сказал:

    При разрушении получите AV (сначала элемент будет разрушен Parent-ом а затем то же самое попытается сделать и Owner...  нет там никаких нотификаций и подписок). 

    Нет, это далеко не так. Parent-ом действительно уничтожается всё дочернее. Но Owner после этого ничего сделать уже не может, потому что он уже не знает об уничтоженном компоненте:

    destructor TComponent.Destroy;
    begin
    ...
      if FOwner <> nil then FOwner.RemoveComponent(Self);

    Ну и напоследок:

    procedure TForm12.btn1Click(Sender: TObject);
    var
      fm: TForm;
      fr: TFrame13;
      i: Integer;
    begin
      fm := TForm12.Create(Self); // создаем дубликат
      try
        for i := 0 to 5 do
          begin
            fr := TFrame13.Create(Self); // Owner - главная форма
            // на фрейм накидал эдитов, лейблов - чтобы не пусто было.
            fr.Name := 'fr' + IntToStr(i);
            fr.Parent := fm; // а Parent - вторая форма того же класса.
            fr.Align := TAlignLayout.Right;
          end;
        fm.ShowModal;
      finally
        fm.Free; // уничтожаем вторую форму
      end;
      // и потом, при закрытии главной формы всё кошерно.
    end;

    Что я делаю не так?

  15. 2 часа назад, slav_z сказал:

    проверка на дублирование имени выполняется родителем... а он у тебя nil

    Родитель-то как раз не nil. Владелец nil.

    Позвольте поинтересоваться, а какой профит помимо счастья обладания геморроем (который сам себе же и сделал) принесет создание компонента с указанием владельца?
    Единственный плюс, который мог бы быть - владелец при высвобождении себя уничтожает всё, чем он владеет.

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

  16. 4 часа назад, FREEFAR сказал:

    не будет ошибки дублирования? по моему будет. по этой причине именовали := 'frame_'+i.toString;

    попробовать религия не позволяет?

    Только что написанный код:

    var
      i: Integer;
      fr: TFrame13; // отдельный фрейм, у которого в ObjectInspector так и написано: Name = Frame13
    begin
      for i := 0 to 5 do
        begin
          fr:=TFrame13.Create(nil);
          fr.Parent:=Self;
          fr.Align:=alRight;
        end;

    всё отрабатывает без проблем, никаких вопросов по именованию рантайм-компонентов не возникает.

  17. 12 часов назад, slav_z сказал:

    Если сразу после Release попытаться создать элемент заново (TFrame), то будет ошибка дублирования имени компонента (старый компонент еще жив в списке компонентов родителя).

    помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой.

  18. И еще в тему ForceQueue.

    Как-то раз потребовалась мне конструкция типа "отложенное действие после отложенного действия". Дык вот, если сделать вот так:

    TThread.ForceQueue(
      procedure
      begin
        SomeAction;
        ForceQueue(SomeAnotherAction);
      end);

    то SomeAnotherAction выполнится сразу же вслед за SomeAction, а не на новом витке Application.Idle.
    Всё дело в том, что выполнятель Queued-действий просто достает их из списка, пока не закончатся. Т.е. выполняется первый ForceQueue, а вложенный, как таковой, не выполняется: второе действие помещается в список, тут же достается из него и сразу же выполняется!

    Как результат - при таком вызове де-факто получается срабатывает только первый ForceQueue, а вместо второго  выполняется прямой вызов действия.

  19. 6 часов назад, krapotkin сказал:

    ну и тут поток. в чем вопрос?

    тут нет потока. forceQueue не использует создание потоков, оно пишет напрямую в структуры синхронизации.

    Я у себя уже давно сделал хелпер с одним методом - Release. И его использую не получая сообщений от компилятора.

  20. 4 часа назад, Вадим Смоленский сказал:

    С таким булевым заграждением всё получилось!

    В обработке сообщения производить действия, которые способны генерировать кучу сообщений, которые приведут к обработке того же сообщения, в котором... , имхо, не есть хорошо.

    Вместо вот такого экранирования я бы попробовал использовать TThread.ForceQueue(procedure begin код, завязанный на IME end);

×
×
  • Создать...