; #########################################################################

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

; #########################################################################

;     include files
;     ~~~~~~~~~~~~~
      include \masm32\include\WINDOWS.INC
      include \masm32\include\masm32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\comctl32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\oleaut32.inc
      include \masm32\include\msimg32.inc
      include \masm32\include\debug.inc

;     libraries
;     ~~~~~~~~~
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib
      includelib \masm32\lib\msimg32.lib
      includelib \masm32\lib\debug.lib
      
      include \masm32\MACROS\Macros.asm    
      
; ########################### Inserted modules ############################

      include 	XXControls.inc
      includelib 	XXControls.lib
        
      ; #? - About #
        
      include 	XXAbout.inc
      includelib 	XXAbout.lib 

; #########################################################################

        ;=============
        ; macros
        ;=============
  
      m2m MACRO M1, M2
        push M2
        pop  M1
      ENDM

      return MACRO arg
        mov eax, arg
        ret
      ENDM

$invoke MACRO Fun:REQ, A:VARARG
  IFB <A>
    invoke Fun
  else
    invoke Fun, A
  endif
  exitm <eax>
        ENDM

LOWORD MACRO bigword    ; Возврвщает младщее слово  
   mov  eax,bigword
   and  eax,0FFFFh     ;; Set to low word 
ENDM


HIWORD macro bigword    ; Возврвщает старшее слово 
   mov  eax,bigword
   shr  eax,16         ;; Get high word
endm

IF_MSG macro WMsg:REQ, DoJmp:REQ
   cmp uMsg, WMsg
   jz  DoJmp
endm

WM_CASE macro reg,msgs
   irp msg,<msgs>
      cmp reg,WM_&msg
      je @@&msg
   endm
endm          
        ;=================
        ; Local prototypes
        ;=================
        WndProc         PROTO :HWND, :UINT, :WPARAM, :LPARAM
        AboutProc       PROTO :HWND, :UINT, :WPARAM, :LPARAM
        GetMsgProc	    PROTO :DWORD, :WPARAM, :LPARAM	
        
    .data?
        hInstance                   HINSTANCE   ?
        hMenu                       HMENU       ?
        hSysMenu                    HMENU       ?
        hContextMenu                HMENU       ?           
        hImageList                  HIMAGELIST  ?
        h_Accel           	      HACCEL      ?
        hMainDlg		      HWND        ?
        hHook		      HHOOK       ?
            
    .const
        IDD_MAIN                    equ         800   ; идентификатор диалогового окна в файле ресурсов
  
        MAINMENU                    equ         600
        
        IDM_FILE_NEW                equ         1002
        IDM_FILE_OPEN               equ         1004
        IDM_FILE_SAVE               equ         1006
        IDM_FILE_SAVE_AS            equ         1008
        IDM_FILE_PRINT              equ         1010
        IDM_FILE_PRINT_PREVIEW      equ         1012
        IDM_FILE_PRINT_SETUP        equ         1014
        IDM_FILE_RECENT_FILE        equ         1016
        IDM_FILE_APP_EXIT           equ         1018
        IDM_EDIT_UNDO               equ         1020
        IDM_EDIT_CUT                equ         1022
        IDM_EDIT_COPY               equ         1024
        IDM_EDIT_PASTE              equ         1026
        IDM_EDIT_DELETE             equ         1028
        
        IDM_EDIT_BMP                equ         1080
        
        IDM_VIEW_TOOLBARS           equ         1030
        IDM_VIEW_TOOLBARS_STANDARD  equ         1032
        IDM_VIEW_TOOLBARS_CUSTOMIZE equ         1034
        IDM_VIEW_SATATUSBAR         equ         1036
        IDM_VIEW_STYLE_DEFAULT      equ         1040
        IDM_VIEW_STYLE_OFFICE_2000  equ         1042
        IDM_VIEW_STYLE_OFFICE_XP    equ         1044
        IDM_VIEW_STYLE_XNET         equ         1046
        IDM_HELP_ABOUT_MENU_XX      equ         1050
        
        IDM_NOT_STANDART_CHECK_ITEM equ	        1072
        
        IDB_BITMAP1                 equ         101
        ACC           	      equ         110    
    
    .code

start:

; #########################################################################

        invoke GetModuleHandle, NULL
        mov hInstance, eax
        
        ; Загружаем таблицу акселераторов
        mov h_Accel, $invoke (LoadAccelerators, hInstance, ACC)        
        
        xor eax, eax
        mov ax, IDD_MAIN
        invoke DialogBoxParam,hInstance,IDD_MAIN,0,ADDR WndProc,0
                        
        invoke DestroyAcceleratorTable, h_Accel 
        
        invoke ExitProcess,eax

; #########################################################################

