📄 delsec05.txt
字号:
scaling. Don't assume that because you're using large fonts, you
don't have to allow for text overflow - somebody else's large
fonts may be larger than yours!
* Be careful about opening a project in the IDE at different
resolutions. The form's PixelsPerInch property will be modified
as soon as the form is opened, and will be saved to the DFM if
you save the project. It's best to test the app by running it
standalone, and edit the form at only one resolution. Editing
at varying resolutions and font sizes invites component drift
and sizing problems.
* Speaking of component drift, don't rescale a form multiple times,
at design time or a runtime. Each rescaling introduces roundoff
errors which accumulate very quickly since coordinates are
strictly integral. As fractional amounts are truncated off
control's origins and sizes with each successive rescaling,
the controls will appear to creep northwest and get smaller.
If you want to allow your users to rescale the form any number
of times, start with a freshly loaded/created form before each
scaling, so that scaling errors do not accumulate.
* Don't change the PixelsPerInch property of the form, period.
* In general, it is not necessary to design forms at any particular
resolution, but it is crucial that you review their appearance at
640x480 with small fonts and large, and at a high-resolution with
small fonts and large before releasing your app. This should be
part of your regular system compatibility testing checklist.
* Pay close attention to any components that are essentially
single-line TMemos - things like TDBLookupCombo. The Windows
multi-line edit control always shows only whole lines of text -
if the control is too short for its font, a TMemo will show
nothing at all (a TEdit will show clipped text). For such
components, it's better to make them a few pixels too large than
to be one pixel too small and show not text at all.
* Keep in mind that all scaling is proportional to the difference
in the font height between runtime and design time, NOT the pixel
resolution or screen size. Remember also that the origins of your
controls will be changed when the form is scaled - you can't very
well make components bigger without also moving them over a bit.
------------------------------------------------------------------------
Q: "How can I get rid of the ReportSmith about box splash screen
when I run a report."
A: Add the following line in [RS_RunTime] section of the
RS_RUN.INI file to not have the ReportSmith about box appear
when a report is ran.
ShowAboutBox=0
------------------------------------------------------------------------
Q: "How do you make a moveable multi-split window?"
A: The following steps and code demonstrate how to make a
simple splitter window.
1) Put a memo on a form and set its Align property to alTop.
2) Place a panel on the form and set its Align property to alTop.
3) Set the panel's Height property to 6 or 7.
4) Set the panel's DragMode property to dmAutomatic.
5) Set the panel's DragCursor property to crVSplit.
6) Set the panel's Cursor property to crVSplit.
7) Add another memo on the form and set its Align property to
alClient.
8) Now select both memos and the panel, and connect them all
to this OnDragOver handler:
procedure TForm1.Memo1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := False;
if Source = Panel1 then begin
Accept := True;
Memo1.Height := Y + (Sender as TControl).Top;
end;
end;
------------------------------------------------------------------------
Q: "How can I determine the current row and column position of
the caret in a TMemo component?
A: You can use the Windows API messages EM_LINEFROMCHAR and
EM_LINEINDEX to determine the current line and offset within that
line (starting from SelStart).
var
LineNum: longint;
CharsBeforeLine: longint;
begin
LineNum := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, Memo1.SelStart,0);
CharsBeforeLine := SendMessage(Memo1.Handle, EM_LINEINDEX, LineNum, 0);
Label1.Caption := 'Line ' + IntToStr(LineNum +1)
Lebel2.Caption := 'Position ' + IntToStr((Memo1.SelStart - CharsBeforeLine) + 1);
end;
------------------------------------------------------------------------
Q: How can I get the pixels per inch of the printer?
A: If you want the value in pixels you can use the API function
GetDeviceCaps(). For example:
VertPixelsPerInch := GetDeviceCaps(Printer.Handle, LogPixelsX);
HorzPixelsPerInch := GetDeviceCaps(Printer.Handle, LogPixelsY);
------------------------------------------------------------------------
Q: "Is there a way to store an integer value along with a string
value in a TString list object or property?"
A: Yes, but it requires some type conversions. The TString
component has an Objects array along with the string array
that can be utilized for the purpose of storing integer datA:
The data type that the Objects array holds is TObject. In
essence it holds a 4 byte pointer value. So to put an integer
value in it you would need to type cast that value. For
example, the following is adding a string and an integer
value of 100 to an items property (TString object) of a
Listbox:
Listbox1.Items.AddObject('Text string', TObject(100));
To get the value out do the following:
Result := LongInt( Listbox1.Items.Objects[0] );
This assumes that Result is of type Longint and that the
value that were after is at index position 0.
Note: Though this works it is never wise to rely on the
internal workings of an object. This is trick code and
should be well commented.
If you want to keep track of more than one value then a new
class can be derived from the TObject base class to hold
these values.
type
ManyValues = class(TObject)
Value1 : Integer;
Value2 : Integer;
end;
...
------------------------------------------------------------------------
Q: Is it possible to access components by their name property (i.e.
'SpeedButton' + IntToStr(i) )
A: Yes it's possible. The following example uses the FindComponent
method of Form1 to disable the first 10 SpeedButtons by name.
for I := 1 to 10 do
with Form1.FindComponent('SpeedButton' + IntToStr(i)) as TSpeedButton do
Enabled := False;
------------------------------------------------------------------------
Q: How do you create a 'modal' form in an MDI application? When my
application calls the ShowModal method I get an error "Can't Show Modal
when Visible is set true". When I try to set Visible to False, I get
the error, can't set Visible to False on an MDI Child.
A: Normally, the first form of a project (the main form) is created with
its Visible property set to True, and all of the other forms are created
with their Visible properties set to False. An MDI child form, on the
other hand, can't be invisible, so its Visible property is set to True.
When you change its form style back to fsNormal, the Visible property
stays True, so you need to set it to False manually.
------------------------------------------------------------------------
Q: Is there a way to change the default font size for components when
they are placed on a form?
A: Just add a form with it's Font property set to your desired font to the
gallery. Since, by default, components reflect the parent's font any
components you add to your form will take on that font. In addition,
you can set your new form as the Default Main Form and Default New
Form from the gallery (Options | Gallery...).
------------------------------------------------------------------------
Q: How can I determine the directory that my program was executed
from?
A: The following function extracts the path from the ExeName
property of the global Application object.
function GetExePath : String;
var
LastBackSlashPos, Index : Integer;
begin
Result := Application.ExeName;
for Index := 1 to length(Result) do
if Result[Index] = '\' then
LastBackSlashPos := Index;
{ subtract 1 so that the last backslash is not included }
Result[0] := chr(LastBackSlashPos - 1);
end;
------------------------------------------------------------------------
Q: How can I change Font.Style back to normal after calling
Canvas.Font.Style := [fsBold]? The online help shows
([fsBold],[fsItalic] etc] but does not mention normal style.
A: You simply specify an empty set for no style at all:
Canvas.Font.Style := [];
or, you might just want to exclude the fsBold style like this:
Canvas.Font.Style := Canvas.Font.Style - [fsBold];
------------------------------------------------------------------------
Q: How can I get some actions to happen after a form is showing
normally? It seems that all the form events (OnCreate, OnPaint,
etc.) happen before the form is show.
A: You can add "Visible := True" inside OnCreate event, and then
do whatever you wish.
------------------------------------------------------------------------
Q: How much GDI resource does each built-in components use?
A: The TGraphicControl descendants like TLabel and TBevel don't use
free system resources at all. On the other hand, TWinControl descendants
like TEdit and TPanel do. Also each radio button in a TRadioGroup is a
window, i.e. has a window handle.
------------------------------------------------------------------------
Q: Why does a TTabbedNotebook use so much of the system resources
when only one page is showing at a time?
A: Even though only one page is showing at a time each pages'
components have already been created thus taking resources.
One solution to this is instead of using a notebook you use
a separate form for each page and when the user clicks on a
tab, the existing page is destroyed and the new one created.
The basic steps to set this is is as follows:
First, each child form needs its creation parameters setup
in a certain way:
...
private
{ Private declarations }
PROCEDURE CreateParams(VAR Params: TCreateParams); override;
...
procedure TForm2.CreateParams(VAR Params: TCreateParams);
begin
Inherited CreateParams(Params);
with Params do begin
WndParent := Application.MainForm.Handle;
Style := (Style OR WS_CHILD) AND NOT (WS_POPUP);
end;
end;
The child form's BorderStyle must be set to bsNone. In the
main form, create a private data field Child of type TForm.
Initialize it in the OnActivate event, NOT OnCreate. And each
time the tab is clicked to change "pages", free the existing
Child and initialize a new one of the desired type. E.g. in
OnActivate do:
Child := TForm2.Create(Self);
with Child do begin
Parent := Self;
Align := alClient;
Visible := True;
end;
When you create a child page due to a tab change, do it in the
same way just shown. Of course you'll need to use the main form
to store any data about the state of the controls in a given
child window, because the data will go bye-bye when the child
is freed.
------------------------------------------------------------------------
Q. How do you deselect one or more items in a listbox or combobox?
A. Listbox1.ItemIndex := -1;
------------------------------------------------------------------------
Q. Why is it that when I call a dialog window such as MessageBox()
from within an event handler such as OnExit that the blinking
cursor (the caret) disappears upon closing the dialog?
A. This is a Windows behavior. Forcing an additional focus change
(e.g., with ShowMessage) during an event associated with a focus
change (e.g., OnExit) will cause Windows to become confused. It is
Windows that is controlling the focus change, and it is Windows that
becomes confused when you force a focus change in the middle of that
process.
------------------------------------------------------------------------
Q. Why do I get the exception 'EInvalidOperation: Cannot make a visalbe
window modal' when I try to open a form with Showmodal? The form is
not open yet.
A. Make sure the form's Visible property is not being set to Ture at
design-time or run-time.
------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -