Требуется отправить сообщение (пользовательское 400h+x), из оконной процедуры при обработке собщения "WM_SIZE", в цикл сообщений (поставить в очередь), попробовал при помощи PostMessage, до цикла доходит только первое сообщение при создании окна, остальные пропадают хотя PostMessage возвращает "ИСТЕННО" тобыш сообщение в очереди. В чём может быть проблема?
[телепатор]: SendNotifyMessage пробовали? зы. а может быть, просто, окну кроме как при создании больше не поступает сообщений WM_SIZE? т.е. ваш Post тупо не вызывается?
SendNotifyMessage передаёт сообщения процедуре окна, сообщения поступают и PostMessage завершается удачно но но сообщения так и не доходят до цикла.
Код оконой процедуры: Код (Text): ;;Точка входа оконной функции Тчк_вхд: ;;Извлечение переданых парамтров push ebx ebp esi edi add esp, 20 mov esi,[esp] add esp, 4 mov edi,[esp] add esp, 4 mov ecx,[esp] add esp, 4 mov edx,[esp] sub esp,32 ;;Определние действия cmp edi,0001h je Взв_вцк cmp edi,0003h je Взв_вцк cmp edi,0005h je Взв_вцк cmp edi,0006h je Взв_вцк cmp edi,0007h je Взв_вцк cmp edi,0008h je Взв_вцк cmp edi,0002h je Унч_окн jmp Обр_пмл ;;Помещение сообщения в очередь потока Взв_вцк: push edx push ecx add edi,400h push edi sub edi,400h push esi call [PostMessage] xor eax,eax jmp Кнц_обр ;;Уничтожение окна Унч_окн: push 0 call [PostQuitMessage] xor eax,eax jmp Кнц_обр ;;Обработка сообщений по умолчанию Обр_пмл: push edx push ecx push edi push esi call [DefWindowProc] ;;Выход из функции Кнц_обр: pop edi esi ebp ebx pop ebx add esp, 010h push ebx xor ebx,ebx ret
Говоря чисто теоретически. В Windows есть такое поведение: пока кнока на мыши не отпущена - очередь стоит и только сообщения от мыши имеют приоритет. Если что-то послано через PostMessage() или, например было вызвано InvalidateRect() - всё это придёт ПОСЛЕ того как кнока на мыши будет отпущена. Теперь, как происходит resize окна? Кнока на мыши всё время нажата, так что сообщения не придут - или придут после resize.
AsmGuru62 Свойства системы -> дополнительно -> быстродействие -> Отображать содержимое окна при перетаскивании От этого флажка и зависит будут сообщения в этом случае приходить сразу или "с опозданием"
Я так понял что пока кнопка нажата сообщения в очередь не поступают вообще и следовательно теряются, если снять флажок "Отображать содержимое окна при перетаскивании" то по за вершению ресайза приходит одно сообщение с окончательными размерами, но как обойти ограничение когда флажок установлен?
Если-бы всё было так просто В цикле сообщений ваполняется функция обрабатывающая данные, которая будет конфликтовать с подпрограммой пререрисовыающей окно если её визивать из процедуры окна. Есть ли способ отследить ресайз иной кроме сообщения "WM_SIZE" чтоб потом определить новые размеры "GetClientRect"ом и перерисовать окно?
Конечно - ставишь флаг и анализирешь его с похожей траблой боролся здесь ([MyFlags] анализируется в очереди сообщений) или можно проверять его при обработке wm_paint.
AlexCab Что-то непонятное происходит. Я сделал достаточно программ на Windows, которые работают с данными и окно надо перерисовывать и никогда не было проблем с resize. В твоей программе обработка данных проис ходит в real-time? Всё время? И тебе надо периодически отрисовывать результат? Если так, то самое лучшее решение - это перенести обработку данных в другой Thread.
Если бы отрисовка и обработка данных могли работать в разных трейдах проблем бы небило. Я пишу редактор при вводе симола, виделении, ресайзе и тп. вызваются функции собственно и виполняющие эти действия, но кроме пользователя этими же функции использует интерпритатор макро язика, работающий в цикле сообщений real-time, именно там потому-что после выполения одной строки макроса выполняется проверка нового сообщения(иначе если зависнет макрос, он заввеси всю прогамму) и например пользоватль запуитл макрос и решил изменть размер окна, интерпретатор выполняет опертор "ОБНОВИТЬ" в трейде выборки сообщений, "WM_SIZE" в тоже время обновляет окно в своём трейде, в результате на этране каша
AlexCab Синхронизация потоков? А какие проблемы-то? В простейшем варинте опять таки собственные флаги, а так всякие там семафоры, мютексы и т.п. Стандартная задача имеет кучу типовых решений, которые элементарно привязываются к нужной задаче. Подробности хорошо описаны у Рихтера. Как вариант сделай три потока, чтобы два работали с данными (редактор, интерпретатор), а третий по этим данным рисовал на экране. Кучеряво ))
"этими же функции использует интерпритатор" Вот это и есть проблема. Ставь на такие функции (в которые могут войти разные треды) критические секции и всё станет на место.
Спасибо всем кто откликнулся! У меня так и не получилось добится возврата сообщений, но я нашол более простое и красивое решение - убрал заглавие и рамку главного окна, в нижнем правом уголу прорисовывается контрол за который можно менять размер окна (используя сообщения "WM_MOUSEMOVE","WM_LBUTTONDOWN","WM_LBUTTONUP"), а таскать окно за любую не активную часть. Выкладываю воследнюю версию оконной процедуры может кому пригодится (работает крайне нестабильно): Код (Text): Тчк_вхд: ;;Извлечение переданых парамтров push ebx ebp esi edi add esp, 20 mov esi,[esp] add esp, 4 mov edi,[esp] add esp, 4 mov ecx,[esp] add esp, 4 mov edx,[esp] sub esp,32 ;;Если одо из возвращаемых сообщений, возврат cmp edi,0001h ;WM_CREATE je Взв_вцк cmp edi,0002h ;WM_DESTROY je Взв_вцк cmp edi,0005h ;WM_SIZE je Взв_вцк cmp edi,0006h ;WM_ACTIVATE je Взв_вцк cmp edi,0007h ;WM_SETFOCUS je Взв_вцк cmp edi,0008h ;WM_KILLFOCUS je Взв_вцк cmp edi,000Fh ;WM_PAINT je Взв_вцк jmp Нет_вцк Взв_вцк: push edx ecx push 1 call [GetKeyState] cmp eax,1 je Лкн_нен push 0 push 0 push 0202h ;WM_LBUTTONUP push esi call [PostMessage] Лкн_нен: pop ecx edx push edx ecx edi add edi,400h push edx push ecx push edi push esi call [PostMessage] pop edi ecx edx Нет_вцк: ;;Сохрание позиции если сообщение WM_NCLBUTTONDOWN cmp edi,00A1h ;WM_NCLBUTTONDOWN jne Нет_схп mov [Буф_пзц + 00h],edx mov [Буф_пзц + 04h],ecx Нет_схп: ;;Уничтожение окна если сообщение WM_DESTROY cmp edi,0002h ;WM_DESTROY jne Нет_унч push 0 call [PostQuitMessage] xor eax,eax jmp Кнц_обр Нет_унч: ;;Если сообщение 405(ресайз) или 403(мув), и если кнопка мыши нажата - повторный захват cmp edi,0405h je Рсз_мув cmp edi,0403h je Рсз_мув jmp Нет_рсз Рсз_мув: push 1 call [GetKeyState] cmp eax,1 je Нет_рсз mov eax,[Буф_пзц + 00h] push eax mov eax,[Буф_пзц + 04h] push eax push 00A1h ; WM_NCLBUTTONDOWN push esi call [PostMessage] jmp Кнц_обр Нет_рсз: ;;Обработка сообщений по умолчанию push edx push ecx push edi push esi call [DefWindowProc] ;;Выход из функции Кнц_обр: pop edi esi ebp ebx pop ebx add esp, 010h push ebx xor ebx,ebx ret ;;Данные Буф_пзц: rb 08h
Решение оказалось чертовски простым Чтоб выполнять обработку данных в цикле сообщений, достаточно слать после проверки сообщения ("PeekMessage") какое нибудь из пользовательских сообщений оконной процедуре, функция "SendMessage" обеспечивает синхранезацию потоков: Код (Text): xor al,al mov [work_on],al msg_loop: mov al,[work_on] cmp al,0 je no_work ;Проверка требуется ли выполнение работы invoke PeekMessage,msg,NULL,0,0,PM_REMOVE ;Проверяем есть ли в очереди сообщения cmp eax,0 jne disp_mes ;Если есть - обработка invoke SendMessage,hwnd,401h,0,0 ;Если нет - цикл работы mov [work_on],al ;Если возвращено 0 - остановить цикл работы jmp msg_loop no_work: invoke GetMessage,msg,NULL,0,0 ;Если нет работы ожедание сообщения disp_mes: cmp eax,1 jb end_loop jne msg_loop invoke TranslateMessage,msg invoke DispatchMessage,msg jmp msg_loop