Owner draw ComboBox

Post Reply
AntoninoP
Posts: 347
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy
Contact:

Owner draw ComboBox

Post by AntoninoP »

Hi everyone, I would like to share a my little experiment with owner draw ComboBox:

Image

Here my code:

Code: Select all

#include <fivewin.ch>

function Main()
   local oWnd, oCombo, aItems, cCurr

    DEFINE WINDOW oWnd from 100,100 to 200,400  PIXEL
    aItems := GETFONTNAMES(oWnd:getDc())
    oWnd:ReleaseDC()
    //@ 10,10 COMBOBOX oCombo VAR cCurr ITEMS aItems SIZE 200,25 PIXEL STYLE CBS_DROPDOWNLIST+CBS_OWNERDRAWFIXED
    // precompile the code upper to get the code below
    oCombo := MyCombo():New( 10, 10, { | u | If( PCount()==0, cCurr, cCurr:= u ) }, aItems, ;
                200, 25,,,,,,, .T.,,, .F.,, .F.,{""},,CBS_DROPDOWNLIST+CBS_OWNERDRAWFIXED,,, "oCombo",,,,,,, )
    oCombo:lOwnerDraw := .T.
    ACTIVATE WINDOW oWnd
return 0

class MyCombo inherit TComboBox
    METHOD DrawItem( nIdCtl, nPStruct ) 
endclass

#define WHITE_BRUSH   0

METHOD DrawItem( nIdCtl, nPStruct ) CLASS MyCombo
    LOCAL aData := GetDrawItemStruct(nPStruct)
    LOCAL hDC := aData[7], aRect := {aData[8],aData[9],aData[10],aData[11]}
    LOCAL cFont, oFont
    if aData[3]>=0
        cFont := ::aItems[aData[3]+1]
    endif
    FillRect(hDC,aRect, GetStockObject( WHITE_BRUSH ) )
    if aData[5]=0
         // unselected item
        //MoveTo(hDC, aData[9], aData[8])
        //LineTo(hDC, aData[11], aData[10])
    else
        // Selected item
        MoveTo(hDC, aData[9], aData[10])
        LineTo(hDC, aData[11], aData[8])
    endif
    if !empty(cFont)
        DEFINE Font oFont NAME cFont
        oFont:Activate(hDC)
        DrawTextEx(hDC,cFont,aRect,1)
        oFont:End()
    endif
return 1
It would be great if FiveWin included a bDrawItem with hDC.

What do you think?
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Owner draw ComboBox

Post by cnavarro »

I think this is a good idea, when lOwnerDraw := .T.
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
AntoninoP
Posts: 347
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy
Contact:

Re: Owner draw ComboBox

Post by AntoninoP »

Another better sample, that uses windows style selected marker :)

Image

Code: Select all

#include <fivewin.ch>
#define CBS_OWNERDRAWVARIABLE 0x0020

function Main()
   local oWnd, oCombo, aItems, cCurr

    DEFINE WINDOW oWnd from 100,100 to 200,400  PIXEL
    aItems := GETFONTNAMES(oWnd:getDc())
    oWnd:ReleaseDC()
    oCombo := MyCombo():New( 10, 10, { | u | If( PCount()==0, cCurr, cCurr:= u ) }, aItems, ;
                200, 25,,,,,,, .T.,,, .F.,, .F.,{""},,CBS_DROPDOWNLIST+CBS_OWNERDRAWFIXED,,, "oCombo",,,,,,, )
    //@ 10,10 COMBOBOX oCombo VAR cCurr ITEMS aItems SIZE 200,25 PIXEL
    oCombo:lOwnerDraw := .T.
    //oCombo:WinStyle(CBS_OWNERDRAWFIXED,.T.)

    ACTIVATE WINDOW oWnd
return 0

//procedure InitDlg(oDlg)


class MyCombo inherit TComboBox
    METHOD DrawItem( nIdCtl, nPStruct ) 
endclass

#define WHITE_BRUSH   0
#define COLOR_HIGHLIGHT      13
#define COLOR_HIGHLIGHTTEXT  14
#define COLOR_WINDOW          5
#define COLOR_WINDOWTEXT      6

