Уважаемые программисты! Некоторое время назад задался я идеей создать чудо-курсор: перекрестье во весь экран (http://forum.sources.ru/index.php?showtopic=161538&st=0&#entry1344384). Писал потихоньку код, консультировался здесь, на форуме (http://www.wasm.ru/forum/viewtopic.php?id=17281) В общем, написал я программулю, вот код (для FASM): Код (Text): include 'win32axp.inc' .data tityl db 'My program',0 klass db 'My klass',0 hwnd dd ? hdc dd ? hp dd ? vysota dd ? shirina dd ? xx dd ? yy dd ? wc WNDCLASS 0,Procedura,0,0,NULL,NULL,NULL,00h,NULL,klass msg MSG rc RECT ps PAINTSTRUCT lpo POINT .code fuck: invoke GetSystemMetrics,SM_CXSCREEN mov [shirina],eax invoke GetSystemMetrics,SM_CYSCREEN mov [vysota],eax invoke GetModuleHandle,0 mov [wc.hInstance],eax invoke LoadIcon,0,IDI_APPLICATION mov [wc.hIcon],eax invoke LoadCursor,0,IDC_ARROW mov [wc.hCursor],eax invoke RegisterClass,wc 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 mov [hwnd],eax invoke SetLayeredWindowAttributes,[hwnd],00h,00h,LWA_COLORKEY invoke SetWindowPos,[hwnd],HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE invoke UpdateWindow,[hwnd] msg_loop: invoke GetMessage,msg,NULL,0,0 or eax,eax jz end_loop invoke TranslateMessage,msg invoke DispatchMessage,msg jmp msg_loop end_loop: invoke ExitProcess,[msg.wParam] proc Procedura hwnd,wmsg,wparam,lparam push ebx push esi push edi cmp [wmsg],WM_MOUSEMOVE je Moving cmp [wmsg],WM_DESTROY je Destroy cmp [wmsg],WM_PAINT je Paint invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp finish Destroy: invoke PostQuitMessage,0 xor eax,eax Paint: invoke BeginPaint,[hwnd],ps mov [hdc],eax invoke GetClientRect,[hwnd],rc invoke CreatePen,PS_SOLID,2,0ff0000h mov [hp],eax invoke SelectObject,[hdc],[hp] push eax invoke SetROP2,[hdc],5 invoke MoveToEx,[hdc],0,[yy],NULL invoke LineTo,[hdc],[shirina],[yy] invoke MoveToEx,[hdc],[xx],0,NULL invoke LineTo,[hdc],[xx],[vysota] invoke GetCursorPos,lpo mov eax,dword [lpo] mov [xx],eax mov eax,dword [lpo+4] mov [yy],eax invoke MoveToEx,[hdc],0,[yy],NULL invoke LineTo,[hdc],[shirina],[yy] invoke MoveToEx,[hdc],[xx],0,NULL invoke LineTo,[hdc],[xx],[vysota] pop eax invoke DeleteObject,[hp] invoke EndPaint,[hwnd],ps Moving: invoke InvalidateRect,[hwnd],rc,TRUE invoke UpdateWindow,[hwnd] finish: pop edi pop esi pop ebx ret endp .end fuck НО вот в чём загвоздка: тормозит очень сильно, загружает проц на 70-99%. Пожалуйста, подскажите: как снизить нагрузку на процессор?
tityl, klass.. мда. Пишите сразу по-русски что ли, фасм позволяет. По теме: ты же не выходишь после обработки сообщения сразу, а продолжаешь обрабатывать нижеследующий код. И после отрисовки сразу же требуешь перерисовать окно снова.
2 IceStudent Т.е. в конце обработчика сообщений сразу писать jmp finish? Щас попробую, спасибо Не... Нифига Если после EndPaint ставлю jmp finish, то перекрестье выводится в одном месте экрана и не следует за курсором
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%.
2 q_q Работаю на Athlon 2800+ За Sleep(1) спасибо! Вроде бы, то что надо! Возник ещё вопрос: если запустить DOS-приложение в полноэкранном режиме, а потом выйти из него, логика моей программы вообще пропадает: перекрестье не следует за курсором или следует, но опять же грузит проц. С чем это связано?
Основная причина тормозов в вашей проге - не устранима: WS_EX_LAYERED просто-напросто "не успевает" с большими окнами (а у вас оно аж с экран). В MSDN есть об этом пара слов.
2 kero А есть возможные варианты решения этой проблемы? Мне говорили про рисование на канве десктопа - лишено ли оно этих недостатков?
Господа программисты! Помогите советом: хочу к этому курсорчику приделать иконку в трее с выпадающим меню - цвет менять, толщину линий на усмотрение юзера и т.д. Ясен палец, что надо будет программку на два потока разбивать: один будет перекрестье рисовать, а другой - с юзером диалог вести. Да вот только я в многопоточном программировании - ни уха, ни рыла не понимаю... Подскажите, пжлст, хоть в паре слов: как сие осуществить, как потоки запустить да синхронизировать, что почитать по этому поводу? А за пример кода буду благодарен нечеловечески
Господа!! Не оставьте без внимания глас вопиющего в пустыне! Помогите советом, ссылкой или фрагментом исходника!
Хм, в многопоточном программировании не понимаешь, а что надо два потока сображаешь... Хотя каждый поток должен иметь свою очередь сообщений, я никогда такие программы не писал(немодальные диалоги не в счет), а поэтому предлогаю использовать или многопроцорное программирование(два процесса, взаимодействие через FindWindow/SendMessage) или же через немодальный диалог. А на счет многопоточности - почти всего тоже что и с одним потоком: создаешь поток(CreateThread) с указанием на функцию которая будет обрабатывать очередь сообщений и в ней создаешь еще одно окно - в чем у тебя возникли затруднения не понимаю...