I have a MDI child form that when opening doesn't maximize at once.
I can see that the datagrid on it is created and then the form is maximized
I use the following constructor to create the form.
Properties:
FormStyle = fsMDIChild
Position = poDefaultPosOnly
WindowState = wsMaximized
constructor TfrmJsContacts.Create(aOwner: TComponent);
begin
WindowState := wsMaximized;
inherited Create(aOwner);
TimerDelay.Enabled := True;
end;
The problem is a visual problem so to speak - everything works as it should. It just looks wrong that the form is shown before it is maximized. What really could be nice was to have a AfterShow event to play with. I think that would help me in this situation.
MDIChild popups comes with a little animation.
If MDIChild.Position is set to
poDefaultPosOnly
poDefaultSizeOnly
poScreenCenter
poDesktopCenter
poMainFormCenter
poOwnerFormCenter
Top and Left are calculated at creating
assume Top = 300 and Left = 400 now
at on Show MDIChild are now part of MDIParent and so
Top = 300 and Left = 400 are now Inside MDIParent.
Means left top corner of MDIChild is now in the middle of MDIParent form.
with wsMaximized the animation is shown from middle right to top left.
Now use Position
poDesigned
poDefault
and with Top and Left set to 0 the animation will not longer be seen.
constructor TfrmJsContacts.Create(aOwner: TComponent);
begin
Top := 0;
Left := 0;
WindowState := wsMaximized;
inherited Create(aOwner);
....
end;
In Design mode when frmJsContacts is selected, go look at the Object Inspector.
IF Property WindowState is set to wsMaximized
You can see for a short time the whole form !
If the changes are as follows, can be seen for a short time only the title bar, not the whole form.
set, Object Inspector : Property WindowState to wsNormal.
move code WindowState := wsMaximized below inherited Create(aOwner).
code should like
constructor TfrmJsContacts.Create(aOwner: TComponent);
begin
Top := 0;
Left := 0;
inherited Create(aOwner);
WindowState := wsMaximized;
....
end;
Related
I've got a game object (InfoBox) with a..
Vertical Layout Group (Padding 20 on all sides, Control Child Size Height active)
an image
a Content Size Fitter (Vertical Fit set to Preferred Size, Horizontal Unconstrained)
Inside this InfoBox is a Text-Element and every time I update the text, I want the InfoBox to expand or collapse, but to the bottom only. Right now my InfoBox always expands or collapses to both top and bottom, but I don't want that to happen. How can I achieve that? I added some screenshots to better visualise this.
These are my settings for the InfoBox:
And these are my settings for the text:
And this is what happens when I use for example less text, the box collapses from bottom and top, but I want it to stay fixed at the top (on the same line as the green box next to it) and only collapse on the bottom:
Any help is really appreciate!
You main issues looks like you are using a ContentSizeFitter also on the parent object. So it depends how this parent object is aligned with its according parent.
This sentence sounds strange I know but what you did is basically shifting up the alignment responsibility to the parent.
=> Make your UI element aligned to the top and grow downwards.
All you need to do for this is either set
Anchors Min y -> 1
Anchors Max y -> 1
Pivot y -> 1
or simply go to the RectTransform Inspector, open the alignment tool and hold Shift + Alt and click on the top alignment:
For the second instead of using the ContentSizeFitter I prefer to have my own script that only does what it should and nothing more.
You can get the preferredHeight which is exactly the value you are looking for.
The following script simply always applies the preferred height to the text rect. Using [ExecuteAlways] this also works in edit mode. Simply attach it on the same GameObject as the UI.Text component
[ExecuteAlways]
[RequireComponent(typeof(Text))]
[RequireComponent(typeof(RectTransform))]
public class TextHeightFitter : MonoBehaviour
{
[SerializeField] private RectTransform _rectTransform;
[SerializeField] private Text _text;
private void Update()
{
if (!_text) _text = GetComponent<Text>();
if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
var desiredHeight = _text.preferredHeight;
var size = _rectTransform.sizeDelta;
size.y = desiredHeight;
_rectTransform.sizeDelta = size;
}
}
How to make infinite scrolling in both directions, up and down. I am using the InfiniteLoader and the List, both are react-virtualized components. I have a list of timestamps with initial date-time range. From there the list should be infinite in both directions. Currently, scroll-down to the bottom of the List will trigger the function _loadMoreRows(). However, I would like to trigger the _loadMoreRows() with the same functionality when scrolling in the direction up.
I have it working now :) Everything is fine. The threshold prop of the <InfiniteLoader> defines the threshold number of indices before the start/end of the List when to prefetch data, i.e. trigger _loadMoreRows().
The first and the last item in this.state.items should have their corresponding loadedRowsMap set to undefined after the initial data fetch.
const items = _getItems(); // fetch items
const rowCount = items.length;
const loadedRowsMap = [];
_.map(this.state.loadedRowsMap,(row,index)=>{
const status = (index===0 || index===rowCount-1) ? undefined : STATUS_LOADED;
loadedRowsMap.push(status)});
scrollToIndex = parseInt(rowCount/2,10);
this.setState({
items, rowCount, loadedRowsMap, scrollToIndex,
});
Before displaying the list, a scrollToIndex prop of the <List> component should be set to the middle of the list, i.e. rowCount/2. This number should satisfy the equation
0 + threshold < scrollToIndex < rowCount - 1 - threshold.
Function _isRowLoaded() will check loadedRowsMap[index]. If it is set to STATUS_LOADED or STATUS_LOADING (internal constants used inside the InfiniteLoader) it will not trigger _loadMoreRows(). If it is set to undefined, then it will trigger _loadMoreRows().
With this setup, trigering _loadMoreRows() works in both scroll directions, up and down.
I have stuck with small problem.
Imagine two things: form, that should be covered - Cover-Form; and forms that will cover Cover-Form - Tiles.
My main goal is to cover my Cover-Form with Tiles. So it will looks like the tiles. I illustrate this idea with image below
Yellow color is a Cover-Form, brown forms - Tiles. On this image you can see that forms are positioned too close each other - there is no free space between them. That's what I need.
But when I try to reach the same effect, I just get non-satisfying result. It is presented on picture below
Second image has an offset after the last tile. It is happens because of different size of form. I don't know exactly what width my Cover-Form will have. I simply divide the whole width of Cover-Form into three parts. But if Cover-Form has width, for example, 173 pixels, each of my Tiles will have width equal 173/3=57.6 pixels, that will be round to 58, but 58*3=174 and it is bad.
Code below runs situation as on second image.
type
TTileArray = Array of Array of TPoint;
// This routine comes here from David's answer below and were changed by me
procedure EvenlySpacedTiles(PixelCountH, PixelCountV, TileCount: Integer; var ArrayOut: TTileArray);
var
X: Integer;
Y: Integer;
OldH: Integer;
OldV: Integer;
OldCount: Integer;
OldCount1: Integer;
TempInt: Integer;
begin
if (PixelCountH) or (PixelCountV) or(TileCount) = 0 then
Exit;
OldH := PixelCountH;
OldCount1 := TileCount;
for X:=Low(ArrayOut) to High(ArrayOut) do
begin
OldV := PixelCountV;
OldCount := TileCount;
TempInt := OldH div OldCount1;
Dec(OldH, TempInt);
Dec(OldCount1);
for Y:=Low(ArrayOut) to High(ArrayOut) do
begin
ArrayOut[X, Y] := Point(TempInt, OldV div OldCount);
Dec(OldV, ArrayOut[X, Y].Y);
Dec(OldCount);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
F: TForm;
P: TForm;
Delta: Integer;
PrevLeft: Integer;
PrevTop: Integer;
X:Integer;
Y: Integer;
Arr: TTileArray;
IncLeft: Integer;
begin
Delta := 3;
F := TForm.Create(Application);
F.BorderStyle := Forms.bsNone;
F.SetBounds(0, 0, 173, 115);
F.Position := poDesktopCenter;
F.Color := $11DFEE;
F.Show;
SetLength(Arr, Delta, Delta);
EvenlySpacedTiles(F.Width, F.Height, Delta, Arr);
PrevLeft := F.Left;
PrevTop := F.Top;
IncLeft := 0;
for X:=Low(Arr) to High(Arr) do
begin
PrevTop := F.Top;
Inc(PrevLeft, IncLeft);
for Y:=Low(Arr) to High(Arr) do
begin
P := TForm.Create(Application);
P.FormStyle := fsStayOnTop;
P.BorderStyle := Forms.bsNone;
P.Color := Random($FFFFFF);//clSkyBlue;
P.Show;
P.Width := Arr[X, Y].X;
P.Height := Arr[X, Y].Y;
P.Left := PrevLeft;
P.Top := PrevTop;
P.Canvas.Rectangle(P.ClientRect);
Inc(PrevTop, Arr[X, Y].y);
IncLeft := Arr[X, Y].X;
end;
end;
end;
So there is my question: how can I adjust width of all tiles (3 per row) independently of cover form's width?
Thanks in advance.
Edited
P.S.
I modified some parts of code above. Now it works perfectly even with extremely small and large Cover-Form width - from 67 px. to 1237 px.
Of course there is a way to improve this code, but the main goal is achieved.
I think I will able to finish vertical Tiles placing tomorrow and publish this part there.
In many ways the comment by David gives me an idea how to do this. Thank you, David!
P.S.S.
I have read David's first comment diagonally, so I update code to work in another way, but the result still not good. You can see it on the picture below.
The first Tile has 57 px. width; the second one - 59 px.; the third Tile - only 31 px.
I just can't get how to place Tiles correctly using an algorithm suggested in David's comment.
P.S.S.S.
And again there is no result.
Right red line demonstrates a big size of the last tile. Each tile has width 58 px.
David wrote this:
173/3=58. 173-58=115. 115/2=58. 115-58=57. 57/1=57
I am able to calculate it in real life, but I am not able to implement it in the code.
Source code is updated.
P.S.S.S.S.
David's procedure doesn't do what it should do. Picture below illustrates it.
There are a gap between the first and the second Tile, and red line on the right side as on previous picture.
P.S.S.S.S.S.
Well, at this time the first part of my task is accomplished. The second one - is adding more tiles, but I don't sure if I really need them. And I am thankful for this to David Heffernan!! He spend so much time to explain me some things and I don't know how to say him more than simlply 'Thank you very much'. I am afraid, I am able just increase his reputation and accept his post as an answer. It really does the job!
On picture we can see the result I needed
P.S.S.S.S.S.S.
I have updated source code, so it can place tile and vertically too.
I would use a simple algorithm like this:
function EvenlySpacedColumns(PixelCount, ColumnCount: Integer): TArray<Integer>;
var
i: Integer;
begin
Assert(PixelCount>0);
Assert(ColumnCount>0);
SetLength(Result, ColumnCount);
for i := low(Result) to high(Result) do begin
Result[i] := PixelCount div ColumnCount;
dec(PixelCount, Result[i]);
dec(ColumnCount);
end;
end;
Here I use div which in effect uses division followed by truncation. But you could equally use Round(PixelCount / ColumnCount) if you would prefer. It's somewhat arbitrary so I personally would opt for integer arithmetic on the grounds that one should avoid floating point arithmetic if it is not necessary.
--UPDATE--
I discovered that the uitable does not register a 'second click' when t.ColumnEditable = true. When this is true, MATLAB waits until you personally deselect the cell to begin registering new clicks. Hence, that entire time it expects that new clicks are edits to the cell. Turn t.ColumnEditable to false and consecutive clicks register as new actions.
--
The CellSelectionCallback only seems to register clicks in new cells. For example, the following only displays 'src' and 'event' during the first click to any particular cell:
close all;
f = figure('Position',[50,62,1340,326],'Units','pixels'); % set figures so they're stacked
f.Name = 'Debugging table';
t = uitable(f,'Units','normalized','Position',[.05,.05,.9,.9]);
t.CellSelectionCallback = #cellSelected;
t.ColumnName = {};
t.RowName = {};
t.Data = magic(10);
t.FontSize = 10;
t.FontName = 'AppleGothic';
function [src,event] = cellSelected(src,event)
src
event
end
Can anyone provide a method that branches off of something like this that would allow the code inside 'cellSelected' to run on more than one consecutive click to a single cell in the active uitable? Thanks in advance.
--UPDATE--
I discovered that the uitable does not register a 'second click' when t.ColumnEditable = true. When this is true, MATLAB waits until you personally deselect the cell to begin registering new clicks. Hence, that entire time it expects that new clicks are edits to the cell. Turn t.ColumnEditable to false and consecutive clicks register as new actions that independently trigger the cellSelected callback function.
--
In Crystal Reports 2008, there's a "Graphic Location" image property where it can be set to a file path so when the report gets run, it uses the selected picture file instead of the one on the report. I tried setting this via the .NET API, but it's only working some of the time.
In the report itself, I've set Graphic Location to {#LogoPath}, then when I run the report via .NET API, I set {#LogoPath} to the filename of the picture. I've put the formula on the report itself, and it's indeed getting set to the correct filename, but the image on the report doesn't always update. It would consistently show up for some time, then consistently not show it again.
Here's what I ended up using, the code is in Delpi Prism. One of the awkward thing to deal with is if the image being replaced is different size to the image on the report, Crystal doesn't resize it correctly. The other problem was I needed to free the picture object manually otherwise Crystal sometimes doesn't display it on the report.
method SetShadingAndLogo(const AReport:ReportDocument);
var
LogoPath:String;
PicObj:PictureObject;
Logo:System.Drawing.Image;
PicRatio:Double;
ContWidth, ContHeight:Double;
ContainerRatio:Double;
NewDimension:Double;
PosAdj:Integer;
Scale:Double;
begin
for each Section:Section in AReport.ReportDefinition.Sections do
begin
for each RptObj:ReportObject in Section.ReportObjects do
begin
if RptObj.Name.StartsWith('LOGO', StringComparison.CurrentCultureIgnoreCase) and
(RptObj.Kind = ReportObjectKind.PictureObject) then
begin
//set to company logo
LogoPath := "C:\logo.jpg";
PicObj := RptObj as PictureObject;
if not System.IO.File.Exists(LogoPath) then
PicObj.ObjectFormat.EnableSuppress := true
else
begin
Logo := System.Drawing.Image.FromFile(LogoPath);
//work out the aspect ratios of the image and the container
PicRatio := Double(Logo.Width) / Double(Logo.Height);
//convert twips to pixels
//96 is the default dpi for Windows, but should really check Windows settings
//instead of hard coding
ContWidth := Double(TwipsToPx(PicObj.Width, 96));
ContHeight := Double(TwipsToPx(PicObj.Height, 96));
ContainerRatio := ContWidth / ContHeight;
// adjust the size of the container on the report to maintiain the original
// image's ratio
if PicRatio > ContainerRatio then
begin
// reset the vertical position to remain centred on the original location
// get the new height of the container (in pixels)
NewDimension := (ContWidth / Logo.Width) * Logo.Height;
// get the movement (in twips)
PosAdj := PxToTwips(Integer((ContHeight - NewDimension) / 2), Integer(Logo.VerticalResolution));
// adjust the position
PicObj.Top := PicObj.Top + PosAdj;
// picture is wider so adjust the height accordingly
// need to scale using the logo's dpi to resize correctly
Scale := Double(PicObj.Width) / Double(PxToTwips(Logo.Width, Integer(Logo.VerticalResolution)));
PicObj.Width := Integer(PicObj.Width * Scale);
PicObj.Height := Integer(PicObj.Height * Scale);
end
else
begin
// picture is taller and needs to be scaled to height
// reset the horizontal position to remain centred on the original location
// get the new width of the container (in pixels)
NewDimension := (ContHeight / Logo.Height) * Logo.Width;
// get the movement (in twips)
PosAdj := PxToTwips(Integer((ContWidth - NewDimension) / 2), Integer(Logo.VerticalResolution));
// adjust the position
PicObj.Left := PicObj.Left + PosAdj;
// picture is taller and needs to be scaled to height
// need to scale using the logo's dpi to resize correctly
Scale := Double(PicObj.Height) / Double(PxToTwips(Logo.Height, Integer(Logo.VerticalResolution)));
PicObj.Width := Integer(PicObj.Width * Scale);
PicObj.Height := Integer(PicObj.Height * Scale);
end;
//must free the logo, otherwise Crystal sometimes doesn't display it on report
Logo.Dispose;
for each fm:FormulaFieldDefinition in AReport.DataDefinition.FormulaFields do
begin
if fm.Name.Equals("LogoPath") then
fm.Text := """"+LogoPath+"""";
end;
end;
end;
end;
end;
end;
method TwipsToPx(const AValue, ADpi:Integer):Integer;
begin
//convert to twips using specified dpi, 96 is Windows' default dpi
Result := System.Convert.ToInt32(Double(AValue) * ADpi / 1440);
end;
method PxToTwips(const AValue, ADpi:Integer):Integer;
begin
//convert to pixels using specified dpi, 96 is Windows' default dpi
Result := System.Convert.ToInt32(Double(AValue) * 1440 / ADpi);
end;
Take a look at my Crystal Reports: Dynamic Images posting.
In Graphics Location formula, you might want to do like as follow:-
{?imageUrl}
You can set this parameter in your CS file dynamically by doing as follow:-
ParameterFields paramFields = new ParameterFields();
ParameterField paramField = new ParameterField();
ParameterDiscreteValue parameterValue = new ParameterDiscreteValue();
paramField.Name = "imageUrl";
parameterValue.Value = "**URL FOR IMAGE**";
paramField.CurrentValues.Add(parameterValue1);
paramFields.Add(paramField);
In Report, Create "imageUrl" Parameter field. By doing as follow :-
1) Go to report and open Field Explorer on your left. If its not there you can get it by going
Crystal Report >> Filed Explorer.
2) Right click on Parameter Field and click on "New"
3) Give Parameter name as "imageUrl". In "Value Option" set "Prompt With display only" and "Optional Prompt" to false.
This should work.
Let me know if it helps.