Page 6 of 7
Posted:
Thu Jul 31, 2008 6:52 am
by James Bott
Otto,
James you are right with you advice to repaint only the changes. But that is much more work.
And as the whole repainting in my initial project works so well I don’t think it is necessary.
Can you just use the same paint code from your original project in the Paint() method of the new class?
James
Posted:
Thu Jul 31, 2008 7:04 am
by Otto
Hello James,
As so many times i posted my request not very clearly.
What I would like to know is:
Could a “control class” be as quick as a “stand alone” class. I don’t know if this is the right term.
Should I have - theoretically doing all the code the right way - the same results or is there some overhead in a control class which you can’t bypass.
oWnd:oClient = oPickDate
CLASS TPickDate FROM TControl
I can’t imagine that all this comfort does not consume speed. Therefore I started my pickdate as a own window.
Regards,
Otto
Posted:
Thu Jul 31, 2008 7:26 am
by Antonio Linares
Otto,
Using your painting method, place the calculator on top on your window, move it and see if it is ok or not.
Posted:
Thu Jul 31, 2008 8:06 am
by Otto
Antonio,
what do you mean by move?
If I click in the title and press the left mouse button then I can move the whole picker without any flickering.
Also if I move another window over the picker it repaints without flickering.
I can not resize because I have not implemented.
But I have no problem with the “control class design” speed if I know that I have to care about speed.
There are many possibilities to reduce the amount of necessary re-paintings.
The first I would try is to re-paint only if the mouse moves to another day.
Regards,
Otto
Posted:
Thu Jul 31, 2008 8:20 am
by Antonio Linares
Otto,
I mean to move the calculator over the pickdate window.
Just curious to know how it behaves.
Posted:
Thu Jul 31, 2008 8:29 am
by Otto
Antonio,
there is no problem.
I uploaded my exe to:
http://www.atzwanger.com/fwtests/testpickdate.zip
Posted:
Thu Jul 31, 2008 8:49 am
by Antonio Linares
Otto,
Yours is painting nicely
Do you repaint the entire surface or just the selected days ?
Posted:
Thu Jul 31, 2008 8:56 am
by Otto
Antonio,
Here I post my code again.
I do not see much different except the control class design and that my code is a little unstructured.
Maybe you can find out the difference.
Regards,
Otto
- Code: Select all Expand view
// This sample shows how to create pickdate.
#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
LOCAL oPickDate
oPickDate := TPickdate():New()
oPickDate:nWidth := 30
oPickDate:nHeight := 50
msginfo(oPickDate:GetDate())
oPickDate:end()
return nil
********************************************************************************
*** CLASS Tpickdate
********************************************************************************
//----------------------------------------------------------------------------//
#include "FiveWin.ch"
//-----------------------------------------------------------------//
CLASS Tpickdate
DATA VERSION
DATA nYear
DATA nWidth,nHeight,nStartCols,nStartRow
DATA oWnd,planFont,sy,sx
DATA ClickRow,syTemp,sxTemp,ClickCol
DATA aPlan,nStartZeile
DATA startDay,endDay,oBrush,lMove
DATA hBru,hPen,hPen1,hPen3,aTemp
DATA nMonat, nStartMonat
METHOD New()
method PreviousYear()
method NextYear()
method GetDate()
method LButtonUp(x,y)
method bLClicked(x,y)
method DrawRowLines ()
method MMoved(x,y)
METHOD End()
ENDCLASS
//-----------------------------------------------------------------//
METHOD New() CLASS Tpickdate
::VERSION := "1.0.0"
::nWidth := 10
::nHeight := 10
::nStartCols := 50
::nStartRow := 30
::nYear := YEAR( DATE() )
::hBru := CreateSolidBrush( RGB(217,230,246) )
::hPen := CreatePen( 0, 1, 12632256 )
::hPen1 := CreatePen( 0, 1, 280 )
::hPen3 := CreatePen( 0, ::nWidth,RGB(183,249,185) ) //Sonntagsspalte
::nMonat := 1
::nStartMonat:=0
DEFINE BRUSH ::oBrush COLOR RGB(255,255,255)
DEFINE FONT ::planFont NAME "ARIAL" SIZE 0,-11
::sy := 1
::sx := 1
::syTemp := 0
::sxTemp := 0
::aPlan := {}
::ClickCol := 0
::ClickRow := 0
::startDay := ""
::endDay := ""
::lMove := .f.
::aTemp := {}
::nStartZeile := 0
aadd(::aTemp,{0,0}) // 1
aadd(::aTemp,{0,0}) // 2
aadd(::aTemp,{0,0}) // 3
aadd(::aTemp,{0,0}) // 4
aadd(::aTemp,{0,0}) // 5
aadd(::aTemp,{0,0}) // 6
aadd(::aTemp,{0,0}) // 7
aadd(::aTemp,{0,0}) // 8
aadd(::aTemp,{0,0}) // 9
aadd(::aTemp,{0,0}) // 10
aadd(::aTemp,{0,0}) // 11
aadd(::aTemp,{0,0}) // 12
SET DATE GERMAN
return Self
//----------------------------------------------------------------------------//
method GetDate()
local cZeitraum := ""
local oSelf := Self
::hPen3 := CreatePen( 0, ::nWidth,RGB(183,249,185) ) //Sonntagsspalte
DEFINE WINDOW ::oWnd TITLE "Kalender" ;
VSCROLL ;
FROM 5, 5 TO 24, 98
::oWnd:bLClicked := { |x,y,flags | ::bLClicked(x,y) }
::oWnd:bMMoved := { |x,y,flags | ::MMoved(x,y) }
::oWnd:bLButtonUp := { |x,y,flags | ::LButtonUp(x,y) }
::oWnd:cTitle := "Kalender [ " + str(::nYear,4) + " ]"
::oWnd:oVScroll:bGoUp := {|| ::PreviousYear() }
::oWnd:oVScroll:bGoDown := {|| ::NextYear() }
ACTIVATE WINDOW ::oWnd ON INIT (oSelf:oWnd:nWidth( oSelf:nStartCols + 38 * oSelf:nWidth + oSelf:nWidth + oSelf:nWidth),;
oSelf:oWnd:nHeight(oSelf:nStartRow + 13 * oSelf:nHeight ) );
ON PAINT ::DrawRowLines() VALID ((cZeitraum := ::startDay + " -- " + ::endDay + " Tage: " + str( ctod(::endDay)-ctod(::startDay) +1 )),.t.)
return (cZeitraum)
//-----------------------------------------------------------------//
method PreviousYear()
//::nYear := ::nYear - 1
//::DrawRowLines()
//::oWnd:refresh()
//::oWnd:cTitle := "Kalender [ " + str(::nYear,4) + " ]"
::nStartMonat := ::nStartMonat + 1
::DrawRowLines()
msginfo(procname()+" " + str(procline())+" ")
::oWnd:refresh()
::oWnd:cTitle := "Kalender [ " + str(::nYear,4) + " ]"
return .t.
//-----------------------------------------------------------------//
method NextYear()
// ::nYear := ::nYear + 1
// ::DrawRowLines()
// ::oWnd:refresh()
// ::oWnd:cTitle := "Kalender [ " + str(::nYear,4) + " ]"
::nStartMonat := ::nStartMonat + 1
::DrawRowLines()
::oWnd:refresh()
::oWnd:cTitle := "Kalender [ " + str(::nYear,4) + " ]"
return .t.
//-----------------------------------------------------------------//
method LButtonUp(x,y)
::endDay := ::aPlan[::sx,::sy]
IF ::sy > 0 .AND. ::sx > 0
if msgYesNo(::startDay + " -- " + ::endDay + " Tage: " + str( ctod(::endDay)-ctod(::startDay) +1 ))=.t.
::oWnd:end()
endif
ENDIF
::lMove:=.f.
return nil
//-----------------------------------------------------------------//
method bLClicked(x,y)
local ITemp := 0
::sx := INT((x - ::nStartRow)/::nHeight ) + 1
::sy := INT((y - ::nStartCols)/::nWidth )
IF ::sy > 0 .AND. ::sx > 0
::startDay := ::aPlan[::sx,::sy]
::nStartZeile := ::sx
::ClickRow := (INT((x-::nStartRow)/::nHeight ))*::nHeight + ::nStartRow
::ClickCol := ::nStartCols + ::sy * ::nWidth
FOR ITemp := 1 TO 12
::aTemp[ITemp,1]:=0
NEXT
::oWnd:refresh()
::lMove:=.t.
ENDIF
return nil
//-----------------------------------------------------------------//
method DrawRowLines ()
//local aInfo := ::oWnd:DispBegin()
local I, nCurrentRows, iZeile
local nCurrentCol
local cHeader1 := ""
local oSay
local hdc
local aDays := {;
"So","Mo","Di", "Mi", "Do", "Fr", "Sa","So",;
"Mo","Di", "Mi", "Do", "Fr", "Sa","So",;
"Mo","Di", "Mi", "Do", "Fr", "Sa","So",;
"Mo","Di", "Mi", "Do", "Fr", "Sa","So",;
"Mo","Di", "Mi", "Do", "Fr", "Sa","So","Mo" }
local cYear := STR( ::nYear, 4 )
local dDate, nStart
local lSchaltJahr := ( DAY( CTOD( "29.02." + cYear ) ) <> 0 )
local aDaysInMonth := { 31, IIF( lSchaltJahr, 29, 28 ), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local aRect1
local IMonate := 0
local ITemp := 0
local cTest := ""
local nEnde
local iSpalte := 0
local nRight
local nBottom
local nLeft
local nTop
local nMonat := 0
FOR IMonate := 1 TO 12
aadd(::aPlan,{"","","", "", "", "", "","",;
"","", "", "", "", "","",;
"","", "", "", "", "","",;
"","", "", "", "", "","",;
"","", "", "", "", "","","",0,0,0 } )
NEXT
aRect1 := { 0,0, ::nStartRow + (13 * ::nHeight) ,::nStartCols + (38 * ::nWidth) + ::nWidth} //procl
FillRect(::oWnd:hDc,aRect1,::oBrush:hBrush)
iZeile := 0
nCurrentCol := ::nStartCols
FOR I := 1 TO 38
SelectObject( ::oWnd:hDc, ::hPen )
IF iZeile = 5
SelectObject( ::oWnd:hDc, ::hPen1 )
iZeile := 0
ENDIF
//vertikale Linie zw. Tage
::oWnd:line (10, ::nWidth + nCurrentCol, ::nStartRow + (13 * ::nHeight), ::nWidth + nCurrentCol )
nCurrentCol := nCurrentCol + ::nWidth
iZeile := iZeile + 1
NEXT
nCurrentCol := ::nStartCols
FOR I := 1 TO len(aDays)
if aDays[I] = "So"
//Farbhintergrund Sonntag
SelectObject( ::oWnd:hDc, ::hPen3 )
// Sonntag erste fette Linie
::oWnd:line (0, ::nWidth + ::nWidth/2 + nCurrentCol,::nStartRow + (13 * ::nHeight), ::nWidth + ::nWidth/2 + nCurrentCol )
SelectObject( ::oWnd:hDc, ::hPen )
::oWnd:say( 8, ::nWidth+36+I* ::nWidth,aDays[I],RGB(255,128,0), RGB(125,236,175),::planFont,.T.)
else
::oWnd:say( 8, ::nWidth+36+I*::nWidth,aDays[I],RGB(255,128,0),16777215,::planFont,.T.)
endif
nCurrentCol := nCurrentCol + ::nWidth
NEXT
nCurrentRows := ::nStartRow
FOR I := 1 TO 13
SelectObject( ::oWnd:hDc, ::hPen )
IF iZeile = 5
SelectObject( ::oWnd:hDc, ::hPen1 )
iZeile := 0
ENDIF
//Lines
::oWnd:line (nCurrentRows, 1,nCurrentRows, ::nStartCols+ 38 * ::nWidth ) //726
nCurrentRows := nCurrentRows + ::nHeight
iZeile := iZeile + 1
NEXT
nCurrentRows := 12
//set startmonat
FOR I := 1 TO 12
SelectObject( ::oWnd:hDc, ::hPen )
IF iZeile = 5
SelectObject( ::oWnd:hDc, ::hPen1 )
iZeile := 0
ENDIF
nCurrentRows := nCurrentRows + ::nHeight
::nMonat :=I+::nStartMonat
nMonat := I+::nStartMonat
IF ::nMonat > 12
nMonat := ::nMonat - 12
cYear := STR( (::nYear+1), 4 )
ENDIF
dDate := CTOD( "01." + PADL( ALLTRIM(STR( nMonat, 2 )), 2, "0" ) + "." + cYear )
cHeader1 := OemToAnsi( CMONTH( dDate ) ) + " " + cYear //Monate
nStart := DOW( dDate )
::aPlan[I,38] := nStart
::aPlan[I,39] := ::nStartCols + ::nWidth * nStart // - ::nWidth //col begin of month
::aPlan[I,40] := nStart + aDaysInMonth[i] // col end of month
FOR iSpalte := nStart TO aDaysInMonth[i] + nStart - 1
//Array füllen
::aPlan[I,iSpalte] = ( PADL( ALLTRIM(STR( (iSpalte-nStart+1), 2 )), 2, "0" )+ "." + PADL( ALLTRIM(STR( (nMonat), 2 )), 2, "0" ) + "." + cYear )
NEXT
::oWnd:say( nCurrentRows+1, 2, cHeader1,RGB(63,63,63),16777215,::planFont,.T.)
NEXT
IF (::sx > 0 .AND. ::sx < 13) .AND. (::sy > 0 .AND. ::sy < 38)
IF ::lMove = .t.
IZeile := ::sx
::aTemp[IZeile,1] := 10
FOR ITemp := IZeile+1 TO 12
::aTemp[ITemp,1] := 0
NEXT
FOR ITemp := 1 TO 12
if ::aTemp[ITemp,1] > 0
IF ctod(::aPlan[::sx,::sy]) > ctod(" . . ")
FillRect( ::oWnd:hDc, {::ClickRow,;
::ClickCol,;
::ClickRow+::nHeight,;
::ClickCol+::nWidth}, ::hBru )
IF ::nStartRow-::nHeight + (::nHeight*(ITemp)) = ::ClickRow .OR. IZeile=1
nTop := ::nStartRow - ::nHeight + (::nHeight*(ITemp))
nLeft := ::ClickCol
IF ::ClickCol < ::aPlan[ITemp,39]
nLeft := ::aPlan[ITemp,39]
ENDIF
nBottom := ::nStartRow + (::nHeight*(ITemp))
nRight := ::syTemp
IF ::syTemp > nLeft
IF ::syTemp <= ::nStartCols+::aPlan[ITemp,40]*::nWidth
FillRect( ::oWnd:hDc, {nTop,;
nLeft,;
nBottom,;
nRight },::hBru)
ENDIF
ENDIF
ELSEIF ITemp > ::nStartZeile
IF ITemp > ::nStartZeile+1
nTop := ::nStartRow - ::nHeight + (::nHeight*(ITemp-1))
nLeft := ::aPlan[ITemp-1,39]
nBottom := ::nStartRow + (::nHeight*(ITemp-1))
nRight := ::nStartCols +( ::nWidth*(::aPlan[ITemp-1,40]))
IF ::syTemp >= ::aPlan[ITemp,39]
IF ::syTemp <= ::nStartCols+::aPlan[ITemp,40]*::nWidth
FillRect( ::oWnd:hDc, {nTop,;
nLeft,;
nBottom,;
nRight },::hBru)
ENDIF
ENDIF
ENDIF
nTop := ::nStartRow - ::nHeight + (::nHeight*(ITemp))
nLeft := ::aPlan[ITemp,39]
nBottom := ::nStartRow + (::nHeight*(ITemp))
nRight := ::syTemp
IF ::syTemp >= ::aPlan[ITemp,39]
IF ::syTemp <= ::nStartCols+::aPlan[ITemp,40]*::nWidth
FillRect( ::oWnd:hDc, {nTop,;
nLeft,;
nBottom,;
nRight },::hBru)
ENDIF
ENDIF
nTop := ::nStartRow-::nHeight+ (::nHeight*(ITemp-1))
nLeft := ::ClickCol
IF ::ClickCol < ::aPlan[ITemp-1,39]
nLeft := ::aPlan[ITemp-1,39]
ENDIF
nBottom := ::nStartRow +(::nHeight*(ITemp-1))
nRight := ::nStartCols +( ::nWidth*(::aPlan[ITemp-1,40]))
FillRect( ::oWnd:hDc, {nTop,;
nLeft,;
nBottom,;
nRight }, ::hBru )
else
ENDIF
ENDIF
endif
NEXT
ENDIF
ENDIF
nCurrentRows := 12
FOR I := 1 TO 12
SelectObject( ::oWnd:hDc, ::hPen )
IF iZeile = 5
SelectObject( ::oWnd:hDc, ::hPen1 )
iZeile := 0
ENDIF
nCurrentRows := nCurrentRows + ::nHeight
::nMonat :=I+::nStartMonat
nMonat := I + ::nStartMonat
IF ::nMonat > 12
nMonat := ::nMonat - 12
cYear := STR( (::nYear+1), 4 )
ENDIF
dDate := CTOD( "01." + PADL( ALLTRIM(STR( nMonat, 2 )), 2, "0" ) + "." + cYear )
dDate := CTOD( "01." + PADL( ALLTRIM(STR( nMonat, 2 )), 2, "0" ) + "." + cYear )
nStart := DOW( dDate )
FOR iZeile := nStart TO aDaysInMonth[i] + nStart - 1
cHeader1 := ALLTRIM(str(iZeile-nStart+1)) //Tage
if aDays[iZeile] = "So"
::oWnd:say( nCurrentRows+3,36 + ::nWidth + (iZeile) * ::nWidth, cHeader1, RGB(63,63,63),RGB(125,236,175),::planFont,.T.,.T.)
else
::oWnd:say( nCurrentRows+3,36 + ::nWidth + (iZeile) * ::nWidth, cHeader1, RGB(63,63,63),16777215,::planFont,.T., .T.)
ENDIF
NEXT
NEXT
IF (::sx > 0 .AND. ::sx < 13) .AND. (::sy > 0 .AND. ::sy < 38)
::oWnd:say(::sxTemp+20, ::syTemp-20, ::aPlan[::sx,::sy] + " # "+str(ctod(::aPlan[::sx,::sy])-ctod(::startDay)+ 1), RGB(63,63,63), RGB(125,236,175), ::planFont, .T. )
endif
//::oWnd:DispEnd( aInfo )
return nil
//-----------------------------------------------------------------//
method MMoved(x,y)
IF ::sx <> (INT((x-::nStartRow)/::nHeight ) + 1) .OR. ::sx <> (INT( (y-::nStartCols )/::nHeight ) + 1 )
::sx := INT((x-::nStartRow)/::nHeight ) + 1
::sy := INT((y -::nStartCols )/::nWidth )
IF x < ::nStartRow
::sx := 0
x := 0
ENDIF
::sxTemp := ::nStartRow + ::sx * ::nHeight
::syTemp := ::nStartCols + ::sy * ::nWidth + ::nWidth
::oWnd:refresh()
ENDIF
return nil
//-----------------------------------------------------------------//
METHOD End()
RELEASE FONT ::planFont
::hBru:end()
::hPen:end()
::hPen1:end()
::hPen3:end()
return NIL
//-----------------------------------------------------------------//
Posted:
Thu Jul 31, 2008 9:03 am
by Antonio Linares
Dear Otto,
Your method DrawRowLines() is quite scaring
You should try to structure it into smaller functions calls to get a cleaner and better maintainable code
Posted:
Thu Jul 31, 2008 1:11 pm
by James Bott
Otto,
I ran the test control class and I find that the hourglass cursor is running continuously. This means it is in a continuous loop and this is the main reason for the slow performance. I do not know where this loop is.
James
Posted:
Thu Jul 31, 2008 1:39 pm
by Silvio
I propose to change something.
this is my idea
to create a control ok to ownd and for odlg
i think to create array items x,y to move the mouse x,y mounth(X),day(Y)
the user can move the mouse and colorize or dotted( rectangule dotted) and select how many day he wants,
but i not know how i can create
i hope antonio understand me
Posted:
Thu Jul 31, 2008 1:45 pm
by James Bott
Antonio,
I have searched the FWH PRG source for an oocurance of the hourglass cursor (cursorWait()) and I cannot find one. Is this cursor either created using other syntax or possibly in the C source? If so, do you have any idea where?
I am trying to find the continous loop that is occuring in Otto's TPickDate class that is showing the hourglass cursor. Any ideas where this might be happening?
James
Posted:
Thu Jul 31, 2008 2:08 pm
by Otto
Hello James,
I too noticed this. But then I looked into task manager and the CPU consumption.
Although you see the hourglass there is no consumption.
If you resize the control then the resize cursor remains.
Regards,
Otto
Posted:
Thu Jul 31, 2008 2:35 pm
by Antonio Linares
James, Otto,
If MouseMove() is redefined then a final call to Super:MouseMove() should be done as one of its tasks is to properly set the mouse cursor.
Posted:
Thu Jul 31, 2008 2:46 pm
by Otto
Thank you Antonio,
Is this the right place and way to insert Super:mouseMove().
If yes, it does not resolve the painting problem.
Regards,
Otto
- Code: Select all Expand view
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TPickDate
if ::lMove = .t.
::syTemp := Int( ( nCol - 60 ) / ( ( ::nWidth - 60 ) / 37 ) ) * ( ( ::nWidth - 60 ) / 37 ) + 60 + ( ( ::nWidth - 60 ) / 37 )
IF ::nRowCol<>::syTemp
::nRowCol := ::syTemp
::refresh()
ENDIF
endif
Super:MouseMove( nRow, nCol, nKeyFlags )
return 0