Y aqui la teneis. La incluiremos en el pr贸ximo build de FWH y nuestra intenci贸n es ir mejor谩ndola.
gantt.prg
#include "FiveWin.ch"
#define GWL_STYLE 聽 聽 聽 -16
static nOldCol, nOldRow
//----------------------------------------------------------------------------//
CLASS TGantt FROM TControl
聽 聽DATA 聽 aItems INIT {}
聽 聽DATA 聽 oItem, oLbx
聽 聽DATA 聽 lCaptured AS LOGICAL INIT .F.
聽 聽DATA 聽 hPen
聽 聽DATA 聽 lLResize, lRResize AS LOGICAL INIT .F.
聽 聽DATA 聽 bChange, bPressed
聽 聽DATA 聽 lGridMonth INIT .F. 聽
聽 聽CLASSDATA lRegistered AS LOGICAL
聽 聽METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lBorder,;
聽 聽 聽 聽 聽 聽 聽 聽lVScroll, lHScroll, nClrFore, nClrBack, bchange, dpresed, oLbx ) CONSTRUCTOR
聽 聽METHOD Redefine( nId, oWnd, nClrFore, nClrBack ) CONSTRUCTOR
聽 聽METHOD AddItem( nTop, nLeft, nBottom, nRight )
聽 聽METHOD AtItem( nRow, nCol )
聽 聽METHOD EraseBkGnd( hDC ) INLINE 1
聽 聽METHOD GridMonth()
聽 聽METHOD Display() INLINE ::BeginPaint(), ::Paint(), ::EndPaint(), 0
聽 聽METHOD Paint()
聽 聽METHOD LButtonDown( nRow, nCol, nKeyFlags )
聽 聽METHOD LButtonUp( nRow, nCol, nKeyFlags ) 聽
聽 聽METHOD MouseMove( nRow, nCol, nKeyFlags )
聽 聽
聽 聽METHOD End()
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( nTop, nLeft, nWidth, nHeight, oWnd, lBorder,;
聽 聽 聽 聽 聽 聽 lVScroll, lHScroll, nClrFore, nClrBack, bChange, bPressed, oLbx ) CLASS TGantt
聽 聽DEFAULT lBorder := .T., nClrFore := 0, nClrBack := CLR_WHITE,;
聽 聽 聽 聽 聽 聽lVScroll := .F., lHScroll := .F.,;
聽 聽 聽 聽 聽 聽oWnd := GetWndDefault()
聽 聽::cCaption 聽 = ""
聽 聽::oWnd 聽 聽 聽= oWnd
聽 聽::bChange 聽 = bChange
聽 聽::bPressed 聽= bPressed
聽 聽::oLbx 聽 聽 聽= oLbx
聽 聽::nStyle 聽 聽= nOr( WS_CHILD,;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 If( lBorder, WS_BORDER, 0 ),;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 If( lVScroll, WS_VSCROLL, 0 ),;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 If( lHScroll, WS_HSCROLL, 0 ),;
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 WS_VISIBLE, WS_TABSTOP )
聽 聽::Register() 聽 聽 聽
聽 聽::SetColor( nClrFore, nClrBack )
聽 聽::hPen = CreatePen( PS_SOLID, 1, nRGB( 128, 128, 128 ) )
聽 聽if oWnd:lVisible
聽 聽 聽 ::Create()
聽 聽 聽 ::Default()
聽 聽 聽 ::lVisible = .t.
聽 聽 聽 oWnd:AddControl( Self )
聽 聽else
聽 聽 聽 oWnd:DefControl( Self )
聽 聽 聽 ::lVisible 聽= .F.
聽 聽endif
聽 聽/*
聽 聽if lVScroll
聽 聽 聽 DEFINE SCROLLBAR ::oVScroll VERTICAL OF Self
聽 聽endif
聽 聽if lHScroll
聽 聽 聽 DEFINE SCROLLBAR ::oHScroll HORIZONTAL OF Self
聽 聽endif
聽 聽*/
聽 聽
return Self
//----------------------------------------------------------------------------//
METHOD Redefine( nId, oWnd, nClrFore, nClrBack, bChange, bPressed, oLbx ) CLASS TGantt
聽 聽DEFAULT oWnd := GetWndDefault()
聽 聽::nId 聽 聽 聽 = nId
聽 聽::cCaption 聽= ""
聽 聽::lCaptured = .F.
聽 聽::oWnd 聽 聽 聽= oWnd
聽 聽::bChange 聽 = bChange
聽 聽::bPressed 聽 = bPressed
聽 聽::oLbx 聽 聽 聽= oLbx
聽 聽::Register()
聽 聽::SetColor( nClrFore, nClrBack )
聽 聽
聽 聽if lAnd( GetWindowLong( ::hWnd, GWL_STYLE ), WS_VSCROLL )
聽 聽 聽 DEFINE SCROLLBAR ::oVScroll VERTICAL OF Self
聽 聽endif
聽 聽if lAnd( GetWindowLong( ::hWnd, GWL_STYLE ), WS_HSCROLL )
聽 聽 聽 DEFINE SCROLLBAR ::oHScroll HORIZONTAL OF Self
聽 聽endif
聽 聽oWnd:DefControl( Self )
return Self
//----------------------------------------------------------------------------//
METHOD AddItem( nTop, nLeft, nBottom, nRight, nClrBack ) CLASS TGantt
聽 聽local oItem := TGanttItem():New( Self, nTop, nLeft, nBottom, nRight, nClrBack )
聽 聽
聽 聽AAdd( ::aItems, oItem )
聽 聽
return oItem 聽
聽 聽
//----------------------------------------------------------------------------//
METHOD AtItem( nRow, nCol ) CLASS TGantt
聽 聽local nItem := AScan( ::aItems, { | oItem | oItem:IsOver( nRow, nCol ) } )
return If( nItem != 0, ::aItems[ nItem ], nil )
//----------------------------------------------------------------------------//
METHOD GridMonth() CLASS TGantt
聽 聽local n, nWidth := ::nWidth() / 31
聽 聽
聽 聽MoveTo( ::hDC, 0, 18 )
聽 聽LineTo( ::hDC, ::nWidth, 18 )
聽 聽
聽 聽for n = 1 to 30
聽 聽 聽 MoveTo( ::hDC, nWidth * n, 0 )
聽 聽 聽 LineTo( ::hDC, nWidth * n, ::nHeight )
聽 聽next 聽
聽 聽
聽 聽for n = 1 to 31
聽 聽 聽 ::Say( 3, 7 + ( ( n - 1 ) * nWidth ),;
聽 聽 聽 聽 聽 聽 聽If( n < 10, " ", "" ) + AllTrim( Str( n ) ),,, If( ::oFont != nil, ::oFont,), .T. )
聽 聽next 聽 聽
return nil
//----------------------------------------------------------------------------//
METHOD Paint() CLASS TGantt
聽 聽local aInfo := ::DispBegin()
聽 聽
聽 聽FillRect( ::hDC, GetClientRect( ::hWnd ), ::oBrush:hBrush )
聽 聽
聽 聽if ::lGridMonth
聽 聽 聽 ::GridMonth()
聽 聽endif 聽
聽 聽
聽 聽AEval( ::aItems, { | oItem | oItem:Paint() } )
聽 聽if ::bPainted != nil
聽 聽 聽 Eval( ::bPainted, ::hDC )
聽 聽endif
聽 聽::DispEnd( aInfo )
return 0
//----------------------------------------------------------------------------//
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TGantt
聽 聽local oItem
聽 聽if ::lCaptured
聽 聽 聽 if ::oItem:IsOver( nRow, nCol, 5 )
聽 聽 聽 聽 聽::oItem:DrawBorder() // to remove the previous painted lines
聽 聽 聽 聽 聽if ::lRResize
聽 聽 聽 聽 聽 聽 ::oItem:nRight = nCol - ( nOldCol - ::oItem:nRight )
聽 聽 聽 聽 聽elseif ::lLResize
聽 聽 聽 聽 聽 聽 ::oItem:nLeft = nCol - ( nOldCol - ::oItem:nLeft )
聽 聽 聽 聽 聽else
聽 聽 聽 聽 聽 聽 ::oItem:nLeft = nCol - ( nOldCol - ::oItem:nLeft )
聽 聽 聽 聽 聽 聽 ::oItem:nRight = nCol - ( nOldCol - ::oItem:nRight )
聽 聽 聽 聽 聽endif
聽 聽 聽 聽 聽::oItem:DrawBorder()
聽 聽 聽 聽 聽nOldCol = nCol
聽 聽 聽 聽 聽return nil
聽 聽 聽 endif 聽
聽 聽else
聽 聽 聽 if ( oItem := ::AtItem( nRow, nCol ) ) != nil
聽 聽 聽 聽 聽if nCol < oItem:nLeft + 5 .or. nCol > oItem:nRight - 5
聽 聽 聽 聽 聽 聽 CursorWE()
聽 聽 聽 聽 聽 聽 return nil
聽 聽 聽 聽 聽endif
聽 聽 聽 endif 聽 聽 聽
聽 聽endif 聽 聽 聽
return Super:MouseMove( nRow, nCol, nKeyFlags )
//----------------------------------------------------------------------------//
METHOD LButtonDown( nRow, nCol, nKeyFlags ) CLASS TGantt
聽 聽local oItem
聽 聽if ::oLbx != nil
聽 聽 聽 ::oLbx:LButtonDown( nRow + 32, 40, nKeyFlags )
聽 聽endif
聽 聽if ( oItem := ::AtItem( nRow, nCol ) ) != nil
聽 聽 聽 nOldCol = nCol
聽 聽 聽 nOldRow = nRow
聽 聽 聽 ::lCaptured = .T.
聽 聽 聽 ::oItem = oItem
聽 聽 聽 ::oItem:DrawBorder()
聽 聽 聽 ::lLResize = nCol < oItem:nLeft + 5
聽 聽 聽 ::lRResize = nCol > oItem:nRight - 5
聽 聽 聽 if ::lLResize .or. ::lRResize
聽 聽 聽 聽 聽CursorWE()
聽 聽 聽 else 聽
聽 聽 聽 聽 聽CursorHand() 聽
聽 聽 聽 endif 聽 聽
聽 聽endif
聽 聽 聽 聽
return Super:LButtonDown( nRow, nCol, nKeyFlags )
//----------------------------------------------------------------------------//
METHOD LButtonUp( nRow, nCol, nKeyFlags ) CLASS TGantt
聽 聽if ::lCaptured
聽 聽 聽 ::oItem:DrawBorder() // to remove the last painted lines
聽 聽 聽 ::Refresh()
聽 聽 聽 if ::bChange != nil
聽 聽 聽 聽 聽Eval( ::bChange, Self )
聽 聽 聽 endif
聽 聽 聽 ::lCaptured = .F.
聽 聽endif
return Super:LButtonUp( nRow, nCol, nKeyFlags )
//----------------------------------------------------------------------------//
METHOD End() CLASS TGantt
聽 聽DeleteObject( ::hPen )
return Super:End()
//----------------------------------------------------------------------------//
CLASS TGanttItem
聽 聽DATA 聽 nTop, nLeft, nBottom, nRight
聽 聽DATA 聽 nClrBack
聽 聽DATA 聽 oGantt
聽 聽
聽 聽METHOD New( oGantt, nTop, nLeft, nBottom, nRight, nClrBack )
聽 聽METHOD DrawBorder()
聽 聽
聽 聽METHOD IsOver( nRow, nCol, nMargin )
聽 聽
聽 聽METHOD Paint()
聽 聽
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New( oGantt, nTop, nLeft, nBottom, nRight, nClrBack ) CLASS TGanttItem
聽 聽::oGantt 聽 = oGantt
聽 聽::nTop 聽 聽 = nTop
聽 聽::nLeft 聽 聽= nLeft
聽 聽::nBottom 聽= nBottom
聽 聽::nRight 聽 = nRight
聽 聽::nClrBack = nClrBack
聽 聽
return Self
//----------------------------------------------------------------------------//
METHOD IsOver( nRow, nCol, nMargin ) CLASS TGanttItem
聽 聽DEFAULT nMargin := 0
return nRow >= ::nTop .and. nCol >= ::nLeft - nMargin .and. ;
聽 聽 聽 聽nRow <= ::nBottom .and. nCol <= ::nRight + nMargin
//----------------------------------------------------------------------------//
METHOD DrawBorder() CLASS TGanttItem
聽 聽local hDC 聽 聽 := ::oGantt:GetDC()
聽 聽local nOldRop := SetROP2( hDC, 7 )
聽 聽local nOldPen := SelectObject( hDC, ::oGantt:hPen )
聽 聽
聽 聽MoveTo( hDC, ::nLeft, 聽::nTop )
聽 聽LineTo( hDC, ::nRight - 1, ::nTop )
聽 聽LineTo( hDC, ::nRight - 1, ::nBottom - 1 )
聽 聽LineTo( hDC, ::nLeft, 聽::nBottom - 1 )
聽 聽LineTo( hDC, ::nLeft, 聽::nTop )
聽 聽SetROP2( hDC, nOldRop )
聽 聽SelectObject( hDC, nOldPen )
聽 聽::oGantt:ReleaseDC()
聽 聽
return nil
//----------------------------------------------------------------------------//
METHOD Paint() CLASS TGanttItem
聽 聽local hPen := CreatePen( 0, 1, ::nClrBack )
聽 聽
聽 聽FillRect( ::oGantt:GetDC(), { ::nTop, ::nLeft, ::nBottom, ::nRight }, hPen )
聽 聽
聽 聽DeleteObject( hPen ) 聽
聽 聽::oGantt:ReleaseDC()
聽 聽
return nil
//-----------------------------------------------------//TestGant.prg
#include "FiveWin.ch"
#include "Gantt.ch"
function Main()
聽 聽local oFont, oWnd, oGantt
聽 聽DEFINE FONT oFont NAME "Verdana" SIZE 0, -10
聽 聽DEFINE WINDOW oWnd TITLE "Class TGantt test"
聽 聽
聽 聽@ 1, 1 GANTT oGantt SIZE 300, 300 OF oWnd
聽 聽
聽 聽oGantt:SetFont( oFont )
聽 聽oGantt:lGridMonth = .T.
聽 聽
聽 聽oGantt:AddItem( 30, 10, 聽50, 聽80, CLR_BLUE )
聽 聽oGantt:AddItem( 60, 30, 聽80, 110, CLR_RED )
聽 聽oGantt:AddItem( 90, 50, 110, 聽90, CLR_GREEN )
聽 聽oGantt:AddItem( 120, 10, 140, 聽80, CLR_CYAN ) 聽
聽 聽oGantt:AddItem( 150, 50, 170, 120, CLR_YELLOW )
聽 聽
聽 聽oWnd:oClient = oGantt
聽 聽oWnd:Center()
聽 聽ACTIVATE WINDOW oWnd
return nil