задачка: после двойного щелчка левой кнопки в рабочей области окна, окно начинает перемещаться в вертикальном направлении. нажатие любой клавиши заканчивает движение. в чем основные проблемы: 1. по идее, после нажатия окно должно постоянно "лететь" вниз, но, проехав некоторое время, оно останавливается, хотя флажок нигде больше не сбрасывается 2. нажатие любой клавиши во время полета не останавливает его Код (Text): .386 .model flat, stdcall option casemap: none ;--------------------------------------------------------------------------- include windows.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib ;--------------------------------------------------------------------------- szText MACRO Name, Text:VARARG LOCAL lbl jmp lbl Name db Text, 0 lbl: ENDM return MACRO arg mov eax, arg ret ENDM m2m MACRO arg1, arg2 push arg2 pop arg1 ENDM delay MACRO local lp, lp2 push cx mov cx, 30000 lp: push cx mov cx, 300 lp2: loop lp2 pop cx loop lp pop cx ENDM ;--------------------------------------------------------------------------- WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD ;--------------------------------------------------------------------------- .data hWnd dd 0 hInstance dd 0 wFlag dd 0 wX dd 0 wY dd 0 wWidth dd 0 wHeight dd 0 ;--------------------------------------------------------------------------- .code start: invoke GetModuleHandle, NULL mov hInstance, eax invoke WinMain, hInstance, NULL, NULL, SW_SHOWDEFAULT invoke ExitProcess, eax ;--------------------------------------------------------------------------- WinMain proc hInst :DWORD, hPrevInst :DWORD, CmdLine :DWORD, CmdShow :DWORD LOCAL wc :WNDCLASSEX LOCAL msg :MSG szText szClassName, "MyClass" mov wc.cbSize, sizeof WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW or CS_DBLCLKS mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL m2m wc.hInstance, hInst mov wc.hbrBackground, COLOR_BTNFACE+1 mov wc.lpszMenuName, NULL mov wc.lpszClassName, offset szClassName mov wc.hIcon, NULL invoke LoadCursor, NULL, IDC_ARROW mov wc.hCursor, eax mov wc.hIconSm, NULL invoke RegisterClassEx, ADDR wc mov wX, 100 mov wY, 200 mov wWidth, 500 mov wHeight, 300 invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, ADDR szClassName, ADDR szClassName, WS_OVERLAPPEDWINDOW, wX, wY, wWidth, wHeight, NULL, NULL, hInst, NULL mov hWnd, eax invoke ShowWindow, hWnd, SW_SHOWNORMAL StartLoop: invoke GetMessage, ADDR msg, NULL, 0, 0 cmp eax, 0 je ExitLoop invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg jmp StartLoop ExitLoop: return msg.wParam WinMain endp ;--------------------------------------------------------------------------- WndProc proc hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD LOCAL r :RECT LOCAL x :DWORD LOCAL y :DWORD .if uMsg == WM_DESTROY invoke PostQuitMessage, NULL return 0 .elseif uMsg == WM_LBUTTONDBLCLK cmp wFlag, 1 je mexit mov wFlag, 1 inc wY invoke MoveWindow, hWin, wX, wY, wWidth, wHeight, 1 .elseif uMsg == WM_CHAR mov wFlag, 0 .elseif uMsg == WM_MOVE cmp wFlag, 0 je mexit inc wY mov wFlag, 1 delay invoke MoveWindow, hWin, wX, wY, wWidth, wHeight, 1 .endif mexit: invoke DefWindowProc, hWin, uMsg, wParam, lParam ret WndProc endp ;--------------------------------------------------------------------------- end start
Нажатие клавиш не срабатывает так как процедура обраб. сообщений зафлужена сообщениями WM_MOVE. Лучше создай таймер и двигай окно по WM_TIMER
Ну, например сделать так: Код (Text): ;--------------------------------------------------------------------------- WndProc proc hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD LOCAL r :RECT LOCAL x :DWORD LOCAL y :DWORD .if uMsg == WM_DESTROY invoke PostQuitMessage, NULL return 0 .const MY_TIMER_ID equ 12345 .code .elseif uMsg == WM_LBUTTONDBLCLK .if wFlag == 0 invoke SetTimer, hWin, ;хэндл окна MY_TIMER_ID, ;ID таймера 50, ;задержка (в миллисекундах) 0 ;указатель на обработчик ;(0 - обработчик не используется) .if eax != 0 mov wFlag, 1 ;.else - не удалось создать таймер .endif .endif .elseif uMsg == WM_CHAR invoke KillTimer, hWin, ;handle to window MY_TIMER_ID ;timer identifier .if eax != 0 mov wFlag, 0 ;.else - не удалось удалить таймер .endif .elseif uMsg == WM_TIMER .if wParam == MY_TIMER_ID inc wY invoke MoveWindow, hWin, wX, wY, wWidth, wHeight, 1 .endif .endif invoke DefWindowProc, hWin, uMsg, wParam, lParam ret WndProc endp ;---------------------------------------------------------------------------
artie В аттаче сорц и exe, написанные по мотивам твоей программы. Падение по нажатию на любую клавишу, остановка - нажатие на любую клавишу. Что интересно, падает пока курсор мыши находится в пределах клиентской части окна, стоит мышь отвести в сторону, падение прекращается. Почему, не пойму
Стиль, кнечно, красивый, но зачем засыпать в таймере? и почему Код (Text): start: xchg eax,ebx гарантивовано вернёт 0 (нуль) в ebx? (это для всей линейки win гарантровано?) и в чём преимущество такого вида процедуры окна перед простым cmp? [added] и ещё я бы добавил крестик всё-таки alt+f4 неохота жать, и обработку WM_MOVE также.
asmfan для 2k, XP в EAX при старте гарантированно 0, для 9Х мои ехе не заработают, так как при сборке я устанавливаю ALIGN=4, да и кому это старье нужно. Процедуру окна я еще и через REP SCASD делал, и через JMP DWORD Table[EAX*4], а через DEC и SUB -- это я в BORLAND BUILDER нашел
А где об этом можно прочитать? Это официальная инфа? С Вистой также? ну у них там ветвления присутствовали (как на бинарных деревьях), а здесь просто cmp прокатывает.
asmfan 1) через SoftIce 2k, XP все сервиспаки, в Vista не знаю 2) был у меня и вариант последовательного приближения, если много сообщений, (100 сообщений за 7 проверок), но если не более 10 сообщений (обычно так и бывает), то дополнительные проверки себя не оправдывают. Преимущества реализации через SUB/DEC в отличие от CMP cmp eax,WM_CREATE (83F801h) 3 байта dec eax (48h) 1 байт или для рядом расположенных сообщений, например WM_LBUTTONDOWN=201h и WM_LBUTTONUP=202h cmp eax,WM_LBUTTONDOWN (3D01020000h) - 5 байт je WMLBUTTONDOWN (7411h) 2 байта cmp eax,WM_LBUTTONUP (3D02020000h) 5 байт je WMLBUTTONUP (7418h) 2 байта - итого 14 байт сравните с sub eax,WM_LBUTTONDOWN (2D01020000h) 5 байт je WMLBUTTONDOWN (7403h) 2 байта dec eax (48h) 1 байт je WMLBUTTONUP (740E) 2 байта - итого 10 байт Разве не дзенно? Кроме того DEC/SUB дают мне EAX=0, и по-моему они быстрее (хотя для процедуры окна это не актуально). Вообще стараюсь оптимизировать по размеру.
Mikl__, извращенец... Есс-но, какая обработка исключений, если главное - Дзен… И Гейтс с ним, с 9х, этим старьём ведь уже никто не пользуется…
Mikl__, пожалуй, для оптимизации по размеру это хороший способ, по скорости не самый, т.к. всё-равно присутствует полный перебор сообщений. /и, кстати, что это за источник, если не секрет? занятно поглядеть/
G13 какие эксепшены в учебном примере?!! А насчет совместимости, почему никто не требует поддержки Win3.11, DOS и *nix, я же не виря написал
Mikl__, валяешь меня под столом просто! %) “Даёшь совместимость Win32PE приложений с NIX/BSD системами к концу третьего квартала!” %))))))))))))
Mikl__, можно, конечно. Тот же HiEW, например. Но ИМХО - сие изврат, по сути ты пишешь две программы сразу. Проще уж сделать отдельно ELF и Win32 версию.