comment $
//-----------------------------------------------------------------------------------//
//  Source code                                                                      //
//                                                                                   //
//  Written      by  Chib, amdtm                     http://www.xxcontrols.com       //
//                                                                                   //
//  FileName   : XNET.inc                                                            //
//  Description: libraries of functions for work with menu                           //
//  Version    : 1.00.000, January 1, 2004                                           //
//-----------------------------------------------------------------------------------//
$ 

; #########################################################################
;                                                                         ;
; Процедура обработки WM_DrawItem_Menu (стиль XP)                              ;
;                                                                         ;
; #########################################################################

DrawItem_MenuXNET proc uses ecx ;edx lParam:LPARAM

    LOCAL mii         :MENUITEMINFO
    LOCAl TextItemLen :DWORD
    LOCAL szBuff[128] :BYTE
    LOCAL hIcon       :HICON
    LOCAL temp        :DWORD
    LOCAL tSelect     :BYTE         ; флаг выделять запрещёный итем при выборе или нет.
    LOCAL RctText     :RECT
    LOCAL RctBorder   :RECT
    LOCAL RctSep      :RECT
    LOCAL RctShade    :RECT
    LOCAL RctCorner   :RECT
    LOCAL RctLeftBorder:RECT

    LOCAl hBrush      :HBRUSH
    LOCAL hPen        :HPEN
    LOCAl OldBrush    :HBRUSH
    LOCAL OldPen      :HPEN
    LOCAL RctCheck    :RECT

    LOCAL hBrushSel   :HBRUSH
    LOCAL hBrushSelBor:HBRUSH
    LOCAL hBrushSep   :HBRUSH  ; Хендл кисти прорисовки сепараторов и рамки запрещенного CheckItema
    LOCAL hBrushRight :HBRUSH  ; Хендл кисти прорисовки меню, когда пункт не выделен.
    LOCAL hBrushBorder:HBRUSH
    
    LOCAL colorText   :COLORREF
    LOCAL colorWindow :COLORREF
    LOCAL colorMenu   :COLORREF
    LOCAL colorMenuBar:COLORREF
    LOCAL colorBorder :COLORREF
    LOCAL colorBitmap :COLORREF
    LOCAL colorSel    :COLORREF
    LOCAL colorSep    :COLORREF
    
    LOCAL clr_start   :COLORREF  
    LOCAL clr_end     :COLORREF
    
    LOCAL fDrawState  :BYTE
    
    LOCAL r           :DWORD
    LOCAL g           :DWORD
    LOCAL b           :DWORD

    ; Кисти, перья и т.д. для прорисовки меню   

    mov colorBorder, $invoke ( GetSysColor, COLOR_HIGHLIGHT )
    mov colorMenuBar, $invoke ( GetSysColor, COLOR_MENU )
    mov colorWindow, $invoke ( GetSysColor, COLOR_WINDOW )
    mov colorBitmap, $invoke ( MixedColor, colorMenuBar, colorWindow )
    mov colorSep, $invoke ( GetSysColor, COLOR_GRAYTEXT )   
    call GetXpHighlightColor
    mov colorSel, eax

    call NumColorBits
    .if eax > 8
    
        invoke MixedColor, colorSel, colorBorder
        invoke DarkenColor, 128, eax
        invoke CreateSolidBrush, eax
        mov hBrushSelBor, eax       

    .else
        invoke CreateSolidBrush, colorSel
        mov hBrushSel, eax
        invoke CreateSolidBrush, colorBorder
        mov hBrushSelBor, eax
        invoke CreateSolidBrush, colorWindow
        mov hBrushRight, eax
        invoke CreateSolidBrush, colorMenuBar
        mov hBrushBorder, eax
        invoke CreateSolidBrush, colorSep
        mov hBrushSep, eax
    .endif 

; ======================================================================

assume ebx: ptr DRAWITEMSTRUCT

