Multicolor Multiline TMemo - delphi

Is it possible to configure Multicolor Multiline TMemo in Delphi XE2?.
When I am writing codes like :
procedure TForm1.BitBtn1Click(Sender: TObject);
var
FirstVariable, SecondVariable, ThirdVariable :BOOL;
begin
if FirstVariable then
begin
Memo1.Font.Color := clGreen;
Memo1.Lines.Add('FirstVariable = True');
end
else if SecondVariable then
begin
Memo1.Font.Color := clBlue;
Memo1.Lines.Add('SecondVariable = True');
end
else
begin
Memo1.Font.Color := clRed;
Memo1.Lines.Add('ThirdVariable = True');
end;
end;
font color for all the previously existing lines are getting changed according to condition of the variables.

No, it is not possible. But you can use a RICHEDIT control instead, e.g., the TRichEdit wrapper.
RichEdit1.SelAttributes.Color := clGreen;
RichEdit1.Lines.Add('First line.');
RichEdit1.SelAttributes.Color := clBlue;
RichEdit1.Lines.Add('Second line.');
RichEdit1.SelAttributes.Color := clRed;
RichEdit1.Lines.Add('Third line.');

Related

Creating custom button in Delphi with different actions [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am creating a custom component, a button-switch like this :
In my "form activate" function, I wrote a for loop in which I call 3 times the button function with a different position parameter like : SwitchButton(30); where 30 is the top position.
What I want to do is assign at these 3 buttons different actions, here some code.
Code for button creation :
procedure TFMain.SwitchButton(posPulsante: Integer);
var
i: Integer;
posDescrizionePulsante: Integer;
strDescrizione: String;
begin
posDescrizionePulsante := 32;
lastPressed := 1;
Pulsante := TPanel.Create(FMain);
BordoPulsante := TShape.Create(self);
LevaPulsante := TPanel.Create(self);
DescrizionePulsante := TLabel.Create(self);
//Proprietà Descrizione
with DescrizionePulsante do
begin
Parent := PComandi;
Top := posDescrizionePulsante;
Left := 100;
Caption := 'Visualizza finestra utenti';
Font.Name := 'Tahoma';
Font.Size := 12;
Font.Style := [fsBold];
Font.Color := clWhite;
end;
//Proprietà Pulsante
with Pulsante do
begin
Parent := PComandi;
ParentColor := false;
ParentBackground := false;
BevelOuter := bvNone;
Color := clWhite;
Width := 57;
Height := 25;
Top := posPulsante;
Left := 20;
Visible := true;
end;
//Proprietà Bordo
with BordoPulsante do
begin
Parent := Pulsante;
Align := alClient;
Brush.Style := bsClear;
Brush.Color := RGB(122,136,201);
Pen.Color := clWhite;
Pen.Style := psSolid;
Pen.Width := 3;
end;
//Proprietà Leva
with LevaPulsante do
begin
Parent := Pulsante;
ParentBackground := false;
ParentColor := false;
BevelOuter := bvNone;
Color := clWhite;
Cursor := crHandPoint;
Width := 23;
Height := 13;
Top := 6;
Left := 28;
LevaPulsante.OnClick := SwitchState;
end;
end;
Code for creating Button object :
procedure TFMain.FormActivate(Sender: TObject);
var
i: Integer;
posPulsante: Integer;
begin
posPulsante := 30;
for i := 1 to 3 do
begin
SwitchButton(posPulsante);
posPulsante := posPulsante + 50;
end;
end;
Would be nice to have some : if SwitchButton 1 is clicked then do something. if SwitchButton 2 is clicked then do something else.
I think this is an acceptable use of the Tag property. You can specify some number, for example the index of the for loop, in each of the panels:
procedure TFMain.FormActivate(Sender: TObject);
var
i: Integer;
posPulsante: Integer;
begin
posPulsante := 30;
for i := 1 to 3 do
begin
SwitchButton(posPulsante, i {For example, add the tag as extra parameter});
posPulsante := posPulsante + 50;
end;
end;
And then set that tag in the button, here using the added parameter indexPulsante.
procedure TFMain.SwitchButton(posPulsante: Integer; indexPulsante: Integer);
var
i: Integer;
posDescrizionePulsante: Integer;
strDescrizione: String;
begin
...
LevaPulsante.Tag := indexPulsante;
end;
And then, in the event handler (which I think you called SwitchState), you'll have the Sender, which is the control that was clicked (the panel, in your case).
procedure TFMain.SwitchState(Sender: TObject);
begin
case (Sender as TComponent).Tag of
1: ShowMessage('You clicked the first. Do something.')
2: ShowMessage('Do something else.')
else
ShowMessage('You clicked another button than 1 or 2');
end;
end;
NB: Tag is introduced in TComponent and therefore also available in TPanel. In the code above I only typecast to TComponent, because it doesn't matter that it's a panel to get the tag, but if you want to use other properties, a more specific cast may be needed. I like to keep the cast generic, to make it easier to make changes like switching to another type than TPanel, for instance when you actually gonna make a component out of this (inherited from TCustomControl?), or use a third party component.

Simulate Align position in Delphi Custom Panel

I'm building a custom panel in Delphi XE5 and I'm having a hard time simulating a new "Gravity" property where I can combine two coordinates (like Right + Bottom) and the effect is similar to "Align" however, it does not resize the object, direction. The main problem I encountered is to simulate this behavior. My initial intention was to create a panel in memory with the same "Parent" in my custom panel and then align to the position defined in "Gravity" overwriting the "SetBounds" method. It's working, but a bit precarious, especially in "Design Time". Could someone suggest me how to more effectively simulate this alignment using VCL?
function TZPanel.GetPosition: TCustomPanel;
var
sid: TZSide;
anch: TAnchors;
panTest: TPanel;
function getGravity(al: TAlign): TRect;
var
panGravity: TPanel;
I: Integer;
begin
try
//Self.Visible := False;
panGravity:= TPanel.Create(Self);
panGravity.BevelInner := panTest.BevelInner;
panGravity.BevelOuter := panTest.BevelOuter;
panGravity.BevelWidth := panTest.BevelWidth;
panGravity.BorderWidth := panTest.BorderWidth;
panGravity.ParentBackground := True;
panGravity.SetBounds(panTest.Left, panTest.Top, panTest.Width, panTest.Height);
panGravity.Parent:= Self.Parent;
panGravity.Align := al;
Result:= panGravity.BoundsRect;
finally
panGravity.Destroy;
Self.Visible := True;
end;
end;
begin
panTest := TPanel.Create(Self);
panTest.Align := Align;
panTest.Anchors := Anchors;
panTest.BevelInner := BevelInner;
panTest.BevelOuter := BevelOuter;
panTest.BevelWidth := BevelWidth;
panTest.BorderWidth := BorderWidth;
panTest.SetBounds(Left, Top, Width, Height);
if (FGravity = []) then
begin
//
end
else
begin
panTest.Align := alCustom;
anch := [];
for sid in FGravity do
begin
case sid of
sTop:
begin
panTest.Top := getGravity(alTop).Top;
anch := anch + [akTop];
end;
sRight:
begin
panTest.Left := getGravity(alRight).Left;
anch := anch + [akRight];
end;
sBottom:
begin
panTest.Top := getGravity(alBottom).Top;
anch := anch + [akBottom];
end;
sLeft:
begin
panTest.Left := getGravity(alLeft).Left;
anch := anch + [akLeft];
end;
end;
end;
panTest.Anchors := anch;
end;
Result := panTest;
end;

Working with Checkbox in Delphi

My problem is like below, so I want all the checkboxes Bold,Italic and Underline to work out if I checked all of them.
I try searching similar problem from this site to help me but their question just to confusing..
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if Checkbox1.Checked = True then
Label1.Font.Style := [fsBold] else
Label1.Font.Style := [];
end;
procedure TForm1.CheckBox2Click(Sender: TObject);
begin
if Checkbox2.Checked = True then
Label1.Font.Style := [fsItalic] else
Label1.Font.Style := [];
end;
procedure TForm1.CheckBox3Click(Sender: TObject);
begin
if Checkbox3.Checked = True then
Label1.Font.Style := [fsUnderline] else
Label1.Font.Style := [];
end;
end;
The font style is a set of different TFontStyles, so for each checkbox you need to add the respective style to the set, if it is checked or remove it, if it is unchecked, e.g.
if Checkbox1.Checked then
Label1.Font.Style := Label1.Font.Style + [fsBold];
else
Label1.Font.Style := Label1.Font.Style - [fsBold]
PS: You should always use Boolean values directly and not compare them to True/False

Colorful text in the same line in TRichEdit

How to write text in the same line but with different color? (I use richedit).
procedure TForm1.btnEClick(sender: TObject);
begin
m0.SelAttributes.Color := clBlue;
m0.SelAttributes.Style := [fsBold];
m0.lines.add('This is blue and it is bold');
m0.SelAttributes.Color := clGreen;
m0.SelAttributes.Style := [fsBold];
m0.lines.add ('This is Green and it is bold');
m0.lines.add('');
m0.lines.add('But how to write text in the same line with different color?');
// i want to have both blue and green in the same line
end;
Best Wishes,
Bee
You're on the right track. Just change SelAttributes and use SelText instead of Lines.Add:
procedure TForm4.FormCreate(Sender: TObject);
begin
RichEdit1.Clear;
RichEdit1.SelAttributes.Color := clBlue;
RichEdit1.SelAttributes.Style := [fsBold];
RichEdit1.SelText := 'This is bold blue text.';
RichEdit1.SelAttributes.Color := clRed;
RichEdit1.SelAttributes.Style := [fsItalic];
RichEdit1.SelText := #32'This is italic red text';
end;
This produces
if you are using themes... answer above won't work..
you cannot see any colors...
till you remove seFont from styles..
RichEdit1.styleElements:=richedit1.styleElements-[seFont];
eg.
....
amsg:='Hola';
RichEdit1.SelStart := Length(RichEdit1.Lines.Text);
RichEdit1.SelAttributes.Color := acolor;
RichEdit1.Lines.Add(amsg + sLineBreak);
RichEdit1.SelLength := Length(amsg + sLineBreak);
For the last piece of text in the line, include a carriage return to finish off the line.
RichEdit1.SelAttributes.Color := clGreen;
RichEdit1.SelAttributes.Style := [];
RichEdit1.SelText := 'This is the last piece of text on the line.' + #13;

Problem with creating tpaintbox on tpanel

I have a little problem. I'm trying to create a TPaintBox on a TPanel like this:
procedure TForm1.mkPaint(S: string);
var PB: TPaintBox;
begin
PB := TPaintBox.Create(Self);
with PB do
begin
Parent := Panel1;
Visible := True;
Name := S;
Height := 100;
Width := 100;
Left := 8;
Top := 8;
// ParentColor := False;
Brush.Style := bsSolid;
Brush.Color := $00000000;
end;
Application.ProcessMessages;
end;
Now, if i change the PaintBox's Parent to Form1, i can see the brush.
But, with parent changed to Panel1, nothing happens. Any idea of how can i fix this?
Thanks in advance!
Is the TPanel visible to begin with?
Also, TPaintBox does not have a public Brush property (perhaps you are thinking of TShape?). TWinControl does, but TPaintBox is not a TWinControl descendant. It is a TGraphicControl descendant.
Yeah that was a mistake of mine. I changed the code to:
pb := TPaintBox.Create(self);
with pb do begin
Parent := Form1;
Visible := true;
Top := 1;
Left := 1;
Width := 250;
Height := 100;
ParentColor := false;
Canvas.Brush.Color := clBlack;
Canvas.Font.Size := 12;
Canvas.Font.Color := clWhite;
Canvas.FillRect(ClientRect);
Canvas.TextOut(1, 1, 'test');
end;
but without success.. i mean, if i drop a PaintBox component to the form then the code is taking effect as it should do, but dynamically creating a TPaintBox.... dunno.

Resources