Рабочий вариант: Код (Text): //---------------------RC--------------------- #include "\masm32\include\resource.h" 136 ACCELERATORS BEGIN VK_F5, 100, ALT, VIRTKEY END ;--------------------ASM--------------------- .486 .model flat, stdcall option casemap: none .nolist include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc .listall includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data? ha HACCEL ? hwMain HWND ? mes MSG <?> .data wcx WNDCLASSEX <sizeof wcx, 0, offset mwp, 0, 0, ?, ?, ?, COLOR_APPWORKSPACE + 1, 0, offset mwcn, ?> mwcn db 'MainWinClass', 0 qn db '&Quit', 0 .code mwp proc hw: HWND, ms: UINT, wp: WPARAM, lp: LPARAM .if ms == WM_DESTROY invoke PostQuitMessage, 0 xor eax, eax .elseif ms == WM_CREATE push ebx invoke CreateMenu mov ebx, eax invoke AppendMenu, ebx, MF_STRING, 100, offset qn invoke SetMenu, hw, ebx pop ebx .elseif ms == WM_COMMAND movzx eax, word ptr wp + 2 dec eax jz @F inc eax jnz @def @@: movzx eax, word ptr wp .if eax == 100 invoke PostQuitMessage, 0 .endif xor eax, eax .else @def: invoke DefWindowProc, hw, ms, wp, lp .endif ret mwp endp @: invoke GetModuleHandle, 0 mov wcx.hInstance, eax invoke LoadAccelerators, eax, 136 mov ha, eax invoke LoadIcon, 0, IDI_APPLICATION mov wcx.hIcon, eax mov wcx.hIconSm, eax invoke LoadCursor, 0, IDC_ARROW mov wcx.hCursor, eax invoke RegisterClassEx, offset wcx invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, offset mwcn, offset mwcn, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wcx.hInstance, 0 test eax, eax jz @quit mov hwMain, eax invoke ShowWindow, eax, SW_SHOWDEFAULT @@: invoke GetMessage, offset mes, 0, 0, 0 inc eax jz @quit dec eax jz @quit invoke TranslateAccelerator, hwMain, ha, offset mes test eax, eax jnz @B invoke TranslateMessage, offset mes invoke DispatchMessage, offset mes jmp @B @quit: invoke ExitProcess, 0 end @ Нерабочий: Код (Text): ;--------------------ASM--------------------- .486 .model flat, stdcall option casemap: none .nolist include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc .listall includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data? ha HACCEL ? hwMain HWND ? mes MSG <?> .data wcx WNDCLASSEX <sizeof wcx, 0, offset mwp, 0, 0, ?, ?, ?, COLOR_APPWORKSPACE + 1, 0, offset mwcn, ?> accs ACCEL <FALT or FVIRTKEY, VK_F5, 100> mwcn db 'MainWinClass', 0 qn db '&Quit', 0 .code mwp proc hw: HWND, ms: UINT, wp: WPARAM, lp: LPARAM .if ms == WM_DESTROY invoke PostQuitMessage, 0 xor eax, eax .elseif ms == WM_CREATE push ebx invoke CreateMenu mov ebx, eax invoke AppendMenu, ebx, MF_STRING, 100, offset qn invoke SetMenu, hw, ebx pop ebx .elseif ms == WM_COMMAND movzx eax, word ptr wp + 2 dec eax jz @F inc eax jnz @def @@: movzx eax, word ptr wp .if eax == 100 invoke PostQuitMessage, 0 .endif xor eax, eax .else @def: invoke DefWindowProc, hw, ms, wp, lp .endif ret mwp endp @: invoke GetModuleHandle, 0 mov wcx.hInstance, eax invoke CreateAcceleratorTable, offset accs, 1 mov ha, eax invoke LoadIcon, 0, IDI_APPLICATION mov wcx.hIcon, eax mov wcx.hIconSm, eax invoke LoadCursor, 0, IDC_ARROW mov wcx.hCursor, eax invoke RegisterClassEx, offset wcx invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW, offset mwcn, offset mwcn, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wcx.hInstance, 0 test eax, eax jz @quit mov hwMain, eax invoke ShowWindow, eax, SW_SHOWDEFAULT @@: invoke GetMessage, offset mes, 0, 0, 0 inc eax jz @quit dec eax jz @quit invoke TranslateAccelerator, hwMain, ha, offset mes test eax, eax jnz @B invoke TranslateMessage, offset mes invoke DispatchMessage, offset mes jmp @B @quit: invoke DestroyAcceleratorTable, ha invoke ExitProcess, 0 end @ CreateAcceleratorTable вызывается успешно, даже DestroyAcceleratorTable возвращает 1, но нужного WM_COMMAND никак не дождаться, если только не через меню. Где налажал?
Код (Text): msg_loop: invoke GetMessage,msg,NULL,0,0 or eax,eax jz exit invoke TranslateAccelerator,[hMain],[hAcc],msg or eax,eax jnz @F invoke TranslateMessage,msg @@: invoke DispatchMessage,msg jmp msg_loop exit: invoke ExitProcess,[msg.wParam] если TranslateAccelerator было успешным, то нужно пропустить TranslateMessage, а DispatchMessage выполнить всё равно, а у тебя во втором варианте идет возврат назад к GetMessage
shoo Не-а, не сработало. Да и наверняка проблема не в этом, ибо первый вариант работает и без довыполнения DispatchMessage. Если во втором варианте поставить брейк на команду после TranslateAccelerator по условию eax != 0, он не сработает. Почему?
1. Код (Text): ;accs ACCEL <FALT or FVIRTKEY, VK_F5, 100> accs dw FALT or FVIRTKEY dw VK_F5 dw 100 2. Код (Text): invoke TranslateAccelerator, hwMain, ha, offset mes test eax, eax jnz dispatch invoke TranslateMessage, offset mes dispatch: invoke DispatchMessage, offset mes
Ура! Спасибо! Заработало! "1." помогло, "2." ignored since: у Iczeliona см. тут. 34 Код (Text): invoke TranslateAccelerator, ... .if eax == 0 invoke TranslateMessage, ... invoke DispatchMesage, ... .endif Хотя с "2." тоже работает. Судя по доке, ваше предложение правильное. Однако учат другому По поводу "1.": странно, как в доке, так и в windows.inc ACCEL struct fVirt BYTE ? key WORD ? cmd WORD ? ACCEL ends Это смело можно исправлять? Откуда такая погрешность? Есть ещё подобные подвохи?
1.масм (как и фасм) не выравнивает члены структур по их размеру, но это делают компиляторы Си. т.е. правильно это выглядит так: Код (Text): ACCEL struct fVirt BYTE ? align 2 ;<-- это неявно подразумевается key WORD ? cmd WORD ? ACCEL ends 2.личное дело