Irregular shapes in Delphi - delphi

With Delphi, using Firemonkey:
How can I get a shape like in the drawing using TShape components?
I do not want to use a bitmap.

Using a TPath component with the following path data should give you a result that's very similar to what you want:
M0,0 L100,0 C110,-5 110,-15 120,-20 L200,-20 C210,-15 210,-5 220,0 L320,0 L320,5 L0,5 Z

Related

Is it possible to draw a line between points on a TChart "point" chart

An instance of TChart in Delphi does a nice job of making a graph showing points. This is the "Point" series in the TeeChart gallery.
I would like to draw lines between some, but not all, of the points.
For example, image a scatter diagram of points, which is easy to make with Delphi/TChart. My objective is to draw straight lines between some of the points.
Is this possible?
This code works:
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
The line crosses over the graph, except the line is not visible over the graph. It seems as if the graph much have its own canvas but I can't find any documentation about finding and using it.
So, I need to find the coordinates of some points, as created by TChart, then draw a line between them.
Some options:
As David Heffernan said, the best option may be to use a series that supports both line segments and pointers. TLineSeries seems to be the perfect series to do this.
The problem here is that this series draws a line segment between each two consecutive points. You can make a point to be null with setNull(index) method and this will make the pointer at that index to disappear, but the predecessor and successor line segments will disappear with it.
The easiest solution could be creating a TMyLineSeries inheriting from TLineSeries to override DrawValue method as explained here.
Add a null point after each point you want to be visible. In this option, the only points not followed by a null point would be those where you want a line segment to be drawn.
Add a TLineSeries per line segment to be drawn.
You always have the possibility to use custom drawing techniques as LU RD said.
Attempting to paint lines yourself is not the way to proceed. The design basis of charting controls is that you define the chart in logical terms and let the control deal with painting it.
So, the way to proceed is to add some line series that represent the lines you wish to be drawn. You can perfectly well add these line series in addition to the other series of your chart.
Regarding your code that attempts to paint on the chart canvas, you should be aware that painting is a delicate process. The design of the system is such that control surfaces are not persistent. Controls are painted in response to the WM_PAINT message. So, whilst you may be able to paint on a control's canvas as you please, what you paint will survive only until the next cycle. Once the control becomes invalid, it needs to repaint itself. The lesson here is, as a general rule, only to paint in response to WM_PAINT messages. Or, in OnPaint events or overridden Paint methods which are called by the VCL in response to WM_PAINT.
To interconnect some points you must follow the drawing principle, all drawing must be done in a paint event.
In TChart, best option here is to do custom drawing in the OnAfterDraw event.
procedure TForm1.Chart2AfterDraw(Sender: TObject);
begin
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
end;
If you need to know the canvas coordinates for a given point in your array of points.
MyYPosX := Series1.CalcXPos( Series1.XValue[ 0 ] ); { <-- first point }
MyYPosY := Series1.CalcYPos( Series1.YValue[ 0 ] ); { <-- first point }
There is a chapter in the TChart help that is a good introduction to custom drawing: "Custom drawing on the Chart".
From the help:
When to draw ?
The order in which you draw to the Canvas is important.
If you wish Custom drawn items to appear above Chart Series you should use the Chart OnAfterDraw event. The Chart1.OnAfterDraw event is fired each time the Chart component is redrawn, just before copying the internal bitmap to screen.
You can place Custom drawn items above the Chart grid and below the Chart Series by placing your code in the Chart OnBeforeDrawSeries event.
Key Chart Paint events:
OnBeforeDrawChart
OnBeforeDrawAxes
OnBeforeDrawSeries
OnAfterDraw

Teechart Custom Lengend tool

