I noticed a strange behavior about the VCL's TMaskEdit component.
When you change the EditMask property's value at design-time, the control's Width reduces by 1 pixel.
Easy to reproduce, drop a TMaskEdit on a Form at design-time and change the EditMask value in the Object Inspector. I repeatedly changed the value to '9' and '0' until the Width went to zero.
The problem does not exist at runtime.
Is it a known problem, and is there a solution? I have a TCustomMaskEdit descendant component and I would love to get rid of this issue.
update:
after some investigation I found the problematic code here: TCustomMaskEdit.SetCursor.
This is where the "magic" happens:
for I := Low(NewKeyState) to High(NewKeyState) do
NewKeyState[I] := 0;
NewKeyState [VK_SHIFT] := $81;
NewKeyState [ArrowKey[UseRightToLeftAlignment]] := $81;
SetKeyboardState(NewKeyState);
FSettingCursor := True;
try
SendMessage(Handle, WM_KEYDOWN, ArrowKey[UseRightToLeftAlignment], 1);
SendMessage(Handle, WM_KEYUP, ArrowKey[UseRightToLeftAlignment], 1);
finally
FSettingCursor := False;
end;
As much as I understand it emulates SHIFT + LEFT, but in design-time it will be handled by the IDE, this causes the control resize.
As a workaround solution I changed my component's ancestor to TCustomMaskEdit, haven't published the EditMask property, and in the code where this property changes I save and restore the Width. Not a nice way, but unfortunately the SetCursor is not virtual, so I can't override to do nothing in design-time.
Related
I have an application which always starts initially maximized. This consists of putting Self.WindowState := wsMaximized; in the OnCreate of the main form.
Just before that, I'm assigning what should be the default dimensions of the main form, if the user were to change the window state to wsNormal.
So, in short, the main form's OnCreate handler looks something like:
procedure TfrmMain.FormCreate(Sender: TObject);
begin
Width:= 1300;
Height:= 800;
WindowState:= wsMaximized;
end;
Theoretically, I could assign these dimensions in design-time, and that does what I need. However, due to the size of my screen, and thus the IDE, the whole form is not visible at one glance without scrolling. In design, I keep the form size small, so I can see everything. But in runtime, I need to assign these default dimensions, and then maximize it by default. When the user changes the window state out of maximized, I expect it to go to those dimensions I dynamically assigned.
The issue is that it seems to lose those dimensions after maximizing the form, and it reverts back to whatever values were in design-time. If I comment out the line WindowState:= wsMaximized; then it shows the form in the desired default dimensions. However, maximizing it seems to overwrite and ignore these values I had just assigned before it.
How can I create and show my main form maximized by default, while at the same time dynamically assigning the default size, without my assigned values getting lost?
(Confirmed with 10.3.3.)
The exact origin of this problem I cannot pinpoint, but a reasonable cause would be that during the constructor the form component is being read and that previous sizes seem to be explicitly backed up:
procedure TControl.SetWidth(Value: Integer);
begin
SetBounds(FLeft, FTop, Value, FHeight);
Include(FScalingFlags, sfWidth);
if csReading in ComponentState then
FExplicitWidth := FWidth;
end;
A possible solution is to set the desired sizes in the OnCreate event, like you are doing now, but postpone setting the desired WindowsState until the OnShow event.
procedure TForm1.FormCreate(Sender: TObject);
begin
Width := 1300;
Height := 800;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
WindowState := wsMaximized;
end;
Of course, you probably should prevent consecutive calls by using a one-off mechanism.
Please take a look at wsMaximized forms do not appear maximized too.
Apparently, the VCL does not store the explicit intermediate size (in some Delphi versions anyway) but seems to merge the change with that of the maximization when the form is actually shown.
Like Sertac Akyuz quite correctly suggested, you can use SetWindowPlacement to bypass this VCL interference:
procedure TForm1.FormCreate(Sender: TObject);
var
WindowPlacement: TWindowPlacement;
begin
GetWindowPlacement(Handle, WindowPlacement);
WindowPlacement.rcNormalPosition := Bounds(Left, Top, 1300, 800);
WindowPlacement.showCmd := SW_SHOWMAXIMIZED;
SetWindowPlacement(Handle, WindowPlacement);
end;
You must set form size on FormActivate:
procedure TfrmMain.FormActivate(Sender: TObject);
begin
if Tag = 0 then
begin
// Top := 100;
// Left := 100;
Width:= 1300;
Height:= 800;
WindowState:= wsMaximized;
Tag := 1;
end;
end;
I am new to Delphi creating runtime Tgrid and want to add some rows and columns. I googled but not getting any thing. i am at level zero. what i have tried i mentioned it below.This code is showing nothing on my form.
procedure TForm1.Button1Click(Sender: TObject);
var
Grid : TGrid;
begin
Grid := TGrid.Create(Form1);
Grid.Visible := True;
Grid.Margins.Left := 10;
Grid.Margins.Right := 10;
Grid.Margins.Top := 10;
Grid.Margins.Bottom := 10;
Grid.RowCount := 5;
end;
The grid control must have a parent control. Indeed, naturally, the system must know where (on the screen) to put your control!
You probably want the grid to have the form as its parent. If so, just add Grid.Parent := Form1; after the construction of the grid.
Of course, when you add this missing line of code and get to see the grid, you'll very soon notice that your Margins assignments have no effect. That's because by default you control the position of the control (no pun intended) manually using its Top, Left, Height, and Width properties.
But should you start experimenting with the Align property, you'll discover the effect of the margins, if you also set AlignWithMargins to True. For instance, if you set Align to alClient, the control will occupy all of its parent's client area, save the margins.
When you compile blank form and you try to resize it's width with mouse, it will stop probably, when it's clientwidth is near screen resolution width.
It is not possible set wider form even in designer. (Strange enough, I would never suppose it happens). I also played with Constraints too, but it is no solution either.
Is it possible to set Form.Width to 10000 pixel?
Window size is limited by system - you can retrieve this value using function GetSystemMetrics(SM_CXMAXTRACK) - it is 1292 for my 1280x1024 display.
To allow your form be wider, you can treat message WM_GETMINMAXINFO providing desired max size:
procedure WMGETMINMAXINFO(var M: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
...
procedure TForm1.WMGETMINMAXINFO(var M: TWMGetMinMaxInfo);
begin
M.MinMaxInfo.ptMaxTrackSize.X := 5000;
M.Result := 0;
inherited;
end;
With such message handler I am able to set Width := 5000; successfully in runtime.
Normally you should be able to use Constraints property of the form and set its MaxWidth to achieve this as in this answer but WM_GETMINMAXINFO of TCustomForm is defective in Delphi 7. Calling of ConstrainedResize method from the message handler depends on some FSizeChanging boolean field, which unfortunately is never set to true. This is corrected and the field is removed somewhere in between D2007 and DXE.
Following code creates knob with labels shifted to the right:
procedure TForm1.FormShow(Sender: TObject);
begin
_chart := TChart.Create(Self);
_chart.Parent := Self;
_chart.Align := alClient;
_knob := TKnobGauge.Create(Self);
_knob.ParentChart := _chart;
_knob.RotateLabels := False;
_knob.RotationAngle := 180;
end;
The same code as DFM produces the right knob.
What could be wrong?
TeeChart Pro v2015.16.150901 32bit VCL
Delphi 10
There is a bug in TChart. When I set
_chart.Title.Text.Text := 'Some title';
labels are on their places.
When I do
_chart.Title.Text.Text := '';
or
_chart.Title.Visible := False;
they are shifted.
The reason why the same code in DFM produced the right knob is that the visual designer extends my minimal chart declaration by adding several properties automatically. Among these properties was a chart title too. It is automatically filled by "TChart" text.
Sounds as exactly what is described in the ticket #1547, initially reported here.
Please, give a try at the workaround described in the ticket:
I can only workaround by having a small title with only a blank in it.
Can you give me the names of the functions needed for this purpose? I'm using Delphi XE 5. I want to get this effect:
Window: half transparent
Font: fully visible.
I will use "System" font (zero problems with AA)
What do I look on MSDN? What functions (name) do I need to use?
This is basically the same idea as in Marcus' answer, but with some enhancements. You might have to adjust this to your needs, but the principle is the following:
Create form1 with the following properties:
AlphaBlend := True;
AlphaBlendValue := 128;
BorderStyle := bsNone;
Create form2 with the controls as desired and the following properties:
Color := clFuchsia; // or whatever color is not used
TransparentColor := true;
TransparentColorValue := Color;
Declare a Boolean field in form1 named AllowMove.
In TForm1.FormShow call the following code:
begin
form2.BorderStyle := bsNone;
form2.SetBounds(0, 0, ClientWidth, ClientHeight);
form2.Show;
AllowMove := true;
end;
Declare a Boolean field in form1 named AllowMove and a message handler for WM_MOVE:
procedure WMMOVE(var Message: TMessage); message WM_MOVE;
procedure TForm1.WMMOVE(var Message: TMessage);
begin
inherited;
if AllowMove then begin
Form2.Left := Message.LParamLo;
Form2.Top := Message.LParamHi;
end;
Message.Result := 0;
end;
The only way that I know to get that kind of effect is to render the window contents to an in-memory bitmap, then apply the desired alpha values to the non-font pixels, and then use UpdateLayeredWindow() to display the bitmap on a window. You cannot achieve that affect with a TForm as it relies on SetLayeredWindowAttributes() instead.
Create a 32bit bitmap and draw the desired background on it with alpha values, using a separate array to keep track of the current pixel values in the spots you are going to draw text on, then draw the actual text and use the array to detect which pixels were changed so you can clear the alpha values from just those pixels. Then display the bitmap.
You can get something close by layering two forms over each other. Set the bottom form's color to blue, enable AlphaBlend, and set AlphaBlend to something like 100. That just provides the blue background.
On second form, set TransparentColor to clBtnFace, and put your label there. Set the label font's quality to fqAntialiased.
Set both form's BorderStyle to bsNone.
Lay the second form over the first form, and there you go.
This might be workable if you don't plan on letting the user move the forms, or you move them together.