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

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

DrawItem2000 proc uses edx ebx


    LOCAL RctEdge     :RECT
    LOCAL RctText     :RECT
    LOCAL RctSep      :RECT
    LOCAL mii         :MENUITEMINFO
    LOCAl TextItemLen :DWORD
    LOCAL szBuff[128] :BYTE
    LOCAL tSelect     :BYTE         ; флаг выделять запрещёный итем при выборе или нет.
    LOCAL hIcon       :DWORD
    LOCAL hPenSep     :HPEN    ; Хендл пера прорисовки сепараторов и рамки запрещенного CheckItema    
    LOCAL OldPen      :HPEN    ; перо по умолчанию    
    LOCAL colorWindow :COLORREF
    LOCAL colorMenu   :COLORREF
    LOCAL colorMenuBar:COLORREF
    LOCAL colorBorder :COLORREF
    LOCAL colorBitmap :COLORREF
    LOCAL colorSel    :COLORREF
    LOCAL colorSep    :COLORREF
    
    LOCAL hBrushCheckUn :HBRUSH

    LOCAL fDrawState  :BYTE
    LOCAL tmp         :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

    invoke LightenColor, 96, colorMenuBar
    invoke CreateSolidBrush, eax
    mov hBrushCheckUn, eax 

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

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
    
        invoke GetMenuString, [ebx].hwndItem, [ebx].itemID, ADDR szBuff, 128, MF_BYCOMMAND ; получим строку
        mov TextItemLen, eax

        ; ЦВЕТ ТЕКСТА ИТЕМА МЕНЮ (ЗАПРЕЩЁННЫЙ?)
    
        .if [ebx].itemState & ODS_GRAYED
                    
            invoke GetSysColor, COLOR_GRAYTEXT           
            
            .if fSelection                      ; выделять запрещёный итем при выборе?
                mov tSelect, TRUE
                
                .if [ebx].itemState & ODS_SELECTED                
                    ; цвет фона не должен совпадать с цветом текста
                    mov edx, eax
                    invoke GetSysColor, COLOR_HIGHLIGHT                                       
                    .if edx == eax
                        invoke LightenColor, 96, eax
                        .if eax == edx
                            invoke DarkenColor, 96, eax                        
                        .endif
                    .else
                        mov eax, edx
                    .endif                
                .endif
                
            .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      
            
            .if hIcon || [ebx].itemState & ODS_CHECKED
                mov eax, WidthBorder
                dec eax
                add [ebx].rcItem.left, eax                 
            .endif        
            invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, COLOR_HIGHLIGHT+1
;            invoke FrameRect, [ebx].hdc, ADDR [ebx].rcItem, hBrushSelBor
            .if hIcon || [ebx].itemState & ODS_CHECKED
                mov eax, WidthBorder
                dec eax
                sub [ebx].rcItem.left, eax
            .endif
            
            
            mov fDrawState, SELECT
            .if !([ebx].itemState & ODS_GRAYED)
                invoke GetSysColor, COLOR_HIGHLIGHTTEXT
                invoke SetTextColor, [ebx].hdc, eax
            .endif                        