; выберем информацию о пункте меню    
    mov mii.cbSize, SIZEOF mii
    mov mii.fMask, MIIM_DATA or MIIM_BITMAP or MIIM_FTYPE ;or MIIM_STRING
    invoke GetMenuItemInfo, [ebx].hwndItem, [ebx].itemID, FALSE, ADDR mii
    m2m hIcon, mii.dwItemData
    
    mov eax, mii.fType
    and eax, MFT_SEPARATOR or MFT_STRING or MFT_BITMAP    

    .if eax == MFT_STRING                  ; Пункт меню STRING
    
        inc [ebx].rcItem.top
        dec [ebx].rcItem.bottom
    
        invoke GetMenuString, [ebx].hwndItem, [ebx].itemID, ADDR szBuff, 128, MF_BYCOMMAND ; получим строку
        mov TextItemLen, eax
        invoke SetSizeBorder, ADDR szBuff, eax, hIcon
   
            ; ЦВЕТ ТЕКСТА ИТЕМА МЕНЮ (ЗАПРЕЩЁННЫЙ?)
        
            .if [ebx].itemState & ODS_GRAYED
                invoke GetSysColor, COLOR_GRAYTEXT
                .if fSelection                      ; выделять запрещёный итем при выборе.
                    mov tSelect, TRUE
                .else
                    mov tSelect, FALSE
                .endif
            .else
                invoke GetSysColor, COLOR_MENUTEXT
                mov tSelect, TRUE
            .endif
            invoke SetTextColor, [ebx].hdc, eax
        
            .if [ebx].itemState & ODS_SELECTED
                cmp tSelect, 0
                je @f      
                
                call NumColorBits
                .if eax > 8
                
                    invoke MidColor, colorSel, colorMenuBar
                    invoke DarkenColor, 16, eax
                    mov clr_start, eax
                    invoke MidColor, colorSel, colorMenuBar
                    invoke LightenColor, 128, eax
                    mov clr_end, eax               
                
                    invoke Gradient_Fill, [ebx].hdc, ADDR [ebx].rcItem, clr_start, clr_end,  RECT_V
                .else        
                    invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, hBrushSel
                .endif
                invoke FrameRect, [ebx].hdc, ADDR [ebx].rcItem, hBrushSelBor
                
                mov fDrawState, SELECT
                                        
@@:
            .else
            
                dec [ebx].rcItem.top
                inc [ebx].rcItem.bottom
               
                call NumColorBits
                .if eax > 8
                    invoke DarkenColor, 16, colorMenuBar
                    m2m clr_start, eax
                    invoke LightenColor, 128, colorMenuBar
                    mov clr_end, eax
                   
                    invoke Gradient_Fill, [ebx].hdc, ADDR [ebx].rcItem, clr_start, clr_end, RECT_H
                    
                .else
                    invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, hBrushBorder
                .endif
                inc [ebx].rcItem.top
                dec [ebx].rcItem.bottom
                
                ;  ПРЯМОУГОЛЬНИК ЗАЛИВКИ БОРДЮРА В ЛЕВОЙ ЧАСТИ ИТЕМА
        
