Unwanted MouseMode

This article was written for phGantTimePackage VCL (Delphi XE5)

We got the question and a repeating sample to support that showed a scenario where the developer wanted to bring up a modal dialog in double click on a TimeItem.

All that is straight forward:

procedure TForm1.phGant1DblClickGantArea(theGant: TphGant_ComBasic;
  theDataEntity: TphDataEntity_GantTime);
var FrmModal:TFrmModal;
begin
  FrmModal:=TFrmModal.create(nil);
  try
    FrmModal.ShowModal;
  finally
    FrmModal.Free;
  end;
end;

 

The problem was that when the user did this double click and was in a resize hot-zone for the time item – the mouse mode Resize was entered and was still set when the modal dialog was closed.

My first response was to call the method MouseMoveModeCancel. This method is useful for programmatically end any current mouse mode.

However it turned out to not work in this case.

The reason for it not working was that after the DblClick event returns – VCL diretly fires the MouseDown once more – and this is where we actually entered the mouse mode.

In phGantTimePackage there is a way do dispatch a call to the windows message queue and this comes in handy here. The mechanism is called TDoLater and the solution looks like this:

 

procedure TForm1.phGant1DblClickGantArea(theGant: TphGant_ComBasic;
  theDataEntity: TphDataEntity_GantTime);
var FrmModal:TFrmModal;
begin
  FrmModal:=TFrmModal.create(nil);
  try
    FrmModal.ShowModal;
    TDoLater.DoLater(LeaveAnyUnintentionalMouseMoveMode,nil);
  finally
    FrmModal.Free;
  end;
end;

procedure TForm1.LeaveAnyUnintentionalMouseMoveMode(a:TObject);
begin
    phGant1.MouseMoveModeCancel;
end;

 

This way the defer the MouseMoveCancel to a time to directly after all the current messages that windows has on user interaction.

To use the TDoLater you need a uses for phDoLater.

11149 : Is there a way to find if the time item is changing a row in the OnValueChangedGantTime event.

Question

 

My question is – Is there a way to find if the time item is changing a row in the OnValueChangedGantTime event.

The thing that I am doing cannot be done in or after the OnGantTimeChangeRow event.

I tried using the theGant.RowList.FindRowFromY(lngY).TreeNode.GridRowIndex but it does not work for some cases.

 

Answer

 

Use the theGant.RowList.FindRowFromY(IphGantX3.MousePositionGantArea.Y) if the returned row is different than the row currently owning the time item (theDataEntity_GantTime.Row) this is a move…

 

You can check this in the OnHintInfo event and put the information in a membervariable that you later read in the OnValueChangedGantTime event.

 

Check the argument theDataEntity!=null, and also check IphGantX3.GetMouseMoveMode==mmMove.

If both these are true, the user is moving a time item…

Use something like this then:

 _ThisIsARowMove=theGant.RowList.FindRowFromY(IphGantX3.MousePositionGantArea.Y)<>theDataEntity_GantTime.Row

 

 

10968 : Is there a 64 bit ActiveX phGantt control I can use with the application?

Question

We currently phGantt ActiveX control for one of our applications and just starting moving our application to 64 bit support.  Is there a 64 bit ActiveX phGantt control I can use with the application?

 

Answer

 

No we do not currently have a 64-bit edition of the phGantTimePackage. The 32-bit version will function on the 64-bit platforms.

We are currently unable to compile the phGantTimePackage for 64-bit since the Delphi compiler does not yet exist in a 64 bit version, it is planned for 2008 according to CodeGear.

11066 : So far it looks great, but I have not been able to change the row height?

Question

We are evaluating your phGantX component for use in visualizing info from a time & attendance app.  So far it looks great, but I have not been able to change the row height.  We need to make them taller since we need to draw a time bar and several markers underneath.  However, using the SetRowHeightGrid does nothing, and the GetRowHeightGrid always return zero.  Please advice.

 

Answer

Make sure you set IphGantX3.UseGrid=true, “Set this to true to use the grid instead of the tree. You must do this before adding any rows since all rows added are owned by the component (grid or tree) that is active when the row is created.”

 

If IphGantX3.UseGrid=false the comctrl treeview is used, and this cannot handle rowheights, columns etc

 