@@:
        .else    
            invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, COLOR_MENU+1   
            mov fDrawState, UNSELECT
        .endif
          
       .if [ebx].itemState & ODS_GRAYED
            mov fDrawState, GRAY
       .endif
        
       .if [ebx].itemState & ODS_CHECKED    ; пункт меню отмечен галочкой       
           
            .if hIcon
            
                mov eax, [ebx].rcItem.left        ;  прямоугольник галочки
                mov RctEdge.left, eax
                mov eax, [ebx].rcItem.top
                mov RctEdge.top, eax
                mov eax, [ebx].rcItem.left
                add eax, WidthBorder
                sub eax, 2
                mov RctEdge.right, eax
                mov eax, [ebx].rcItem.bottom
                mov RctEdge.bottom, eax
            
                .if fDrawState == GRAY
                    invoke DrawEdge, [ebx].hdc, ADDR RctEdge, BDR_SUNKENOUTER, BF_RECT
                .elseif fDrawState == SELECT
                    invoke InflateRect, ADDR RctEdge, -1, -1
                    invoke FillRect, [ebx].hdc, ADDR RctEdge, COLOR_MENU+1
                    invoke InflateRect, ADDR RctEdge, 1, 1
                    invoke DrawEdge, [ebx].hdc, ADDR RctEdge, BDR_SUNKENINNER, BF_TOPLEFT
                .elseif fDrawState == UNSELECT
                    invoke InflateRect, ADDR RctEdge, -1, -1
                    invoke FillRect, [ebx].hdc, ADDR RctEdge, hBrushCheckUn
                    invoke InflateRect, ADDR RctEdge, 1, 1
                    invoke DrawEdge, [ebx].hdc, ADDR RctEdge, BDR_SUNKENOUTER, BF_RECT
                .endif
            
                .if fDrawState == SELECT
                    mov fDrawState, UNSELECT
                .endif                       
                
                dec [ebx].rcItem.top 
                invoke DrawIcn, [ebx].hdc, ADDR [ebx].rcItem, hIcon, fDrawState, TRUE
                inc [ebx].rcItem.top                
                
            .else
           
                ; Прорисовать прямоугольник галочки и саму галочку        
                ; Опредилим что рисовать галочку или точку        
                mov eax, mii.fType
                and eax, MFT_RADIOCHECK
                .if eax == MFT_RADIOCHECK
                    mov al, TRUE
                .else
                    mov al, FALSE
                .endif
                invoke DrawCheck_2000, [ebx].hdc, ADDR [ebx].rcItem, fDrawState, al
    
            .endif
    
       .else
       
            .if hIcon 
            
                .if [ebx].itemState & ODS_SELECTED && tSelect
            
                    mov eax, [ebx].rcItem.left        ;  прямоугольник Edge
                    mov RctEdge.left, eax
                    mov eax, [ebx].rcItem.top
                    mov RctEdge.top, eax
                    mov eax, [ebx].rcItem.left
                    add eax, WidthBorder
                    sub eax, 2       
                    mov RctEdge.right, eax
                    mov eax, [ebx].rcItem.bottom
                    mov RctEdge.bottom, eax
                    invoke DrawEdge, [ebx].hdc, ADDR RctEdge, BDR_RAISEDINNER, BF_RECT
                    
                .endif
                
                .if fDrawState == SELECT
                    mov fDrawState, UNSELECT
                .endif                
                
                dec [ebx].rcItem.left   ; для всех
                
                .if fDrawState != GRAY
                    dec [ebx].rcItem.top
                .elseif fDrawState == GRAY 
                    dec [ebx].rcItem.left
                .endif
                 
                invoke DrawIcn, [ebx].hdc, ADDR [ebx].rcItem, hIcon, fDrawState, TRUE    ; DRAW ICON
                
                inc [ebx].rcItem.left   ; для всех
                .if fDrawState != GRAY 
                    inc [ebx].rcItem.top
                .elseif fDrawState == GRAY 
                    inc [ebx].rcItem.left   
                .endif
                
            .elseif mii.hbmpItem                    
                invoke DrawBmp, [ebx].hdc, ADDR [ebx].rcItem, mii.hbmpItem, fDrawState                    
            .endif
                
       .endif
    
        ;ТЕКСТ 
        ;
    
    ; вычислим прямоугольник текста
        invoke CopyRect, ADDR RctText, ADDR [ebx].rcItem
        mov eax, WidthBorder
        dec eax                   ; всё сдвигали, и текст сдвинем
        add RctText.left, eax
        add RctText.left, 6
        mov eax, WidthBorder
        shr eax, 1
        add eax, 5
        sub RctText.right, eax     ; смещение от правого края если есть символ Tab       
       
       .if ([ebx].itemState & ODS_GRAYED) && !([ebx].itemState & ODS_SELECTED)
            invoke GetSysColor, COLOR_BTNHIGHLIGHT
            invoke SetTextColor, [ebx].hdc, eax
            
            inc RctText.left
            inc RctText.bottom
            inc RctText.right
            inc RctText.top
            mov tmp, 0                       
        .endif        

@@: 
            
    ; поиск символа табуляции в строке
        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    
    
        cmp tmp, 1
        je @f    
    
       .if ([ebx].itemState & ODS_GRAYED) && !([ebx].itemState & ODS_SELECTED)
            invoke GetSysColor, COLOR_BTNSHADOW
            invoke SetTextColor, [ebx].hdc, eax
            dec RctText.left
            dec RctText.bottom
            dec RctText.right
            dec RctText.top 
            
            mov tmp, 1            
            jmp @b           
        .endif

@@:

        
   .elseif eax == MFT_SEPARATOR           ; Пункт меню SEPARATOR
    
        invoke FillRect,[ebx].hdc,ADDR [ebx].rcItem,COLOR_MENU+1
        
        ; Draw the seperator         
         
        invoke CopyRect, ADDR RctSep, ADDR [ebx].rcItem
        
        mov eax, WidthBorder
        shr eax, 1
        inc eax
        mov RctSep.left, eax        
        sub RctSep.right, eax
          
        mov eax, RctSep.bottom
        sub eax, RctSep.top
        shr eax, 1
        dec eax
        add RctSep.top, eax        
        m2m RctSep.bottom, RctSep.top
        add RctSep.bottom, 2
        
        invoke FillRect, [ebx].hdc, ADDR RctSep, COLOR_BTNHIGHLIGHT+1        
                
        dec RctSep.right
        dec RctSep.bottom
        
        invoke FillRect, [ebx].hdc, ADDR RctSep, COLOR_BTNSHADOW+1
        
    
    .elseif eax == MFT_BITMAP              ; Пункт меню BITMAP
    
    
    
    .endif
    
    invoke DeleteObject, hBrushCheckUn
    
    ret