;                invoke CopyRect, ADDR RctBorder, ADDR [ebx].rcItem
;                mov eax, WidthBorder
;                add RctBorder.left, eax                 
;                invoke FillRect, [ebx].hdc, ADDR RctBorder, hBrushRight
                mov fDrawState, UNSELECT
            .endif
              
           .if [ebx].itemState & ODS_GRAYED
                mov fDrawState, GRAY
           .endif
            
           .if [ebx].itemState & ODS_CHECKED    ; пункт меню отмечен галочкой       
               
                .if hIcon
                
                    .if fDrawState == SELECT
                        mov fDrawState, UNSELECT
                    .endif                
                
                    invoke DrawRctCheckXNET, [ebx].hdc, ADDR [ebx].rcItem, fDrawState
                    invoke DrawIcn, [ebx].hdc, ADDR [ebx].rcItem, hIcon, fDrawState, FALSE
                                       
                .else
               
                    ; Прорисовать прямоугольник галочки и саму галочку        
                    ; Опредилим что рисовать галочку или точку        
                    mov eax, mii.fType
                    and eax, MFT_RADIOCHECK
                    .if eax == MFT_RADIOCHECK
                        mov al, TRUE
                    .else
                        mov al, FALSE
                    .endif
                    invoke DrawCheckXNET, [ebx].hdc, ADDR [ebx].rcItem, fDrawState, al
        
                .endif
        
           .else
           
                 .if fDrawState == SELECT
                    mov fDrawState, UNSELECT
                 .endif
          
                .if hIcon
                    invoke DrawIcn, [ebx].hdc, ADDR [ebx].rcItem, hIcon, fDrawState, FALSE    ; DRAW ICON
                .elseif mii.hbmpItem                    
                    invoke DrawBmp, [ebx].hdc, ADDR [ebx].rcItem, mii.hbmpItem, fDrawState                    
                .endif
                    
           .endif
        
            ;ТЕКСТ
             
           .if TextItemLen
                   
                ; вычислим прямоугольник текста
                invoke CopyRect, ADDR RctText, ADDR [ebx].rcItem
                mov eax, WidthBorder
                add RctText.left, eax
                add RctText.left,4        ; сместим что бы не был сразу  на краю
                sub RctText.right, 10     ; смещение от правого края если есть символ Tab
                
                ; поиск символа табуляции в строке
                push TextItemLen
                
                cld                         ; поиск вперёд по строке
                lea edi, szBuff             ; адрес строки
                mov al, 09h                 ; искомый символ
                mov ecx, TextItemLen        ; длина строки
                repne scasb                 ; поиск символа '\t' в строке
                jne no_tab                  ; символ '\t' в строке не найден    
                
                push ecx
                invoke DrawText, [ebx].hdc, edi, ecx, ADDR RctText, DT_VCENTER + DT_SINGLELINE + DT_RIGHT + DT_NOCLIP
                pop ecx
                sub TextItemLen, ecx
                dec TextItemLen
                no_tab: 
                invoke DrawText, [ebx].hdc, ADDR szBuff, TextItemLen, ADDR RctText, DT_VCENTER + DT_SINGLELINE + DT_LEFT + DT_NOCLIP
                
                pop TextItemLen

           .endif
    
    .elseif eax == MFT_SEPARATOR           ; Пункт меню SEPARATOR
 
        .if hIcon
    
            invoke GetClipBox, [ebx].hdc, ADDR RctLeftBorder
            m2m RctLeftBorder.left, [ebx].rcItem.left
            m2m RctLeftBorder.right, [ebx].rcItem.right

;            mov eax, offset RctLeftBorder
            lea eax, RctLeftBorder
            push eax
            push [ebx].hdc
            push [ebx].hwndItem
            call hIcon
           
        .else 
    
         call NumColorBits
         .if eax > 8
            
            invoke DarkenColor, 16, colorMenuBar
            m2m clr_start, eax
            invoke LightenColor, 128, colorMenuBar
            mov clr_end, eax
            invoke Gradient_Fill, [ebx].hdc, ADDR [ebx].rcItem, clr_start, clr_end, RECT_H
        
         .else
            invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, hBrushBorder
         .endif        
;        invoke CopyRect, ADDR RctBorder, ADDR [ebx].rcItem
;        mov eax, WidthBorder
;        add RctBorder.left, eax                     
;        invoke FillRect, [ebx].hdc, ADDR RctBorder, hBrushRight
        
        ; Draw the seperator
         
            invoke CopyRect, ADDR RctSep, ADDR [ebx].rcItem
            mov eax, WidthBorder        
            add RctSep.left, eax
            add RctSep.left, 5          ; 5 - отступ линии сепартора от бордюра слева
            mov eax, RctSep.bottom
            sub eax, RctSep.top
            shr eax, 1
            add RctSep.top, eax
            m2m RctSep.bottom, RctSep.top
            dec RctSep.top
            ;inc RctSep.bottom
                        
            call NumColorBits
            .if eax > 8
                invoke Gradient_Fill, [ebx].hdc, ADDR RctSep, colorSep, colorMenuBar, RECT_H
            .else
                invoke FillRect, [ebx].hdc, ADDR RctSep, hBrushSep
            .endif
            
        .endif
    
    .elseif eax == MFT_BITMAP              ; Пункт меню BITMAP
    
    
    
    .endif

    invoke DeleteObject, hBrushSelBor
    call NumColorBits
    .if eax <= 8
        invoke DeleteObject, hBrushSel    
        invoke DeleteObject, hBrushSep      ; Хендл кисти прорисовки сепараторов и рамки запрещенного CheckItema
        invoke DeleteObject, hBrushRight    ; Хендл кисти прорисовки меню, когда пункт не выделен.
        invoke DeleteObject, hBrushBorder
    .endif

