Перейти к содержанию

Antonshka

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

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

  • Посещение

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

    16

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

  1. Загрузил User.32 dll в Ghydra.

    DrawIconEx из User.32 dll вызывает NtUserDrawIconEx в win32u.dll, предварительно записав все нужные параметры в регистры и стек.

    NtUserDrawIconEx из win32u.dll вызывает syscall.

    Спойлер
    //win32u.dll
    undefined8 NtUserDrawIconEx(void)
    
    {
      code *pcVar1;
      undefined8 uVar2;
      
                        /* 0x1ec0  883  NtUserDrawIconEx */
      if ((DAT_7ffe0308 & 1) == 0) {
        syscall();
        return 0x105a;
      }
      pcVar1 = (code *)swi(0x2e);
      uVar2 = (*pcVar1)();
      return uVar2;
    }

     

    А дальше все, тайна кода ядра.

  2. Привет, кто-нибудь пробовал такое?

    Есть функция DrawIconEx в User.32 dll. Нужно узнать как она работает изнутри. Как она обрабатывает маску иконки и само изображение иконки.

     

    Зачем это нужно? Дело в том что DrawIconEx корректно рисует иконку. Но если пробовать сделать тоже самое вручную, через BitBlt, как например это описано у Фень, Щупака, на MSDN, то получаются артефакты.

    Спойлер
    HDC hdcColor = CreateCompatibleDC(compatibleDC.origDC);
    HDC hdcMask = CreateCompatibleDC(compatibleDC.origDC);
    HBITMAP prevColor = reinterpret_cast<HBITMAP>(GetCurrentObject(hdcColor, OBJ_BITMAP));
    HBITMAP prevMask = reinterpret_cast<HBITMAP>(GetCurrentObject(hdcMask, OBJ_BITMAP));
    HBITMAP color = CreateCompatibleBitmap(compatibleDC.origDC, 32, 32);
    HBITMAP mask = CreateCompatibleBitmap(compatibleDC.origDC, 32, 32);
    HICON icon1 = reinterpret_cast<HICON>(LoadImageW(WGW::hInstance, MAKEINTRESOURCE(_IDI_FRUT), IMAGE_ICON, 32, 32, 0));
    
    SelectObject(hdcColor, color);
    SelectObject(hdcMask, mask);
    ICONINFO iconInfo{ 0 };
    BITMAP bitmap{ 0 };
    
    GetIconInfo(icon1, &iconInfo);
    GetObjectW(iconInfo.hbmMask, sizeof(bitmap), &bitmap);
    
    SelectObject(hdcColor, iconInfo.hbmMask);
    BitBlt(compatibleDC.origDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcColor, 0, 0, SRCAND);
    SelectObject(hdcMask, iconInfo.hbmColor);
    BitBlt(compatibleDC.origDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMask, 0, 0,	SRCINVERT);
    
    DrawIconEx(compatibleDC.origDC, 50, 0, icon1, 32, 32, NULL, NULL, DI_MASK | DI_IMAGE);

     

     

    Спойлер

    spacer.png

     

  3. Оказывается в Windows есть ограничение на количество User, GDI, и Kernel объектов, для сессии в общем, и в частности для процесса.

    Для User и для GDI, максимальное возможное количество объектов на процесс равно 10 000. Для Kernel цифра побольше. Я открыл 5 PopupMenu и у меня уже более 10 000 GDI объектов. Утечки нет, при закрытии PopupMenu становится около 300. Проверял через ProcessExplorer.

    Придется переписывать всю логику обращения с объектами. Переходить на постоянное создание/удаление. Не знаю как сильно это скажется на производительности, но такова реальность.

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

     

    Кстати, ImGUI не использует задержку и плавность для PopupMenu и для ToolTip. Думал тоже убрать, но с ними все же интересней.

     

  4. Интересно было поностальгировать по СЕ.

    Не Velocity ли это было? В ESP+50. На 12:48.

    Обычно объекты ускоряют через Velocity * свой множитель.

     

    Я бы посоветовал использовать всегда pushfd/popfd при наличии своего cmp.

    Спойлер
    //Когда-то давно в далекой галактике
    PLACECamera_Shake_scr_7:
    pushfq //x64
    cmp [Camera_Control_Main_Checker],#0
    je @f
    cmp [Disable_Camera_Shake_Checker],#0
    je @f
    mov ecx,#0
    @@:
    popfq
    mov [rbx+00000100],ecx //origin
    jmp BACKCamera_Shake_scr_7

     

     

  5. 11 часов назад, Xipho сказал:

    Да, именно отдельный поток

    Почему не главный поток?

    Спойлер
    В 18.08.2022 в 12:57, Antonshka сказал:

    Главный поток должен быть абстрагирован

    Ты планировщик можешь хоть в основной поток, хоть в дополнительный воткнуть. Следует абстрагироваться от таких загонов, как абстрагирование, WaitForSingleObject и т.п. И не забывай, что ты всё-таки на плюсах пишешь.

     

    Такой планировщик справиться с плавным появлением/скрытием окна? А также с отменой отложенного задания? Думается мне что создать такой планировщик будет непростой задачей. Но сама идея конечно отличная.

  6. 1 час назад, Xipho сказал:

    Так тебе вроде все расписали уже о_О. Мой планировщик тебе ничего нового не покажет. Не, если очень надо, я набросаю, конечно, но исходя из того, что выше писали, ты там уже ничего нового не увидишь.

    Я думал у тебя что-то иное.

    Что он из себя представляет? Опиши в нескольких словах. Это дополнительный поток, время жизни которого равно времени жизни главного GUI потока, и который обрабатывает очередь задач? Или это просто обработчик задач встроенный в главный GUI поток?

    Ты сказал, - "планировщик". Но не сказал что он из себя конкретно представляет. Или и сказал, но мне для понимания этого было не достаточно.

  7. 15 часов назад, youneuoy сказал:

    А желания у тебя странные. Мне казалось, что ты хочешь либу для интерфейса написать. А это проще делать на плюсах. WinAPI хороши для управления виндой, но тебе это нужно по минимуму.

    Ну лааадно, зааажаааааарится как-нибудь

    Спойлер

     

     

    15 часов назад, youneuoy сказал:

    я тебе их и предложил. Ты выше не писал о том, что разные способы изучаешь - ты в один единственный упёрся.

    Я все ждал решения от @Xipho. А он молчит, как партизан.

    Все хотел посмотреть на его планировщика.

  8. 55 минут назад, Xipho сказал:

    Не припомню, чтобы я эту задачку решал, если честно. Пришел в тему, потому что меня тут отметили. Задачку посмотрю по наличию времени, должно быть, интересная...

    А я подумал что вы все еще ее решаете и никак решить не можете.

  9. Помимо задержки создания/удаления окна, должно еще быть плавное его появление/скрытие. Альфабленд от 0 до 255. Я забыл про этот момент.

    Если реализовать плавность в главном потоке, то отзывчивость GUI будет зависеть от того как быстро изменяется прозрачность окна. Ведь при изменении прозрачности нужен Sleep(1), иначе прозрачность будет изменяться мгновенно.

    Получается что без создания дополнительного потока, который будет управлять прозрачностью и вдобавок задержкой, не обойтись.

  10. 9 часов назад, Garik66 сказал:

    3. 20 - 25 минут (больше времени ушло на укладывание в голове объяснения  автора видео

    Значит у тебя первое место, у меня второе, у @Xipho и @youneuoy третье или четвертое, соответственно. А мы молодцы.

  11. 1 час назад, Garik66 сказал:

    Задача норм, в кометах есть хороший разбор

    Я до часу ночи читал комментарии и даже смотрел другие видеоролики на эту задачу. И только один, один единственный комментарий, навел меня на нужную мысль. Утром я ее развил и понял ответ.

    А кто-то ее понял, как пишут, и за 15 - 30 минут.

     

    А ты все понял в этой задаче? Почему именно такое решение, а не другое? Долго думал? Только не пиши ход мыслей, пусть и другие попробуют себя.

     

     

  12. Привет всем, хотите ли проверить себя на смекалку? Тогда эта вирусная логическая задача будет вам интересна.

    Спойлер

     

     

    Сам я смог ее решить/осознать только сегодня... Увидел вчера.

    Сразу скажу, что для меня объяснение её решения автором видео является недостаточным. Также считают и некоторые комментаторы. Первое непонимание с которым столкнулись люди, - почему удаляем весь май? А вы, сможете ее целиком осознать?

    • Плюс 1
  13. 42 минуты назад, youneuoy сказал:

    он и при слипе не тратит.

    Я не говорил что он при Sleep тратит. Sleep меня пока вообще не интересует.

     

    44 минуты назад, youneuoy сказал:

     Ты видел, на что ответ цитировал?

    В твоем сообщении ты написал

    5 часов назад, youneuoy сказал:

    в отсутствии сообщений процессорное время у тебя отдельный поток будет потреблять(и кажется он будет не один)🙂

    Я тебе привел цитаты, с форума и из книги, что это не так, что процессорное время не тратится, в моем конкретном случае, при использовании WaitForSingleObject.

     

    47 минут назад, youneuoy сказал:

    потому, что ты как минимум с понедельника этим загоняешься😀А мог бы сделать нужную штуку и забыть уже.

    Это не загон, это обучение. Поиск лучших вариантов.

     

    53 минуты назад, youneuoy сказал:

    место простое, задачу можно поставить простую и просто же её разрешить. А ты сам себе палки в колёса пихаешь.

    Дай же пообщаться с интересными людьми. Развеяться 🤗.

     

    55 минут назад, youneuoy сказал:

    В плюсах есть над подобными штуками обёртки для всего, что тебе нужно - thread, atomic, cancellation_token, condition_variable, mutex, scoped_lock, не перечесть всего. Это всё удобнее, чем стандартные

    Понял теперь о чем ты. Тут такая ситуация, - я читал Рихтера, читал Щупака, в этих книгах не было разговора об std. В них все про WinAPI. Потому у меня такое восприятие.

    Ну и плюс я сам, низкоуровневый любитель. Я хочу работать с "главарями", не с посредниками. Я не люблю за это с#. За то что он за меня решает. Но ты скажешь может быть тогда, пиши на ассемблере. Ассемблер тоже крут, его я тоже люблю. Но С++ интереснее.

     

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

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

    Что-то в этом есть. Но мне хочется самому все организовать. Я бы не сказал что это требует особых усилий. Это достаточно быстро все пишется. Плюс я знакомлюсь с внутренним устройством всех этих систем. С внутренним это относительно, насколько это позволяет Microsoft. Где-то в книге читал что это полезно знать.

    Придет время, и я возможно перейду на std. Хотя я и сейчас ее очень часто использую.

    • Спасибо 1
  14. 41 минуту назад, youneuoy сказал:

    если очень хочешь, используй WaitForSingleObject, CreateWaitableTimer или любую другую вещь в качестве замены для sleep🙂И задержка для sleep как-то вроде настраивается(но не всеми системами поддерживается, и вообще это бесполезная для написания подобных библиотек инфа).

    Sleep или замену Sleep я не планировал использовать. Это я просто привел цитату с сайта о том что поток не тратит CPU время при функции WaitForSingleObject.

    Также и про спин, - речь не о самом спине, а о том что система умеет распределить процессорное время при заблокированном потоке, как я понял из всего прочитанного.

    Вот пример более конкретный относительно объекта события и WaitForSinlgeObject. Из Рихтера.

    Спойлер

    If the resource is unavailable or the special event hasn't yet occurred, the system places the thread in a wait state, making
    the thread unschedulable. This prevents the thread from wasting any CPU time. While your thread is waiting, the system
    acts as an agent on your thread's behalf. The system remembers what your thread wants and automatically takes it out of
    the wait state when the resource becomes available—the thread's execution is synchronized with the special event.

     

    49 минут назад, youneuoy сказал:

    Следует абстрагироваться от таких загонов, как абстрагирование, WaitForSingleObject и т.п. И не забывай, что ты всё-таки на плюсах пишешь.

    Этот момент я не понял. Почему эти вещи загоны? Есть же принцип такой, Принцип единственной ответственности, что сущность должна заниматься исключительно своим делом. Вот и пускай объекты-контролы занимаются своими делами, а не основной поток.

    WaitForSingleObject чем плох? Я пишу на плюсах, что значит не забывать? Твои сообщения я часто не понимаю, даже с нескольких раз, поэтому переспрашиваю. Дело во мне, потому что я замечаю это и при общении с другими.

     

    53 минуты назад, youneuoy сказал:

    Ты чего-то всё время в кучу сваливаешь огромное количество вещей и топчешься в самых простых местах😀

    Да где же это простые вещи. На таких мелочах все и строится. Я пока возился с этим, да и вообще, с тем что раньше, многое чего узнал. А если бы не возился, то так бы и оставался с тем что было. Так что это к лучшему.

  15. 1 час назад, youneuoy сказал:

    в отсутствии сообщений процессорное время у тебя отдельный поток будет потреблять(и кажется он будет не один)

    Отдельный поток будет потреблять самую малость времени сидя на WaitForSingleObject.

    Цитата

    The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters an efficient wait state. The thread consumes very little processor time while waiting for the object state to become signaled or the time-out interval to elapse.

    Это время будет уходить лишь на проверку освободился ли объект событие. Далее поток не будет занимать процессорное время. То есть если поток ждет 3 секунды, он не тратит все эти 3 секунды зря. Он просто уступает время другим потокам в системе.

    Raymond Chen

     

    То есть я про то что отдельный поток по моему мнению лучше чем система с PeekMessage в MessageLoop. Пускай PopupMenu сам отвечает за себя, вообще любой элемент которому нужен таймер, пусть сам его и создает, в виде потока.  Главный поток должен быть абстрагирован от всех этих замеров прошедшего времени, проверки есть ли отложенные задания для все контролов библиотеки для которых это предусмотрено. Зачем нужна эта холостая проверки всех этих отложенных заданий, в случае если ни один контрол пока его не требует.

     

    2 часа назад, Xipho сказал:

    Да ничего такого я не придумал, это обычный механизм. Тот же самый event loop в рамках одного потока. Так работал в кишках JS до того, как наконец-то стал много поточным, так работает еще куча всего всякого. И это оптимальный механизм, на мой взгляд (да и не только на мой).

    В рамках одного главного GUI потока? То есть использование PeekMesage вместо GetMessage для постоянной работы потока?

    До конца я не понял схему, все равно. Объясни на конкретном примере, на куске кода, если не трудно. На словах мне иногда трудно понять о чем идет речь.

     

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

    в отсутствии сообщений процессорное время у тебя отдельный поток будет потреблять(и кажется он будет не один)

    Вот еще на одного сайте нашел

    Спойлер

    WaitForSingleObject в заблокированном состоянии вообще не потребляет процессора до тех пор пока объект ядра не придет в засигналенное состояние (т.о. проверка условия выхода из цикла делается 1 раз, правда в другом месте, там где происходит измениние состояния семафора), а Sleep раз в милисекунду пробуждает ваш поток (все равно через ядро) и потребляет ресурсы (т.е. проверка выхода из цикла делается 1 раз в милисекунду и срабатывает за все это время 1 раз).  

    Это из Рихтера

    Спойлер

    Spinlocks assume that the protected resource is always accessed for short periods of time. This makes it more efficient to
    spin and then transition to kernel mode and wait. Many developers spin some number of times (say 4000), and if access to
    the resource is still denied, the thread transitions to kernel mode, where it waits (consuming no CPU time) until the
    resource becomes available. This is how critical sections are implemented.

     

  16. 8 часов назад, youneuoy сказал:

    а почему бы не воткнуть туда PeekMessage?

    В главный MessageLoop? Там лучше использовать GetMessage, чтобы не было потребления процессорного времени в отсутствии сообщений.

    8 часов назад, youneuoy сказал:

    Ну и std thread довольно удобная штука, а в отличие от виндовых функций ещё и кроссплатформенная. Зря не пользуешься.

    _beginthreadex использую из-за совместимости с CRT функциями. Не знаю как в этом плане ведет себя std::thread, скорее всего, по логике, std::thread должна быть также совместима. Но, так как в я пока не чувствую себя ущемленным при использоании _beginthreadex , я не перехожу на std::thread.

    Кроссплатформенность мне пока не по карману, иначе нужно весь код писать в таком стиле.

     

    8 часов назад, youneuoy сказал:

    почему?

    Мне известно только 3 вида таймера.

    - Стандартный таймер (WM_TIMER Post сообщение). Он не подходит. Неизвестно когда до него дойдет очередь, а мне нужен точный интервал. Плюс из-за него подвисает главный поток, в котором он обрабатывается, незначительно, но все же. Даже если для таймера использовать свою отдельную процедуру.

    - Мультимедийный таймер. Он тоже не подходит. Он устарел. Плюс для обработки своей процедуры он использует свой поток.

    - CreateTimerQueueTimer. Но там может возникнуть ситуация, что создастся новый поток. Но зачем мне это, я могу тогда сам создать поток.

     

    8 часов назад, youneuoy сказал:

    не хочешь поток - используй PeekMessage

    Нет, я хочу использовать другой поток. Один поток на все дерево PopupMenu. Он контролирует задержки, плавность появления/скрытия. Он создается и удаляется только для главного родительского PopupMenu окна. Но, @Xipho говорит что это не лучший вариант.

     

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

    Да в смысле название функций? Самописный планировщик.

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

    Понятно, я думал что это какой-то предопределенный механизм WinAPI.

    А как он будет устроен, этот самописный планировщик. Что из себя он будет представлять? Это какой-то отдельный поток, который создается в начале работы приложения, и удаляется после его завершения? И например у него есть буферная очередь с заданиями. Опиши вкратце его схему. Мне уже не столько интересно это для проекта, сколько просто, для себя, что ты там такое придумал, чего я не нашел ни в интернете ни у себя в голове.

     

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

    В край, конечно, можно упороться и по PeekMessage, но лично моё мнение - это изврат.

    Как понять по PeekMessage? Это то что предлагал выше @youneuoy? Даже если воткнуть вместо GetMessage, PeekMessage, то что это меняет? Кто подаст команду/сообщение в очередь сообщений Потока А? Ведь в этом вся суть проблему, - кто будет инициатором для главного потока. Главный поток только имеет право создавать окна, по задумке.

     

    Использовать PeekMessage чтобы поток не засыпал? Ну хорошо, используем, поток не спит, а дальше что? Кто отсчитывает интервал, кто подает нужное сообщение. Сам Поток А, используя что-то вроде GetTickCount? Что-то так себе такая схема.

  17. 1 час назад, Xipho сказал:

    https://blog.andreiavram.ro/job-scheduler-cpp/ 
    Если не зайдет, гугли writing simple job scheduler c++

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

    Ну да, у него основа std::thread. Я кстати почему-то не склонен к std::thread. Предпочитаю beginthreadex.

    Хотя std::vector, std::wstring, очень приветствую.

     

    Скажи название функций, этого таинственного планировщика.

     

    По логике, - должен быть "кто-то", кто разбудить главный GUI поток А. Который засыпает в функции GetMessage. Кто-то кто пошлет в очередь сообщений новое Post сообщение. Или кто-то кто пошлет сообщение Send-типа, что также разбудит Поток А, обойдя очередь.. В любом случае, кто-то должен разбудить Поток А через и только через сообщение. Иначе поток не проснется.

    Таймер, - нет. Другой поток, - нет. DCP, - нет, там куча заморочек. Не представляю что еще способно разбудить Поток А. Таинственный планировщик? Но не лежит ли в его основе ThreadPool, вообще манипуляция своими собственными потоками?

  18. 5 часов назад, Xipho сказал:

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

    Это понятно. Я про функции, которые управляют этими заданиями. Создают их, удаляют.

     

    5 часов назад, Xipho сказал:

    Можно посмотреть примеры, как в винде организован отложенный вызов процедур (Deferred Procedure Call), и сделать по аналогии.

    Посмотрел, ничего не понятно. Что-то на уровне драйверов.

     

    5 часов назад, Xipho сказал:

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

    Подумал. Есть еще вариант с ThreadPool.

    CreateTimerQueueTimer. Но там может возникнуть ситуация, что создастся новый поток.

    Спойлер
    WT_EXECUTELONGFUNCTION
    0x00000010
    The callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.

     

    Еще есть мультимедийным таймер, более точный.

    Но все это оверинженеринг. Поток на родителя, и все.

  19. 2 часа назад, Xipho сказал:

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

    Что за отложенные задания? Не могу ничего найти на них.

  20. 5 часов назад, Xipho сказал:

    Потому что ты хочешь изымать из этой очереди сообщения выборочно. Очередь сообщений винды под это не затачивалась. Чтобы извлечь одно сообщение, тебе надо вычитать все предыдущие и снова их положить в очередь. Разве это не бред?

    Хорошая новость, - оказывается все намного проще. Вначале это показали тесты, а теперь и более внимательное чтение MSDN.

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

    PeekMessage

    Спойлер

    During this call, the system dispatches (DispatchMessage) pending, nonqueued messages, that is, messages sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are processed in the following order:

    • Sent messages
    • Posted messages
    • Input (hardware) messages and system internal events
    • Sent messages (again)
    • WM_PAINT messages
    • WM_TIMER messages

    Нужно лишь указать фильтр. У меня это

    while (PeekMessageW(&msg, currentPopupMenu->hWnd, WM_APP + 1, WM_APP + 5, PM_REMOVE)) {

     

    Я запихал сообщения в очередь

    Спойлер
    PostMessageW(thisPopupMenu->hWnd, WM_USERSetIcon, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_USERGetIcon, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_CTLCOLORSTATIC, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_USERIsWindowVScrollActive, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_USERPopupMenuDestroyTreeOfFLoatPopupMenu, 0, 0); //Это и все сообщения выше имеют номер сообщение выше WM_APP + 5
    PostMessageW(thisPopupMenu->hWnd, WM_USERPopupMenuCreatePopupMenuByDelay, 0, 0); //WM_APP + 5
    PostMessageW(thisPopupMenu->hWnd, WM_USERSetDCFontColor, 0, 0); //Это и все сообщения ниже имеют номер сообщение выше WM_APP + 5
    PostMessageW(thisPopupMenu->hWnd, WM_USERIconChanged, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_CTLCOLOR, 0, 0);
    PostMessageW(thisPopupMenu->hWnd, WM_CTLCOLOREDIT, 0, 0);

     

    , и только WM_APP + 5 удалилось, как показала консоль-отладчик. То есть сообщение WM_APP + 5 было не в начале очереди, однако нормально удалилось.

    Буду использовать один специальный поток на родителе PopupMenu. Все дочернии окна, их появление/скрытие, будут управляться им. Думаю это хорошая схема.

  21. 33 минуты назад, Xipho сказал:

    что-то вроде местечкового планировщика, почитай, как их обычно пишут.

    Что-то ничего не нашел в интернете. Поиск выдает планировщик Windows.

     

    35 минут назад, Xipho сказал:

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

    Главный поток приложения тоже простаивает, когда нет сообщений. Да и другие потоки, тоже случается что засыпают.

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

    • Печалька 1
  22. 17 минут назад, Xipho сказал:

    Чтобы извлечь одно сообщение, тебе надо вычитать все предыдущие и снова их положить в очередь. Разве это не бред?

    Ну вообще, наверно бред. Я бы хотел способ попроще. Способ удалить одно сообщение.

    Но что я могу сделать, так устроили Microsoft.

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

    То WM_NCLBUTTONUP не ловится процедурой, потому что так устроено окно, то это, то то. Куча костылей.

     

    24 минуты назад, Xipho сказал:

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

    Это PopupMenu. Реализация задержки появления дочернего PopupMenu. Навел на пункт меню, но окно показывается только спустя несколько секунд. А если отвел курсор с пункта, то таймер должен отключится, и окно не должно появиться. Вот и вся задача.

    Таймеры это дно, у них наименьший приоритет. Потому я использую потоки, для задержки. Поток-таймер не должен сам создавть окно, поэтому он посылает сообщение главному потоку. Но посылка через SendMessage приводит к DeadLock'y. Я использую PostMessage.

  23. 5 часов назад, Xipho сказал:

    Наверное, ты это читал, но скину на всякий случай: https://docs.microsoft.com/ru-ru/windows/win32/winmsg/about-messages-and-message-queues#message-routing

    Вчера читал всю эту статью. Также про функции. Также на других сайтах.

     

    5 часов назад, Xipho сказал:

    Конечно, бред. Потому что положенное в очередь сообщение будет дожидаться обработки по порядку (в общем случае) поступления. FIFO принцип. То есть, чтобы добраться до последнего сообщения, нужно вычитать все предыдущие. Ну и плюс вычитка сообщений всё-таки предполагается в основном потоке приложения. А в том кейсе, что ты описал, это не выглядит как FIFO, так как есть дополнительные условия и желание изымать сообщение из очереди при определенных обстоятельствах.

    Все равно не понял почему работа с очередью сообщений это бред.

    Поток А - это главный GUI поток, он создал кнопку, и он создал поток Б.

    Поток А вызывает функцию "отмена", в которой закрывает поток Б, ждет его окончания, и зачищает свою же очередь сообщений, перед тем как выйти из функции "отмена". То есть зачистка сообщений производится главным потоком А.

    Вот так примерно

    Спойлер
    VOID PopupMenu::clearMessageQueueFromUserMessages() {
      MSG msg{ 0 };
      PopupMenu* currentPopupMenu = rootPopupMenu;
      while (currentPopupMenu) {
        if (currentPopupMenu->hWnd) {
          std::vector<MSG> messagesToReturn;
          while (PeekMessageW(&msg, currentPopupMenu->hWnd, 0, 0, PM_REMOVE)) {
            switch (msg.message)
            {
              case WM_USERCREATEPOPUPMENUWINDOWBYDELAY:
                break;
              default:
                messagesToReturn.push_back(msg);
                break;
            }
          }
          if (messagesToReturn.size()) {
            std::ranges::reverse_view reverseView{ messagesToReturn };
            for (auto& messageToReturn : reverseView) {
              PostMessageW(currentPopupMenu->hWnd, messageToReturn.message, messageToReturn.wParam, messageToReturn.lParam);
            }
          }
        }
        currentPopupMenu = currentPopupMenu->childPopupMenu;
      }
    }

     

    Сообщения засовываются обратно в очередь в правильном порядке. Будет как и было, в FIFO.

     

    5 часов назад, Xipho сказал:

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

    Идея интересная, но по моему не реализуемая. Буфер создать не проблема. Пусть поток Б заполняет его для потока А.

     

    Вот ситуация без отмены потока Б.

    - Поток А создал поток Б.

    - Поток А вернулся в MessageLoop, вызвал GetMessage, GetMessage обнаружил что новых сообщений нет, и поэтому Поток А ушел в спячку.

    - Поток Б завершился сам, после 30 секунд, и заполнил буфер.

    Но поток А спит, он не может понять что нужно обработать буфер. Нужен кто-то кто его разбудит. Это не может быть поток Б, иначе зачем тогда нужен буфер. Значит это Поток С, который пусть будет создан вместе с потоком Б. Тогда, Поток С, увидев что поток Б завершился сам, вызывает (PostMessageW) поток А, чтобы тот обработал буфер. Но где-то в этот самый момент, я передумал, хочу отменить обработку. Для этого Поток А идет и отменяет Поток С, но он не успел, Поток С уже запостил сообщения из буфера. Ситуация повторилась, стала как и с потоком Б.

    Значит нужно обязательное удаление сообщений из потока А самим потоком А.

     

    Пока что-то иногда вылазят ошибки. Нужно разбираться.

  24. 57 минут назад, Xipho сказал:

    В цикле GetMessage/DispatchMessage

    В главном MessageLoop приложения? В этом?

    Спойлер
    while ((getMessageResult = GetMessageW(&msg, NULL, 0, 0)) != 0)	{
      if (getMessageResult == -1) {
        break;
      }
      else {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
      }
    }

     

     

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

    Но осуществлять подобное средствами очереди сообщений винды - имхо, бред.

    Я не понял этот момент. Что такое "средства очереди сообщений винды"? Это функции типа GetMessage/PeekMessage?

    Осуществлять удаление этими функциями бред? Тогда какими не бред?

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

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.