METHOD DrawItem( nIdCtl, nPStruct ) CLASS MyCombo
    LOCAL aData := GetDrawItemStruct(nPStruct)
    LOCAL hDC := aData[7], aRect := {aData[8],aData[9],aData[10],aData[11]}
    LOCAL cFont, oFont
    if aData[3]>=0
        cFont := ::aItems[aData[3]+1]
    endif
    FillRect(hDC,aRect, GetStockObject( WHITE_BRUSH ) )
    if hb_bitAnd(aData[5],1)>0
        SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT))
        SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT))
    else
        SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT))
        SetBkColor(hDC, GetSysColor(COLOR_WINDOW))
    endif
    if !empty(cFont)
        DEFINE Font oFont NAME cFont SIZE nil,aData[10]-aData[8]
        oFont:Activate(hDC)
        //DrawTextEx(hDC,cFont,aRect,1)
        //SetTextAlign(hDC, 6)
        //ExtTextOut(hDC, aData[8], (aData[9]+aData[11])/2, aRect, cFont, 6)
        ExtTextOut(hDC, aData[8], aData[9]+3, aRect, cFont,2)
        oFont:End()
    endif
    if hb_bitAnd(aData[5],1)>0
        DrawFocusRect(hDC,aData[8],aData[9],aData[10],aData[11])
        SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT))
        SetBkColor(hDC, GetSysColor(COLOR_WINDOW))
    endif
    //MsgInfo("Called")
return 1
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Owner draw ComboBox

Post by nageswaragunupudi »

Thanks for the suggestion.

There already exists bDrawItem. Now a new data bOwnerDraw is provided for this purpose in the new version.

This sample is an adaptation of the proposed code posted above.

Code: Select all

#include "fivewin.ch"

#define WHITE_BRUSH           0
#define COLOR_HIGHLIGHT      13
#define COLOR_HIGHLIGHTTEXT  14
#define COLOR_WINDOW          5
#define COLOR_WINDOWTEXT      6

//----------------------------------------------------------------------------//

function Main()

   local oWnd, oCbx, aItems, cItem, oFont

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-24
   DEFINE WINDOW oWnd
   oWnd:SetFont( oFont )

   aItems   := GetFontNames( oWnd:GetDC() )
   oWnd:ReleaseDC()
   cItem    := aItems[ 1 ]

   @ 40,40 COMBOBOX oCbx VAR cItem ITEMS aItems SIZE 300,400 PIXEL OF oWnd ;
      OWNERDRAW OwnerDrawItem( Self, nIdCtl, oItemStruct )

   ACTIVATE WINDOW oWnd CENTERED
   RELEASE FONT oFont

return nil

//----------------------------------------------------------------------------//

function OwnerDrawItem( Self, nIdCtl, oItem )

   local cFont, oFont
   local hDC      := oItem:hDC

    if oItem:itemID >= 0
        cFont := oItem:itemData
    endif

    FillRect( hDC, oItem:aRect, GetStockObject( WHITE_BRUSH ) )

    if lAnd( oItem:itemState, 1 )
        SetTextColor( hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) )
        SetBkColor(   hDC, GetSysColor( COLOR_HIGHLIGHT ) )
    else
        SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) )
        SetBkColor(   hDC, GetSysColor( COLOR_WINDOW ) )
    endif

    if !Empty( cFont )
        DEFINE Font oFont NAME cFont SIZE nil, oItem:nHeight
        oFont:Activate( hDC )
        ExtTextOut( hDC, oItem:nTop, oItem:nLeft + 3, oItem:aRect, cFont, 2 )
        oFont:End()
    endif

    if lAnd( oItem:itemState, 1 )
        DrawFocusRect( hDC, oItem:nTop, oItem:nLeft, oItem:nBottom, oItem:nRight )
        SetTextColor(  hDC, GetSysColor( COLOR_WINDOWTEXT ) )
        SetBkColor(    hDC, GetSysColor( COLOR_WINDOW ) )
    endif

return 1

//----------------------------------------------------------------------------//
 
Image
Regards

G. N. Rao.
Hyderabad, India
AntoninoP
Posts: 347
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy
Contact:

Re: Owner draw ComboBox

Post by AntoninoP »

I like it very much!
Post Reply