Проблема с PostMessage

Тема в разделе "WASM.WIN32", создана пользователем AlexCab, 8 сен 2008.

  1. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Требуется отправить сообщение (пользовательское 400h+x), из оконной процедуры при обработке собщения "WM_SIZE",
    в цикл сообщений (поставить в очередь), попробовал при помощи PostMessage, до цикла доходит только первое сообщение
    при создании окна, остальные пропадают хотя PostMessage возвращает "ИСТЕННО" тобыш сообщение в очереди.
    В чём может быть проблема?
     
  2. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    [телепатор]: SendNotifyMessage пробовали?

    зы. а может быть, просто, окну кроме как при создании больше не поступает сообщений WM_SIZE?
    т.е. ваш Post тупо не вызывается?
     
  3. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    SendNotifyMessage передаёт сообщения процедуре окна, сообщения поступают и PostMessage завершается удачно но
    но сообщения так и не доходят до цикла.
     
  4. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Код оконой процедуры:
    Код (Text):
    1.      
    2.                ;;Точка входа оконной функции
    3.                Тчк_вхд:
    4.                ;;Извлечение переданых  парамтров
    5.                push ebx ebp esi edi
    6.                add esp, 20
    7.                mov esi,[esp]
    8.                add esp, 4
    9.                mov edi,[esp]
    10.                add esp, 4
    11.                mov ecx,[esp]
    12.                add esp, 4
    13.                mov edx,[esp]
    14.                sub esp,32
    15.                ;;Определние действия
    16.                cmp edi,0001h
    17.                je Взв_вцк
    18.                cmp edi,0003h
    19.                je Взв_вцк
    20.                cmp edi,0005h
    21.                je Взв_вцк
    22.                cmp edi,0006h
    23.                je Взв_вцк
    24.                cmp edi,0007h
    25.                je Взв_вцк
    26.                cmp edi,0008h
    27.                je Взв_вцк
    28.                cmp edi,0002h
    29.                je Унч_окн
    30.                jmp Обр_пмл
    31.                ;;Помещение сообщения в очередь потока
    32.                Взв_вцк:
    33.                push edx
    34.                push ecx
    35.                add edi,400h
    36.                push edi
    37.                sub edi,400h
    38.                push esi
    39.                call [PostMessage]
    40.                xor eax,eax
    41.                jmp Кнц_обр
    42.                ;;Уничтожение окна
    43.                Унч_окн:
    44.                push 0
    45.                call [PostQuitMessage]
    46.                xor eax,eax
    47.                jmp Кнц_обр
    48.                ;;Обработка сообщений по умолчанию
    49.                Обр_пмл:
    50.                push edx
    51.                push ecx
    52.                push edi
    53.                push esi
    54.                call [DefWindowProc]
    55.                ;;Выход из функции
    56.                Кнц_обр:
    57.                pop edi esi ebp ebx
    58.                pop ebx
    59.                add esp, 010h
    60.                push ebx
    61.                xor ebx,ebx
    62.                ret
     
  5. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Говоря чисто теоретически.

    В Windows есть такое поведение: пока кнока на мыши не отпущена - очередь стоит и только сообщения от мыши имеют приоритет. Если что-то послано через PostMessage() или, например было вызвано InvalidateRect() - всё это придёт ПОСЛЕ того как кнока на мыши будет отпущена.

    Теперь, как происходит resize окна? Кнока на мыши всё время нажата, так что сообщения не придут - или придут после resize.
     
  6. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    AsmGuru62
    Свойства системы -> дополнительно -> быстродействие -> Отображать содержимое окна при перетаскивании
    От этого флажка и зависит будут сообщения в этом случае приходить сразу или "с опозданием"
     
  7. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Я так понял что пока кнопка нажата сообщения в очередь не поступают вообще и следовательно теряются,
    если снять флажок "Отображать содержимое окна при перетаскивании" то по за вершению ресайза приходит одно сообщение
    с окончательными размерами, но как обойти ограничение когда флажок установлен?
     
  8. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Тогда только SendMessage() или просто вызвать напрямик то что надо вместо PostMessage().
     
  9. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Если-бы всё было так просто:) В цикле сообщений ваполняется функция обрабатывающая данные, которая будет конфликтовать
    с подпрограммой пререрисовыающей окно если её визивать из процедуры окна. Есть ли способ отследить ресайз иной кроме
    сообщения "WM_SIZE" чтоб потом определить новые размеры "GetClientRect"ом и перерисовать окно?
     
  10. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Или может передать сообжение через другой трейд?
     
  11. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    >Или может передать сообжение через другой трейд?

    Ну, так сами и проверьте, это не опасно :)
     
  12. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Конечно - ставишь флаг и анализирешь его
    с похожей траблой боролся здесь ([MyFlags] анализируется в очереди сообщений) или можно проверять его при обработке wm_paint.
     
  13. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    AlexCab
    Что-то непонятное происходит. Я сделал достаточно программ на Windows, которые работают с данными и окно надо перерисовывать и никогда не было проблем с resize. В твоей программе обработка данных проис ходит в real-time? Всё время? И тебе надо периодически отрисовывать результат? Если так, то самое лучшее решение - это перенести обработку данных в другой Thread.
     
  14. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Если бы отрисовка и обработка данных могли работать в разных трейдах проблем бы небило:). Я пишу редактор при вводе симола,
    виделении, ресайзе и тп. вызваются функции собственно и виполняющие эти действия, но кроме пользователя этими же
    функции использует интерпритатор макро язика, работающий в цикле сообщений real-time, именно там потому-что после
    выполения одной строки макроса выполняется проверка нового сообщения(иначе если зависнет макрос, он заввеси всю прогамму)
    и например пользоватль запуитл макрос и решил изменть размер окна, интерпретатор выполняет опертор "ОБНОВИТЬ" в трейде
    выборки сообщений, "WM_SIZE" в тоже время обновляет окно в своём трейде, в результате на этране каша:dntknw:
     
  15. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    AlexCab
    Синхронизация потоков? А какие проблемы-то?
    В простейшем варинте опять таки собственные флаги, а так всякие там семафоры, мютексы и т.п. Стандартная задача имеет кучу типовых решений, которые элементарно привязываются к нужной задаче.
    Подробности хорошо описаны у Рихтера.
    Как вариант сделай три потока, чтобы два работали с данными (редактор, интерпретатор), а третий по этим данным рисовал на экране.

    Кучеряво ;)))
     
  16. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    "этими же функции использует интерпритатор"

    Вот это и есть проблема. Ставь на такие функции (в которые могут войти разные треды) критические секции и всё станет на место.
     
  17. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Спасибо всем кто откликнулся!
    У меня так и не получилось добится возврата сообщений, но я нашол более простое и красивое решение - убрал заглавие и рамку
    главного окна, в нижнем правом уголу прорисовывается контрол за который можно менять размер окна (используя сообщения
    "WM_MOUSEMOVE","WM_LBUTTONDOWN","WM_LBUTTONUP"), а таскать окно за любую не активную часть.
    Выкладываю воследнюю версию оконной процедуры может кому пригодится (работает крайне нестабильно):
    Код (Text):
    1.         Тчк_вхд:
    2.         ;;Извлечение переданых  парамтров
    3.         push ebx ebp esi edi
    4.         add esp, 20
    5.         mov esi,[esp]
    6.         add esp, 4
    7.         mov edi,[esp]
    8.         add esp, 4
    9.         mov ecx,[esp]
    10.         add esp, 4
    11.         mov edx,[esp]
    12.         sub esp,32
    13.         ;;Если одо из возвращаемых сообщений, возврат
    14.         cmp edi,0001h ;WM_CREATE
    15.         je Взв_вцк
    16.         cmp edi,0002h ;WM_DESTROY
    17.         je Взв_вцк
    18.         cmp edi,0005h ;WM_SIZE
    19.         je Взв_вцк
    20.         cmp edi,0006h ;WM_ACTIVATE
    21.         je Взв_вцк
    22.         cmp edi,0007h ;WM_SETFOCUS
    23.         je Взв_вцк
    24.         cmp edi,0008h ;WM_KILLFOCUS
    25.         je Взв_вцк
    26.         cmp edi,000Fh ;WM_PAINT
    27.         je Взв_вцк
    28.         jmp Нет_вцк
    29.         Взв_вцк:
    30.         push edx ecx
    31.         push 1
    32.         call [GetKeyState]
    33.         cmp eax,1
    34.         je Лкн_нен
    35.         push 0
    36.         push 0
    37.         push 0202h  ;WM_LBUTTONUP
    38.         push esi
    39.         call [PostMessage]
    40.         Лкн_нен:
    41.         pop ecx edx
    42.         push edx ecx edi
    43.         add edi,400h
    44.         push edx
    45.         push ecx
    46.         push edi
    47.         push esi
    48.         call [PostMessage]
    49.         pop edi ecx edx
    50.         Нет_вцк:
    51.         ;;Сохрание позиции если сообщение WM_NCLBUTTONDOWN
    52.         cmp edi,00A1h ;WM_NCLBUTTONDOWN
    53.         jne Нет_схп
    54.         mov [Буф_пзц + 00h],edx
    55.         mov [Буф_пзц + 04h],ecx
    56.         Нет_схп:
    57.         ;;Уничтожение окна если сообщение WM_DESTROY
    58.         cmp edi,0002h ;WM_DESTROY
    59.         jne Нет_унч
    60.         push 0
    61.         call [PostQuitMessage]
    62.         xor eax,eax
    63.         jmp Кнц_обр
    64.         Нет_унч:
    65.         ;;Если сообщение 405(ресайз) или 403(мув), и если кнопка мыши нажата - повторный захват
    66.         cmp edi,0405h
    67.         je Рсз_мув
    68.         cmp edi,0403h
    69.         je Рсз_мув
    70.         jmp Нет_рсз
    71.         Рсз_мув:
    72.         push 1
    73.         call [GetKeyState]
    74.         cmp eax,1
    75.         je Нет_рсз
    76.         mov eax,[Буф_пзц + 00h]
    77.         push eax
    78.         mov eax,[Буф_пзц + 04h]
    79.         push eax
    80.         push 00A1h ; WM_NCLBUTTONDOWN
    81.         push esi
    82.         call [PostMessage]
    83.         jmp Кнц_обр
    84.         Нет_рсз:
    85.         ;;Обработка сообщений по умолчанию
    86.         push edx
    87.         push ecx
    88.         push edi
    89.         push esi
    90.         call [DefWindowProc]
    91.         ;;Выход из функции
    92.         Кнц_обр:
    93.         pop edi esi ebp ebx
    94.         pop ebx
    95.         add esp, 010h
    96.         push ebx
    97.         xor ebx,ebx
    98.         ret
    99.         ;;Данные
    100.         Буф_пзц: rb 08h
     
  18. AlexCab

    AlexCab New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2008
    Сообщения:
    142
    Решение оказалось чертовски простым:)
    Чтоб выполнять обработку данных в цикле сообщений, достаточно слать после проверки сообщения ("PeekMessage") какое нибудь из пользовательских
    сообщений оконной процедуре, функция "SendMessage" обеспечивает синхранезацию потоков:
    Код (Text):
    1.         xor al,al
    2.         mov [work_on],al
    3.   msg_loop:
    4.         mov al,[work_on]
    5.         cmp al,0
    6.         je no_work                                                   ;Проверка требуется ли выполнение работы
    7.         invoke  PeekMessage,msg,NULL,0,0,PM_REMOVE ;Проверяем есть ли в очереди сообщения
    8.         cmp eax,0
    9.         jne disp_mes                                                ;Если есть - обработка
    10.         invoke  SendMessage,hwnd,401h,0,0                ;Если нет - цикл работы
    11.         mov [work_on],al                                          ;Если возвращено 0 - остановить цикл работы
    12.         jmp msg_loop
    13.   no_work:
    14.         invoke  GetMessage,msg,NULL,0,0                    ;Если нет работы ожедание сообщения
    15.   disp_mes:
    16.         cmp     eax,1
    17.         jb      end_loop
    18.         jne     msg_loop
    19.         invoke  TranslateMessage,msg
    20.         invoke  DispatchMessage,msg
    21.         jmp     msg_loop