Page 6 of 7

PostPosted: 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

PostPosted: 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

PostPosted: 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.

PostPosted: 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

PostPosted: 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.

PostPosted: 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

PostPosted: 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 ?

PostPosted: 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
//-----------------------------------------------------------------//

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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

PostPosted: 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.

PostPosted: 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