assume ebx: nothing        
   ret
DrawItem_MenuXNET endp

; #########################################################################
;                                                                         ;
; Процедура рисования пункта отметки в меню Стиль XP                      ;                           ;
;                                                                         ;
; #########################################################################

DrawCheckXNET proc uses ebx hDC:HDC, lpRect:DWORD, State:BYTE, CheckMark:BYTE

LOCAL RctCheck              :RECT
LOCAL hPen                  :HPEN
LOCAL hBrush                :HBRUSH    ; Кисть заливки CheckItema
LOCAL OldPen                :HPEN      ; перо и кисть по умолчанию
LOCAL OldBrush              :HBRUSH
LOCAL hGlyphFont            :HFONT
LOCAL OldFont               :HFONT     ; шрифт по умолчанию 
LOCAL colorSel              :COLORREF
LOCAL colorBorder           :COLORREF
LOCAL GlyphArray[2]         :BYTE
LOCAL ncinfo                :NONCLIENTMETRICS

    mov colorBorder, $invoke ( GetSysColor, COLOR_HIGHLIGHT )
    call GetXpHighlightColor
    mov colorSel, eax
    
   ; Шрифт для прорисовки галочки CheckItema.   
   
    mov ncinfo.cbSize, sizeof(NONCLIENTMETRICS)           ; обязательно размер структуры
    invoke SystemParametersInfo,SPI_GETNONCLIENTMETRICS,\
                              sizeof(NONCLIENTMETRICS),\
                              addr ncinfo, 0                                      ; взять параметры, в том числе Фонта
    
 
    .if ncinfo.lfMenuFont.lfHeight > -15
        mov ncinfo.lfMenuFont.lfHeight, -15
    .endif

;   mov ncinfo.lfMenuFont.lfWidth, 14
    
    mov ncinfo.lfMenuFont.lfCharSet, DEFAULT_CHARSET
    
    invoke memfill, ADDR ncinfo.lfMenuFont.lfFaceName, LF_FACESIZE, 0
    invoke szCopy, ADDR szGlyphFont, ADDR ncinfo.lfMenuFont.lfFaceName                             
    invoke CreateFontIndirect,  ADDR ncinfo.lfMenuFont
       
    mov hGlyphFont, eax             ; дескриптор  шрифта


    invoke DrawRctCheckXNET, hDC, lpRect, State
    mov ebx, lpRect
    mov eax, [ebx].RECT.left        ;  прямоугольник галочки
    mov RctCheck.left, eax
    mov eax, [ebx].RECT.top
    mov RctCheck.top, eax
    mov eax, [ebx].RECT.left
    add eax, WidthBorder
    mov RctCheck.right, eax
    mov eax, [ebx].RECT.bottom
    mov RctCheck.bottom, eax
   
;--------------Прорисуем галочку-------------------------------------------------
    
    invoke SetBkMode,hDC,TRANSPARENT
    invoke SelectObject, hDC, hGlyphFont
    mov OldFont, eax
    
    .if CheckMark               
        mov GlyphArray, 69h         ; Bullet
    .else
        add RctCheck.top, 1  
        mov GlyphArray, 62h         ; Checkmark
    .endif 
                               
    invoke DrawText, hDC,ADDR GlyphArray, 1, ADDR RctCheck, DT_CENTER or DT_VCENTER or DT_SINGLELINE   
    
    invoke SelectObject, hDC, OldFont   ; востановим прежний шрифт    
    invoke DeleteObject, hGlyphFont
    
    ret
DrawCheckXNET endp

DrawRctCheckXNET proc uses ebx hDC:HDC, lpRect:DWORD, State:BYTE

