10886 : I would like to color columns for certain days in a different color with the phGantTimePackage.

Question

Hi, I’d like to color columns for certain days in a different color with the phGantTimePackage. Could you pleace provide an example on how to achieve this with the OnGantAreaDrawBackground handler?

Thanks!

Answer

In order to do this you must know when a day starts and stops in pixels, this is easily found by sending in a datetime to the IphGantX3.DateToPixel method.

So in pseudo code I would go like this:

int numberOfDaysOnScreen=Round(phGant.Stop-phGant.Start)
for i=0 to numberOfDaysOnScreen-1 do
begin
  DateTime oneDay=phGantt.Start+i
  Color c=GetColorForThisDay(oneDay)
  int PixelForStartOfDay=phGantt.DateToPixel(Trunc(oneDay))
  int PixelForEndOfDay=phGantt.DateToPixel(Trunc(oneDay)+1)
  DrawColoredRectangle(PixelForStartOfDay,0,PixelForEndOfDay,Gantt.Height)
end

10702 : I would like more control over the appearance of Links.

Question

I would like more control over the appearance of Links. I have been attempting to use the OnUserDrawLinks with limited success. Are there any examples (Delphi preferred) of how to use OnUserDrawLinks?

Answer

Drawing links so that they look good in all situtions is hard. That is partly why we left a door open for you with the user draw link event.

This is our code to draw links:


procedure TphGant_ComBasic.DrawLink(theStartPoint,theStopPoint:TPoint;
  theCanvas:TCanvas;theLinkStyle:TLinkStyle; theLinkColor:TColor;theLinkPenWidth: Integer;
  aDataEntity_Link:TphDataEntity_Link);
var
  aMiddlePoint, aNewStopPoint:TPoint;
  cLRArr, cUDArr ,cOri,ssFold,ssMinDist, OldPenWidth:Integer;
  aColor : TColor;
begin
  OldPenWidth := theCanvas.Pen.Width;
  try
    theCanvas.Pen.Color := theLinkColor;
    theCanvas.Pen.Width := theLinkPenWidth;
    theCanvas.MoveTo(theStartPoint.X,theStartPoint.Y);
    cLRArr := 3;
    cUDArr := 3;
    cOri:=1;
    ssMinDist:=7;
    if GA.IsPrinting then
    begin
      cLRArr := Round(3*GA.Scalex);
      cUDArr := Round(3*GA.Scaley);
      ssMinDist:=Round(ssMinDist*GA.Scalex);
    end;

    aNewStopPoint := theStopPoint;

    if Assigned(aDataEntity_Link) and (aDataEntity_Link.StartFinishOption=tlsfSS) then
    begin
      // tlsfSS is treated the same way for tlsDefault and tlsMSProject
      if theStartPoint.X>theStopPoint.X then
        ssFold:=theStopPoint.X-ssMinDist
      else
        ssFold:=theStartPoint.X-ssMinDist;

      theCanvas.LineTo(ssFold,theStartPoint.Y);
      theCanvas.LineTo(ssFold,aNewStopPoint.Y);
      theCanvas.LineTo(aNewStopPoint.X,aNewStopPoint.Y);

      theLinkStyle:=tlsDefault;
    end
    else
    begin

      case theLinkStyle of
        tlsDefault:
    begin
      if theStartPoint.X>theStopPoint.X then
              cOri:=-1;
            // Moves horizonatal endpoint one extra pixel to get get nicer looking arrows
            aNewStopPoint.X := theStopPoint.X-cOri;
            // This code draws the line cut in three parts - horizontal - vertical - horizontal
            aMiddlePoint.X:=theStartPoint.X+((aNewStopPoint.X-theStartPoint.X) div 2);
            aMiddlePoint.Y:=theStartPoint.Y+((aNewStopPoint.Y-theStartPoint.Y) div 2);
            theCanvas.LineTo(aMiddlePoint.X,theStartPoint.Y);
            theCanvas.LineTo(aMiddlePoint.X,aNewStopPoint.Y);
            theCanvas.LineTo(aNewStopPoint.X,aNewStopPoint.Y);
          end;
        tlsMSProject:
          begin
            if theStartPoint.Y<theStopPoint.Y then
              cOri:=-1;
            if theStartPoint.X < theStopPoint.X then
              aNewStopPoint.X := theStopPoint.X + cUDArr  // Moves endpoint horizontal get the arrow "inside" the box
            else
              aNewStopPoint.X := theStopPoint.X - cUDArr; // Moves endpoint horizontal get the arrow "inside" the box
            // Moves endpoint one extra pixel up/down to get nicer looking arrows
            aNewStopPoint.Y := theStopPoint.Y+cOri;
            // Draw horizontal line, then downwards to the recieving point
            theCanvas.LineTo(aNewStopPoint.X,theStartPoint.Y);
            theCanvas.LineTo(aNewStopPoint.X,aNewStopPoint.Y+cUDArr*cOri);
          end;
      end;
    end;
    // Don't draw the arrow if we are "out of bounds"
    if PointInRect( aNewStopPoint, theCanvas.ClipRect ) then
    begin
      case theLinkStyle of
        tlsDefault:
          begin
            // This code draws the arrow
            theCanvas.LineTo(aNewStopPoint.X-cLRArr*cOri,aNewStopPoint.Y-cLRArr);
            theCanvas.LineTo(aNewStopPoint.X-cLRArr*cOri,aNewStopPoint.Y+cLRArr);
            theCanvas.LineTo(aNewStopPoint.X,aNewStopPoint.Y);
          end;
        tlsMSProject:
          begin
            // This code draws the arrow downwards or upwards!
            aColor := theCanvas.Brush.Color;
            theCanvas.Brush.Color := theLinkColor;
            theCanvas.Polygon( [
              Point(aNewStopPoint.X,aNewStopPoint.Y),
              Point(aNewStopPoint.X-cUDArr,aNewStopPoint.Y+cUDArr*cOri),
              Point(aNewStopPoint.X+cUDArr,aNewStopPoint.Y+cUDArr*cOri)
              ] );
            theCanvas.Brush.Color := aColor;
          end;
      end;
    end;
  finally
    theCanvas.Pen.Width := OldPenWidth;
  end;