The Grid is fully hierarcical and can do everything the old tree can.

10782 : How can I print a Gant with the Rave Reports? I my reports using code, not the visual rave environment.

Question

I’m starting to use your software in VCL for Delphi 2006. How can I print a Gant with the Rave Reports? I create my reports using code, not the visual rave environment.

I use the TRvSystem, and all other renders.

Thanks

Answer

We have no specific information on Rave reports but either it will allow you to get a Canvas to draw to and then you use the PrintToHdc sending in the Canvas.Handle, or you can render to an EMF image (vector based) and send that image to the report generator.

10793 : I would like to move all linked items in one click and drag motion.

Question

I would like to move all linked items in one click and drag motion. I have not been able to figure out how to do this. I started by creating a list of all TphDataEntity_GantTime items in the link list and setting each items selected value to true in the gant mouse down event however this only works if I click a second time to initiate the move. Any suggestions?

Answer

If you do the exact same thing but in the IphGantX3.OnSelectionChangedGantTime event instead it will work better I am sure.

The problem is that when you get the mouse down the Gantt has already decidid what will be in the drag or not.

10742 : How do I change the font color (forecolor) of a time item?

Question

Hi, I allow customers to color code schedules. How do I change the font color (forecolor) of a time item?

Answer

There are properties on the IphGantX interface that controls font things:

TimeItemTextFont1 
TimeItemTextFont1Color 
TimeItemTextFont2 
TimeItemTextFont2Color 
TimeItemTextFont3 
TimeItemTextFont3Color 

There are three different fonts to choose from. You choose which one to use when you set ithe values on the TimeItemText IphDataEntity_GantTime2.TimeItemsTextSet.

  Set gr = de.GantRow
  gr.TimeItems_CanChangeRow = False
  gr.TimeItems_CanMove = True

  Set gt = phGantX1.AddGantTime(de, 0)
  gt.Style = tsNormal
  gt.Start = Date
  gt.Stop = Date + 5

  gt.TimeItemsTextAdd
  gt.TimeItemsTextSet 0, de.Text, 2, 2, 0 <- index zero -> font1

10730 : Is there a way to multi- timeitems so I can move them all together in the Gantt?

Question

Is there a way to multi-select timeitems so I can move them all together in the Gantt?

Answer

Yes. When the user holds the ctrl key, the selected property of clicked time items will be toggled. When the user drag time items all with the Selected=true is moved the same distance.

 

10888 : I would like to apply a vertical stripe to a specific day (or days)

Question

I would like to apply a ‘vertical stripe’ to a specific day (or days), I want to use this to show non working (or holidays) using the same technique you use for painting your vertical stripes. How can I achieve this please.

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 Gantt.DateScaler.TimeToPixel method.

So in pseudo code I would go like this:

In the implementation of the OnTimeItemAreaPaintBackground event

int numberOfDaysOnScreen=Round(Gantt.StopTime-Gantt.StartTime)
for i=0 to numberOfDaysOnScreen-1 do
begin
  DateTime oneDay=Gantt.StartTime+i
  Color c=GetColorForThisDay(oneDay)
  int PixelForStartOfDay=Gantt.DateScaler.TimeToPixel(Trunc(oneDay))
  int PixelForEndOfDay=Gantt.DateScaler.TimeToPixel(Trunc(oneDay)+1)
  DrawColoredRectangle(PixelForStartOfDay,0,PixelForEndOfDay,Gantt.Height)
end

 

10812 : Is there a basic example on how to use OnVirtualLoad_GantTime?

Question

Question:Is there a basic example on how to use OnVirtualLoad_GantTime. I found one for the Grid, but not the GantTimes. I am using the phGantTimePackage for VCL v3.2.1.

Thanks in Advance,

Answer

Actually there is no specific virtual load solution for the Time items. Partly because the time axis is easier to handle with normal events than the Grid-Y axis. The grid Y axis suffers from all kinds of problems when wanting to make it appear to have more information that it really has; like the scroll bar for example.

The time axis is easier in that respect. You can implement the phGant.OnScalerChange () event and simple check what visual span you have. Based in that you can delete data (Gantt time items) no longer needed and fetch new ones.

This could be packaged as a Virtual Load mechanism for time items, but it is currently not.