For loop continue going after reaching goal. Delphi - delphi

This issue appears only with numbers, bigger, then 12 including.
Those two pictures captured in one time. How it is even possible?
For loop must go from 0 to 12-1=11, doesn't it?
Nevertheless, when I use while loop instead, it works fine.
Is it my fault or Delphi's?
P.S. Code down bellow.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
Label1: TLabel;
Button3: TButton;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
n:Integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); //Button, that sets array length
var
i, index:Integer;
begin
val(Edit1.Text, n, index);
if(index<>0) then
begin
ShowMessage('Wrong number');
Edit1.Clear();
exit;
end;
StringGrid1.ColCount:=n;
for i:=0 to n-1 do
StringGrid1.Cells[i,0]:=IntToStr(i+1);
StringGrid1.SetFocus();
end;
procedure TForm1.Button2Click(Sender: TObject); //Main button
var
i, index:Integer;
a:array[0..10] of Real;
denom, sum:Real;
begin
i:=0;
sum:=0;
denom:=-1;
//that for loop from screenshot is here
for i:=0 to n-1 do
//while i<=(n-1) do
begin
Val(StringGrid1.cells[i,1], a[i], index);
if(index<>0) then
begin
ShowMessage('Wrong number with ' + IntToStr(i+1) + ' Id');
StringGrid1.Col:=i;
StringGrid1.Row:=1;
StringGrid1.SetFocus();
exit;
end;
a[i]:=a[i]/denom;
sum:=sum+a[i];
StringGrid1.Cells[i,2]:=FloatToStrF(a[i],ffFixed,5,3);
denom:=-denom*(i+2);
//Inc(i);
end;
Label2.Caption:=FloatToStrF(sum,ffFixed,5,3);
end;
//code down bellow just allow to go to another cell by pressing Enter
procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
begin
if (Key=#13) and (StringGrid1.Col=(n-1)) then
Button2.SetFocus()
else if (Key=#13) and (StringGrid1.Col<>(n-1)) then
StringGrid1.Col:=StringGrid1.Col+1;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Close();
end;
end.

As to answer your question of 'how is this even possible'...
In your screen, n is 12. As pointed out by Kermation, the highest index of a is 10, so when i is 11, unless you have range checking activated, when you write to a[11] (i=11) you will overwrite something else. This is in the local variable area so it might be i, for instance, or even internal variables you can't see like the limit used for the for loop, which is calculated at the start of the loop. Once you allow this to happen, pretty much anything is possible.
Of course the exact manifestation of the problem will very from one version of the compiler to another. In one version you might get away with it. in another you won't.

Array a size was smaller, then amount of cells.

Related

How do I move an image up and down when a button is clicked

I am trying to animate a celebratory trophy image that will 'bounce' up and down. I tried using a timer and then I used modulus to determine whether its odd or even, if its odd it goes up 10 if even it goes down 10 etc. I think the problem is looping, I need to use some form of loop right?
unit Unit11;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, pngimage, ExtCtrls,math, StdCtrls;
type
Tfrmwinner = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Label2: TLabel;
Image1: TImage;
Image2: TImage;
Label3: TLabel;
Label4: TLabel;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
procedure Label4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmwinner: Tfrmwinner;
implementation
uses Unit12,Unit4;
{$R *.dfm}
procedure Tfrmwinner.Label4Click(Sender: TObject);
var
position:integer;
begin
frmwinner.Hide;
frmboard.show;
unit12.frmboard.memlead.Lines.Add('Position'+#9+'Name'+#9+'ID Number');
unit12.frmboard.memlead.Lines.Add('___________________________________');
while not unit4.frmcontest.ADOLead.Eof do
begin
position:=position+1;
unit4.frmcontest.ADOLead.First;
unit12.frmboard.memlead.Lines.Add(inttostr(position)+#9+unit4.frmcontest.ADOLead['Name(s)']+#9+inttostr(unit4.frmcontest.ADOLead['ID Number']));
unit4.frmcontest.ADOLead.Next;
end;
end;
procedure Tfrmwinner.Timer1Timer(Sender: TObject);
var
icount,i:integer;
begin
icount:=0;
icount:=icount+1;
if (icount mod 2)=1 then
begin
image1.top:= image1.top+10;
image2.top:= image2.top+10;
end;
if (icount mod 2)=0 then
begin
image1.top:= image1.top-10;
image2.top:= image2.top-10;
end;
if icount=16 then
begin
timer1.Enabled:=false;
end;
end;
end.
This is what I've tried, with no luck
The problems related to how the image jumps (or doesn't jump) are in procedure TfrmWinner.Timer1Timer(Sender: TObject);
Note that event handlers like an OnTimer or OnKeyPress etc. are triggered by certain system events, and that the event handler you write should do its task as fast as possible and then exit. Also, anything you need to persist until the event handler is called the next time, must be saved in a "safe place" outside of the event handler.
First, the icount: integer variable cannot be declared in the OnTimer handler, because it would cease to exist every time the procedure exits.
Secondly, you can not initialize it (assign 0 to it) in the OnTimer handler, because then it would obviously never reach the final value of 16.
So, move the declaration of icount: integer to the private section of the form:
private
{ Private declarations }
icount: integer;
Then, initialize it to 0 and start the timer in the Label4Click() procedure if that is the purpose (it's unclear in your current code).
icount := 0;
Timer1.Enabled := True;

Setfocus to the searchbox in a tlistview

I am working in Seattle, writing a FM application for windows only.
I have A tlistview on my form and have it populated with data.
I have the search option turned on.
How do I programmatically set focus to the search box?
How do I increase the size and font size of the search box?
thanks
The searchbox is not intended to be accessed programmatically except for setting it visible and to fire event when changed. Otherwise it is intended to be accessed only by the user.
Therefore, access is a little bit involved. However, the example of the OnSearchChange event inspired the following answer:
uses ..., FMX.SearchBox;
type
TForm17 = class(TForm)
ListView1: TListView;
Button1: TButton;
Label1: TLabel;
...
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
sb: TSearchBox; // a local reference
...
end;
implementation
procedure TForm17.Button1Click(Sender: TObject);
begin
if Assigned(sb) then
sb.SetFocus;
end;
procedure TForm17.FormCreate(Sender: TObject);
var
i: integer;
begin
ListView1.SearchVisible := True; // or set in the Object Inspector at design time
for i := 0 to ListView1.Controls.Count-1 do
if ListView1.Controls[I].ClassType = TSearchBox then
begin
sb := TSearchBox(ListView1.Controls[i]);
Break;
end;
end;
procedure TForm17.ListView1SearchChange(Sender: TObject);
begin
if Assigned(sb) then
Label1.Text := sb.Text;
end;
At form creation we search the SearchBox control and if found we store a reference to it in the sb: TSearchBox; field. Then access is quite straightforward.

WMI with delphi

I've been working on a project which would read the temperature of the CPU.
Unfortunately I'm getting a conversion error. The whole thing compiles without a problem. But when I actually try to execute the code it gives me this error:
"Could not convert variant of type (Dispatch) into type (String)"
I'm not actually trying to get the Temp, On this bit I'm just looking if the way this is coded works. Temp part is going to be added later on...
The particular code:
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls, jpeg, WbemScripting_TLB, StdCtrls;
type
TForm3 = class(TForm)
MainMenu1: TMainMenu;
F1: TMenuItem;
Quit1: TMenuItem;
Help1: TMenuItem;
Programms1: TMenuItem;
CalCulator1: TMenuItem;
Browser1: TMenuItem;
emperature1: TMenuItem;
WallPad1: TMenuItem;
MediaPlayer1: TMenuItem;
Image1: TImage;
Image2: TImage;
Load1: TMenuItem;
Background1: TMenuItem;
Label1: TLabel;
Button1: TButton;
procedure CalCulator1Click(Sender: TObject);
procedure Image1DblClick(Sender: TObject);
procedure Browser1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure MediaPlayer1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
WMIServices: ISWbemServices;
Root : ISWbemObjectSet;
Item : Variant;
I : Integer;
implementation
uses Unit4, Unit2, Unit5;
{$R *.dfm}
procedure TForm3.Browser1Click(Sender: TObject);
begin
Form2.Show;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
WMIServices := CoSWbemLocator.Create.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);
Root := WMIServices.ExecQuery('Select DeviceID FROM Win32_TemperatureProbe','WQL', 0, nil);
Label1.caption := VarToStr(Root)
end;
procedure TForm3.CalCulator1Click(Sender: TObject);
begin
form4.show;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
image1.bringtofront
end;
procedure TForm3.Image1DblClick(Sender: TObject);
begin
Form4.show;
end;
procedure TForm3.MediaPlayer1Click(Sender: TObject);
begin
form5.show;
end;
end.
I'm assuming the solution is going to be quite simple, yet I can't see it...
The error is created on this bit
Label1.caption := VarToStr(Root)
Before continuing on this path maybe you should read the documentation Win32_TemperatureProbe class.
In the header you can read:
"Most of the information That the Win32_TemperatureProbe WMI class Provides you eat from SMBIOS. Real-time readings for the CurrentReading property can not be Retrieved from SMBIOS tables. For this reason, current implementations of WMI do not populate the CurrentReading property. The CurrentReading property's Presence is reserved for future use."
if you want to use WMI correctly, you can find much information on the website of Rodrigo Ruz or on my website including samples and specific components to WMI (GLibWMI on Sourceforge).
There is an interesting project (opensource) in http://openhardwaremonitor.org to access hardware properties (including the ones you need). Check it out.
A greeting.

Listbox (Listing Error)

Hi Im doing a raffle program for my friend.Everything was going good but then when i delete a value,the result was changing... Please help me!
Example:
Listbox;
1-a
2-c
3-b
4-f
5-h
6-j
After delete line 3:
1-a
2-c
4-f
5-h
6-j
6-g
What i want:
1-a
2-c
3-f
4-h
5-j
6-g
Here are the codes:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Label1: TLabel;
ComboBox1: TComboBox;
Edit1: TEdit;
Button1: TButton;
Label2: TLabel;
ComboBox2: TComboBox;
Label3: TLabel;
Button2: TButton;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
Edit6: TEdit;
Button3: TButton;
Button4: TButton;
SaveDialog1: TSaveDialog;
OpenDialog1: TOpenDialog;
Button5: TButton;
Button6: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
b,sayac:integer;
sonkayit,deneme:integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
sayac:=0;
listbox1.MultiSelect:=true;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
sayac:=sayac+1;
b:=listbox1.Count + 1;
listbox1.Items.Add(IntToStr(b) + ' ' + edit1.Text);
edit1.Text:='';
end;
procedure TForm1.Button2Click(Sender: TObject);
var
a:integer;
kisi:string;
begin
Randomize;
a:=Random(b);
kisi:= listbox1.Items.Strings[a];
edit2.Text:=(kisi);
if combobox1.ItemIndex=0 then
begin
edit2.Visible:=true;
edit3.Visible:=false;
edit4.Visible:=false;
edit5.Visible:=false;
edit6.Visible:=false;
end;
if combobox1.ItemIndex=1 then
begin
edit2.Visible:=true;
edit3.Visible:=true;
edit4.Visible:=false;
edit5.Visible:=false;
edit6.Visible:=false;
end;
if combobox1.ItemIndex=2 then
begin
edit2.Visible:=true;
edit3.Visible:=true;
edit4.Visible:=true;
edit5.Visible:=false;
edit6.Visible:=false;
end;
if combobox1.ItemIndex=3 then
begin
edit2.Visible:=true;
edit3.Visible:=true;
edit4.Visible:=true;
edit5.Visible:=true;
edit6.Visible:=false;
end;
if combobox1.ItemIndex=4 then
begin
edit2.Visible:=true;
edit3.Visible:=true;
edit4.Visible:=true;
edit5.Visible:=true;
edit6.Visible:=true;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
savedialog1.FileName:='çekiliş';
if savedialog1.Execute then
begin
listbox1.Items.SaveToFile(savedialog1.FileName + '.txt');
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
if opendialog1.Execute then
begin
listbox1.Items.LoadFromFile(opendialog1.FileName);
end;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
listbox1.DeleteSelected;
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
listbox1.Clear;
end;
end.
listbox1.Items.Add(IntToStr(b) + ' ' + edit1.Text);
instead of directly adding to listbox,store both IntToStr(b) and edit1.Text seperate in two string list,and populate the listbox data from the stringlists.
also performing delete delete from the second stringlist the corresponding index,and repopulate in listbox
or you can just store the edit1.Text in a stringlist,and delete the string from stringlist that you delete from listbox . and populate the data in listbox with the index+string combination.....
I would use a virtual list box here. These are the basic steps:
Store the data in a container other than the GUI control, for instance a string list. This is good practise in any case.
Set the Style to lbVirtual.
Implement on OnData event handler for the list. It needs to return a string composed of the index, and the underlying item in your container.
When you delete an item, delete it from the string list container and call Invalidate on the list box to force a paint cycle. That paint cycle will request new values by calling OnData and your code can supply the updated text.
Whenever the underlying container is modified, you must let the control know how many items it is displaying by setting the Count property of the list box control.
Here is a very simple example:
Pascal unit
unit Unit1;
interface
uses
SysUtils, Classes, Controls, StdCtrls, Forms;
type
TForm1 = class(TForm)
List: TListBox;
Delete: TButton;
procedure FormCreate(Sender: TObject);
procedure ListData(Control: TWinControl; Index: Integer; var Data: string);
procedure DeleteClick(Sender: TObject);
private
FItems: TStringList;
end;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
c: Char;
begin
FItems := TStringList.Create;
for c := 'a' to 'z' do
FItems.Add(c);
List.Count := FItems.Count;
end;
procedure TForm1.ListData(Control: TWinControl; Index: Integer;
var Data: string);
begin
Data := Format('%d %s', [Index+1, FItems[Index]]);
end;
procedure TForm1.DeleteClick(Sender: TObject);
var
Index: Integer;
begin
for Index := FItems.Count-1 downto 0 do
if List.Selected[Index] then
FItems.Delete(Index);
List.Count := FItems.Count;
List.Invalidate;
end;
end.
Associated form file
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 303
ClientWidth = 307
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object List: TListBox
Left = 8
Top = 8
Width = 201
Height = 287
Style = lbVirtual
Anchors = [akLeft, akTop, akRight, akBottom]
MultiSelect = True
TabOrder = 0
OnData = ListData
end
object Delete: TButton
Left = 224
Top = 8
Width = 75
Height = 23
Anchors = [akTop, akRight]
Caption = 'Delete'
TabOrder = 1
OnClick = DeleteClick
end
end

Delphi Grid Visible Item

HI all,
I am working with Delphi 7. I am facing a problem with Grid.
My Grid having 100 rows, I am appending some more after that. For example, I am selected item is on 1oth. The grid shows 20 items on screen at a time. I scrolled the grid to downward. I reached last one. Here grid's Itemindex= 10; Please note the selected item is not showing on the visible window. When I adds the item, the grid refresh and moving to show 10th item.
I don't want to do this.
My requirement is When Adding new rows, Screen should remain same, as shown last time.
Expecting quick reply.
Thanks and Regards,
VIJESH V.NAIR
System Analyst.
Delhi, India.
Before adding an item bookmark the current row of your table that correspond to dbgrid.
Afer adding an item goto your bookmark
a sample for working with TBookmark:
(you can replace clientdataset1 with your tableName like table1)
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, DBClient, ExtCtrls, ActnList, Grids, DBGrids,
DBCtrls;
type
TfrmMain = class(TForm)
DataSource1: TDataSource;
pnlClient: TPanel;
pnlBottom: TPanel;
btnFirst: TButton;
btnLast: TButton;
btnNext: TButton;
btnPrior: TButton;
DBGrid1: TDBGrid;
ClientDataSet1: TClientDataSet;
btnSetRecNo: TButton;
DBNavigator1: TDBNavigator;
btnGetBookmark: TButton;
btnGotoBookmark: TButton;
procedure FormCreate(Sender: TObject);
procedure btnNextClick(Sender: TObject);
procedure btnLastClick(Sender: TObject);
procedure btnSetRecNoClick(Sender: TObject);
procedure btnFirstClick(Sender: TObject);
procedure btnPriorClick(Sender: TObject);
procedure btnGetBookmarkClick(Sender: TObject);
procedure btnGotoBookmarkClick(Sender: TObject);
private
{ Private declarations }
FBookmark: TBookmark;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.FormCreate(Sender: TObject);
begin
ClientDataSet1.LoadFromFile('C:\Employee.cds');
end;
procedure TfrmMain.btnFirstClick(Sender: TObject);
begin
ClientDataSet1.First;
end;
procedure TfrmMain.btnPriorClick(Sender: TObject);
begin
ClientDataSet1.Prior;
end;
procedure TfrmMain.btnNextClick(Sender: TObject);
begin
ClientDataSet1.Next;
end;
procedure TfrmMain.btnLastClick(Sender: TObject);
begin
ClientDataSet1.Last;
end;
procedure TfrmMain.btnSetRecNoClick(Sender: TObject);
var
Value: string;
begin
Value := '1';
if InputQuery('RecNo', 'Enter Record Number', Value) then
ClientDataSet1.RecNo := StrToInt(Value);
end;
procedure TfrmMain.btnGetBookmarkClick(Sender: TObject);
begin
if Assigned(FBookmark) then
ClientDataSet1.FreeBookmark(FBookmark);
FBookmark := ClientDataSet1.GetBookmark;
end;
procedure TfrmMain.btnGotoBookmarkClick(Sender: TObject);
begin
if Assigned(FBookmark) then
ClientDataSet1.GotoBookmark(FBookmark)
else
ShowMessage('No bookmark set!');
end;
end.

Resources