Report Builder Spacing DBMemo Delphi - delphi

I am using a DBMemo (TPPDBMemo) component in reportbuilder within delphi. The Stretch property is true but the control doesn't always stretch itself out correctly within the region.
For example if there is lower case text, that dips downward, eg, chars like p,g,q... The bottom part of the text will get cut off if it's on the last line.
I tried adding an event to the onPrint to slightly grow the DBMemo when it prints,
procedure Tfrm.ppDBMemPrint(Sender: TObject);
begin
ppDBMem.Height := ppDBMem.Height + 10;
end;
But this didn't work.
Any thoughts on how this can be achieved. If I could simply add a border to the DBMemo that would be ideal, although I do not see that property anywhere.
Thank you!

Related

Get Top and Left position of an FMX Control, based on screen bounds

I'm trying to place an outside program right into an FMX TPanel using SetWindowPOS from WinAPI.
In order to do that I need the exact Top and Left values of the TPanel to pass it to SetWindowPOS. However, this value is always according to its parent, so i.e. if the Tpanel's parent is a TLayout and no margins are set, then the value of Top will be 0.
I need the Top value according to the screen.
I tried searching for that quite a bit but I can't figure it out.
Any help with that would be greatly appreciated.
After just posting the question I got the simple solution
var
pnt: TPointF;
begin
pnt := myRctngl.LocalRect.TopLeft;
pnt := myRctngl.LocalToAbsolute(pnt);
pnt := ClientToScreen(pnt);
End;
pnt should now have the value of the Point according to the screen.
You can now use pnt.x and pnt.y to get the top/left values.

Is it possible to change the inter-character spacing in a Delphi FMX TEdit control?

I am in the process of creating a custom component descended from a FMX TEdit control. One requirement is I need this control to be able to mimic/act like a combed field. This requires a max length and increased spacing between characters so the characters fall between the vertical lines. Please see image below for example.
The max length functionality is already part of the TEdit control but I am unable to find any information on how to increase the spacing between characters. I've looked into Delphi source code and have not come across anything that might be helpful. The font settings I came across were the typical font styles of bold/italic and font alignment of leading/center/trailing.
I also came across TFontStretch under TFontStyleExt but was not able to find out much more about it. Delphi's own website states "Embarcadero Technologies does not currently have any additional information." I'm not even sure this is related to what I'm looking for but I'm shooting from the hip on this one.
If anyone can point me in the right direction it would be much appreciated.
Thank you
I think that the best solution for your would be to use one of Monospaced fonts
If you can't find Monospaced ont that has desired character with to fit properly into your control you might want to use one of many font editing tools that you can find online to make necessary changes to your desired font.
And the best thing about using of Monospaced font is that you can use it in just about every FMX control that allows you to specify which font to use.
Do note that you will probably have to ship this custom font with your application and then dynamically register it at application start and unregister it at application close.
I used this to implement a serial key typing style:
procedure TForm4.Edit1Typing(Sender: TObject);
var
atext,tmp_str,d_str:unicodestring;
index:integer;
begin
if not(edit1.Text.Length>=30)then // 30 is the max length
begin
///////////////// take ' ' out (space between letters)
atext:=edit1.Text;
tmp_str:='';
if not(edit1.Text.Length=0) then
begin
for index := 1 to Length(aText) do
begin
if not(aText[index]=' ')then
begin
tmp_str:=tmp_str+aText[index];
end;
end;
end;
///////////////// now put the data back to the edit with the space
d_str:='';
if not(Length(tmp_str)=0) then
begin
for index := 1 to Length(tmp_str) do
begin
d_str:=d_str+tmp_str[index]+' ';
end;
end;
edit1.Text:=d_str;
edit1.CaretPosition:=length(d_str)-1;
end;
end;
Override your component Ontyping event handler, this code puts a 'space' between letters so they would be drawn within each rectangle.
Make sure that your font size would allow that.
This is the result.

Print fields alignment misaligned on report

I have the following PrintValue code that prints a line to the report (tbasedxreportlink). It prints two fields on one line in the header, the caption and m. The problem is that m is never aligned straight for multiple lines. It always prints all over the place.
How do I get it to align to the right or even print decimal aligned.
Printed Data
Caption One 4,685.33
Caption 2 4.99
Caption three 74,586.88
Caption 4 58.66
Code
procedure PrintValue(Caption, Value: string);
var
m: string;
s: string;
begin
m := FormatFloat(',0.00 ;(,0.00);0.00 ', StrToFloat(Value));
s := Format('%-24s %15s', [Caption, m]);
AReportLink.PrinterPage.PageHeader.LeftTitle.Add(s);
end;
The font used on the report is Segoe UI if it matters.
Thanks
The simplest way is using monospace (fixed-width) font, for example, Courier New or Lucida Console
I found no easy way to format the strings to get the desired effect. The main reason for that is the simplicity of using the LeftTitle, CenterTitle or RightTitle 'boxes' - they only allow simple string text to be inserted. Nothing fancy allowed not to mention the True Type Font issue.
In order to solve the problem I added a tPanel to the screen and dropped the all screen fields I needed to show up on the grid print to it. I added a tdxCustomContainerReportLink to link to that panel. I then used a tdxCompositionReportLink to print both the grid and the tdxCustomContainerReportLink (panel) as individual items when the print button was pressed by overwriting the current link code:
procedure TFrmViewAcct.dxBarBtnPrintClick(Sender: TObject);
begin
dxCmpntPrtrDetail.CurrentLink := dxCmpntPrtrDetailLink2;
inherited;
end;
Thus it prints the grid info then prints what ever is on the panel. Problem solved and you can see how this solution can be flexible.
Yes I could have easily changed to a True Type font but that is an ugly workaround as far as I am concerned especially where standardized fonts need to be observed.

