I have an application having one TEdit which is disabled when the application runs. After some calculations it will be enabled. My requirement is to set the Font.Color of this disabled TEdit as Blue instead of Grey (Disabled Font Color).
This is not supported by the standard TEdit. You could set the edit to ReadOnly instead of Disabled - this way the font color is preserved but user can't change the value of the edit. Ie to "disable" the edit
Edit1.ReadOnly := True;
Edit1.Font.Color := clBlue;
and to enable it again
Edit1.ReadOnly := False;
Edit1.Font.Color := clWindowText;
See Peter Below's two suggestions for accomplishing your objective on Torry's Delphi Pages at this link. Judging from your comment about what you Googled, his first suggestion will be simpler for you to implement. Drop a TPanel on a form and drag a TEdit onto the TPanel (i.e., TPanel is TEdit's parent. Then drop a Button on the form to simulate when your calculations are done.
procedure TForm1.btnToggleEnabledClick(Sender: TObject);
begin
if Panel1.Enabled then
begin
{Calcs are not done, so disable the TEdit}
Panel1.Enabled := false;
Edit1.Font.Color := clBlue;
Edit1.Text := 'Calcs not done';
end
else
begin
{Calcs are done, so enable the TEdit}
Panel1.Enabled := true;
Edit1.Font.Color := clWindowText;
Edit1.Text := 'Calcs all done';
end;
end;
Related
I will try to simplify my problem. If for example you drop 2 TSpeedButton and do:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
SpeedButton2.Cursor := crHandPoint; // note I'm setting other cursor than crDefault
end;
The SpeedButton2.Cursor remains showing Screen.Cursor which was set to crHourGlass.
I have looked into the TScreen.SetCursor code, and realize it sets the cursor for the entire form.
My question: is it somehow possible to use the Screen.Cursor for the entire form, BUT without impacting some control(s) which I want to set other cursor.
The same happens with a TButton. I don't mind placing the SpeedButton on a windowed control if I can somehow control it's cursor while Screen.Cursor is set to crHourGlass.
Thanks.
This is intentional behavior as explained in the documentation for TScreen.Cursor:
... When Cursor is crDefault, the individual objects determine the
cursor image. Assigning any other value sets the mouse cursor image
for all windows belonging to the application. The global mouse cursor
image remains in effect until the screen's Cursor property is changed
back to crDefault. ..
Windowed controls handle their cursors in TWinControl.WMSetCursor procedure, handler of WM_SETCURSOR message, where they explicitly set the screen cursor if it is anything other than crDefault and disregard their own cursor.
So to change the behavior you can handle the mentioned message. For a TButton interposer, an example could be:
procedure TButton.WMSetCursor(var Message: TWMSetCursor);
begin
if (Cursor <> crDefault) and (Message.HitTest = HTCLIENT) then begin
Message.Result := 1;
Windows.SetCursor(Screen.Cursors[Cursor]);
end else
inherited;
end;
Graphic controls' cursors are handled by their parent TWinControl. So to change the behavior of a speed button, you would still need to handle the same message on its parent. This would likely be impractical since the parent class might not be known beforehand.
Still, a very non-generalized implementation, for example for a graphic control placed directly on the form, might look like the below:
procedure TForm1.WMSetCursor(var Message: TWMSetCursor);
var
SmPt: TSmallPoint;
Control: TControl;
begin
DWORD(SmPt) := GetMessagePos;
Control := ControlAtPos(ScreenToClient(SmallPointToPoint(SmPt)), True);
if Assigned(Control) and Boolean(Control.Tag) then begin
Message.Result := 1;
Windows.SetCursor(Screen.Cursors[Control.Cursor])
end else
inherited;
end;
Above example would require the graphic control to have a non zero tag value. E.g.:
procedure TForm1.Button1Click(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
SpeedButton1.Cursor := crHandPoint;
SpeedButton1.Tag := 1;
end;
I have a statusbar with 3 panels. When I change the text of them in runtime, it is not changed in the first one (index 0).
I see, this is happening only if other VCL theme is chosen (f.e. Cyan Dusk).
Initial design texts are:
StatusBar.Panels[0].Text := '1';
StatusBar.Panels[1].Text := '2';
StatusBar.Panels[2].Text := '3';
And in the runtime I changed it:
StatusBar.Panels[0].Text := '11'; // this is not changed visually
StatusBar.Panels[1].Text := '22';
StatusBar.Panels[2].Text := '33';
I tried also all this code after, nothing worked:
Application.ProcessMessages;
StatusBar.Refresh;
StatusBar.Update;
Refresh;
I tried it also in the blank new application, the same issue.
When I try to debug it, in Code Inspector I see, the value has been changed also for index 0.
Also I tried this:
procedure TMainForm.StatusBarClick(Sender: TObject);
begin
ShowMessage(StatusBar.Panels[0].Text); // 11
ShowMessage(StatusBar.Panels[1].Text); // 22
ShowMessage(StatusBar.Panels[2].Text); // 33
end;
But still in the Statusbar panel index 0 is only 1.
Note: this is happening only if different VCL theme is used.
Is this bug in VCL themes? How can I evoke to update changed text?
UPDATE:
When I set StatusBar.StyleElements := StatusBar.StyleElements - [seClient]; it is working also for the first panel. But why without this it is working only for panels with index > 0?
So, it is bug in VCL themes. This solved the issue, and also updated text in the StatusBar.Panels[0]:
StatusBar.StyleElements := StatusBar.StyleElements - [seClient];
Application.ProcessMessages;
StatusBar.Panels[0].Text := '11'; // now the text is updated visually
StatusBar.Panels[1].Text := '22';
StatusBar.Panels[2].Text := '33';
Application.ProcessMessages;
StatusBar.StyleElements := StatusBar.StyleElements + [seClient];
Application.ProcessMessages;
i'm trying to dynamically show a form in a TPanel
using this function
procedure Show_form_in_panel(form: TForm; Panel: Tpanel);
begin
form.Parent := Panel;
form.Show;
form.WindowState := wsMaximized;
end;
the form is showing very normal but he's not maximized in my panel and also i want to make this form automaticly react like components that have the Alight property = (alClient)
I want to make this form automatically react like components that have the Align property set to alClient.
That's the solution. Remove
form.WindowState := wsMaximized;
and replace with
form.Align := alClient;
I try to make a new project add a TEdit and a TButton.
Set Edit1.Text to 'This is a test message'.
And add an event to the button:
procedure TForm7.Button1Click(Sender: TObject);
begin
Edit1.SelStart := 5;
Edit1.SelLength := 5;
end;
Nothing is selected when I click the button. Can someone explain why and how it should be done to select some part of the text ?
Regards
Roland
It works as expected, but since your button stealed the focus by clicking on it, you're then trying to focus that edit box back again. And by focusing an edit box, all of its text is selected by default. Here's a simple proof, that the text is selected if the edit box has focus while selecting:
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.SetFocus;
Edit1.SelStart := 5;
Edit1.SelLength := 5;
end;
Delphi implementation of the TFlowPanel control seems to lack an important feature of the C# version, the AutoScroll one.
The C# control with AutoWrap= False and AutoScroll=True behave like a horizontal scrollable list of controls.
How can i mimic the behavior of the C# version of the control ?
Thanks,
Alin
P.S.
I know i can use TScrollBox to get this behavior but TFlowPanel (in the not crippled version) allow for much more flexibility.
Create your TFlowPanel inside a TScrollBox, with the following properties:
Align : alLeft
AutoSize : TRUE
AutoWrap : FALSE
That should get you the behaviour you are after I think.
If you want to scroll vertically set
FlowPanel1.Align := alTop;
FlowPanel1.AutoSize := True;
FlowPanel1.AUtoWrap := False;
For people who are looking for a working vertical scrolling method:
procedure TfrmSample.FixVerticalScroll(const AFloatPanel: TFloatPanel);
begin
fFloatPanel.Align := alTop;
fFloatPanel.AutoSize := True;
fFloatPanel.AutoWrap := True;
fFloatPanel.OnResize := OnFlowPanelResize;
end;
procedure TfrmSample.OnFlowPanelResize(Sender: TObject);
begin
// Fix: otherwise panel is not operating on the full width
fFloatPanel.Align := alClient;
fFloatPanel.Align := alTop;
end;