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)                            ;
;                                                                         ;
; #########################################################################

DrawItem_Menu2000 proc uses edx ebx


    LOCAL RctEdge     :RECT
    LOCAL RctText     :RECT
    LOCAL RctSep      :RECT
    LOCAL RctLeftBorder: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 hMemDC      :HDC
    LOCAL hOldBmp     :DWORD
    LOCAL nX          :DWORD
    LOCAL nY          :DWORD
    LOCAL bm          :BITMAP
    
    
    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    

;    invoke GetMenuItemID, [ebx].hwndItem, 0
;    
;    .if hBmpBackground && ( eax == [ebx].itemID || eax == 0FFFFFFFFh )
;        invoke GetClipBox, [ebx].hdc, ADDR RctAll
;        invoke CreateCompatibleDC, [ebx].hdc
;        mov hMemDC, eax
;        invoke SelectObject, hMemDC, hBmpBackground
;        mov hOldBmp, eax
;        ; Get the bitmap information.
;        invoke GetObject, hBmpBackground, sizeof( BITMAP ), ADDR bm
;        
;        .if StyleBackground == FILL_ALL
;
;            mov nX, 0
;            mov nY, 0
;            jmp s_t            
;
;yy:
;            mov eax, bm.bmHeight
;            add nY, eax
;            mov nX, 0
;            jmp s_t
;
;xx:
;            mov eax, bm.bmWidth
;            add nX, eax 
;s_t:                      
;            invoke BitBlt, [ebx].hdc, nX, nY, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY                       
;            
;            mov eax, RctAll.right
;            cmp nX, eax
;            jb xx
;            
;            mov eax, RctAll.bottom
;            cmp nY, eax
;            jb yy            
;
;        .else        
;            invoke StretchBlt, [ebx].hdc, 0, 0, RctAll.right, RctAll.bottom, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY
;        .endif
;        
;        invoke SelectObject, hMemDC, hOldBmp
;        invoke DeleteDC, hMemDC        
;    .endif
   
    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
                
                .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
                inc 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
                inc 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
        
            dec [ebx].rcItem.top
            inc [ebx].rcItem.bottom
        
            invoke FillRect, [ebx].hdc, ADDR [ebx].rcItem, COLOR_MENU+1
            
            inc [ebx].rcItem.top
            dec [ebx].rcItem.bottom
            
            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
                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
            
                jmp icon_draw               
                
            .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
                    mov RctEdge.right, eax
                    mov eax, [ebx].rcItem.bottom
                    mov RctEdge.bottom, eax

                    invoke DrawEdge, [ebx].hdc, ADDR RctEdge, BDR_RAISEDINNER, BF_RECT
                    
                .endif

icon_draw:
                
            .if fDrawState == SELECT
                mov fDrawState, UNSELECT
            .endif               
                 
            invoke DrawIcn, [ebx].hdc, ADDR [ebx].rcItem, hIcon, fDrawState, TRUE    ; 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, 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
@@:

        .endif

        dec [ebx].rcItem.top
        inc [ebx].rcItem.bottom
        
   .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 mii.dwItemData
           
        .else    
    
            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
            add 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
            
        .endif        
    
    .elseif eax == MFT_BITMAP              ; Пункт меню BITMAP
    
    
    
    .endif
    
    invoke DeleteObject, hBrushCheckUn
;    assume ebx: nothing
    ret
DrawItem_Menu2000 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

    call NumColorBits
    .if eax >= 8   
        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
    .else
        invoke CreateSolidBrush, $invoke ( GetSysColor, COLOR_GRAYTEXT )
        mov hBrushCheckDisabled, eax
        invoke CreateSolidBrush, $invoke ( GetSysColor, COLOR_MENU )
        mov hBrushCheckUn , eax 
    .endif    
    
   ; Шрифт для прорисовки галочки 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        ;  прямоугольник галочки
    mov RctCheck.left, eax
    mov eax, [edx].RECT.top
    mov RctCheck.top, eax
    mov eax, [edx].RECT.left
    add eax, WidthBorder
    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