Shifting the erroneous horizontal position of SubItemImages in a Delphi TListView?

In a Delphi TListView, is it possible to shift the erroneous horizontal position of SubItemImages, as they are drawn too far left? Something like this, for example (pseudo-code, which just shows the intention):
x := MyListView.Items[i].SubItemImages[2].HorizontalPosition;
MyListView.Items[i].SubItemImages[2].HorizontalPosition := x + 2;
This screenshot which shows the bug:
No. TListItem.SubItemImages is an integer, and integers don't have horizontal positions.
property SubItemImages[Index: Integer]: Integer read GetSubItemImage
write SetSubItemImage;
You can find this out by looking at the VCL source code, in this case in the ComCtrls unit. The relevant code is in TListItem.GetSubItemImage (code from XE3 shown below, but it's the same as the code in previous versions of Delphi).
function TListItem.GetSubItemImage(Index: Integer): Integer;
begin
Result := TSubItems(FSubItems).ImageIndex[Index];
end;
As far as I can see from the MSDN documentation, there's no way to change that image's location. The columns are created by sending the underlying Windows ListView control an LVCOLUMN record (structure) for each column's definition, which has no location information available to assign. It has a flag to set the image right-aligned (LVCFMT_BITMAP_ON_RIGHT), but nothing else to allow you to actually position the image to a specific location in the column.

How to find the real size ("logical area") of a TScrollBox

I need to find the entire size (also called "logical area") of a TScrollBox - as opposite to visible area that you get via Width and Height property (or ClientWidth ClientHeight).
I want to create some controls inside that TScrollBox. One of them (called TViewer) needs to be as high as the TScrollBox itself. The thing is that during creation, the TScrollBox is scrolled down to show last created control. So, using Top=1 will not work because my control will have top=1 which is not the top of the logical area.
Delphi 7
Drop a component, like a TLabel, on the TScrollBox.
Set the component's Left and Top properties to 0.
Set the component's Visible property to False.
Now you always have the origin. The "logical height" is now:
myScrollBox.Height + (myOriginControl.Top * -1);
Maybe ScrollBox.HorzScrollBar.Range and ScrollBox.VertScrollBar.Range + the corresponding .Positions are what you need.
Look at Scrollbars:
ScrollBox1.VertScrollBar.Range
ScrollBox1.HorzScrollBar.Range
It can be less than height and width if the scrollbox logical area is not bigger than phisical area (scrollbars not visible in that case)
Or use this to get the max of both:
var
AHeight, AWidth: Integer;
begin
AHeight := Max(ScrollBox1.VertScrollBar.Range, ScrollBox1.Height);
AWidth := Max(ScrollBox1.HorzScrollBar.Range, ScrollBox1.Width);
ShowMessageFmt('%d,%d', [AHeight, AWidth]);
end;
Edit
From #Altar comments, I can add the logical height and/or width is not the problem. If you want to add any control which occupies all the height of the scrollbar, use the AHeight from the above calculation, but set the Top to the negative of VertScrollBar.Position, something like this:
procedure TForm2.Button3Click(Sender: TObject);
var
AHeight, AWidth: Integer;
Btn: TButton;
begin
AHeight := Max(ScrollBox1.VertScrollBar.Range, Height);
AWidth := Max(ScrollBox1.HorzScrollBar.Range, Width);
Btn := TButton.Create(Self);
Btn.Parent := ScrollBox1;
Btn.Left := 15;
Btn.Top := -ScrollBox1.VertScrollBar.Position;
Btn.Height := AHeight;
end;
Im not sure i understand exactly what you want to do, but to get the complete area defined as "scrollable" you would have to write ScrollBox.HorScrollBar.Range + ScrollBox.Clientwidth (and the same thing for the vertical section). The scrollbox always deducts the visible "page" size from the total. So if you define a height of 1000 pixels, with 100 pixels showing - it will have a scrolling range of 900. You have to add the clientheight to get the rest.
Also, to get the correct "top" position you will have to read Canvas.Cliprect.Top, since a scrolling window does not change the top position of sub-controls. Windows handles this for you and only tells you what to re-draw once the scrollbars are initialized.
Since you want to create a control that is just as high as the complete scrollable area, i presume you are creating an editor of sorts?
If so you would probably get better results taking a look at SynEdit and extract the base-class that adds scrollbars to a normal TCustomControl (it's quite easy). That way you can control both the painting and the layout of your controls.
Here is one I wrote for Lazarus and FreePascal a while back. If you add messages to the uses clause and prefix the message handlers with WM rather than TLM it will compile under Delphi.
(code to long, had to use external link): http://delphimax.wordpress.com/2010/09/20/platform-independent-image-component-for-lazarus/
I have tried to do that, and believe me, I was not able to.
If you have the instances of the controls that are inside TScrollBox, you can use them to calculate (not precisely) the area.
Here is a complicated (but complete) solution:
I create my first child control during TScrollBox.Create (when TScrollBox does not have yet a scrollbar)
Set Child.Top:= 1
Create the rest of the child controls (this may force the TScrollBox to show the scrollbar)
Scroll the TScrollBox up
Use one of the above solutions to calculate the height of the TScrollBox

Resources