.386
.model flat, stdcall
option casemap :none   ; case sensitive

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comctl32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comctl32.lib

LOWORD MACRO bigword
    mov  eax,bigword
        and  eax,0FFFFh 
ENDM
HIWORD MACRO bigword
    mov eax,bigword
        shr eax,16
ENDM     

WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
EnumProc PROTO :DWORD,:DWORD
GetBoxHwnd PROTO :HWND

.data
    dlgname     db "MAIN",0
    szTitle     db "Hot Key Adder",0
    szAbout     db "Coded by: Betrayed",13,10
                db "Coded in: Assembly(masm)",13,10
                db "Homepage: http://betrayed.virtualave.net",13,10
                db "E-mail: odin77@hotmail.com",0
    szProgMan   db "Program Manager",0
    szError     db "Unable to set a hotkey to this window",0
    szNoWin     db "Unable to locate specified window...",0

.data?
    hInstance   dd ?
    hList       dd ?
    hHot        dd ?
    buffer      db 255 dup (?)

.code
start:

    invoke GetModuleHandle, NULL
        mov hInstance, eax
    invoke DialogBoxParam,hInstance,addr dlgname,0,ADDR WndProc,0
        invoke ExitProcess,eax

WndProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
    .if uMsg == WM_INITDIALOG
        invoke InitCommonControls                                               ;Loads the common controls so we can use the hotkey control
        invoke SetWindowPos,hWin,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE+SWP_NOMOVE     ;Set on top
        invoke GetDlgItem,hWin,1000                                             ;Get the listbox and store it
            mov hList,eax
        invoke GetDlgItem,hWin,2000                                             ;get the hotkey control and store it
            mov hHot,eax
        invoke EnumWindows,addr EnumProc,NULL                                   ;enum all windows
            xor eax,eax                                                         ;return to the dialog
                ret
    .elseif uMsg == WM_COMMAND
        LOWORD wParam                                                           ;get the id of the control
            .if eax == 3002
                invoke SendMessage,hWin,WM_CLOSE,NULL,NULL
            .elseif eax == 3001
                invoke MessageBox,hWin,addr szAbout,addr szTitle,MB_OK+MB_ICONINFORMATION
            .elseif eax == 3000
                invoke SendMessage,hList,LB_RESETCONTENT,0,0                    ;reset the list
                    invoke EnumWindows,addr EnumProc,NULL                           ;Enum the windows
            .elseif eax == 2002                                                 ;remove button
                invoke GetBoxHwnd,hWin                                          ;Get the hwnd of the chose item
                    .if eax != NULL
                        invoke SendMessage,eax,WM_SETHOTKEY,0,0                 ;Get rid of the hotkey
                            invoke SendMessage,hHot,HKM_SETHOTKEY,0,0               ;Set the hot key control to none
                    .endif
            .elseif eax == 2001                                                 ;Set button
                invoke GetBoxHwnd,hWin
                    mov ebx,eax                                                 ;store the handle in ebx
                        .if eax != NULL
                            invoke SendMessage,hHot,HKM_GETHOTKEY,0,0           ;Get the hotkey
                                invoke SendMessage,ebx,WM_SETHOTKEY,ax,0            ;hotkey is return in a word so we use ax instead of eax
                                    .if eax != 1                                    ;if it does = one the hotkey did not work
                                        invoke MessageBox,hWin,addr szError,addr szTitle,MB_OK+MB_ICONSTOP
                                    .endif
                        .endif
            .elseif eax == 1000                                                 ;listbox
                HIWORD wParam
                    .if eax == LBN_SELCHANGE
                        invoke GetBoxHwnd,hWin
                            .if eax != NULL
                                invoke SendMessage,eax,WM_GETHOTKEY,0,0             ;get the window's hotkey
                                    invoke SendMessage,hHot,HKM_SETHOTKEY,ax,0          ;update the hotkey control again using ax instead of eax
                            .endif
                    .elseif eax == LBN_SELCANCEL
                        invoke SendMessage,hHot,HKM_SETHOTKEY,0,0
                    .endif
            .endif
                xor eax,eax
                    ret
    .elseif uMsg == WM_CLOSE
        invoke ShowWindow,hWin,SW_MINIMIZE                                      ;eyecandy
            invoke EndDialog,hWin,0
                ret
    .endif
        xor eax, eax
            ret
WndProc endp

EnumProc proc hWnd:DWORD,lParam:LPARAM
    invoke GetWindowText,hWnd,addr buffer,255                                   ;Get the windows text
        .if eax         
            invoke IsWindowVisible,hWnd                                         ;see if it is visble
                push eax                                                      ;save result
            invoke lstrcmp,addr buffer,addr szProgMan                           ;We don't want the program manager
                push eax
            invoke lstrcmp,addr buffer,addr szTitle                             ;Lets not do this window either
                pop edx
                pop ecx
                .if !(edx == 0 || ecx == 0 || eax == 0)                          ;Met our criteria
                    invoke SendMessage,hList,LB_ADDSTRING,0,addr buffer     ;Add to the list
                .endif
        .endif
    mov eax, hWnd
        ret
EnumProc endp

GetBoxHwnd proc hDlg:HWND
    invoke SendMessage,hList,LB_GETCURSEL,0,0                                   ;get list number
        invoke SendMessage,hList,LB_GETTEXT,eax,addr buffer                     ;get the text
            invoke FindWindow,NULL,addr buffer                                  ;find the window
                .if eax == NULL                                                 ;if null the window is no longer there or changed titles
                    invoke MessageBox,hDlg,addr szNoWin,addr szTitle,MB_OK+MB_ICONINFORMATION
                        invoke SendMessage,hDlg,WM_COMMAND,3000,0
                            invoke SetFocus,hList
                                xor eax,eax
                .endif
                    ret
GetBoxHwnd endp
end start

