#include "FiveWin.ch"
#include "Constant.ch"
#define GWL_STYLE -16
#ifndef __CLIPPER__
#define COMBO_BASE 320
#else
#define COMBO_BASE WM_USER
#endif
#define CB_ADDSTRING ( COMBO_BASE + 3 )
#define CB_DELETESTRING ( COMBO_BASE + 4 )
#define CB_GETCURSEL ( COMBO_BASE + 7 )
#define CB_INSERTSTRING ( COMBO_BASE + 10 )
#define CB_RESETCONTENT ( COMBO_BASE + 11 )
#define CB_FINDSTRING ( COMBO_BASE + 12 )
#define CB_SETCURSEL ( COMBO_BASE + 14 )
#define CB_SHOWDROPDOWN ( COMBO_BASE + 15 )
#define CB_GETDROPPEDSTATE ( COMBO_BASE + 23 )
#define CB_ERR -1
#define CB_SETMINVISIBLE 5889 // 0x1701
#define CB_GETMINVISIBLE 5890 // 0x1702
#define COLOR_WINDOW 5
#define COLOR_WINDOWTEXT 8
#define GW_CHILD 5
#define GW_HWNDNEXT 2
//----------------------------------------------------------------------------//
CLASS TComboBox FROM TControl
DATA aItems, aBitmaps
DATA lOwnerDraw, nBmpHeight, nBmpWidth
DATA nAt
DATA bDrawItem, bCloseUp
DATA cError AS String
DATA oGet
DATA cSearchKey // Holds current search key for incremental search.
DATA lIncSearch AS LOGICAL // incremental search
DATA lCaseSensitive INIT .F.
CLASSDATA aProperties ;
INIT { "aItems", "cTitle", "cVarName", "l3D", "nClrText",;
"nClrPane", "nAlign", "nTop", "nLeft",;
"nWidth", "nHeight", "oFont", "Cargo" }
METHOD New( nRow, nCol, bSetGet, aItems, nWidth, nHeight, oWnd, nHelpId,;
bChange, bValid, nClrText, nClrBack, lPixel, oFont,;
cMsg, lUpdate, bWhen, lDesign, acBitmaps, bDrawItem, nStyle,;
cPict, bEChange ) CONSTRUCTOR
METHOD ReDefine( nId, bSetGet, aItems, oWnd, nHelpId, bValid, ;
bChange, nClrText, nClrBack, cMsg, lUpdate,;
bWhen, acBitmaps, bDrawItem, nStyle, cPict, bEChange ) CONSTRUCTOR
METHOD Add( cItem, nAt )
METHOD GenLocals()
METHOD cGenPrg()
METHOD cToChar() INLINE ::Super:cToChar( "COMBOBOX" )
METHOD Change()
METHOD Close() INLINE ::SendMsg( CB_SHOWDROPDOWN, 0 )
METHOD CloseUp() INLINE If( ::bCloseUp != nil, Eval( ::bCloseUp, Self ),)
METHOD CtlColor( hWndChild, hDCChild )
METHOD Default()
METHOD DefControl( oControl )
METHOD Del( nAt )
METHOD Destroy()
METHOD DrawItem( nIdCtl, nPStruct )
METHOD FillMeasure( nPInfo ) INLINE LbxMeasure( nPInfo, ::nBmpHeight )
METHOD FindString( cItem, nFrom ) INLINE ;
nFrom := If( nFrom == nil, 0, nFrom ),;
::SendMsg( CB_FINDSTRING, nFrom, cItem ) + 1
METHOD Find( cItem, nFrom ) INLINE ::FindString( cItem, nFrom ) != 0
METHOD GetKeyChar( nKey )
METHOD GetMinVisible() INLINE If( IsAppThemed(), ;
::SendMsg( CB_GETMINVISIBLE, 0, 0 ), 0 )
METHOD HandleEvent( nMsg, nWParam, nLParam )
METHOD Initiate( hDlg )
METHOD Insert( cItem, nAt )
METHOD KeyChar( nKey, nFlags )
METHOD KeyDown( nKey, nFlags )
METHOD LostFocus( hWndGetFocus )
METHOD lValid()
METHOD Modify( cItem, nAt )
METHOD MouseMove( nRow, nCol, nKeyFlags )
METHOD Open() INLINE ::SendMsg( CB_SHOWDROPDOWN, 1 )
METHOD Refresh() INLINE ::Set( Eval( ::bSetGet ) ), ::Super:Refresh()
METHOD Reset( lChanged ) INLINE Eval( ::bSetGet,;
If( ValType( Eval( ::bSetGet ) ) == "N", 0, "" ) ),;
::nAt := 0, ::SendMsg( CB_RESETCONTENT ),;
if( ( lChanged != NIL .and. lChanged ) .or. ( lChanged == NIL ), ::Change(), )
METHOD Select( nItem ) INLINE ::nAt := nItem,;
::SendMsg( CB_SETCURSEL, nItem - 1, 0 )
METHOD Set( cNewItem )
METHOD SetBitmaps( acBitmaps )
METHOD SetItems( aItems, lChanged ) INLINE ::Reset( lChanged ), ::aItems := aItems,;
::Default(),;
if( ( lChanged != NIL .and. lChanged ) .or. ( lChanged == NIL ), ::Change(), )
// By default, 30 is the minimum number of visible items in XP Visual Themes
METHOD SetMinVisible( nItems ) INLINE ;
If( IsAppThemed(), ( ::SendMsg( CB_SETMINVISIBLE, nItems, 0 ) == 1 ), .f. )
METHOD ShowToolTip()
METHOD VarGet()
METHOD State() INLINE ::SendMsg( CB_GETDROPPEDSTATE, 0 )
METHOD IsClosed() INLINE ::State() == 0
METHOD IsOpen() INLINE ::State() == 1
METHOD GotFocus()
METHOD End() INLINE ::Hide(), If( ::oGet != nil, ::oGet:End(),), ::Super:End()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( nRow, nCol, bSetGet, aItems, nWidth, nHeight, oWnd, nHelpId,;
bChange, bValid, nClrFore, nClrBack, lPixel, oFont,;
cMsg, lUpdate, bWhen, lDesign, acBitmaps, bDrawItem, nStyle,;
cPict, bEChange, cVarName ) CLASS TComboBox
if nClrFore == nil
nClrBack := GetSysColor( COLOR_WINDOW )
endif
DEFAULT nRow := 0, nCol := 0, bSetGet := { || nil },;
oWnd := GetWndDefault(),;
oFont := oWnd:oFont,;
aItems := {}, nWidth := 40, nHeight := 60,;
nClrFore := GetSysColor( COLOR_WINDOWTEXT ),;
lPixel := .f., lUpdate := .f., lDesign := .f.,;
nStyle := CBS_DROPDOWNLIST
::cCaption = ""
::nTop = nRow * If( lPixel, 1, CMB_CHARPIX_H )
::nLeft = nCol * If( lPixel, 1, CMB_CHARPIX_W )
::nBottom = ::nTop + nHeight - 1
::nRight = ::nLeft + nWidth - 1
::nAt = 0
::aItems = aItems
::bChange = bChange
::bSetGet = bSetGet
::oWnd = oWnd
::oFont = oFont
::cSearchKey := ""
if acBitmaps != nil
::SetBitmaps( acBitmaps )
else
::lOwnerDraw = .f.
endif
::nStyle = nOR( If( nStyle == CBS_DROPDOWN, 0, LBS_NOTIFY ), WS_TABSTOP,;
nStyle,;
LBS_DISABLENOSCROLL, WS_CHILD, WS_VISIBLE, WS_BORDER,;
WS_VSCROLL, If( lDesign, WS_CLIPSIBLINGS, 0 ),;
If( ::lOwnerDraw, CBS_OWNERDRAWFIXED, 0 ) )
::nId = ::GetNewId()
::nHelpId = nHelpId
::bValid = bValid
::lDrag = lDesign
::lCaptured = .f.
::cMsg = cMsg
::lUpdate = lUpdate
::bWhen = bWhen
::bDrawItem = bDrawItem
::SetColor( nClrFore, nClrBack )
if Empty( ::oFont )
DEFINE FONT ::oFont NAME GetSysFont() SIZE 0, -12
endif
::oGet := TGet():ReDefine( nil, ; // ID not used
::bSetGet, ; // bSETGET(uVar)
Self, ; // oDlg
::nHelpID, ; // Help Context ID
cPict, ; // Picture
nil, ; // Valid is handled by the CBx
::nClrText,;
::nClrPane,;
::oFont, ; // <oFont>
nil, ; // <oCursor>
cMsg, ; // cMsg
nil, ; // <.update.>
nil, ; // <{uWhen}>
bEChange, ; // {|nKey,nFlags,Self| <uEChange>}
.F. ) // <.readonly.> )
if ! Empty( oWnd:hWnd )
::Create( "COMBOBOX" )
::Default()
if oFont != nil
::SetFont( oFont )
endif
oWnd:AddControl( Self )
else
oWnd:DefControl( Self )
endif
DEFAULT cVarName := "oCbx" + ::GetCtrlIndex()
::cVarName = cVarName
if ::oGet != nil
::oGet:hWnd = GetWindow( ::hWnd, GW_CHILD )
::oGet:Link()
::oGet:bLostFocus = ;
{ | hCtlFocus, nAt, cItem| cItem := GetWindowText( ::hWnd ), ;
nAt := ::SendMsg( CB_FINDSTRING, 0, Trim( cItem )) + 1,;
Eval( ::bSetGet, cItem ),;
::Select( nAt ),;
SetWindowText( ::hWnd, cItem ),;
If( ::bValid != nil .and. ;
GetParent( hCtlFocus ) == GetParent( ::hWnd ),;
If( ! Eval( ::bValid, ::oGet, Self ),;
::PostMsg( WM_SETFOCUS ),),) }
::oGet:bKeyChar = { | nKey | ::GetKeyChar( nKey ) }
endif
if lDesign
::CheckDots()
endif
return Self
//----------------------------------------------------------------------------//
METHOD ReDefine( nId, bSetGet, aItems, oWnd, nHelpId, bValid, ;
bChange, nClrFore, nClrBack, cMsg, lUpdate, ;
bWhen, acBitmaps, bDrawItem, nStyle, cPict, ;
bEChange ) CLASS TComboBox
DEFAULT oWnd := GetWndDefault()
if nClrFore == nil
nClrBack := GetSysColor( COLOR_WINDOW )
endif
DEFAULT aItems := {},;
nClrFore := GetSysColor( COLOR_WINDOWTEXT ),;
lUpdate := .f., ;
nStyle := CBS_DROPDOWNLIST
::nId = nId
::hWnd = 0
::aItems = aItems
::bChange = bChange
::bSetGet = bSetGet
::oWnd = oWnd
::nHelpId = nHelpId
::bValid = bValid
::nAt = 0
::lDrag = .f.
::lCaptured = .f.
::cMsg = cMsg
::lUpdate = lUpdate
::bWhen = bWhen
::bDrawItem = bDrawItem
::nStyle = nStyle
::cSearchKey = ""
if acBitmaps != nil
::SetBitmaps( acBitmaps )
else
::lOwnerDraw = .F.
endif
::SetColor( nClrFore, nClrBack )
::oGet := TGet():ReDefine( nil, ; // ID not used
::bSetGet, ; // bSETGET(uVar)
Self, ; // oDlg
::nHelpID, ; // Help Context ID
cPict, ; // Picture
nil, ; // Valid is handled by the CBx
::nClrText,;
::nClrPane,;
::oFont, ; // <oFont>
nil, ; // <oCursor>
cMsg, ; // cMsg
nil, ; // <.update.>
nil, ; // <{uWhen}>
bEChange, ; // {|nKey,nFlags,Self| <uEChange>}
.F. ) // <.readonly.> )
::oGet:bKeyChar = { | nKey | ::GetKeyChar( nKey ) }
oWnd:DefControl( Self )
return Self
//----------------------------------------------------------------------------//
METHOD Add( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt == 0
AAdd( ::aItems, cItem )
else
ASize( ::aItems, Len( ::aItems ) + 1 )
AIns( ::aItems, nAt )
::aItems[ nAt ] = cItem
endif
::SendMsg( CB_ADDSTRING, nAt, cItem )
return nil
//----------------------------------------------------------------------------//
METHOD GenLocals() CLASS TComboBox
local cCode := ", " + ::cVarName
cCode += ", " + "c" + SubStr( ::cVarName, 2 )
cCode += " := " + If( ! Empty( ::GetText() ),;
'PadR( "' + ::GetText() + '", 20 )',;
'""' )
return cCode
//----------------------------------------------------------------------------//
METHOD cGenPrg() CLASS TComboBox
local cCode := ""
local n
cCode += CRLF + " @ " + Str( ::nTop, 3 ) + ", " + Str( ::nLeft, 3 ) + ;
" COMBOBOX " + ::cVarName + " VAR " + "c" + ;
SubStr( ::cVarName, 2 ) + " ITEMS {" + ;
If( Len( ::aItems ) > 0, " ", "" )
for n = 1 to Len( ::aItems )
if n > 1
cCode += ", "
endif
cCode += '"' + ::aItems[ n ] + '"'
next
cCode += If( Len( ::aItems ) > 0, " ", "" ) + "} ;" + CRLF + ;
" SIZE " + Str( ::nRight - ::nLeft + 1, 3 ) + ", " + ;
Str( ::nBottom - ::nTop + 1, 3 ) + " PIXEL OF " + ;
::oWnd:cVarName + CRLF
return cCode
//----------------------------------------------------------------------------//
METHOD Change() CLASS TComboBox
local cItem := ::GetText() // Current Value
local nAt
nAt = ::SendMsg( CB_GETCURSEL ) + 1
if nAt == ::nAt .and. ! Empty( Eval( ::bSetGet ) )
return nil
endif
::nAt := nAt
if ::nAt != 0 .and. ::nAt <= Len( ::aItems )
if ValType( Eval( ::bSetGet ) ) == "N"
Eval( ::bSetGet, ::nAt )
else
Eval( ::bSetGet, ::aItems[ ::nAt ] )
endif
endif
if ::oGet != nil // Always not nil for dropdown
::oGet:VarPut( Eval( ::bSetGet ) ) // udate variable before calling bChange
::oGet:Refresh()
endif
if ::bChange != nil
Eval( ::bChange, Self, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD DefControl( oControl ) CLASS TComboBox
if ::aControls == nil
::aControls = {}
endif
AAdd( ::AControls, oControl )
return nil
//----------------------------------------------------------------------------//
METHOD Set( cNewItem ) CLASS TComboBox
local nAt
if ValType( cNewItem ) == "N"
nAt = cNewItem
if nAt == 0
nAt = 1
endif
else
nAt = AScan( ::aItems,;
{ | cItem | Upper( AllTrim( cItem ) ) == ;
Upper( AllTrim( cNewItem ) ) } )
endif
if ValType( cNewItem ) == "N" .or. nAt != 0 .and. ::oGet == nil
::Select( nAt )
else
cNewItem = cValToChar( cNewItem )
endif
Eval( ::bSetGet, cNewItem )
SetWindowText( ::hWnd , cNewItem )
return nil
//----------------------------------------------------------------------------//
METHOD LostFocus( hWndGetFocus ) CLASS TComboBox
local nAt := ::SendMsg( CB_GETCURSEL )
::Super:LostFocus( hWndGetFocus )
if nAt != CB_ERR
::nAt = nAt + 1
if ValType( Eval( ::bSetGet ) ) == "N"
Eval( ::bSetGet, nAt + 1 )
else
Eval( ::bSetGet, If( ::oGet == nil, ::aItems[ nAt + 1 ], ::oGet:GetText() ) )
endif
else
Eval( ::bSetGet, GetWindowText( ::hWnd ) )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Modify( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
::aItems[ nAt ] = cItem
::SendMsg( CB_DELETESTRING, nAt - 1 )
::SendMsg( CB_INSERTSTRING, nAt - 1, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Insert( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
ASize( ::aItems, Len( ::aItems ) + 1 )
AIns( ::aItems, nAt )
::aItems[ nAt ] = cItem
::SendMsg( CB_INSERTSTRING, nAt - 1, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD GotFocus() CLASS TComboBox
::cSearchKey := ""
return ::Super:GotFocus()
//----------------------------------------------------------------------------//
METHOD KeyChar( nKey, nFlags ) CLASS TComboBox
local nNewAT := 0, nOldAT := ::nAT, uItem
if Len( ::aItems ) == 0
return 0
endif
if ::lIncSearch
do case
case nKey = 32 // VK_DELETE (DO NOT WORK!)
if ::oGet == nil
::cSearchKey = ""
nNewAt = 1
uItem = ::aItems[ nNewAt ]
else
::cSearchKey += " "
endif
case nKey = VK_BACK
::cSearchKey = Left( ::cSearchKey, Len( ::cSearchKey ) - 1 )
case nKey = 190
nKey = 0
::cSearchKey += "."
case ::oGet != nil .and. nKey = VK_TAB
if ! GetKeyState( VK_SHIFT )
::oWnd:GoNextCtrl( ::hWnd )
else
::oWnd:GoPrevCtrl( ::hWnd )
endif
return 0
otherwise
if ::lCaseSensitive
::cSearchKey += Chr( nKey )
else
::cSearchKey += Upper( Chr( nKey ) )
endif
endcase
if Empty( uItem )
if nNewAt == 0
if ::lCaseSensitive
nNewAt = AScan( ::aItems, { | x | SubStr( x, 1, Len( ::cSearchKey ) ) == ::cSearchKey } )
else
nNewAt = AScan( ::aItems, { | x | SubStr( Upper( x ), 1, Len( ::cSearchKey ) ) == ::cSearchKey } )
endif
if ::oGet == nil
uItem = ::aItems[ If( nNewAt > 0, nNewAt, Max( ::nAT, 1 ) ) ]
else
uItem = If( nNewAt > 0, ::aItems[ nNewAt ], ::cSearchKey )
endif
else
uItem = ::aItems[ Max( nNewAt, 1) ]
endif
endif
::Set( If( ValType( Eval( ::bSetGet ) ) == "N", AScan( ::aItems, uItem ), uItem ) )
if ::oGet != nil
::oGet:SetPos( Len( ::cSearchKey ) + 1 )
endif
endif
if ::bChange != nil
if ::oGet != nil .or. ( nNewAT != nOldAt .and. nNewAt != 0 )
Eval( ::bChange, Self, ::VarGet() )
endif
endif
if nKey == VK_RETURN
return ::oWnd:GoNextCtrl( ::hWnd )
endif
return If( ::lIncSearch, 0, nil )
//----------------------------------------------------------------------------//
METHOD KeyDown( nKey, nFlags ) CLASS TComboBox
if nKey == VK_ESCAPE .and. ::IsOpen()
::Close()
return 1
endif
return ::Super:KeyDown( nKey, nFlags )
//----------------------------------------------------------------------------//
METHOD Del( nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
ADel( ::aItems, nAt )
ASize( ::aItems, Len( ::aItems ) - 1 )
::SendMsg( CB_DELETESTRING, nAt - 1 )
endif
return nil
//----------------------------------------------------------------------------//
METHOD GetKeyChar( nKey ) CLASS TComboBox
local nAt, cText
if ( nKey == VK_TAB .and. ! GetKeyState( VK_SHIFT ) ) .or. nKey == VK_RETURN
::oWnd:GoNextCtrl( ::hWnd )
return 0
else
if nKey == VK_TAB .and. GetKeyState( VK_SHIFT )
::oWnd:GoPrevCtrl( ::hWnd )
return 0
endif
endif
if ( nKey >= Asc( "A" ) .and. nKey <= Asc( "Z" ) ) .or. ;
( nKey >= Asc( "a" ) .and. nKey <= Asc( "z" ) )
cText = AllTrim( ::oGet:GetText() ) + Chr( nKey )
if ( nAt := AScan( ::aItems, { | c | Upper( Left( c, Len( cText ) ) ) == ;
Upper( cText ) } ) ) != 0
::oGet:SetText( ::aItems[ nAt ] )
::oGet:oGet:buffer = PadR( ::aItems[ nAt ], Len( ::oGet:oGet:buffer ) )
::oGet:SetPos( ::oGet:oGet:pos + 1 )
return 0
endif
endif
return nKey
//----------------------------------------------------------------------------//
METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TComboBox
if nMsg == FM_CLOSEUP
return ::CloseUp()
endif
return ::Super:HandleEvent( nMsg, nWParam, nLParam )
//----------------------------------------------------------------------------//
METHOD Initiate( hDlg ) CLASS TComboBox
::Super:Initiate( hDlg )
::Default()
if ::oGet != nil
::oGet:hWnd = GetWindow( ::hWnd, GW_CHILD )
::oGet:Link()
::oGet:bLostFocus = ;
{| hCtlFocus, nAt, cItem| cItem := GetWindowText( ::hWnd ), ;
nAt := ::SendMsg( CB_FINDSTRING, 0, Trim( cItem )) + 1,;
Eval( ::bSetGet, cItem ),;
::Select( nAt ),;
SetWindowText( ::hWnd, cItem ),;
If( ::bValid != nil .and. ;
GetParent( hCtlFocus ) == GetParent( ::hWnd ),;
If( ! Eval( ::bValid, ::oGet, Self ),;
::PostMsg( WM_SETFOCUS ),),) }
::oGet:SetFont( ::oFont )
endif
::Refresh()
return nil
//----------------------------------------------------------------------------//
METHOD CtlColor( hWndChild, hDCChild ) CLASS TComboBox
if lAnd( GetWindowLong( ::hWnd, GWL_STYLE ), CBS_DROPDOWN )
SetTextColor( hDCChild, ::nClrText )
SetBkColor( hDCChild, ::nClrPane )
DEFAULT ::oBrush := TBrush():New( , ::nClrPane )
return ::oBrush:hBrush
endif
return nil
//----------------------------------------------------------------------------//
METHOD Default() CLASS TComboBox
local cStart := Eval( ::bSetGet )
if ! Empty( ::hWnd ) .and. ::nStyle == CBS_DROPDOWNLIST
::nStyle := GetWindowLong( ::hWnd, GWL_STYLE )
endif
if cStart == nil
Eval( ::bSetGet, If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" ) )
cStart = If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" )
endif
AEval( ::aItems, { | cItem, nAt | ::SendMsg( CB_ADDSTRING, nAt, cItem ) } ) // " " required by 64 bits
if ValType( cStart ) != "N"
::nAt = AScan( ::aItems, { | cItem | Upper( AllTrim( cItem ) ) == ;
Upper( AllTrim( cStart ) ) } )
else
::nAt = cStart
endif
::nAt = If( ::nAt > 0, ::nAt, 1 )
if cStart == nil
::Select( ::nAt )
else
::Set( cStart )
endif
return nil
//----------------------------------------------------------------------------//
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TComboBox
local nResult := ::Super:MouseMove( nRow, nCol, nKeyFlags )
return If( ::lDrag, nResult, nil ) // We want standard behavior !!!
//----------------------------------------------------------------------------//
METHOD SetBitmaps( acBitmaps ) CLASS TComboBox
local n
::lOwnerDraw = .t.
if acBitmaps != nil
::aBitmaps = Array( Len( acBitmaps ) )
for n = 1 to Len( acBitmaps )
if File( acBitmaps[ n ] )
::aBitmaps[ n ] = ReadBitmap( 0, acBitmaps[ n ] )
else
::aBitmaps[ n ] = LoadBitmap( GetResources(), acBitmaps[ n ] )
endif
next
::nBmpHeight = nBmpHeight( ::aBitmaps[ 1 ] )
::nBmpWidth = nBmpWidth( ::aBitmaps[ 1 ] )
SetOwnerDrawItemHeight( ::nBmpHeight )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Destroy() CLASS TComboBox
local n
if ::aBitmaps != nil
for n = 1 to Len( ::aBitmaps )
DeleteObject( ::aBitmaps[ n ] )
next
endif
if ::oGet != nil
::oGet:Destroy()
endif
return ::Super:Destroy()
//----------------------------------------------------------------------------//
METHOD DrawItem( nIdCtl, nPStruct ) CLASS TComboBox
if ::oPopup != nil
return ::Super:DrawItem( nIdCtl, nPStruct )
endif
return LbxDrawItem( nPStruct, ::aBitmaps, ::aItems, ::nBmpWidth, ::bDrawItem )
//----------------------------------------------------------------------------//
METHOD VarGet() CLASS TComboBox
local cRet, nAt := ::SendMsg( CB_GETCURSEL )
if nAt != CB_ERR
::nAt = nAt + 1
cRet := If( ::oGet == nil, ::aItems[ nAt + 1 ], ::oGet:GetText() )
else
cRet := GetWindowText( ::hWnd )
endif
return cRet
//----------------------------------------------------------------------------//
METHOD lValid() CLASS TComboBox
local lRet := .t.
if ValType( ::bValid ) == "B"
lRet = Eval( ::bValid, ::oGet, Self )
endif
return lRet
//----------------------------------------------------------------------------//
METHOD ShowToolTip() CLASS TComboBox
local nOldBottom
nOldBottom = ::nBottom
::nBottom = ::nTop + GetTextHeight( ::hWnd ) + 8
::Super:ShowToolTip()
::nBottom = nOldBottom
return nil
//----------------------------------------------------------------------------//
if ::oGet != nil
function Main()
local oDlg, oCbx, oSayItem, oSayAt
local cItem := "Lucas"
SET _3DLOOK ON
DEFINE DIALOg oDlg RESOURCE "TestCombo"
REDEFINE COMBOBOX oCbx VAR cItem ITEMS { "Testing", "this", "ComboBox", "Lucas" } ;
ID 110 OF oDlg ;
ON CHANGE ( oSayItem:cTitle := cItem,; // We should use also :SetText()
oSayAt:cTitle := ":nAt = " + Str( oCbx:nAt, 2 ) ) ;
VALID ( MsgBeep(), .t. )
REDEFINE SAY oSayItem ID 120 OF oDlg
REDEFINE BUTTON ID 130 OF oDlg ACTION oCbx:Reset()
REDEFINE BUTTON ID 140 OF oDlg ;
ACTION oCbx:SetItems( { "Let's", "Set", "a new", "List" } )
REDEFINE BUTTON ID 220 OF oDlg ACTION MsgInfo( Str( oCbx:nAt ) )
REDEFINE SAY oSayAt ID 150 OF oDlg
ACTIVATE DIALOG oDlg CENTERED
msgalert(cItem, "ITEM SELECTED")
return nil
#include "FiveWin.ch"
#include "Constant.ch"
#define GWL_STYLE -16
#ifndef __CLIPPER__
#define COMBO_BASE 320
#else
#define COMBO_BASE WM_USER
#endif
#define CB_ADDSTRING ( COMBO_BASE + 3 )
#define CB_DELETESTRING ( COMBO_BASE + 4 )
#define CB_GETCURSEL ( COMBO_BASE + 7 )
#define CB_INSERTSTRING ( COMBO_BASE + 10 )
#define CB_RESETCONTENT ( COMBO_BASE + 11 )
#define CB_FINDSTRING ( COMBO_BASE + 12 )
#define CB_SETCURSEL ( COMBO_BASE + 14 )
#define CB_SHOWDROPDOWN ( COMBO_BASE + 15 )
#define CB_GETDROPPEDSTATE ( COMBO_BASE + 23 )
#define CB_ERR -1
#define CB_SETMINVISIBLE 5889 // 0x1701
#define CB_GETMINVISIBLE 5890 // 0x1702
#define COLOR_WINDOW 5
#define COLOR_WINDOWTEXT 8
#define GW_CHILD 5
#define GW_HWNDNEXT 2
//----------------------------------------------------------------------------//
CLASS TComboBox FROM TControl
DATA aItems, aBitmaps
DATA lOwnerDraw, nBmpHeight, nBmpWidth
DATA nAt
DATA bDrawItem, bCloseUp
DATA cError AS String
DATA oGet
DATA cSearchKey // Holds current search key for incremental search.
DATA lIncSearch AS LOGICAL // incremental search
DATA lCaseSensitive INIT .F.
CLASSDATA aProperties ;
INIT { "aItems", "cTitle", "cVarName", "l3D", "nClrText",;
"nClrPane", "nAlign", "nTop", "nLeft",;
"nWidth", "nHeight", "oFont", "Cargo" }
METHOD New( nRow, nCol, bSetGet, aItems, nWidth, nHeight, oWnd, nHelpId,;
bChange, bValid, nClrText, nClrBack, lPixel, oFont,;
cMsg, lUpdate, bWhen, lDesign, acBitmaps, bDrawItem, nStyle,;
cPict, bEChange ) CONSTRUCTOR
METHOD ReDefine( nId, bSetGet, aItems, oWnd, nHelpId, bValid, ;
bChange, nClrText, nClrBack, cMsg, lUpdate,;
bWhen, acBitmaps, bDrawItem, nStyle, cPict, bEChange ) CONSTRUCTOR
METHOD Add( cItem, nAt )
METHOD GenLocals()
METHOD cGenPrg()
METHOD cToChar() INLINE ::Super:cToChar( "COMBOBOX" )
METHOD Change()
METHOD Close() INLINE ::SendMsg( CB_SHOWDROPDOWN, 0 )
METHOD CloseUp() INLINE If( ::bCloseUp != nil, Eval( ::bCloseUp, Self ),)
METHOD CtlColor( hWndChild, hDCChild )
METHOD Default()
METHOD DefControl( oControl )
METHOD Del( nAt )
METHOD Destroy()
METHOD DrawItem( nIdCtl, nPStruct )
METHOD FillMeasure( nPInfo ) INLINE LbxMeasure( nPInfo, ::nBmpHeight )
METHOD FindString( cItem, nFrom ) INLINE ;
nFrom := If( nFrom == nil, 0, nFrom ),;
::SendMsg( CB_FINDSTRING, nFrom, cItem ) + 1
METHOD Find( cItem, nFrom ) INLINE ::FindString( cItem, nFrom ) != 0
METHOD GetKeyChar( nKey )
METHOD GetMinVisible() INLINE If( IsAppThemed(), ;
::SendMsg( CB_GETMINVISIBLE, 0, 0 ), 0 )
METHOD HandleEvent( nMsg, nWParam, nLParam )
METHOD Initiate( hDlg )
METHOD Insert( cItem, nAt )
METHOD KeyChar( nKey, nFlags )
METHOD KeyDown( nKey, nFlags )
METHOD LostFocus( hWndGetFocus )
METHOD lValid()
METHOD Modify( cItem, nAt )
METHOD MouseMove( nRow, nCol, nKeyFlags )
METHOD Open() INLINE ::SendMsg( CB_SHOWDROPDOWN, 1 )
METHOD Refresh() INLINE ::Set( Eval( ::bSetGet ) ), ::Super:Refresh()
METHOD Reset( lChanged ) INLINE Eval( ::bSetGet,;
If( ValType( Eval( ::bSetGet ) ) == "N", 0, "" ) ),;
::nAt := 0, ::SendMsg( CB_RESETCONTENT ),;
if( ( lChanged != NIL .and. lChanged ) .or. ( lChanged == NIL ), ::Change(), )
METHOD Select( nItem ) INLINE ::nAt := nItem,;
::SendMsg( CB_SETCURSEL, nItem - 1, 0 )
METHOD Set( cNewItem )
METHOD SetBitmaps( acBitmaps )
METHOD SetItems( aItems, lChanged ) INLINE ::Reset( lChanged ), ::aItems := aItems,;
::Default(),;
if( ( lChanged != NIL .and. lChanged ) .or. ( lChanged == NIL ), ::Change(), )
// By default, 30 is the minimum number of visible items in XP Visual Themes
METHOD SetMinVisible( nItems ) INLINE ;
If( IsAppThemed(), ( ::SendMsg( CB_SETMINVISIBLE, nItems, 0 ) == 1 ), .f. )
METHOD ShowToolTip()
METHOD VarGet()
METHOD State() INLINE ::SendMsg( CB_GETDROPPEDSTATE, 0 )
METHOD IsClosed() INLINE ::State() == 0
METHOD IsOpen() INLINE ::State() == 1
METHOD GotFocus()
METHOD End() INLINE ::Hide(), If( ::oGet != nil, ::oGet:End(),), ::Super:End()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( nRow, nCol, bSetGet, aItems, nWidth, nHeight, oWnd, nHelpId,;
bChange, bValid, nClrFore, nClrBack, lPixel, oFont,;
cMsg, lUpdate, bWhen, lDesign, acBitmaps, bDrawItem, nStyle,;
cPict, bEChange, cVarName ) CLASS TComboBox
if nClrFore == nil
nClrBack := GetSysColor( COLOR_WINDOW )
endif
DEFAULT nRow := 0, nCol := 0, bSetGet := { || nil },;
oWnd := GetWndDefault(),;
oFont := oWnd:oFont,;
aItems := {}, nWidth := 40, nHeight := 60,;
nClrFore := GetSysColor( COLOR_WINDOWTEXT ),;
lPixel := .f., lUpdate := .f., lDesign := .f.,;
nStyle := CBS_DROPDOWNLIST
::cCaption = ""
::nTop = nRow * If( lPixel, 1, CMB_CHARPIX_H )
::nLeft = nCol * If( lPixel, 1, CMB_CHARPIX_W )
::nBottom = ::nTop + nHeight - 1
::nRight = ::nLeft + nWidth - 1
::nAt = 0
::aItems = aItems
::bChange = bChange
::bSetGet = bSetGet
::oWnd = oWnd
::oFont = oFont
::cSearchKey := ""
if acBitmaps != nil
::SetBitmaps( acBitmaps )
else
::lOwnerDraw = .f.
endif
::nStyle = nOR( If( nStyle == CBS_DROPDOWN, 0, LBS_NOTIFY ), WS_TABSTOP,;
nStyle,;
LBS_DISABLENOSCROLL, WS_CHILD, WS_VISIBLE, WS_BORDER,;
WS_VSCROLL, If( lDesign, WS_CLIPSIBLINGS, 0 ),;
If( ::lOwnerDraw, CBS_OWNERDRAWFIXED, 0 ) )
::nId = ::GetNewId()
::nHelpId = nHelpId
::bValid = bValid
::lDrag = lDesign
::lCaptured = .f.
::cMsg = cMsg
::lUpdate = lUpdate
::bWhen = bWhen
::bDrawItem = bDrawItem
::SetColor( nClrFore, nClrBack )
if Empty( ::oFont )
DEFINE FONT ::oFont NAME GetSysFont() SIZE 0, -12
endif
::oGet := TGet():ReDefine( nil, ; // ID not used
::bSetGet, ; // bSETGET(uVar)
Self, ; // oDlg
::nHelpID, ; // Help Context ID
cPict, ; // Picture
nil, ; // Valid is handled by the CBx
::nClrText,;
::nClrPane,;
::oFont, ; // <oFont>
nil, ; // <oCursor>
cMsg, ; // cMsg
nil, ; // <.update.>
nil, ; // <{uWhen}>
bEChange, ; // {|nKey,nFlags,Self| <uEChange>}
.F. ) // <.readonly.> )
if ! Empty( oWnd:hWnd )
::Create( "COMBOBOX" )
::Default()
if oFont != nil
::SetFont( oFont )
endif
oWnd:AddControl( Self )
else
oWnd:DefControl( Self )
endif
DEFAULT cVarName := "oCbx" + ::GetCtrlIndex()
::cVarName = cVarName
if ::oGet != nil
::oGet:hWnd = GetWindow( ::hWnd, GW_CHILD )
::oGet:Link()
::oGet:bLostFocus = ;
{ | hCtlFocus, nAt, cItem| cItem := GetWindowText( ::hWnd ), ;
nAt := ::SendMsg( CB_FINDSTRING, 0, Trim( cItem )) + 1,;
Eval( ::bSetGet, cItem ),;
::Select( nAt ),;
SetWindowText( ::hWnd, cItem ),;
If( ::bValid != nil .and. ;
GetParent( hCtlFocus ) == GetParent( ::hWnd ),;
If( ! Eval( ::bValid, ::oGet, Self ),;
::PostMsg( WM_SETFOCUS ),),) }
::oGet:bKeyChar = { | nKey | ::GetKeyChar( nKey ) }
endif
if lDesign
::CheckDots()
endif
return Self
//----------------------------------------------------------------------------//
METHOD ReDefine( nId, bSetGet, aItems, oWnd, nHelpId, bValid, ;
bChange, nClrFore, nClrBack, cMsg, lUpdate, ;
bWhen, acBitmaps, bDrawItem, nStyle, cPict, ;
bEChange ) CLASS TComboBox
DEFAULT oWnd := GetWndDefault()
if nClrFore == nil
nClrBack := GetSysColor( COLOR_WINDOW )
endif
DEFAULT aItems := {},;
nClrFore := GetSysColor( COLOR_WINDOWTEXT ),;
lUpdate := .f., ;
nStyle := CBS_DROPDOWNLIST
::nId = nId
::hWnd = 0
::aItems = aItems
::bChange = bChange
::bSetGet = bSetGet
::oWnd = oWnd
::nHelpId = nHelpId
::bValid = bValid
::nAt = 0
::lDrag = .f.
::lCaptured = .f.
::cMsg = cMsg
::lUpdate = lUpdate
::bWhen = bWhen
::bDrawItem = bDrawItem
::nStyle = nStyle
::cSearchKey = ""
if acBitmaps != nil
::SetBitmaps( acBitmaps )
else
::lOwnerDraw = .F.
endif
::SetColor( nClrFore, nClrBack )
::oGet := TGet():ReDefine( nil, ; // ID not used
::bSetGet, ; // bSETGET(uVar)
Self, ; // oDlg
::nHelpID, ; // Help Context ID
cPict, ; // Picture
nil, ; // Valid is handled by the CBx
::nClrText,;
::nClrPane,;
::oFont, ; // <oFont>
nil, ; // <oCursor>
cMsg, ; // cMsg
nil, ; // <.update.>
nil, ; // <{uWhen}>
bEChange, ; // {|nKey,nFlags,Self| <uEChange>}
.F. ) // <.readonly.> )
::oGet:bKeyChar = { | nKey | ::GetKeyChar( nKey ) }
oWnd:DefControl( Self )
return Self
//----------------------------------------------------------------------------//
METHOD Add( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt == 0
AAdd( ::aItems, cItem )
else
ASize( ::aItems, Len( ::aItems ) + 1 )
AIns( ::aItems, nAt )
::aItems[ nAt ] = cItem
endif
::SendMsg( CB_ADDSTRING, nAt, cItem )
return nil
//----------------------------------------------------------------------------//
METHOD GenLocals() CLASS TComboBox
local cCode := ", " + ::cVarName
cCode += ", " + "c" + SubStr( ::cVarName, 2 )
cCode += " := " + If( ! Empty( ::GetText() ),;
'PadR( "' + ::GetText() + '", 20 )',;
'""' )
return cCode
//----------------------------------------------------------------------------//
METHOD cGenPrg() CLASS TComboBox
local cCode := ""
local n
cCode += CRLF + " @ " + Str( ::nTop, 3 ) + ", " + Str( ::nLeft, 3 ) + ;
" COMBOBOX " + ::cVarName + " VAR " + "c" + ;
SubStr( ::cVarName, 2 ) + " ITEMS {" + ;
If( Len( ::aItems ) > 0, " ", "" )
for n = 1 to Len( ::aItems )
if n > 1
cCode += ", "
endif
cCode += '"' + ::aItems[ n ] + '"'
next
cCode += If( Len( ::aItems ) > 0, " ", "" ) + "} ;" + CRLF + ;
" SIZE " + Str( ::nRight - ::nLeft + 1, 3 ) + ", " + ;
Str( ::nBottom - ::nTop + 1, 3 ) + " PIXEL OF " + ;
::oWnd:cVarName + CRLF
return cCode
//----------------------------------------------------------------------------//
METHOD Change() CLASS TComboBox
local cItem := ::GetText() // Current Value
local nAt
nAt = ::SendMsg( CB_GETCURSEL ) + 1
if nAt == ::nAt .and. ! Empty( Eval( ::bSetGet ) )
return nil
endif
::nAt := nAt
if ::nAt != 0 .and. ::nAt <= Len( ::aItems )
if ValType( Eval( ::bSetGet ) ) == "N"
Eval( ::bSetGet, ::nAt )
else
Eval( ::bSetGet, ::aItems[ ::nAt ] )
endif
endif
if ::oGet != nil // Always not nil for dropdown
::oGet:VarPut( Eval( ::bSetGet ) ) // udate variable before calling bChange
::oGet:Refresh()
endif
if ::bChange != nil
Eval( ::bChange, Self, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD DefControl( oControl ) CLASS TComboBox
if ::aControls == nil
::aControls = {}
endif
AAdd( ::AControls, oControl )
return nil
//----------------------------------------------------------------------------//
METHOD Set( cNewItem ) CLASS TComboBox
local nAt
if ValType( cNewItem ) == "N"
nAt = cNewItem
if nAt == 0
nAt = 1
endif
else
nAt = AScan( ::aItems,;
{ | cItem | Upper( AllTrim( cItem ) ) == ;
Upper( AllTrim( cNewItem ) ) } )
endif
if ValType( cNewItem ) == "N" .or. nAt != 0
::Select( nAt )
else
cNewItem = cValToChar( cNewItem )
SetWindowText( ::hWnd , cNewItem )
endif
Eval( ::bSetGet, cNewItem )
return nil
//----------------------------------------------------------------------------//
METHOD LostFocus( hWndGetFocus ) CLASS TComboBox
local nAt := ::SendMsg( CB_GETCURSEL )
::Super:LostFocus( hWndGetFocus )
if nAt != CB_ERR
::nAt = nAt + 1
if ValType( Eval( ::bSetGet ) ) == "N"
Eval( ::bSetGet, nAt + 1 )
else
Eval( ::bSetGet, GetWindowText( ::hWnd ) )
endif
else
Eval( ::bSetGet, GetWindowText( ::hWnd ) )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Modify( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
::aItems[ nAt ] = cItem
::SendMsg( CB_DELETESTRING, nAt - 1 )
::SendMsg( CB_INSERTSTRING, nAt - 1, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Insert( cItem, nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
ASize( ::aItems, Len( ::aItems ) + 1 )
AIns( ::aItems, nAt )
::aItems[ nAt ] = cItem
::SendMsg( CB_INSERTSTRING, nAt - 1, cItem )
endif
return nil
//----------------------------------------------------------------------------//
METHOD GotFocus() CLASS TComboBox
::cSearchKey := ""
return ::Super:GotFocus()
//----------------------------------------------------------------------------//
METHOD KeyChar( nKey, nFlags ) CLASS TComboBox
local nNewAT := 0, nOldAT := ::nAT, uItem
if Len( ::aItems ) == 0
return 0
endif
if ::lIncSearch
do case
case nKey = 32 // VK_DELETE (DO NOT WORK!)
if ::oGet == nil
::cSearchKey = ""
nNewAt = 1
uItem = ::aItems[ nNewAt ]
else
::cSearchKey += " "
endif
case nKey = VK_BACK
::cSearchKey = Left( ::cSearchKey, Len( ::cSearchKey ) - 1 )
case nKey = 190
nKey = 0
::cSearchKey += "."
case ::oGet != nil .and. nKey = VK_TAB
if ! GetKeyState( VK_SHIFT )
::oWnd:GoNextCtrl( ::hWnd )
else
::oWnd:GoPrevCtrl( ::hWnd )
endif
return 0
otherwise
if ::lCaseSensitive
::cSearchKey += Chr( nKey )
else
::cSearchKey += Upper( Chr( nKey ) )
endif
endcase
if Empty( uItem )
if nNewAt == 0
if ::lCaseSensitive
nNewAt = AScan( ::aItems, { | x | SubStr( x, 1, Len( ::cSearchKey ) ) == ::cSearchKey } )
else
nNewAt = AScan( ::aItems, { | x | SubStr( Upper( x ), 1, Len( ::cSearchKey ) ) == ::cSearchKey } )
endif
if ::oGet == nil
uItem = ::aItems[ If( nNewAt > 0, nNewAt, Max( ::nAT, 1 ) ) ]
else
uItem = If( nNewAt > 0, ::aItems[ nNewAt ], ::cSearchKey )
endif
else
uItem = ::aItems[ Max( nNewAt, 1) ]
endif
endif
::Set( If( ValType( Eval( ::bSetGet ) ) == "N", AScan( ::aItems, uItem ), uItem ) )
if ::oGet != nil
::oGet:SetPos( Len( ::cSearchKey ) + 1 )
endif
endif
if ::bChange != nil
if ::oGet != nil .or. ( nNewAT != nOldAt .and. nNewAt != 0 )
Eval( ::bChange, Self, ::VarGet() )
endif
endif
if nKey == VK_RETURN
return ::oWnd:GoNextCtrl( ::hWnd )
endif
return If( ::lIncSearch, 0, nil )
//----------------------------------------------------------------------------//
METHOD KeyDown( nKey, nFlags ) CLASS TComboBox
if nKey == VK_ESCAPE .and. ::IsOpen()
::Close()
return 1
endif
return ::Super:KeyDown( nKey, nFlags )
//----------------------------------------------------------------------------//
METHOD Del( nAt ) CLASS TComboBox
DEFAULT nAt := 0
if nAt != 0
ADel( ::aItems, nAt )
ASize( ::aItems, Len( ::aItems ) - 1 )
::SendMsg( CB_DELETESTRING, nAt - 1 )
endif
return nil
//----------------------------------------------------------------------------//
METHOD GetKeyChar( nKey ) CLASS TComboBox
local nAt, cText
if ( nKey == VK_TAB .and. ! GetKeyState( VK_SHIFT ) ) .or. nKey == VK_RETURN
::oWnd:GoNextCtrl( ::hWnd )
return 0
else
if nKey == VK_TAB .and. GetKeyState( VK_SHIFT )
::oWnd:GoPrevCtrl( ::hWnd )
return 0
endif
endif
if ( nKey >= Asc( "A" ) .and. nKey <= Asc( "Z" ) ) .or. ;
( nKey >= Asc( "a" ) .and. nKey <= Asc( "z" ) )
cText = AllTrim( ::oGet:GetText() ) + Chr( nKey )
if ( nAt := AScan( ::aItems, { | c | Upper( Left( c, Len( cText ) ) ) == ;
Upper( cText ) } ) ) != 0
::oGet:SetText( ::aItems[ nAt ] )
::oGet:oGet:buffer = PadR( ::aItems[ nAt ], Len( ::oGet:oGet:buffer ) )
::oGet:SetPos( ::oGet:oGet:pos + 1 )
return 0
endif
endif
return nKey
//----------------------------------------------------------------------------//
METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TComboBox
if nMsg == FM_CLOSEUP
return ::CloseUp()
endif
return ::Super:HandleEvent( nMsg, nWParam, nLParam )
//----------------------------------------------------------------------------//
METHOD Initiate( hDlg ) CLASS TComboBox
::Super:Initiate( hDlg )
::Default()
if ::oGet != nil
::oGet:hWnd = GetWindow( ::hWnd, GW_CHILD )
::oGet:Link()
::oGet:bLostFocus = ;
{| hCtlFocus, nAt, cItem| cItem := GetWindowText( ::hWnd ), ;
nAt := ::SendMsg( CB_FINDSTRING, 0, Trim( cItem )) + 1,;
Eval( ::bSetGet, cItem ),;
::Select( nAt ),;
SetWindowText( ::hWnd, cItem ),;
If( ::bValid != nil .and. ;
GetParent( hCtlFocus ) == GetParent( ::hWnd ),;
If( ! Eval( ::bValid, ::oGet, Self ),;
::PostMsg( WM_SETFOCUS ),),) }
::oGet:SetFont( ::oFont )
endif
::Refresh()
return nil
//----------------------------------------------------------------------------//
METHOD CtlColor( hWndChild, hDCChild ) CLASS TComboBox
if lAnd( GetWindowLong( ::hWnd, GWL_STYLE ), CBS_DROPDOWN )
SetTextColor( hDCChild, ::nClrText )
SetBkColor( hDCChild, ::nClrPane )
DEFAULT ::oBrush := TBrush():New( , ::nClrPane )
return ::oBrush:hBrush
endif
return nil
//----------------------------------------------------------------------------//
METHOD Default() CLASS TComboBox
local cStart := Eval( ::bSetGet )
if ! Empty( ::hWnd ) .and. ::nStyle == CBS_DROPDOWNLIST
::nStyle := GetWindowLong( ::hWnd, GWL_STYLE )
endif
if cStart == nil
Eval( ::bSetGet, If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" ) )
cStart = If( Len( ::aItems ) > 0, ::aItems[ 1 ], "" )
endif
AEval( ::aItems, { | cItem, nAt | ::SendMsg( CB_ADDSTRING, nAt, cItem ) } ) // " " required by 64 bits
if ValType( cStart ) != "N"
::nAt = AScan( ::aItems, { | cItem | Upper( AllTrim( cItem ) ) == ;
Upper( AllTrim( cStart ) ) } )
else
::nAt = cStart
endif
::nAt = If( ::nAt > 0, ::nAt, 1 )
if cStart == nil
::Select( ::nAt )
else
::Set( cStart )
endif
return nil
//----------------------------------------------------------------------------//
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TComboBox
local nResult := ::Super:MouseMove( nRow, nCol, nKeyFlags )
return If( ::lDrag, nResult, nil ) // We want standard behavior !!!
//----------------------------------------------------------------------------//
METHOD SetBitmaps( acBitmaps ) CLASS TComboBox
local n
::lOwnerDraw = .t.
if acBitmaps != nil
::aBitmaps = Array( Len( acBitmaps ) )
for n = 1 to Len( acBitmaps )
if File( acBitmaps[ n ] )
::aBitmaps[ n ] = ReadBitmap( 0, acBitmaps[ n ] )
else
::aBitmaps[ n ] = LoadBitmap( GetResources(), acBitmaps[ n ] )
endif
next
::nBmpHeight = nBmpHeight( ::aBitmaps[ 1 ] )
::nBmpWidth = nBmpWidth( ::aBitmaps[ 1 ] )
SetOwnerDrawItemHeight( ::nBmpHeight )
endif
return nil
//----------------------------------------------------------------------------//
METHOD Destroy() CLASS TComboBox
local n
if ::aBitmaps != nil
for n = 1 to Len( ::aBitmaps )
DeleteObject( ::aBitmaps[ n ] )
next
endif
if ::oGet != nil
::oGet:Destroy()
endif
return ::Super:Destroy()
//----------------------------------------------------------------------------//
METHOD DrawItem( nIdCtl, nPStruct ) CLASS TComboBox
if ::oPopup != nil
return ::Super:DrawItem( nIdCtl, nPStruct )
endif
return LbxDrawItem( nPStruct, ::aBitmaps, ::aItems, ::nBmpWidth, ::bDrawItem )
//----------------------------------------------------------------------------//
METHOD VarGet() CLASS TComboBox
local cRet, nAt := ::SendMsg( CB_GETCURSEL )
if nAt != CB_ERR
::nAt = nAt + 1
cRet := If( ::oGet == nil, ::aItems[ nAt + 1 ], ::oGet:GetText() )
else
cRet := GetWindowText( ::hWnd )
endif
return cRet
//----------------------------------------------------------------------------//
METHOD lValid() CLASS TComboBox
local lRet := .t.
if ValType( ::bValid ) == "B"
lRet = Eval( ::bValid, ::oGet, Self )
endif
return lRet
//----------------------------------------------------------------------------//
METHOD ShowToolTip() CLASS TComboBox
local nOldBottom
nOldBottom = ::nBottom
::nBottom = ::nTop + GetTextHeight( ::hWnd ) + 8
::Super:ShowToolTip()
::nBottom = nOldBottom
return nil
//----------------------------------------------------------------------------//
Return to FiveWin for Harbour/xHarbour
Users browsing this forum: No registered users and 51 guests