end;

10669 : Hide non working days

Question

On a calendar I require to post just the days of reel work that means I needn’t to post the week ends and public holidays. So can you please inform me how I can post on the calendar just the working days that I fix myself and finally can you send to me a vb6 code.

Answer

The datescaler can only “hide” specific day types (like all fridays) and not specific days (like 23 february).

When we developed the time hiding functionality we saw that people got confused when there where sporadic days missing. But not when it was consequent (like all fridays).

To hide all fridays you can call SetHiddenDayType 5,true

 

 

 

10673 : Hiding rows

Question

I use phGantTime in my application and would like to hide a whole row, so that the user can differentiate between different rows (each row representing an activity). From the help, I found that each IphGantRow3 has a property named “visible”, but this one is read only. How do I set this property in order to hide the row ?

Answer

To completly hide a grid node and its GanttRow from view (but still have it in the component) you can set the HideNode property of the IphDataEntity_Tree2 (TphDataEntity_GridTreeNode in VCL).

To Hide specific time items from view you can set their Visible property.

10854 : Ive got a problem with the AddText of the TextCollection in VCL.

Question

I’ve got a problem with the ‘AddText’ of the ‘TextCollection’.

For exemple after an ‘AddText’ method when i test the ‘TextCollection.Count’ it’s said 0.
I don’t know how to change the text of my ‘TphDataEntity_GantTime’ after i create it.

Answer

The code below adds a text to a time item, and then changes it…

procedure TForm1.Button4Click(Sender: TObject);
begin
  if Assigned(phGant1.ActiveDataEntity) then
  begin
    phGant1.ActiveDataEntity.TextCollection.AddText(‘Hello’,0,0);
    ShowMessage(IntToStr(phGant1.ActiveDataEntity.TextCollection.Count));
    phGant1.ActiveDataEntity.TextCollection.Text[0].Text:=phGant1.ActiveDataEntity.TextCollection.Text[0].Text+’+’;
  end;
end;

10907 : How can I render a custom link when I set the link style to tlsUserDraw?

Question

How can I render a custom link when I set the link style to
tlsUserDraw. Can you supply an example please?

Answer

The first thing to do is to create the link and set its style to User:

Private Sub LinkTimes(theFrom As IphDataEntity_GantTime, theTo As IphDataEntity_GantTime)< ?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Dim aLink As IphDataEntity_Link

