As the dots distance is variable we should have to create the bitmap for the brush dinamically...
As the dots distance is variable we should have to create the bitmap for the brush dinamically...
// Object inspector using TXBrowse
#include "FiveWin.ch"
#include "xBrowse.ch"
static oWnd, oBrw, oForm, oInspected, nAt, cName, nColor, cFont, cMethod, aNames,;
aValues, aColors, aMethods
function Main()
local oCol, oBrush
nAt := 1
cName := space(50)
nColor := 1
cFont := "Ms Sans Serif"
cMethod := space(50)
aColors := {"Red", "Blue", "Green"}
aMethods := {"OnLeftClick", "OnLostFocus", "OnInit"}
oForm = TForm():New()
oForm:cTitle = "Form1"
oForm:nTop = 175
oForm:nLeft = 291
// oForm:bPainted = { | hDC, cPS | DrawGrid( oForm:hWnd, hDC, cPS, 8, 8 ) }
oForm:bRClicked = { | nRow, nCol | ShowPopup( nRow, nCol ) }
oForm:bLClicked = { || InspectForm() }
aNames = oForm:aProperties
oInspected = oForm
oForm:cVarName = "oForm1"
oForm:Cargo = { 1, 2, 3 } // test for array inspector
oForm:SetBrush( oBrush := TBrush():New( ,,,, DotsBmp( 8, 8 ) ) )
oBrush:End()
oForm:Show()
DEFINE WINDOW oWnd TITLE "Object Inspector" ;
FROM 151, 16 TO 550, 237 PIXEL
oBrw := TXBrowse():New( oWnd )
oCol := oBrw:AddCol()
oCol:cHeader := "Properties"
oCol:bStrData := { || aNames[ nAt ] }
oCol:nWidth := 80
oCol:bClrSel := oBrw:bClrSel
oCol:bClrSelFocus := oBrw:bClrSelFocus
oCol:bLDClickData := { || oBrw:aCols[ 2 ]:Edit() }
oCol := oBrw:AddCol()
oCol:cHeader := "Value"
oCol:bStrData := {|| ValToStr( __objSendMsg( oInspected, aNames[ nAt ] ) ) }
oCol:bEditValue := {|| __objSendMsg( oInspected, aNames[ nAt ] ) }
oCol:bOnPostEdit := {|o,x,k| PostEdit(o,x,k) }
oCol:nWidth := 110
oCol:nEditType := 1
oCol:lEditBorder := .t.
oCol:bClrSel := oBrw:bClrStd
oCol:bClrSelFocus := oBrw:bClrStd
oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
oBrw:nColDividerStyle := 0
oBrw:lHScroll := .f.
oBrw:lAllowColSwapping := .f.
oBrw:lRecordSelector := .f.
oBrw:lAllowRowSizing := .f.
oBrw:bClrSel := oBrw:bClrStd
oBrw:bClrSelFocus := oBrw:bClrStd
oBrw:bKeyDown := {|nKey| If( nKey >= 32 .and. nKey <= 255 .or. ;
nKey == 13, oBrw:aCols[ 2 ]:Edit( If( nKey != 13,;
nKey, 0 ) ),) }
oBrw:bChange := { || SelectInspector( oBrw ) }
oBrw:nFreeze := 2
oBrw:bGoTop := {|| nAt := 1 }
oBrw:bGoBottom := {|| nAt := len( aNames ) }
oBrw:bSkip := { | nSkip, nOld | ;
iif(nSkip == nil, nSkip := 1, ),;
nOld := nAt,;
nAt += nSkip,;
nAt := Min( Max( nAt, 1 ), len( aNames ) ),;
nAt - nOld }
oBrw:bBof := {|| nAt == 1 }
oBrw:bEof := {|| nAt == len( aNames ) }
oBrw:bBookMark := {| n | iif( n == nil, nAt, nAt := n ) }
oBrw:bKeyNo := oBrw:bBookMark
oBrw:bKeyCount := {|| len( aNames ) }
oBrw:CreateFromCode()
oWnd:oClient = oBrw
ACTIVATE WINDOW oWnd ;
ON INIT oBrw:SetFocus()
return nil
STATIC FUNCTION SelectInspector( oBrw )
local uVal := __objSendMsg( oInspected, aNames[ nAt ] )
local cType := ValType( uVal )
do case
case aNames[ nAt ] $ "nClrText,nClrPane"
oBrw:aCols[ 2 ]:bEditBlock = { || uVal := ChooseColor( uVal ), oInspected:Refresh(), uVal }
oBrw:aCols[ 2 ]:nEditType = 3 // dots
case aNames[ nAt ] == "nBorderStyle"
oBrw:aCols[ 2 ]:aEditListTxt := { "bsStandard", "bsNone", "bsDialog" }
oBrw:aCols[ 2 ]:aEditListBound := { "bsStandard", "bsNone", "bsDialog" }
oBrw:aCols[ 2 ]:nEditType = 2 // combo non editable
case aNames[ nAt ] == "oMenu"
oBrw:aCols[ 2 ]:bEditBlock = { || MsgInfo( "Menu inspector not implemented yet" ) }
oBrw:aCols[ 2 ]:nEditType = 3 // dots
case aNames[ nAt ] == "oIcon"
oBrw:aCols[ 2 ]:bEditBlock = { || MsgInfo( "Icon inspector not implemented yet" ) }
oBrw:aCols[ 2 ]:nEditType = 3 // dots
case cType == "C"
oBrw:aCols[ 2 ]:nEditType = 1 // Get standard
case cType == "N"
oBrw:aCols[ 2 ]:nEditType = 1 // Get standard
case cType == "O"
do case
case uVal:ClassName() == "TFONT"
oBrw:aCols[ 2 ]:bEditBlock = { || oInspected:SelFont(), oInspected:oFont }
oBrw:aCols[ 2 ]:nEditType = 3 // dots
endcase
case cType == "A"
oBrw:aCols[ 2 ]:bEditBlock = { || MsgInfo( "Array inspector not implemented yet" ), uVal }
oBrw:aCols[ 2 ]:nEditType = 3 // dots
/*
case nAt == 2 // color
oBrw:aCols[ 2 ]:aEditListTxt := aColors
oBrw:aCols[ 2 ]:aEditListBound := {1, 2, 3}
case nAt == 4 // method
oBrw:aCols[ 2 ]:aEditListTxt := aMethods
oBrw:aCols[ 2 ]:aEditListBound := aMethods
Endcase */
endcase
return nil
STATIC FUNCTION PostEdit( oCol, xValue, nKey )
if nKey != VK_ESCAPE
__ObjSendMsg( oInspected, "_" + aNames[ nAt ], xValue )
endif
return nil
static function ValToStr( uVal )
local nType := ValType( uVal )
do case
case nType == "C"
return uVal
case nType == "N"
return Str( uVal )
case nType == "L"
return If( uVal, "True", "False" )
case nType == "D"
return DToC( uVal )
case nType == "O"
return uVal:ClassName()
case nType == "A"
return "{...}"
otherwise
return "nil"
endcase
return nil
function ShowPopup( nRow, nCol )
local oPopup
MENU oPopup POPUP
MENUITEM "Add Control"
MENU
MENUITEM "Standard"
MENU
MENUITEM "EditBox" ACTION AddControl( "TGet" )
MENUITEM "PushButton" ACTION AddControl( "TButton" )
ENDMENU
MENUITEM "Advanced"
ENDMENU
SEPARATOR
MENUITEM "Save as"
ENDMENU
ACTIVATE POPUP oPopup AT nRow, nCol OF oForm
return nil
function AddControl( cCtrlName )
local oCtrl, cVar := Space( 50 )
do case
case cCtrlName == "TGet"
@ 20, 20 GET oCtrl VAR cVar OF oForm ;
SIZE 140, 30 PIXEL DESIGN
case cCtrlName == "TButton"
@ 20, 20 BUTTON oCtrl PROMPT "Button1" OF oForm ;
SIZE 80, 30 PIXEL DESIGN
endcase
aNames = oCtrl:aProperties
oInspected = oCtrl
oBrw:Refresh()
oCtrl:SetFocus()
oCtrl:bLClicked = { || InspectCtrl( oCtrl ) }
return nil
function InspectForm()
if ! oInspected == oForm
oInspected:HideDots()
oInspected = oForm
aNames = oInspected:aProperties
oBrw:Refresh()
oForm:SetFocus()
endif
return nil
function InspectCtrl( oCtrl )
if ! oInspected == oCtrl
oInspected = oCtrl
aNames = oInspected:aProperties
oBrw:Refresh()
oCtrl:SetFocus()
endif
return nil
static function DotsBmp( nWidth, nHeight )
local hDC1 := GetDC( GetDesktopWindow() )
local hDC2 := CreateCompatibleDC( hDC1 )
local hBmp := CreateCompatibleBitmap( hDC1, nWidth, nHeight )
local hOldBmp := SelectObject( hDC2, hBmp )
local oBrush := TBrush():New( , CLR_WHITE )
FillRect( hDC2, { 0, 0, 8, 8 }, oBrush:hBrush )
oBrush:End()
SetPixel( hDC2, 0, 0 )
SetPixel( hDC2, nWidth, nHeight )
SelectObject( hDC2, hOldBmp )
DeleteDC( hDC2 )
ReleaseDC( hDC1 )
return hBmpAntonio Linares wrote:Here it is
Antonio,
I think it's not possible to use a bitmap when the grid dots have to be aligned to dialog units and not pixels, am I wrong?
EMG
Enrico,
You can convert from units to pixels and viceversa, so I don't see any limitation
Antonio Linares wrote:Enrico,
You can convert from units to pixels and viceversa, so I don't see any limitation