i used Delphi XE7 and DevExpress component, i need to create dxTileBarItem at runtime and add this to my dxTileBar but i cant.
var
//Tile4:TdxTileControlItem;
Tile4:TdxTileBarItem;
begin
Tile4 := TdxTileBarItem.Create(dxTileBar1);
Tile4.Name := 'Tile4';
Tile4.GroupIndex := 0;
Tile4.IndexInGroup := 3;
what is my mistake?
then i want to store a form object in manually created dxTileItem and call each from on OnTileClick such as ListBox, what do i should?
You can use the CreateItem method, for example:
var
MyTile: TdxTileBarItem;
begin
MyTile := dxTileBar1.CreateItem(tbisRegular);
MyTile.Name := 'My Tile';
...
end;
Or you can follow quite common pattern used by Delphi controls, add the item to the control's Items collection, for example:
var
MyTile: TdxTileBarItem;
begin
dxTileBar1.BeginUpdate;
try
MyTile := TdxTileBarItem(dxTileBar1.Items.Add);
MyTile.Name := 'My Tile';
...
finally
dxTileBar1.EndUpdate;
end;
MyTile.MakeVisible;
end;
Related
Searching for a Delphi label component with basic format/markup support I came across Delphi Markup Label (MDLabel). As a bonus it supports links. Unfortunately I can't get it working. The component is provided as a single MD_Label.pas file. I've created a component package for it and installed it. I can now select it from the components list, but adding it to a form throws an error:
Control 'MDLabel1' has no parent window."
I traced it down to the call CreateWnd and found some topics for similar problems, but still wasn't able to solve this. Did I do something wrong or is this something that needs to be adjusted because the initial code was written for Delphi 2007 and I'm using XE?
The component is to large to post the whole source code here, but you can download it from the link above. Here's the creation part:
constructor TMDLabel.Create(AOwner: TComponent);
begin
FInitialized := False; // required for runtime creation of MDLabel
inherited;
ControlStyle := [csOpaque, csCaptureMouse, csClickEvents, csSetCaption];
FLinkFontNormal := TFont.Create;
FLinkFontNormal.Assign(Font);
FLinkFontNormal.Color := clBlue;
FLinkFontNormal.Style := [];
FLinkFontHover := TFont.Create;
FLinkFontHover.Assign(Font);
FLinkFontHover.Color := clRed;
FLinkFontHover.Style := [fsUnderline];
Width := 100;
Height := 13;
Cursor := crArrow;
TabStop := False;
DoubleBuffered := True;
FTextHeight := 0;
FAutoSizeWidth := True;
FAutoSizeHeight := True;
FTextAlignment := taLeftJustify;
FCompressSpaces := False;
FTabWidth := 8;
FParsingText := False;
FBuildingLines := False;
FRebuildLines := False;
FMaxWidth := 0;
FLinkFontNormal.OnChange := DoFontChange;
FLinkFontHover.OnChange := DoFontChange;
FOnLinkClicked := nil;
FOnPaintBackground := nil;
FOnHeightChanged := nil;
FOnWidthChanged := nil;
FLines := TList.Create;
FWords := TList.Create;
FLinkRCs := TList.Create;
FMouseDownMove := False;
FMouseWasDown := False;
FMouseDownIndex := - 1;
FInitialized := True;
end;
procedure TMDLabel.CreateWnd;
begin
inherited CreateWnd;
{$IFNDEF UNICODE}
if (inherited Caption <> '') and (FCaptionUTF8 = '') then CaptionUTF8 := inherited Caption;
{$ENDIF}
end;
Full source: http://pastebin.com/sxYvpqTy
As a side note: If you feel that there's a better component that supports formating text within labels, please feel free to share as a comment (TJvHTLabel and TJvMarkupLabel are not good).
This error is a very common one for component authors who don't understand how the VCL works internally.
The fact that the error occurs while dropping the component on the Form at design-time means that the component's constructor is doing something it should not be. One of the operations requires the component's Handle to have an allocated HWND, but that is not possible at the time of the error because the component's Parent property has not been assigned yet, or the Parent.Handle does not have an allocated HWND of its own. The Parent is not assigned until after the constructor exits.
So, you need to debug the code and find the offending constructor code that relies on the component's Handle property, and move it out of the constructor. Depending on which code it is, it either belongs in Loaded() or CreateWnd(), or even SetParent(), or it may even need to be disabled completely at design-time (sometimes run-time code should not be executed at design-time or during DFM streaming at all).
I am creating a component at runtime but i am having an issue because when I create 2 of these components, I would change the value of the properties on one of them but it seems to also change it on the other.
How can I create components at runtime so they are seperate components and not instances of eachother?
Ok so this is the code I am using to create the component.
Cell[CellCount]:= TBattery.Create(nil);
Cell[CellCount].Top := Random(500);
Cell[CellCount].Left := Random(500);
Cell[CellCount].Parent := Self;
Cell[CellCount].ID := CellCount;
CellCount := CellCount + 1;
I am using the GDI graphics to draw lines between multiple instances of TBattery. The problem I am having is; if I create two components then add a third, when I move the third one the lines get drawn to that one instead of sticking to the second component.
I uploaded my source files, I'm sure a lot of it won't make sense and my implementation may be bad but any help is appreciated! Thanks in advance
http://pastebin.com/8WUkT1rw
http://pastebin.com/BpASvc7N
They are both part of a electrical circuit simulator for my school project if that helps understanding what the code is for :s
A simple runtime component creation is...
first create a unit
second create a procedure
ex
procedure Label_Comp(Location: TWinControl; Text: String; Label_Left,Label_Top,Numofcomp: Integer; NameOwn: string; Label_Autosize,Label_FontBold,Label_Trans: Boolean);
add in var
var
MyLabel: TsLabel;
and then the procedure code
procedure Label_Comp(Location: TWinControl; Text: String;
Label_Left,Label_Top,Numofcomp: Integer; NameOwn: string;
Label_Autosize,Label_FontBold,Label_Trans: Boolean);
begin
MyLabel := TLabel.Create(main);
MyLabel.Name := 'Label' + NameOwn + IntToStr(Numofcomp);
MyLabel.Parent := Location;
MyLabel.Caption := Text;
MyLabel.Left := Label_Left;
MyLabel.Top := Label_Top;
MyLabel.Font.Name := 'Tahoma';
MyLabel.Font.Size := 8;
MyLabel.Font.Color := clWindowText;
MyLabel.AutoSize := Label_Autosize;
if Label_FontBold = True then
MyLabel.Font.Style := MyLabel.Font.Style + [fsBold];
MyLabel.Transparent := Label_Trans;
MyLabel.Visible := True;
end;
and call it from your program as you want
ex
for i := 0 to 10 do
Label_Comp(main.panelBattery,'Exit',90,24,i,'',True,True,True);
The problem here is to remember the i statement...
I hope i help...
Creating TQReport elements at run time.
Well, at least trying...
I don't know what headings or data shall appear on this report. I get a TList of TStrings representing the data rows and columns. I plant the 'Create' directives in the band print event for the group and the OnNeedData event for main data row bands.
But nothing appears. Must I make the labels at design time? Do not want.
To get you started, this works:
// uses QuickRpt, qrpBaseCtrls, QRCtrls, QRPrntr;
procedure TForm1.Button1Click(Sender: TObject);
var QR: TQuickRep;
QB: TQRBand;
QL: TQRLabel;
begin
QR := TQuickRep.Create(Self);
try
QR.PrintIfEmpty := True;
QB := TQRBand.Create(Self);
QB.Parent := QR;
QB.BandType := rbTitle;
QL := TQRLabel.Create(Self);
QL.Parent := QB;
QL.Left := 10;
QL.Top := 10;
QL.AutoSize := True;
QL.Caption := 'This works';
QR.Preview;
finally QR.Free;
end;
end;
I want to know if it is possible in delphi to populate a combobox component from object Tcollection.
somme codes:
// My product list
procedure TfoMain.InitForm;
begin
FListProduct := TListeDispoProduit.Create(TProduct);
with (FListProduct ) do
begin
with TProduct(Add) do
begin
Name := 'Product 01';
CIP := 'A001';
StockQty := 3;
end;
with TProduct(Add) do
begin
Name := 'Product 02';
CIP := 'A002';
StockQty := 5;
end;
end;
// need to fill a combobox (name's cbxListProduct)
procedure TfoMain.fFillCbxFromProductList(aProductList: FListProduct);
begin
// I don't know how to do this follow
foMain.cbxListProduct.Items.Add()
end;
thank you.
Something like this (change combobox and collection names to reflect your case):
for i := 0 to Collection.Count-1 do
myComboBox.Items.Add(TProduct(Collection.Items[i]).Name);
And by the way, you don't need that "foMain" in
foMain.cbxListProduct.Items.Add()
It's enough to write
cbxListProduct.Items.Add()
When you're inside of TfoMain's procedure, TfoMain's contents is accessible by default.
In newer Delphis you can do
for item in collection do
myComboBox.Items.Add(TProduct(item).Name)
Is it possible to, for instance, replace and free a TEdit with a subclassed component instantiated (conditionally) at runtime? If so, how and when it should be done? I've tried to set the parent to nil and to call free() in the form constructor and AfterConstruction methods but in both cases I got a runtime error.
Being more specific, I got an Access violation error (EAccessViolation). It seems François is right when he says that freeing components at frame costruction messes with Form controls housekeeping.
This more generic routine works either with a Form or Frame (updated to use a subclass for the new control):
function ReplaceControlEx(AControl: TControl; const AControlClass: TControlClass; const ANewName: string; const IsFreed : Boolean = True): TControl;
begin
if AControl = nil then
begin
Result := nil;
Exit;
end;
Result := AControlClass.Create(AControl.Owner);
CloneProperties(AControl, Result);// copy all properties to new control
// Result.Left := AControl.Left; // or copy some properties manually...
// Result.Top := AControl.Top;
Result.Name := ANewName;
Result.Parent := AControl.Parent; // needed for the InsertControl & RemoveControl magic
if IsFreed then
FreeAndNil(AControl);
end;
function ReplaceControl(AControl: TControl; const ANewName: string; const IsFreed : Boolean = True): TControl;
begin
if AControl = nil then
Result := nil
else
Result := ReplaceControlEx(AControl, TControlClass(AControl.ClassType), ANewName, IsFreed);
end;
using this routine to pass the properties to the new control
procedure CloneProperties(const Source: TControl; const Dest: TControl);
var
ms: TMemoryStream;
OldName: string;
begin
OldName := Source.Name;
Source.Name := ''; // needed to avoid Name collision
try
ms := TMemoryStream.Create;
try
ms.WriteComponent(Source);
ms.Position := 0;
ms.ReadComponent(Dest);
finally
ms.Free;
end;
finally
Source.Name := OldName;
end;
end;
use it like:
procedure TFrame1.AfterConstruction;
var
I: Integer;
NewEdit: TMyEdit;
begin
inherited;
NewEdit := ReplaceControlEx(Edit1, TMyEdit, 'Edit2') as TMyEdit;
if Assigned(NewEdit) then
begin
NewEdit.Text := 'My Brand New Edit';
NewEdit.Author := 'Myself';
end;
for I:=0 to ControlCount-1 do
begin
ShowMessage(Controls[I].Name);
end;
end;
CAUTION: If you are doing this inside the AfterConstruction of the Frame, beware that the hosting Form construction is not finished yet.
Freeing Controls there, might cause a lot of problems as you're messing up with Form controls housekeeping.
See what you get if you try to read the new Edit Caption to display in the ShowMessage...
In that case you would want to use
...ReplaceControl(Edit1, 'Edit2', False)
and then do a
...FreeAndNil(Edit1)
later.
You have to call RemoveControl of the TEdit's parent to remove the control. Use InsertControl to add the new control.
var Edit2: TEdit;
begin
Edit2 := TEdit.Create(self);
Edit2.Left := Edit1.Left;
Edit2.Top := Edit2.Top;
Edit1.Parent.Insertcontrol(Edit2);
TWinControl(Edit1.parent).RemoveControl(Edit1);
Edit1.Free;
end;
Replace TEdit.Create to the class you want to use, and copy all properties you need like I did with Left and Top.
You can actually use RTTI (look in the TypInfo unit) to clone all the matching properties. I wrote code for this a while back, but I can't find it now. I'll keep looking.