WndProc proc hWin :HWND,uMsg :DWORD, wParam :DWORD, lParam :DWORD

    LOCAL hBmpImgList :HBITMAP
    LOCAL var         :DWORD
    LOCAL buffer1[128]:BYTE  ; these are two spare buffers
    LOCAL buffer2[128]:BYTE  ; for text manipulation etc..

      .if uMsg == WM_INITDIALOG

        ;	Подключим оперативные клавиши
        ; Устанавливаем локальный хук WH_GETMESSAGE на текущий поток.
      
        call GetCurrentThreadId
        invoke SetWindowsHookEx, WH_GETMESSAGE, ADDR GetMsgProc, NULL, eax 
        mov hHook, eax       
      
        ; Сохраняем хэндл диалога, чтобы функция хука могла на него ссылаться.
        m2m hMainDlg, hWin
      
        ; создадим список изображений
        mov hImageList, $invoke (ImageList_Create, 16, 16, ILC_COLOR or ILC_MASK, 14,0)
        mov hBmpImgList, $invoke (LoadBitmap, hInstance, IDB_BITMAP1)
        RGB 192, 192, 192
        invoke ImageList_AddMasked, hImageList, hBmpImgList, eax
        invoke DeleteObject, hBmpImgList
        
        mov hMenu, $invoke (GetMenu, hWin)              ; выберем дескриптор меню
        mov hContextMenu, $invoke (GetSubMenu, hMenu, 1); выберем дескриптор конекстного меню
        ; системному меню новый стиль
        mov hSysMenu, $invoke (GetSystemMenu, hWin, FALSE) ; выберем дескриптор меню
        
        invoke RedrawMenu, hWin, hMenu, STYLE_OFFICE_XP     ; Перерисуем меню
        invoke SetMenuItemIcon, hMenu, IDM_FILE_NEW, $invoke (ImageList_GetIcon, hImageList, 0, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_FILE_OPEN, $invoke (ImageList_GetIcon, hImageList, 1, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_FILE_SAVE, $invoke (ImageList_GetIcon, hImageList, 2, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_FILE_PRINT, $invoke (ImageList_GetIcon, hImageList, 3, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_FILE_PRINT_PREVIEW,  $invoke (ImageList_GetIcon, hImageList, 4, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_FILE_PRINT_SETUP, $invoke (ImageList_GetIcon, hImageList, 5, ILD_NORMAL) 
        
        invoke SetMenuItemIcon, hMenu, IDM_EDIT_UNDO, $invoke (ImageList_GetIcon, hImageList, 6, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_EDIT_CUT, $invoke (ImageList_GetIcon, hImageList, 7, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_EDIT_COPY, $invoke (ImageList_GetIcon, hImageList, 8, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_EDIT_PASTE, $invoke (ImageList_GetIcon,  hImageList, 9, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_EDIT_DELETE, $invoke (ImageList_GetIcon, hImageList, 10, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_VIEW_TOOLBARS_CUSTOMIZE, $invoke (ImageList_GetIcon, hImageList, 11, ILD_NORMAL) 
        invoke SetMenuItemIcon, hMenu, IDM_HELP_ABOUT_MENU_XX,  $invoke (ImageList_GetIcon, hImageList, 12, ILD_NORMAL)
        invoke SetMenuItemIcon, hMenu, IDM_NOT_STANDART_CHECK_ITEM, $invoke (ImageList_GetIcon, hImageList, 13, ILD_NORMAL)	; Check item with icon
        
        ; установим переключатели стилей в меню
        invoke CheckMenuRadioItem, hMenu, IDM_VIEW_STYLE_DEFAULT, IDM_VIEW_STYLE_XNET, IDM_VIEW_STYLE_OFFICE_XP, MF_BYCOMMAND

        ; ИЗМЕНИМ СИСТЕМНОЕ МЕНЮ
        mov hSysMenu, $invoke ( GetSystemMenu, hWin, FALSE )   ; выбрем дескриптор системного меню
        invoke AppendMenu, hSysMenu, MF_SEPARATOR, 0, 0        ; Добавим к системному меню пункт меню сепартор
        ; Добавим к системному меню пункт меню "О программе"
        invoke GetMenuString, hMenu, IDM_HELP_ABOUT_MENU_XX, ADDR buffer1, 128, MF_BYCOMMAND    ; получим строку
        invoke AppendMenu, hSysMenu, MF_STRING, IDM_HELP_ABOUT_MENU_XX, ADDR buffer1    
        invoke RedrawMenu, hWin, hSysMenu, STYLE_OFFICE_XP     ; Перерисуем добавленные в меню пунты
        ; Установим иконку на добавленом пункте меню.
        invoke SetMenuItemIcon, hSysMenu, IDM_HELP_ABOUT_MENU_XX, $invoke (ImageList_GetIcon, hImageList, 12, ILD_NORMAL)

        mov eax, TRUE
        
      .elseif uMsg == WM_COMMAND
      
              ;======== menu commands ========
        mov eax, wParam        
            .if ax == IDM_FILE_APP_EXIT
            
                invoke  SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL
            
            .elseif ax == IDM_VIEW_TOOLBARS_STANDARD
                  
                jmp reverse                     
            .elseif ax == IDM_VIEW_TOOLBARS_CUSTOMIZE
                 
            .elseif ax == IDM_VIEW_SATATUSBAR
            
reverse:        
                invoke GetMenuState, hMenu, wParam, MF_BYCOMMAND            
                and eax, MF_CHECKED
                
                .if eax == MF_CHECKED
                    invoke CheckMenuItem,hMenu, wParam, MF_BYCOMMAND or MF_UNCHECKED                        
                .else                           
                    invoke CheckMenuItem,hMenu, wParam, MF_BYCOMMAND or MF_CHECKED             
                .endif
                
            .elseif ax == IDM_NOT_STANDART_CHECK_ITEM

                jmp reverse                
            .elseif ax == IDM_VIEW_STYLE_DEFAULT
                mov var, STYLE_DEFAULT                        
                jmp radio_check
                
            .elseif ax == IDM_VIEW_STYLE_OFFICE_2000
                mov var, STYLE_OFFICE_2000
                jmp radio_check
                 
            .elseif ax == IDM_VIEW_STYLE_OFFICE_XP
                mov var, STYLE_OFFICE_XP
                jmp radio_check
                
            .elseif ax == IDM_VIEW_STYLE_XNET
                mov var, STYLE_XNET
         
radio_check:
                invoke RedrawMenu, hWin, hMenu, var
                invoke RedrawMenu, hWin, hSysMenu, var
                invoke CheckMenuRadioItem, hMenu, IDM_VIEW_STYLE_DEFAULT, IDM_VIEW_STYLE_XNET, wParam, MF_BYCOMMAND                                        
    
            .elseif ax == IDM_HELP_ABOUT_MENU_XX        ; О ПРОГРАММЕ
    
                invoke CreateXXAboutDlg, hWin  
                
            .else
    
                invoke GetMenuString, hMenu, wParam, ADDR buffer1, 128, MF_BYCOMMAND
                mov eax, wParam
                xor edx, edx
                mov dx, ax   
                invoke dwtoa, edx, ADDR buffer2 
                invoke MessageBox, hWin, ADDR buffer1, ADDR buffer2, MB_OK
            .endif
            
        ;====== end menu commands ======
      .elseif uMsg == WM_CONTEXTMENU
        push 0
        push hWin       ; ВАЖНО!!! Здесь должен стоять хендл окна которое обрабатывает
                        ; сообщения от меню, WM_COMMAND и т.п.
        push 0        
        HIWORD lParam   ; вертикальное расположение всплывающего меню
        push eax
        LOWORD lParam   ; горизонтальное расположение всплывающего меню
        push eax
        push 0
        push hContextMenu
        call TrackPopupMenu 
        
      .elseif uMsg == WM_SYSCOMMAND
      
        mov eax, wParam    
        .if ax == IDM_HELP_ABOUT_MENU_XX        ; О ПРОГРАММЕ
            invoke CreateXXAboutDlg, hWin
        .endif
        
      .elseif uMsg == WM_CLOSE
      
        ; Снимаем хук.
        invoke UnhookWindowsHookEx, hHook 
      
        invoke ImageList_Destroy, hImageList
        invoke EndDialog,hWin,0	; Закрываем диалог.

      .endif

    xor eax, eax
    ret

WndProc endp

; ########################################################################
; Процедура хука, генерирует сообщение WM_COMMAND для оперативных клавиш
; ########################################################################

GetMsgProc proc uses ebx nCode :DWORD, wParam :WPARAM, lParam :LPARAM

mov ebx, lParam
assume ebx: ptr MSG

	.if [ebx].message >= WM_KEYFIRST && [ebx].message <= WM_KEYLAST
	
		; Преобразуем нажатия клавиш в WM_COMMAND.
	 	invoke TranslateAccelerator, hMainDlg, h_Accel, lParam
	 	
		.if eax
			; Если сообщение преобразовано, уничтожаем его, устанавливая код в WM_NULL.
			; Если этого не сделать, сообщение попадёт в диалог, и он недовольно "запищит".
			mov [ebx].message, WM_NULL
		.endif	
	.endif

assume ebx: nothing

    ; Вызываем следующий фильтр.
    invoke CallNextHookEx, hHook, nCode, wParam, lParam 
    xor eax, eax
    ret
GetMsgProc endp

; ########################################################################

end start