I want to show a table for Box Plot containing Values such as mean Median , S.D , Range etc.
The Data Table tool shows only X, X2 data doesn't allow for customization data.I am trying too use Custom Legend Tool using which we can create Table specifying Grid Row and Column. Can anyone let me know how we can enter data into the table.
Thanks
Akshay
If I'm not wrong, you are using VC++. The CustomLegend tool is a quite new tool and I'm afraid there are some features missing in it for VC++.
I've added it to the wish list to be implemented in future releases (TA05015410/B395).
In the meanwhile, note TeeChart ActiveX supports custom drawing so you can manually draw your table if the other tools in the component don't allow you to draw what you exactly want to.
Custom drawing techniques basically consist on a set of methods and properties (set the Canvas Pen, Brush and Font, and draw lines, shapes or texts) to draw directly onto the canvas. These methods are commonly called at the OnAfterDraw event so the custom drawing can be redone after each repaint.
You can find examples written in VC++ under the \Examples\Visual C++\Version 6\ folder in your TeeChart ActiveX installation. Concretely, you can see a simple example of how to use custom drawing techniques in the Dragging Points project. In the DraggingDlg.cpp file you can see how some custom drawing techniques are used in the OnAfterDraw method:
void CDraggingDlg::OnAfterDrawTChart()
{
// Draw a white circle around the clicked pyramid...
if (-1 != m_ClickedBar)
{
CCanvas aCanvas = m_ctrlChart.GetCanvas();
CPen1 aPen = aCanvas.GetPen();
aPen.SetColor(RGB(255, 255, 255));
aPen.SetWidth(1);
aPen.SetStyle(psDot);
aCanvas.GetBrush().SetStyle(bsClear);
int x = m_ctrlChart.Series(0).CalcXPos(m_ClickedBar);
int y = m_ctrlChart.Series(0).CalcYPos(m_ClickedBar);
aCanvas.Ellipse(x, y, x + 40, y + 40);
}
}

Delphi: old QuickReport element size as autostretched or aligntobottom?

We have old QuickReport with Delphi 6 Professional.
We uses QRShape to make "table" (as in html, or Excel), not the frame (because the frame size is commonly different than shape, and in QRLabel/QRDBText we don't have spacing option...
So QRShape used as Rectangles (Cells) and Lines.
The main problem that when I have a Memo Field with AutoStretch option then I cannot set the Height of the Shape.
In these cases it would be good if I can set the shape to AutoStretched, or Aligned...
Have the QR some mechanism to set the Shape height as the parent Band's height dynamically?
Thanks for your help!
Regards: dd
The QuickReport suppor said:
Hi, we have added these features to the later versions of
QuickReport. I can't think of any way to do it with old QR. Regards,
Lut Mentz
Such a life... :-)
For anyone still interested in the solution to this, the component QRFrameLine does the job to change to the height of band

Implementing a 'tag panel' control in Delphi?

Please have a look at this screenshot
alt text http://www.maclife.com/files/u18/Yep3-big.jpg
I think these are the main features of such a 'tag panel':
1) Each tag on the panel is a standalone control and can be clicked
2) Auto line wrapping when there is not enough space to show the next tag in the current line.
3) Rounded corner rectangle border for each tag is a nice-to-have feature.
I want to implement the similar function in Delphi, Is there an existing control to do this? If not, what's the best way to implement such a control?
Thank you.
When you are on a recent Delphi version use a TFlowPanel and some appropriate controls for the tags. A simple TButton or a TLinkLabel should do for that.
Each clickable tag doesn't necessarily have to be its own control. It just has to be a region that you can detect being clicked.
Suppose you represent each area as a Windows region. You can figure out how wide each one should be based on its text with the TCanvas.TextExtent function. Then create a region with a function like CreateRectRgn. For rounded corners, try CreateRoundRectRgn instead. You can test for mouse events in each region with the PtInRegion function. You can paint borders around them with FrameRgn. The last obstacle is to draw them on the screen so they'll all fit. You're creating the regions and you know their widths, so assign tags to a row until you run out of space, and then start the next line.
There are two possible solutions to custom alignment in Delphi 7. You can make your own flowpanel by deriving from TCustomPanel and override the AlignControls( )-method, or you can set alignment to alCustom and handle the OnAlignPosition-event.
I guess I would have gone for the TCustomPanel-derivative option. TFlowPanel in form Delphi 2007 uses that option- I have to admit, though, that I have never tried either my self...

Delphi component spTbxToolbar skin change

How to change at runtime by code (not for groupskintype), the skin type for a sptbxtoolbar component?
You can only change the skin of all SpTBXLib components at once.
Use this code
SkinManager.SetSkin('Office 2007 Blue');
You can however set for each SpTBXLib component if it is drawed using the skin, Windows look or the default look, by setting assigning the SkinType property.
MyComponent.SkinType := sknWindows;
Hint: Toolbars itself do not have the SkinType property. They are always drawn using the skin.
I don't know that component, but found this with Google. Hope it helps.

Resources