SetWindowRgn и окна нестанд. формы

Тема в разделе "WASM.WIN32", создана пользователем mc black, 19 янв 2005.

  1. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    Собственно пытался сделать Subj, да ничего не вышло. Мой код для masm32 в аттачменте. Переписывал пример для TASM, взятый из исходников wasm.ru. С регионами раньше много пробовал в VB6, а вот что не так тут - я не понимаю. Да ведь и при компилировании, запуске, нет ошибок... И нет нужного результата. Может, WM_PAINT как-то надо по-другому?

    [​IMG] 93937023__rgn.zip
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Тут пример региона, masm, файл из проекта radasm, но думаю разберешься.

    [​IMG] 15256341__Region.zip
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    mc black



    в твоём примере регион создается после получения в оконной процедуре WM_CREATE. Попробуй вызвать CreateEllipticRgn и все остальные манипуляции с регионами непосредственно сразу после CreateWindowEx. Должно помочь.
     
  4. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    Еееессс! Заработала :) Твой исходник я пока не смотрел, cresta. Очень убедительным был совет насчет делать это после CreateWindowEx! СПАСИБО!!! Ещё наблидается одна трабла: регион красиво рисуется, курсор принимает форму часиков, когда находится над окном. Если окно минимизировать, а потом показать, то трабла проходит. Что в этом случае может быть не так? В смысле я считаю, что часиков я видеть не должен.

    [​IMG] 396839516__rgn.zip
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    mc black



    Я в твоём исходнике хрен разберусь, какой-то старинный стиль написания кода :) У тебя вроде не обрабатывается никакое из сообщений, присылаемых при активации\деактивации окна. Если тебе надо, чтобы при деактивации твоего окна менялся курсор на старый, обрабатывай например сообщение WM_ACTIVATE, и смотри, что содержится в wParam, точнее в его low word. Там константа, соответствующая состоянию окна:


    Код (Text):
    1.     mov eax,wParam
    2.     and eax,0FFFFh
    3.     cmp eax,WA_INACTIVE
    4.     jne @ActivState
    5.     ;тут что-нибудь делаем, если окно было деактивировано
    6.     ;например восстанавливаем стандартный курсор
    7.     jmp @Ret
    8.     @ActivState:
    9.     ;тут действия, если окно активировано
    10.     ;например устанавливаем новый курсор
    11.     @Ret:
    12.     xor eax,eax
    13.     ret




    P.S.

    Это в чем ты так программу пишешь?
     
  6. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Создавать регион по событию WM_CREATE можно.

    Для этого нужно обработать WM_NCCREATE и сохранить хендл переданный в оконную процедуру в качестве первого параметра в NEWHWND (значение возвращаемое CreateWindowEx сохранять смысла уже не будет).

    Подобный способ получения хэндла вообще предпочтителен.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    S_T_A_S_



    А в чем предпочтительность?
     
  8. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    cresta, этот стиль написания кода называется MASM 6.15 - ассемблер без макросредств (почти). Код с минимальными переделками можно откомпилить в TASM. Просто фрагменты кода я брал из книжки одного чукака (не запомнил фамилию..), который является сторонником "чистоты языка ассемблера". Это не hutch'евские макросы. А то получается, что немного макросов и ASM от VB6 уже не отличишь. Скриптовый язык получается, а не низкоуровневый :) Только какой это будет после всего ASM? invoke не используется - вместо этого параметры надо в обратном порядке в стэк ложить. Прототипы API объявляются в виде APIFunctionName@n:NEAR, где n - размер в байтах под параметры - смотрится так же, как в PEViewer'ах. В общем, вот...



    S_T_A_S, пытаюсь переварить тобой сказанное:

    > Для этого нужно обработать WM_NCCREATE и сохранить

    > хендл переданный в оконную процедуру в качестве

    > первого параметра в NEWHWND

    WNDPROC PROC

    ...

    CMP DWORD PTR [EBP+0CH], WMNCCREATE

    JE WMNCCREATE

    CMP DWORD PTR [EBP+0CH], WMCREATE

    JE WMCREATE

    ...

    WMNCCREATE:

    MOV [NEWHWND], DWORD PTR [EBP+08H]

    WMCREATE:

    PUSH 1 ;TRUE

    PUSH [hRgn]

    PUSH [NEWHWND]

    CALL SetWindowRgn@12

    Правильно ли я тебя понял?
     
  9. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    cresta >




    Хэндл окна получаешь сразу, как он становится валиден, и можно его использовать _до_ возвращения из CreateWindow.

    В случае проги mc black можно конечно оставить почти всё как есть: при WM_CREATE брать хэндл из параметров, а не из глобальной переменной (в которой ещё 0).

    Но когда создаётся несколько окошек на базе одного оконного класса, но нужны разные обработчики WM_CREATE, то проще эти хэндлы куда-нибудь сохранять по WM_NCCREATE.





    mc black







    Видимо стОит заменить на

    push DWORD PTR [EBP+08H]

    pop [NEWHWND]



    хотя в твоём случае проще убрать WMNCCREATE и делать

    push DWORD PTR [EBP+08H] вместо PUSH [NEWHWND] в WMCREATE
     
  10. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    По поводу MOV [NEWHWND], DWORD PTR [EBP+08H] я уже сам догадался.. Что так не делают. Без WMNCCREATE - так действительно гораздо лучше смотрится :) Спасибо за помощь, S_T_A_S!!!



    Как мне "часики"-курсор сразу после создания убрать? cresta, неужели надо так напрямую делать с курсором, а можно сделать так, чтобы эта ситуация *до этого момента* не возникала? Такое чуство, что окно себя недорисованным считает.



    DeleteObject обязательно использовать, чтобы освобождать память от регионов или всё само освободится? Просто в примере cresta из RadASM и в примере для TASM там этого не делается. А в проектах на VB удалить объект - правило хорошего тона..



    cresta, пишу в Aditor (там прикольная подсветка синтаксиса, типа как в RadASM), компилю не через RadASM, а ручками. Нормальный код, изучишь его - понятны будут и макросы.. надеюсь :) В общем можно смотреть венец моего творчества здесь:
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ну DeleteObject само собой :)



    Можно вызвать SetClassLong для своего класса окна с индексом GCL_HCURSOR, и указать курсор. Можно при регистрации указать wc.hCursor. Пока курсор в пределах окна, принадлежащего классу, курсор будет указанный тобой. При покидании пределов окна курсор сам сменится на дефолтный. О чистоте языка: дело вкуса. Как говорится, можно и в гамаке стоя :) О макросах: имхо достаточно знать что он из себя представляет и что вместо него будет скомпилировано. Необязательно ежесекундно доказывать себе, что ты полностью осознаешь каждый байт своего кода.

    В общем дело вкуса. Есть ведь люди, которые пишут в debug'e :) Или говорят что пишут.
     
  12. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    cresta



    А ты, например, не поленился посмотреть, что будет вместо каждого используемого макроса? Мне бы лень было, скажу честно. А вообще, не буду спорить на эту тему - сам ещё не определился как буду писать. Я ведь в masm32 новичок. Насчет в гамаке стоя - прикольно :)



    А я так и делал.
    Код (Text):
    1. ;----------курсор окна
    2.   PUSH        IDC_ARROW
    3.   PUSH        0
    4.   CALL        LoadCursorA@8
    5.   MOV         [WC.CLSHICON], EAX


    И всё равно...



    В WM_ACTIVATE повторно устанавливаю курсор - помогло, да это как-то неестественно.. :) В общем можно смотреть венец моего творчества здесь:

    [​IMG] _1213742057__rgn.zip
     
  13. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    mc black >




    Это требование ОС - максимальное кол-во объектов GDI (общее для всех процессов) в 2K - 16384. Так что слишком много их не создашь. По завершению программы система сама всё должна освободить, но во всяких 9x это вроде бы плохо получается...
     
  14. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    mc black



    А что ты раз за разом устанавливаешь один и тот же курсор IDC_ARROW ? К тому же и как для активного окна, так и для неактивного (wParam не проверяешь).

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

    Если надо менять курсоры при активации\деактивации окна, то измени обработку WM_ACTIVATE так:


    Код (Text):
    1. WMACTIVATE:   ;проверка low word wParam'a
    2.   MOV  EAX,DWORD PTR [EBP+10H]  
    3.   AND  EAX,0FFFFH
    4.   CMP  EAX,WA_INACTIVE   ;если окно неактивное
    5.   JE   DEFAULTCURSOR     ;прыг на восстановление дефолтного курсора (стрелочка)
    6.   PUSH IDC_HAND          ;загружаем курсор, соответствующий активному состоянию
    7.   PUSH 0
    8.   CALL LoadCursorA@8
    9.   PUSH EAX
    10.   CALL SetCursor@4       ;устанавливаем "активный курсор"
    11.   JMP  FINISH
    12. DEFAULTCURSOR:                          
    13.   PUSH IDC_ARROW         ;загружаем курсор, соответствующий неактивному состоянию
    14.   PUSH 0
    15.   CALL LoadCursorA@8
    16.   PUSH EAX
    17.   CALL SetCursor@4       ;устанавливаем "неактивный курсор"
    18.   JMP  FINISH




    Код не проверял, но вроде должно работать. Кроме того, SetCursor возвращает предыдущий(заменяемый) курсор, можно его сохранить где-нибудь в глобальной переменной, и не дергать постоянно LoadCursor, просто подставлять из переменной.

    А макросы... Ну может с десяток использую, вряд ли больше. invoke,FUNC,SADD,local,m2m,.if-endif - даже эти несколько сильно экономят время и место.