Курсор: перекрестье на весь экран (рисую на прозрачном окне)

Тема в разделе "WASM.BEGINNERS", создана пользователем Adrax, 5 апр 2007.

  1. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    Уважаемые программисты! Некоторое время назад задался я идеей создать чудо-курсор: перекрестье во весь экран (http://forum.sources.ru/index.php?showtopic=161538&st=0&#entry1344384). Писал потихоньку код, консультировался здесь, на форуме (http://www.wasm.ru/forum/viewtopic.php?id=17281)
    В общем, написал я программулю, вот код (для FASM):
    Код (Text):
    1. include 'win32axp.inc'
    2.  
    3. .data
    4.  
    5.   tityl db 'My program',0
    6.   klass db 'My klass',0
    7.   hwnd dd ?
    8.   hdc dd ?
    9.   hp dd ?
    10.  
    11.   vysota dd ?
    12.   shirina dd ?
    13.   xx dd ?
    14.   yy dd ?
    15.  
    16.   wc WNDCLASS 0,Procedura,0,0,NULL,NULL,NULL,00h,NULL,klass
    17.  
    18.   msg MSG
    19.   rc RECT
    20.   ps PAINTSTRUCT
    21.   lpo POINT
    22.  
    23. .code
    24.  
    25.   fuck:
    26.         invoke GetSystemMetrics,SM_CXSCREEN
    27.         mov [shirina],eax
    28.         invoke GetSystemMetrics,SM_CYSCREEN
    29.         mov [vysota],eax
    30.  
    31.         invoke  GetModuleHandle,0
    32.         mov     [wc.hInstance],eax
    33.         invoke  LoadIcon,0,IDI_APPLICATION
    34.         mov     [wc.hIcon],eax
    35.         invoke  LoadCursor,0,IDC_ARROW
    36.         mov     [wc.hCursor],eax
    37.         invoke  RegisterClass,wc
    38.         invoke  CreateWindowEx,WS_EX_TOPMOST or WS_EX_TRANSPARENT or WS_EX_LAYERED,klass,tityl,WS_POPUP+WS_VISIBLE,0,0,[shirina],[vysota],NULL,NULL,[wc.hInstance],NULL
    39.         mov [hwnd],eax
    40.        invoke SetLayeredWindowAttributes,[hwnd],00h,00h,LWA_COLORKEY
    41.        invoke SetWindowPos,[hwnd],HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE
    42.        invoke UpdateWindow,[hwnd]
    43.  
    44.  
    45.   msg_loop:
    46.         invoke  GetMessage,msg,NULL,0,0
    47.         or      eax,eax
    48.         jz      end_loop
    49.         invoke  TranslateMessage,msg
    50.         invoke  DispatchMessage,msg
    51.         jmp     msg_loop
    52.   end_loop:
    53.         invoke  ExitProcess,[msg.wParam]
    54.  
    55.  
    56.  
    57. proc Procedura hwnd,wmsg,wparam,lparam
    58.         push ebx
    59.         push esi
    60.         push edi
    61.         cmp [wmsg],WM_MOUSEMOVE
    62.         je Moving
    63.         cmp     [wmsg],WM_DESTROY
    64.         je      Destroy
    65.         cmp [wmsg],WM_PAINT
    66.         je Paint
    67.  
    68.  
    69.         invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
    70.         jmp     finish
    71.   Destroy:
    72.         invoke  PostQuitMessage,0
    73.         xor     eax,eax
    74.  
    75.   Paint:
    76.  
    77.        invoke BeginPaint,[hwnd],ps
    78.         mov [hdc],eax
    79.         invoke GetClientRect,[hwnd],rc
    80.         invoke CreatePen,PS_SOLID,2,0ff0000h
    81.         mov [hp],eax
    82.         invoke SelectObject,[hdc],[hp]
    83.         push eax
    84.         invoke SetROP2,[hdc],5
    85.         invoke MoveToEx,[hdc],0,[yy],NULL
    86.         invoke LineTo,[hdc],[shirina],[yy]
    87.         invoke MoveToEx,[hdc],[xx],0,NULL
    88.         invoke LineTo,[hdc],[xx],[vysota]
    89.  
    90.         invoke GetCursorPos,lpo
    91.         mov eax,dword [lpo]
    92.         mov [xx],eax
    93.         mov eax,dword [lpo+4]
    94.         mov [yy],eax
    95.  
    96.         invoke MoveToEx,[hdc],0,[yy],NULL
    97.         invoke LineTo,[hdc],[shirina],[yy]
    98.         invoke MoveToEx,[hdc],[xx],0,NULL
    99.         invoke LineTo,[hdc],[xx],[vysota]
    100.         pop eax
    101.         invoke DeleteObject,[hp]
    102.         invoke EndPaint,[hwnd],ps
    103.  
    104. Moving:
    105.        invoke InvalidateRect,[hwnd],rc,TRUE
    106.        invoke UpdateWindow,[hwnd]
    107.  
    108.   finish:
    109.         pop edi
    110.         pop esi
    111.         pop ebx
    112.         ret
    113. endp
    114. .end fuck
    НО вот в чём загвоздка: тормозит очень сильно, загружает проц на 70-99%. Пожалуйста, подскажите: как снизить нагрузку на процессор?
     
  2. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    tityl, klass.. мда. Пишите сразу по-русски что ли, фасм позволяет.

    По теме: ты же не выходишь после обработки сообщения сразу, а продолжаешь обрабатывать нижеследующий код. И после отрисовки сразу же требуешь перерисовать окно снова.
     
  3. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    2 IceStudent
    Т.е. в конце обработчика сообщений сразу писать jmp finish? Щас попробую, спасибо

    Не... Нифига:dntknw: Если после EndPaint ставлю jmp finish, то перекрестье выводится в одном месте экрана и не следует за курсором
     
  4. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Adrax
    Не... Нифига
    Тогда между EndPaint и Moving: invoke Sleep, 20.
     
  5. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    2 q_q
    Со Sleep'ом хреновенько получается: мерцать начинает
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Adrax
    Хорошо. Давай разберемся.
    Как справедливо отметил IceStudent, в твоей программе "намертво" зациклено обновление окна. Обработчик WM_PAINT переходит в обработчик WM_MOUSEMOVE, который содержит вызов InvalidateRect добавляющий всю клиентскую область окна в update region. Следом идет UpdateWindow, который, согласно документации, в обход очереди событий, непосредственно вызывает (если есть update region, их наличие я обосновал выше) оконную процедуру для обработки WM_PAINT. Круг замкнулся (по идее стек должен закончиться). Добавление Sleep позволяет ОС дать часть процессорного времени другим потокам. Попробуй Sleep(1).

    Чтобы избежать рекурсии можно вместо UpdateWindow вызывать PostMessage(hwnd, WM_PAINT, 0, 0).

    На каком железе тестируешь? У меня на Cel3.2GHz & ATI X700 даже без sleep'а не тормозит, только в диспетчере задач загрузка процессора 100%, со sleep'ом ~5%.
     
  7. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    2 q_q
    Работаю на Athlon 2800+
    За Sleep(1) спасибо! Вроде бы, то что надо!

    Возник ещё вопрос: если запустить DOS-приложение в полноэкранном режиме, а потом выйти из него, логика моей программы вообще пропадает: перекрестье не следует за курсором или следует, но опять же грузит проц. С чем это связано?
     
  8. kero

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

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Основная причина тормозов в вашей проге - не устранима:
    WS_EX_LAYERED просто-напросто "не успевает" с большими окнами (а у вас оно аж с экран).
    В MSDN есть об этом пара слов.
     
  9. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    2 kero
    А есть возможные варианты решения этой проблемы? Мне говорили про рисование на канве десктопа - лишено ли оно этих недостатков?
     
  10. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    Господа программисты!
    Помогите советом: хочу к этому курсорчику приделать иконку в трее с выпадающим меню - цвет менять, толщину линий на усмотрение юзера и т.д. Ясен палец, что надо будет программку на два потока разбивать: один будет перекрестье рисовать, а другой - с юзером диалог вести. Да вот только я в многопоточном программировании - ни уха, ни рыла не понимаю...
    Подскажите, пжлст, хоть в паре слов: как сие осуществить, как потоки запустить да синхронизировать, что почитать по этому поводу? А за пример кода буду благодарен нечеловечески:)
     
  11. Adrax

    Adrax Алексей

    Публикаций:
    0
    Регистрация:
    14 окт 2006
    Сообщения:
    135
    Адрес:
    г. Курск
    Господа!! Не оставьте без внимания глас вопиющего в пустыне!
    Помогите советом, ссылкой или фрагментом исходника!
     
  12. CodeTao

    CodeTao Евгений

    Публикаций:
    0
    Регистрация:
    31 окт 2006
    Сообщения:
    177
    Адрес:
    штаты
    Хм, в многопоточном программировании не понимаешь, а что надо два потока сображаешь...:) Хотя каждый поток должен иметь свою очередь сообщений, я никогда такие программы не писал(немодальные диалоги не в счет), а поэтому предлогаю использовать или многопроцорное программирование(два процесса, взаимодействие через FindWindow/SendMessage) или же через немодальный диалог. А на счет многопоточности - почти всего тоже что и с одним потоком: создаешь поток(CreateThread) с указанием на функцию которая будет обрабатывать очередь сообщений и в ней создаешь еще одно окно - в чем у тебя возникли затруднения не понимаю...
     
  13. mc black

    mc black Member

    Публикаций:
    0
    Регистрация:
    19 янв 2005
    Сообщения:
    213
    Адрес:
    Russia, N.Novgorod
    У izcelion'а почитай туториалы, там всё вроде разжевано - осталось в рот положить...