I use Teechart pro VCL v2018.24.18 32bit.
I wrote some code that plots a chart from input data, which the user can save in a file or DB.
I have one problem, however. This process may be repeated several times, and I need create a new project. I reset the series value before receiving new input data:
if DbChart1.SeriesCount <> 0 then // clear all series data
begin
for dp := 0 to DbChart1.SeriesCount-1 do
begin
DbChart1.Series[dp].Clear;
DbChart1.Series[dp].XValues.FillSequence;
DbChart1.Series[dp].YValues.FillSequence;
dbchart1.Series[dp].CleanupInstance;
end;
end;
Dbchart1.BottomWall.EndPosition := 0;
Dbchart1.LeftWall.EndPosition := 0;
Dbchart1.DepthAxis.Maximum := 0;
All series points have been removed except the last point!
I want the serial to be clean, like the first time the program ran. How do I do this?
problem solved. the last point in series do not remove ( why ? maybe a Bug ).at the first i use another codes for remove points but problem not solved. look at this codes :
With Dbchart1.Series[0] Do
Begin
dec:=series0.Count;
if dec<>0 then
begin
Series0.Delete(0,dec,true);
end;
End;
but with repeat the codes the problem solved :
With Dbchart1.Series[0] Do
Begin
dec:=series0.Count;
label44.Caption := inttostr(dec);
if dec<>0 then
begin
Series0.Delete(0,dec,true);
dec:=series0.Count;
Series0.Delete(0,dec,true);
end;
End;
Related
For this question please refer to a previous question I asked a while back: Do I need TThreads? If so can I pause, resume and stop them? LU RD answered the question with a provided demo and some comments.
I stopped using Delphi for quite a long time but now I am getting back into it and redoing a project. This project has time consuming operations such as opening a Gif, extracting the frames and then adding those frames (bitmaps) into a TImageList and TListView. This time I actually add the bitmaps directly into a TObjectList, as seen here: How to add and retrieve Bitmaps to and from a TList?
Typically nothing special needs doing here to speed it up as most Gif animations are small, but with medium to large Gifs the application can hang. This is going to get worse though as those bitmaps are going to be modified at runtime using various imaging filters such as grayscale, change hue etc. So I am sure I need multi-threading for this otherwise accessing each bitmap and then manipulating is going to be very slow (as I found out before).
So with that said, I am foolishly trying to adapt (without a clue of what I am doing) some of my procedures to work with the TThread example posted by LU RD I linked to at the top.
I wish I spent a bit more time with the original question to ask for more information but I guess I got sidetracked and moved onto something else, which meant I learned nothing.
Take this snippet from the threading example:
const
cWorkLoopMax = 500;
function TForm1.HeavyWork: boolean; // True when ready
var
i, j: integer;
begin
j := 0;
for i := 0 to 10000000 do
Inc(j);
Inc(workLoopIx);
Result := (workLoopIx >= cWorkLoopMax);
end;
For a start I have no idea what cWorkLoopMax is for, and why its value is set to 500?
Secondly I guess the HeavyWork procedure is just a sample, which runs in a loop a 10000000 times whilst incrementing the j variable?
Then we have the workLoopIx which I am unsure what is for? Maybe something to do with the position within the thread maybe?
So, here I have my current code (no threading) which handles opening the Gif and adding to the TListView and TImageList. The procedures I use are in another unit, if needed I will post it also, but this is what I use inside a TAction (actOpen):
if OpenPictureDialog.Execute then
begin
Screen.Cursor := crHourGlass;
try
BitmapCollection.AddFromGif(OpenPictureDialog.FileName, ImageList1);
ListView1.Items.BeginUpdate;
try
ListView1.Items.Clear;
for I := 0 to BitmapCollection.BitmapList.Count - 1 do
begin
with ListView1.Items.Add do
begin
Caption := 'bitmap' + IntToStr(I+1);
ImageIndex := I;
end;
end;
finally
ListView1.Items.EndUpdate;
end;
finally
Screen.Cursor := crDefault;
end;
end;
What I dont understand is how to put that into a thread procedure, such as HeavyWork? I just created a new one called Job_Open and did this:
procedure TForm1.actOpenExecute(Sender: TObject);
begin
if OpenPictureDialog.Execute then
begin
if not Assigned(MyThread) then
begin
workLoopIx := 0;
btnStartTask.Enabled := false;
btnPauseResume.Enabled := true;
btnCancelTask.Enabled := true;
MyThread := TWorkerThread.Create(Self.Handle, WM_MyProgress, Job_Open);
end;
end;
end;
function TForm1.Job_Open: boolean;
var
I: Integer;
begin
BitmapCollection.AddFromGif(OpenPictureDialog.FileName, ImageList1);
for I := 0 to BitmapCollection.BitmapList.Count - 1 do
begin
with ListView1.Items.Add do
begin
Caption := 'bitmap' + IntToStr(I+1);
ImageIndex := I;
end;
Inc(workLoopIx);
end;
Result := (workLoopIx >= BitmapCollection.BitmapList.Count);// cWorkLoopMax);
end;
This is clearly not right, the performance is slower and I am getting all kind of errors such as Invalid Handle.
I would be extremely grateful if someone could take some time to explain my comments, what I am doing wrong and what I should be doing instead, updated code and comments in source are welcome but I am hoping to learn a bit more of what is going on with the code ideally.
In a perfect world if there is a library of sorts that exists out there that is easy to use then that would be a massive help if I cannot understand what is happening above. Is there such a library that can do something like:
procedure DoSomething;
begin
BeginThreading();
HeavyWork;
StopThreading();
end;
Thanks in advance, and apologies for the lengthy post.
DISCLAIMER: While my answer is not an answer directly to your question it is a psobile solution to your problem.
After reading your questions I have one question to you:
Are you applying same image graphical effects on all ImageList images?
If you are then I must say that you started on working on your problem from wrong approach.
First you need to know that Imagelist doesen't store all those images seperately but that it is storing them all in same verry wide image. So when you read any ImageList image internally ImageList creates output bitmap and then uses Canvas.CopyRect which is quite. When you save image to image list it internally uses Canvas.Draw.
So when you do this many times you create lots of unnecessary data movment.
So instead of your approach where you work on seperate images I recomend you work on ImageLists internal image whose handle you can get using ImageList.GetImageBitmap. This will alow you to apply same graphical effect on all ImageList images at once. And if you don't need to apply graphical effects to all ImageList images I bet you can modify your mage processing method to work only on parts of the image.
In order to learn more about ImageList I recomed you read its documentation:
Image list explanation: http://docwiki.embarcadero.com/Libraries/XE6/en/Vcl.Controls.TImageList
Image list GetImageBitmap explanation
http://docwiki.embarcadero.com/Libraries/XE6/en/Vcl.ImgList.TCustomImageList.GetImageBitmap
It is not bad enough that I am so new to programming; This week I have done more Google searching and less Google finding than I have ever before.
Delphi v7
I have figured out how to create bullets in my richedit control. What I can't find out is how to indent them when the user creates them.
Any ideas?
Set the TRichEdit.Paragraph.FirstIndent. The bullets will be indented by the additional amount of FirstIndent. (You use FirstIndent because a bullet item is the first line of a new paragraph.)
RichEdit1.Paragraph.FirstIndent := RichEdit1.Paragraph.FirstIndent + 10;
Here's a quick demo based on the RichEdit demo that's shipped with Delphi for years. I simply added two new TToolButtons to the ToolBar (the two right-most buttons, named tbLessIndent and tbMoreIndent respectively, with glyphs from the GlyFx images supplied with Delphi), and added the following event handlers to the existing form as the ToolButton.OnClick events:
procedure TMainForm.tbLessIndentClick(Sender: TObject);
begin
Editor.Paragraph.FirstIndent := Editor.Paragraph.FirstIndent - 10;
tbLessIndent.Enabled := Editor.Paragraph.FirstIndent > 9;
end;
procedure TMainForm.tbMoreIndentClick(Sender: TObject);
begin
Editor.Paragraph.FirstIndent := Editor.Paragraph.FirstIndent + 10;
tbLessIndent.Enabled := True;
end;
Here's a sample new document with a few items added:
For more info, see the documentation on Numbering and FirstIndent (XE2 docs, but they're about the same)
I've run into the following problem:
My Delphi7 program runs smoothly on most computers running WinXP/Vista/7 BUT on some older Windows XP installs (only a few) I'm getting the following problem:
I have a system image list, and I'm adding my own icons to a copy of the system image list. Upon adding my icons I get an "Invalid image size." EInvalidOperation error.
Here is the code in question:
function GetSystemLargeIconsList: TCustomImageList;
// This gets the system image list.
var
SysIL: HImageList;
SFI: TSHFileInfo;
MyImages: TCustomImageList;
begin
SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI),
SHGFI_SYSICONINDEX or SHGFI_LARGEICON);
if SysIL <> 0 then begin
MyImages:=TCustomImageList.Create(nil);
// Assign the system list to the component
MyImages.Handle := SysIL;
// The following prevents the image list handle from being
// destroyed when the component is.
MyImages.ShareImages := TRUE;
Result:=MyImages;
end;
end;
var
DocumentImgList: TCustomImageList;
IconToAdd: TIcon;
begin
DocumentImgList:=GetSystemLargeIconsList;
Documents.LargeImages:=DocumentImgList;
Documents.SmallImages:=DocumentImgList;
IconToAdd:=TIcon.Create;
DocumentListIcons.GetIcon(0, IconToAdd);
DocumentImgList.AddIcon(IconToAdd); ----> this is the line of the exception
To make the problem worse, I'm using the TPngImageList component, but according to the code, it just seems to call the standard Delphi function:
if TObject(Self) is TPngImageList
then if Image = nil
...
else begin
Patch := FindMethodPatch('AddIcon');
if Patch <> nil
then begin
Patch.BeginInvokeOldMethod;
try
Result := TCustomImageList(Self).AddIcon(Image); ----> this is where the exception happens
finally
Patch.FinishInvokeOldMethod;
end;
end
else Result := -1;
end;
I've recently found out that on one of the computers that have this problem, either uxtheme.dll or explorer.exe has been patched with some Windows-skinning program.
So I suppose that somebody or a program is hacking the system image list in a way that is making my Delphi program crash.
Any ideas on how to fix this?
Thanks!
One thing you could try would be to load your icon into a separate tBitmap, then resize it before adding it into the image list.
I'm using Delphi 2010 and Rave Reports (comes built in, v. 7.7.0).
I have been using this couple for 5 months without any problem. In my company i use two languages, first i use our primary language (Turkish) and when people wants to use another language i change the specific text and memo values according to their tag value.
This approach worked fine till last week. Last week changing the values at runtime stopped working. I don't know why, everything seems ok with the code, i also tried to check changed values, the values seemed to changed but when i execute reports all the values changed the their defaults.
Here is my code for changing :
procedure ProcessRaveReport( APageName : string ); // 'rp411.rp411Page'
var
myPage : TRavePage;
myText : TRaveText;
i, iTag : Integer;
begin
dm.Rave.Open;
with dm.Rave.ProjMan do
begin
myPage := FindRaveComponent(APageName,nil) as TRavePage;
if myPage = nil then Exit;
for i:= 0 to myPage.ComponentCount-1 do
begin
if myPage.Components[i] is TComponent then
iTag := (myPage.Components[i] as TComponent).Tag;
if (iTag > 0) then
begin
if myPage.Components[i] is TRaveText then
begin
//ShowMessage((myPage.Components[i] as TRaveText).Text);
//ShowMessage(getLangIDS((myPage.Components[i] as TRaveText).Tag));
(myPage.Components[i] as TRaveText).Text := getLangIDS((myPage.Components[i] as TRaveText).Tag);
//ShowMessage('Sonuc : '+(myPage.Components[i] as TRaveText).Text);
end
else if myPage.Components[i] is TRaveMemo then
(myPage.Components[i] as TRaveMemo).Text := getLangIDS((myPage.Components[i] as TRaveMemo).Tag);
end;
//iTag := 0;
end;
end;
dm.Rave.Close;
end;
You can see my showmessage calls, this messages prove that value changed to new language but at the end i always see the default values.
Is there anyone knows any solution that problem?
Denizhan
I miss the .execute of the RvProject-component "Rave" ... on a quick check it looks good but you only change the instance of the RvProject and not the file itself.
I'm trying to work with the class from JosephStyons but I do get an "Invalid Index" Error on the line where the "User ID" should get set.
FRpt.Database.Tables[i].ConnectionProperties.Item['User ID'] := edUserName.Text;
Here's my environment:
WinXP Sp3, Crystal Reports Developer XI Rel.2 SP4, Delphi 5 Update Pack 1
Any help or ideas greatly appreciated!
Thx,
Reinhard
Your value for [i] could be the culprit...I can't remember for sure but I believe the first table will be Table[1] instead of Table[0] as one would expect.
I altered my loop to use:
CrTables := CrDatabase.Tables;
for crTableObj in crTables do
You might try stepping through the table using a for loop as shown above or by starting with 1 instead of 0.
I hope this helps.
Put a break point on that line and use Evaluate/Modify.
It will return an error if you try something invalid.
Examine FRpt.Database.Tables[i] and see if it's valid for what you think are the min and max values for i.
If Tables is an array, one way to avoid that is to use ...Low(Tables) to High(Tables)
If you get your Table Ok, examine FRpt.Database.Tables[i].ConnectionProperties.Item['User ID'] and see if it's valid.
It might be that the Item getter does not like the space embedded in "User ID". Some products need either to surround by special characters like "[User ID]", other to replace by an underscore like "User_ID"
Are you also setting the password, server name and database name?
procedure TReports.LogonToDBTables(cReport:
CrystalDecisions.CrystalReports.Engine.ReportDocument;
ConnInfo: ConnectionInfo);
var
CrDataBase: Database;
CrTables: Tables;
CrTableObj: TObject;
CrTable: Table;
CrTableLogonInfo: TableLogonInfo;
iSubReportIndex: smallint;
begin
CrDataBase := CReport.Database;
CrTables := CrDatabase.Tables;
cReport.DataSourceConnections[0].IntegratedSecurity := False;
for crTableObj in crTables do
begin
crTable := CrystalDecisions.CrystalReports.Engine.Table(crTableObj);
crTableLogonInfo := crTable.LogOnInfo;
crTableLogonInfo.ConnectionInfo := ConnInfo;
crTable.ApplyLogOnInfo(crTableLogonInfo);
end;
end;
function TReports.GetConnectionInfo(): ConnectionInfo;
var
cTemp: ConnectionInfo;
begin
cTemp := ConnectionInfo.Create();
cTemp.AllowCustomConnection := True;
cTemp.ServerName := GetServerName();
cTemp.DatabaseName := GetDBName();
cTemp.UserID := GetDBUserID();
cTemp.Password := GetDBPassword();
Result := cTemp;
end;