LOCAL RctCheck              :RECT
LOCAL hPen                  :HPEN
LOCAL hBrush                :HBRUSH    ; Кисть заливки CheckItema
LOCAL OldPen                :HPEN      ; перо и кисть по умолчанию
LOCAL OldBrush              :HBRUSH
LOCAL colorSel              :COLORREF
LOCAL colorBorder           :COLORREF
LOCAL clr_start             :COLORREF
LOCAL clr_end               :COLORREF

    mov colorBorder, $invoke ( GetSysColor, COLOR_HIGHLIGHT )
    call GetXpHighlightColor
    mov colorSel, eax

    mov ebx, lpRect
    mov eax, [ebx].RECT.left        ;  прямоугольник галочки
    mov RctCheck.left, eax
    mov eax, [ebx].RECT.top
    mov RctCheck.top, eax
    mov eax, [ebx].RECT.left
    add eax, WidthBorder
    mov RctCheck.right, eax
    mov eax, [ebx].RECT.bottom
    mov RctCheck.bottom, eax
    
;--------------Выберем кисть в соответствии с соостоянием итема------------------
    
    xor eax, eax                    ; состояние вывода
    mov al, State 
    and al, GRAY or SELECT or UNSELECT

    .if al == GRAY    
    
        call NumColorBits
        .if eax > 8
            ; создадим кисть и перо для прорисовки запрещённого CheckItema        
            invoke MixedColor, colorSel, colorBorder
            invoke LightenColor, 128, eax
            mov clr_end, eax
            invoke DarkenColor, 24, colorSel
            mov clr_start, eax

;            mov clr_start, $invoke ( GetSysColor, COLOR_MENU )
;            mov clr_end, $invoke ( GetSysColor, COLOR_GRAYTEXT ) 
      
            invoke MixedColor, colorSel, colorBorder
            invoke DarkenColor, 128, eax
            invoke CreateSolidBrush, eax
            mov hBrush, eax
        .else
            invoke CreateSolidBrush, $invoke ( GetSysColor, COLOR_MENU )
            mov hBrush, eax
            invoke CreatePen,PS_SOLID,1, $invoke ( GetSysColor, COLOR_GRAYTEXT )
            mov hPen, eax             
        .endif
        
;        jmp no_frame
        
    .elseif al == SELECT

        call NumColorBits
        .if eax > 8
            ; создадим кисть и перо для прорисовки CheckItema имеющего фокус ввода
            invoke LightenColor, 128, colorSel
            mov clr_end, eax
            invoke DarkenColor, 48, colorSel
            mov clr_start, eax
            invoke MixedColor, colorSel, colorBorder        
            invoke DarkenColor, 160, eax
            invoke CreateSolidBrush, eax
            mov hBrush, eax
        .else
            invoke CreateSolidBrush, colorSel
            mov hBrush, eax
            invoke CreatePen,PS_SOLID,1, colorBorder
            mov hPen, eax         
        .endif 
     
    .elseif al == UNSELECT

        call NumColorBits
        .if eax > 8
            ; создадим кисть для прорисовки CheckItema потерявшего фокус ввода.    
            invoke LightenColor, 200, colorSel
            mov clr_end, eax
            invoke DarkenColor, 24, colorSel
            mov clr_start, eax
            invoke MixedColor, colorSel, colorBorder
            invoke DarkenColor, 128, eax
            invoke CreateSolidBrush, eax
            mov hBrush, eax
        .else
            invoke CreateSolidBrush, $invoke ( GetSysColor, COLOR_MENU )
            mov hBrush, eax
            invoke CreatePen,PS_SOLID,1, colorSel
            mov hPen, eax        
        .endif 
            
    .endif    

;--------------Прорисуем рамку CheckItema----------------------------------------

    call NumColorBits
    .if eax > 8
        invoke Gradient_Fill, hDC, ADDR RctCheck, clr_start, clr_end,  RECT_V
        invoke FrameRect, hDC, ADDR RctCheck, hBrush
    .else
        mov OldPen, $invoke ( SelectObject, hDC, hPen )
        mov OldBrush, $invoke ( SelectObject, hDC, hBrush )
        invoke Rectangle,hDC,RctCheck.left,RctCheck.top,
                         RctCheck.right,RctCheck.bottom
        invoke SelectObject, hDC, OldBrush                 
    .endif
  
    invoke DeleteObject, hBrush
    call NumColorBits
    .if eax <= 8
        invoke SelectObject, hDC, OldPen   
        invoke DeleteObject, hPen
    .endif

    ret
DrawRctCheckXNET endp