Dim aInt As Integer

  

   If (theFrom Is Nothing) Or (theTo Is Nothing) Then

     ‘ Dont do anything

   Else

     Set aLink = phGantX1.AddLink

       

     aLink.LinkOwner = theFrom

     aLink.LinkedTo = theTo

    

     aInt = globalCounter Mod 4

     ‘aLink.LinkStyle = tlsMSProject

     aLink.LinkStyle = tlsUserDraw

    

     aLink.LinkColor = vbBlue

    

     If aInt = 1 Then

       aLink.StartFinishOption = tlsfFS

     ElseIf aInt = 2 Then

       aLink.StartFinishOption = tlsfSS

     ElseIf aInt = 3 Then

       aLink.StartFinishOption = tlsfFF

     ElseIf aInt = 3 Then

       aLink.StartFinishOption = tlsfFS

     End If

     globalCounter = globalCounter + 1

   End If

   Set globalToLinkTo = theTo

End Sub

 

And then you must implement the OnUserDrawLink event and simply draw your link between the start and stop. Mind you that this sample only draws a straight line, and the implementations in the phGantTimePackage does a lot more to bend the line etc.

 

 

 

Private Sub phGantX1_OnUserDrawLink(ByVal theGant As phGantXControl.IphGantX2, ByVal theDataEntity_Link As phGantXControl.IphDataEntity_Link, ByVal theHDC As Long, ByVal Startx As Long, ByVal Starty As Long, ByVal Stopx As Long, ByVal Stopy As Long)

    aDummy = Module1.MoveTo(theHDC, Startx, Starty)

    aDummy = Module1.LineTo(theHDC, Stopx, Stopy)

 

End Sub

 

 

 

10844 : phGantXControl.ocx under Vista Home Premium

Question

I’m can not register the phGantXControl.ocx under Vista Home Premium ( I’m using the command :regsvr32 phGantXControl.ocx). The system returns that a call to the DllRegisterServer failed with the error code : 0x80004005. Also (maybe for the same reason?) I can not import this activex into the Delphi 7 IDE. Please help me as I’m in the proccess of migrating my develpment from XP to new vista and I’m faced with many combatibility problems.

Answer

You must run regsvr32 as administrator in Vista. Just start a command prompt and choose “Run as administrator”, then execute regsvr32.

Further info on installing the phGantXControl.ocx in Vista Ultimate. You must have the UAC (the advanced user rights thingy) turned ON.

11040 : I want to keep the original Height of Some time items…

Question

For the gantrow I have set the property CollisionDetect = True
So on Collision the height of the timeItems are changed (just what I want). But I want to keep the original Height of Some time items because it is another activity. How can I arrange this in VB. Thnx in advance.

Answer

You can set IphGantRow3.CollisionDetectBetweenLayers=false and keep some activities in one layer and the others in another layer.

10619 : Controlling z order of time items

Question

When I add several TimeItems to a Gantt row (where times overlap each other) they all appear; however are split horizontally across the Grid displaying several thin TimeItems.

What I really want, is a single row to be shown, where the last item added will overwrite (appear on top) of the other items. I know I could iterate through the different time items and calculate where each starts/stops to ensure the times don’t overlap (resulting in a single row) but this will take some time.

Can this be achieved by using different Layers?

Answer

First you may turn off the automatic collision detection by setting the IphGantRow3.CollisionDetect=false.

But to further control the z-order of drawing (which time item that is drawn on top of another) you should place your time items on different layers.

If you add a time item to layer zero and one to layer one it would look like this:

layer0_TimeItem=phGantX.AddGantTime(0)
layer1_TimeItem=phGantX.AddGantTime(1)

The deafult drawing order is from 0 to n. You can control where the drawing starts (maybe you want a “send to back” choice on your time item) and this is controlled by the IphGantRow3.DrawLayerStart property.

This is the help file description of the IphGantRow3.DrawLayerStart property

Since there can be many datalists on a GantRow, you can use these different lists as layers. In order to control in wich order the layers are drawn you set the drawLayerStart property. Say that you have 5 layers or datalist. Then they will span from 0 to 4 and normally be drawn 0,1,2,3,4. When you set DrawLayerStart to 3 for exemple they will be drawn in the following order: 3,4,0,1,2.