как правильно использовать GetKeyState

Discussion in 'WASM.BEGINNERS' started by xlinuks, Aug 27, 2006.

  1. xlinuks

    xlinuks New Member

    Blog Posts:
    0
    Joined:
    May 25, 2006
    Messages:
    181
    Привет всем, я пытаюсь заставить окно отвечать на событие когда нажата клавиша Shift, но видимо чтото делаю не правильно, если не трудно подскажите что не так:

    Code (Text):
    1. format PE GUI 4.0
    2. entry start
    3.  
    4. include '%fasminc%\win32a.inc'
    5.  
    6. section '.data' data readable writeable
    7.  
    8.   _title db 'Win32 program template',0
    9.   _class db 'FASMWIN32',0
    10.   _sKeyPressed db 'Shift key is down!!', 0
    11.  
    12.   wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class
    13.  
    14.   msg MSG
    15.  
    16. section '.code' code readable executable
    17.  
    18.   start:
    19.  
    20.         invoke  GetModuleHandle,0
    21.         mov     [wc.hInstance],eax
    22.         invoke  LoadIcon,0,IDI_APPLICATION
    23.         mov     [wc.hIcon],eax
    24.         invoke  LoadCursor,0,IDC_ARROW
    25.         mov     [wc.hCursor],eax
    26.         invoke  RegisterClass,wc
    27.  
    28.         invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,192,192,NULL,NULL,[wc.hInstance],NULL
    29.  
    30.   msg_loop:
    31.         invoke  GetMessage,msg,NULL,0,0
    32.         or      eax,eax
    33.         jz      end_loop
    34.         invoke  TranslateMessage,msg
    35.         invoke  DispatchMessage,msg
    36.         jmp     msg_loop
    37.  
    38.   end_loop:
    39.         invoke  ExitProcess,[msg.wParam]
    40.  
    41. proc WindowProc hwnd,wmsg,wparam,lparam
    42.         push    ebx esi edi
    43.         cmp     [wmsg],WM_DESTROY
    44.         je      wmdestroy
    45.  
    46.          ;ЗДЕСЬ:
    47.         ;=====================================================;
    48.         xor eax, eax                                          
    49.         invoke GetKeyState, VK_SHIFT                
    50.         test eax, 80000000h                              
    51.         jz ignore                                            
    52.         invoke MessageBox, NULL, _sKeyPressed, _title, MB_OK
    53.         ;======================================================
    54.  
    55.         ignore:
    56.  
    57.   defwndproc:
    58.         invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
    59.         jmp     finish
    60.   wmdestroy:
    61.         invoke  PostQuitMessage,0
    62.         xor     eax,eax
    63.   finish:
    64.         pop     edi esi ebx
    65.         ret
    66. endp
    67.  
    68. section '.idata' import data readable writeable
    69.  
    70.   library kernel32,'KERNEL32.DLL',\
    71.           user32,'USER32.DLL'
    72.  
    73.   include '%fasminc%\apia\kernel32.inc'
    74.   include '%fasminc%\apia\user32.inc'
     
  2. Asterix

    Asterix New Member

    Blog Posts:
    0
    Joined:
    Feb 25, 2003
    Messages:
    3,576
    Code (Text):
    1. SHORT GetKeyState(          int nVirtKey
    2. );
    возвращает SHORT !
     
  3. xlinuks

    xlinuks New Member

    Blog Posts:
    0
    Joined:
    May 25, 2006
    Messages:
    181
    хм.. ты знаешь я тоже это заметил, что ШОРТ, но я предварительно залез в нет посмотреть как это другие делают и там именно 80000000h !! в 22 туториале Iczeliona а также на еще одном форуме тоже самое было - и я был уверен что SHORT имеет тоже значение как INT (потому что как я недавно выяснил LONG = INT в си), тогда я только удивляюсь как у Iczeliona работало!
    А я сейчас переделал как ты предложил и поставил 8000h, все пучком однако!
     
  4. Asterix

    Asterix New Member

    Blog Posts:
    0
    Joined:
    Feb 25, 2003
    Messages:
    3,576
    многие из-за самоуверенности или копипаста наступают на эти грабли, Iczelion не исключение :)
     
  5. xlinuks

    xlinuks New Member

    Blog Posts:
    0
    Joined:
    May 25, 2006
    Messages:
    181
    Наверное так, уфффф стока непоняток, мне короче надо чтобы моя маленькая прога отвечала на нажатие клавиш Ctrl+Shift+(0...9), т.е. например на комбинацию Ctrl+Shift+5, так вот, код свыше работает, а когда я добавиль чтобы отвечала только на клавиши от 0 до 9 не работает, только что я не пробовал!
    Code (Text):
    1.      xor eax, eax
    2.      invoke GetKeyState, VK_SHIFT
    3.      test eax, 8000h
    4.      jz .getOut
    5.  
    6.      xor eax, eax
    7.      invoke GetKeyState, VK_CONTROL
    8.      test eax, 8000h
    9.      jz .getOut
    10. ;=========================дальше не работает, фильтрую от 0...9
    11.      xor eax, eax
    12.      mov eax, dword ptr wParam
    13.      test eax, '1'
    14.      jl .getOut
    15.  
    16.      xor eax, eax
    17.      mov eax, dword ptr wParam
    18.      test eax, '9'
    19.      jg .getOut
    (wParam - потому что вообщето эта функция в хуке и она получает клавишные события)
    полный код DLL выглядит так:
    Code (Text):
    1. format PE GUI 4.0 DLL
    2. entry DllEntryPoint
    3.  
    4. include '%fasminc%\win32a.inc'
    5.  
    6. section '.data' data readable writeable shareable
    7.         sHookInstalled db 'The hook has been installed!', 0
    8.         sHookRemoved db 'The hook has been removed!', 0
    9.         sHookFailedToInstall db 'Failed to install hook', 0
    10.         sKeyPressed db 'Key pressed!', 0
    11.         sTitle db 'Title', 0
    12.         g_hInstance dd 0
    13.         hCurrentHook dd 0
    14.         g_bHookSet db FALSE
    15.  
    16.  
    17. section '.code' code readable executable
    18.  
    19. proc DllEntryPoint, hMod:DWORD, fdwReason:DWORD, lpvReserved:DWORD
    20.      mov [g_bHookSet], FALSE
    21.      push [hMod]
    22.      pop [g_hInstance]
    23.  
    24.      mov eax,TRUE
    25.      ret
    26. endp
    27.  
    28. proc InstallHook
    29.      mov al, [g_bHookSet]
    30.      cmp al, TRUE
    31.      je .getOut
    32.      mov al, TRUE
    33.      mov [g_bHookSet], al
    34.  
    35.      invoke SetWindowsHookEx, WH_KEYBOARD, KbHookProc, [g_hInstance], 0
    36.      cmp eax, NULL
    37.      jne .goOn
    38.      invoke MessageBox, NULL, sHookFailedToInstall, sTitle, MB_OK
    39.      jmp .getOut
    40.  
    41.      .goOn:
    42.      mov [hCurrentHook], eax
    43.      mov [g_bHookSet], TRUE
    44.  
    45.  
    46.      invoke MessageBox, NULL, sHookInstalled, sTitle, MB_OK
    47.      xor eax, eax
    48.  
    49.      .getOut:
    50.      ret
    51. endp
    52.  
    53. proc KbHookProc, nCode:DWORD, wParam:DWORD, lParam:DWORD
    54.  
    55.      xor eax, eax
    56.      mov eax, [nCode]
    57.      cmp eax, 0
    58.      jg .callNextHook
    59.  
    60.      xor eax, eax
    61.      mov eax, dword ptr lParam
    62.      shr eax, 16
    63.      and ax, KF_UP
    64.      jnz .getOut
    65.  
    66.      xor eax, eax
    67.      mov eax, dword ptr lParam
    68.      shr eax, 16
    69.      and ax, KF_REPEAT
    70.      jnz .getOut
    71.  
    72.      xor eax, eax
    73.      mov eax, dword ptr lParam
    74.      shr eax, 16
    75.      and ax, KF_EXTENDED
    76.      jnz .getOut
    77.  
    78.      xor eax, eax
    79.      invoke GetKeyState, VK_SHIFT
    80.      test eax, 8000h
    81.      jz .getOut
    82.  
    83.      xor eax, eax
    84.      invoke GetKeyState, VK_CONTROL
    85.      test eax, 8000h
    86.      jz .getOut
    87.  
    88.      xor eax, eax
    89.      mov eax, dword ptr wParam
    90.      test eax, '1'
    91.      jl .getOut
    92.  
    93.      xor eax, eax
    94.      mov eax, dword ptr wParam
    95.      test eax, '9'
    96.      jg .getOut
    97.  
    98.      invoke MessageBox, NULL, sKeyPressed, sTitle, MB_OK
    99.  
    100.      jmp .getOut
    101.  
    102.      .callNextHook:
    103.      invoke CallNextHookEx, [hCurrentHook], [nCode], [wParam], [lParam]
    104.      .getOut:
    105.      ret
    106. endp
    107.  
    108. proc RemoveHook
    109.      xor al, al
    110.      mov al, [g_bHookSet]
    111.      cmp al, FALSE
    112.      je .getOut
    113.      invoke UnhookWindowsHookEx, hCurrentHook
    114.      invoke MessageBox, NULL, sHookRemoved, sTitle, MB_OK
    115.  
    116.      .getOut:
    117.      ret
    118. endp
    119.  
    120. section '.idata' import data readable writeable
    121.  
    122.   library kernel,'KERNEL32.DLL',\
    123.           user,'USER32.DLL'
    124.  
    125.   import kernel,\
    126.          GetLastError, 'GetLastError'
    127.  
    128.   import user,\
    129.          MessageBox,'MessageBoxA',\
    130.          SetWindowsHookEx, 'SetWindowsHookExA',\
    131.          UnhookWindowsHookEx, 'UnhookWindowsHookEx',\
    132.          CallNextHookEx, 'CallNextHookEx',\
    133.          GetKeyState, 'GetKeyState'
    134.  
    135. section '.edata' export data readable
    136.  
    137. export 'VITDLL.DLL',\
    138.          InstallHook,'InstallHook',\
    139.          RemoveHook,'RemoveHook'
    140.  
    141.  
    142. section '.reloc' fixups data discardable
     
  6. Asterix

    Asterix New Member

    Blog Posts:
    0
    Joined:
    Feb 25, 2003
    Messages:
    3,576
    Code (Text):
    1. mov eax, dword ptr wParam
    2.      test eax, '1'
    какой-то странный код

    я бы переписал так:

    mov eax, [wParam]
    cmp al, '1'
    je ...

    кстати, отладчик никто не отменял, проверь все-ли правильно отрабатывается
     
  7. leo

    leo Active Member

    Blog Posts:
    0
    Joined:
    Aug 4, 2004
    Messages:
    2,542
    Location:
    Russia
    Ес-но, после test допустимы только проверки флагов ZF,SF и PF, но уж никак не jl и jg
     
  8. xlinuks

    xlinuks New Member

    Blog Posts:
    0
    Joined:
    May 25, 2006
    Messages:
    181
    Asterix, leo, вы правы, спасибо. У меня есть определенная неприязнь к дебаггерам но деватся некуда. Теперь работает, дело за малым!
    Code (Text):
    1.      xor eax, eax
    2.      mov eax, dword ptr wParam
    3.      cmp eax, '1'
    4.      jl .getOut
    5.  
    6.      xor eax, eax
    7.      mov eax, dword ptr wParam
    8.      cmp eax, '9'
    9.      jg .getOut
    10.  
    11.      invoke MessageBox, NULL, sKeyPressed, sTitle, MB_OK
     
  9. IceStudent

    IceStudent Active Member

    Blog Posts:
    0
    Joined:
    Oct 2, 2003
    Messages:
    4,300
    Location:
    Ukraine
    По поводу сабжа, пример из мсдн:
    Code (Text):
    1. #define SHIFTED 0x8000
    2. nVirtKey = GetKeyState(VK_SHIFT);
    3. if (nVirtKey & SHIFTED){
    4. ...
    5. }
    6.  
    7. ; на асме проще
    8. invoke GetKeyState,VK_SHIFT
    9. test ax,ax
    10. jns @F
    11.  ; shifted
    12.  ....
    13. @@:
     
  10. xlinuks

    xlinuks New Member

    Blog Posts:
    0
    Joined:
    May 25, 2006
    Messages:
    181
    Все, получилось, кому интересно может пользоватся прогой с
    http://www.geocities.com/xlinuks/TransWindows.zip
    Она умеет изменять прозрачность окон и ставить окно 'always on top', т.е. чтобы была всегда на виду.
    Всего 4 Кб.