Search code examples
delphiteechart

Canvas.textout doesn´t show text after a new series is made visible


So what i'm doing is display the x and y values of the mouse pointer on a teechart chart using the following code, inside the onmousemove event:

oscilografia.Repaint;

if ((x>236) and (x<927)) and ((y>42) and (y<424)) then
begin
  oscilografia.Canvas.Brush.Style := bsSolid;
  oscilografia.Canvas.Pen.Color := clBlack;
  oscilografia.Canvas.Brush.Color := clWhite;
  oscilografia.Canvas.TextOut(x+10,y,datetimetostr(oscilografia.Series[0].XScreenToValue(x))+','+FormatFloat('#0.00',oscilografia.series[0].YScreenToValue(y)));
  edit1.Text:=inttostr(x)+'  '+inttostr(y);
end;

The code works fine, but a problem happens when i make another series visible by selecting it on the legend: the text inside the box created by canvas.textout isn´t shown anymore.

The box is still there following the mouse, but without any text. So i would like a solution to this.


Solution

  • The basic problem is down to how painting works. Windows do not have persistent drawing surfaces. What you paint onto a window will be overwritten the next time the system needs to repaint it.

    You need to arrange that all painting is in response to WM_PAINT messages. In Delphi terms that typically means that you would put your painting code in an overridden Paint method.

    So the basic process goes like this:

    1. Derive a sub-class of the chart control and in that class override Paint. Call the inherited Paint method and then execute your code to display the desired text.
    2. In your OnMouseMove event handler, if you detect that the mouse coordinates text needs to be updated, call Invalidate on the chart.
    3. The call to Invalidate will mark that window as being dirty and when the next paint cycle occurs, your code in Paint will be executed.
    4. What is more, when anything else occurs that forces a paint cycle, for instance other modifications to the chart, your paint code will execute again.

    Note, as an alternative to sub-classing, you can probably use the TChart event OnAfterDraw. But I'm not an expert on TChart, so am not sure. The main points though are as I state above.