DrawItem2000 endp


DrawCheck_2000 proc uses edx hDC:HDC, lpRect:DWORD, State:BYTE, CheckMark:BYTE

LOCAL RctCheck              :RECT
LOCAL hBrushCheckDisabled   :HBRUSH
LOCAL hPenFrameGray         :HPEN      ; Хендл пера прорисовки рамки запрещенного CheckItema
LOCAL OldPen                :HPEN      ; перо и кисть по умолчанию
LOCAL OldBrush              :HBRUSH
LOCAL hGlyphFont            :HFONT
LOCAL colorSel              :COLORREF
LOCAL colorBorder           :COLORREF
LOCAL GlyphArray[2]         :BYTE
LOCAL OldClr                :DWORD
LOCAL ncinfo                :NONCLIENTMETRICS
LOCAL hBrushCheckUn         :HBRUSH

    
    invoke LightenColor, 128, $invoke ( GetSysColor, COLOR_GRAYTEXT )     ; запрещённый
    invoke CreateSolidBrush, eax
    mov hBrushCheckDisabled, eax
    
    invoke GetSysColor, COLOR_MENU
    invoke LightenColor, 96, eax
    invoke CreateSolidBrush, eax
    mov hBrushCheckUn , 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             ; дескриптор  шрифта
    
; цвет рамки запрещенного CheckItema
    
    invoke DarkenColor, 8, $invoke ( GetSysColor, COLOR_GRAYTEXT )
    invoke CreatePen,PS_SOLID,1,eax
    mov hPenFrameGray, eax     

    mov edx, lpRect

;    invoke CopyRect, ADDR RctCheck, lpRect

    mov eax, [edx].RECT.left        ;  прямоугольник галочки
;    add eax, 1
    mov RctCheck.left, eax
    mov eax, [edx].RECT.top
    mov RctCheck.top, eax
    mov eax, [edx].RECT.left
    add eax, WidthBorder
    sub eax, 2                        ; как для ширины, смотри MEASUREITEM    
    mov RctCheck.right, eax
    mov eax, [edx].RECT.bottom
    mov RctCheck.bottom, eax
    
    xor eax, eax                    ; состояние вывода
    mov al, State 
    and al, GRAY or SELECT or UNSELECT

    .if al == GRAY
    
        mov OldClr, $invoke (SetTextColor, hDC, $invoke ( GetSysColor, COLOR_GRAYTEXT ))
        mov OldPen, $invoke ( SelectObject, hDC, hPenFrameGray )
        mov OldBrush, $invoke ( SelectObject, hDC, hBrushCheckDisabled )
        invoke DrawEdge, hDC, ADDR RctCheck, BDR_SUNKENOUTER, BF_RECT
        invoke SelectObject, hDC, OldPen    ; вернём контексту его объекты,                             
        invoke SelectObject, hDC, OldBrush  ; что бы можно было удалить созданные объекты    

    .elseif al == SELECT

        mov OldClr, $invoke (SetTextColor, hDC, Black)
        invoke InflateRect, ADDR RctCheck, -1, -1
        invoke FillRect, [ebx].hdc, ADDR RctCheck, COLOR_MENU+1
        invoke InflateRect, ADDR RctCheck, 1, 1
        invoke DrawEdge, hDC, ADDR RctCheck, BDR_SUNKENINNER, BF_TOPLEFT
                
    .elseif al == UNSELECT

        mov OldClr, $invoke (SetTextColor, hDC, Black)
        invoke InflateRect, ADDR RctCheck, -1, -1
        invoke FillRect, [ebx].hdc, ADDR RctCheck, hBrushCheckUn
        invoke InflateRect, ADDR RctCheck, 1, 1
        invoke DrawEdge, hDC, ADDR RctCheck, BDR_SUNKENOUTER, BF_RECT
    
    .endif

    invoke SetBkMode,hDC,TRANSPARENT
    invoke SelectObject, hDC, hGlyphFont
    push eax
    
    .if CheckMark               
        mov GlyphArray, 69h         ; Bullet
    .else 
        mov GlyphArray, 62h         ; Checkmark
    .endif 
                               
    invoke DrawText, hDC,ADDR GlyphArray, 1, ADDR RctCheck, DT_CENTER or DT_VCENTER or DT_SINGLELINE
    pop eax
    invoke SelectObject,hDC, eax            ; востановим прежний шрифт
    
    invoke SetTextColor, hDC, OldClr
    invoke DeleteObject, hGlyphFont
    invoke DeleteObject, hPenFrameGray
    invoke DeleteObject, hBrushCheckDisabled
    invoke DeleteObject, hBrushCheckUn
    
    ret
DrawCheck_2000 endp