tamaño - como cambiar la fuente de windows 10 2018
¿Cómo hago para que mi GUI se comporte bien cuando la escala de la fuente de Windows es mayor al 100%? (4)
Al elegir tamaños de letra grandes en el panel de control de Windows (como 125%, o 150%), entonces hay problemas en una aplicación VCL, cada vez que algo se ha configurado en píxeles.
Tome el TStatusBar.Panel
. He configurado su ancho para que contenga exactamente una etiqueta, ahora con letras grandes, la etiqueta "se desborda". Mismo problema con otros componentes.
Algunas computadoras portátiles nuevas de Dell ya vienen con un 125% como configuración predeterminada, por lo que, si bien en el pasado este problema era bastante raro, ahora es realmente importante.
¿Qué se puede hacer para superar este problema?
Aquí está mi regalo. Una función que puede ayudarlo con el posicionamiento horizontal de los elementos en sus diseños de GUI. Gratuita para todos.
function CenterInParent(Place,NumberOfPlaces,ObjectWidth,ParentWidth,CropPercent: Integer): Integer;
{returns formated centered position of an object relative to parent.
Place - P order number of an object beeing centered
NumberOfPlaces - NOP total number of places available for object beeing centered
ObjectWidth - OW width of an object beeing centered
ParentWidth - PW width of an parent
CropPercent - CP percentage of safe margin on both sides which we want to omit from calculation
+-----------------------------------------------------+
| |
| +--------+ +---+ +--------+ |
| | | | | | | |
| +--------+ +---+ +--------+ |
| | | | | |
+-----------------------------------------------------+
| |<---------------------A----------------->| |
|<-C->|<------B----->|<-----B----->|<-----B---->|<-C->|
| |<-D>|
|<----------E------------>|
A = PW-C B = A/NOP C=(CP*PW)/100 D = (B-OW)/2
E = C+(P-1)*B+D }
var
A, B, C, D: Integer;
begin
C := Trunc((CropPercent*ParentWidth)/100);
A := ParentWidth - C;
B := Trunc(A/NumberOfPlaces);
D := Trunc((B-ObjectWidth)/2);
Result := C+(Place-1)*B+D;
end;
Nota: Por favor, vea las otras respuestas, ya que contienen técnicas muy valiosas. Mi respuesta aquí solo proporciona advertencias y precauciones en contra de asumir DPI-awareness es fácil.
Por lo general, evito el escalado con TForm.Scaled = True
DPI con TForm.Scaled = True
. La conciencia DPI es solo importante para mí cuando se vuelve importante para los clientes que me llaman y están dispuestos a pagar por ello. La razón técnica detrás de ese punto de vista es que, con conocimiento de DPI o no, está abriendo una ventana a un mundo de dolor. Muchos controles de VCL estándar y de terceros no funcionan bien en DPI alto. La notable excepción es que las partes de VCL que envuelven los Controles Comunes de Windows funcionan extraordinariamente bien con DPI alto. Una gran cantidad de controles personalizados Delphi VCL de terceros y integrados no funcionan bien, o en absoluto, a un alto nivel de DPI. Si planea activar TForm.Scaled, asegúrese de realizar una prueba a 96, 125 y 150 ppp para cada formulario en su proyecto y para cada tercero y control integrado que utilice.
Delphi en sí está escrito en Delphi. Tiene activada la bandera de reconocimiento Alto DPI, para la mayoría de los formularios, aunque incluso tan recientemente como en Delphi XE2, los propios autores IDE decidieron NO activar ese indicador de manifiesto de Alto DPI. Tenga en cuenta que en Delphi XE4 y posterior, la bandera de conciencia de HIGH DPI está activada, y el IDE se ve bien.
Sugiero que no uses TForm.Scaled = true (que es un valor predeterminado en Delphi, a menos que lo hayas modificado, la mayoría de tus formularios tengan Scaled = true) con las banderas de High DPI Aware (como se muestra en las respuestas de David) con Las aplicaciones VCL que se crean utilizando el diseñador de formularios delphi incorporado.
He intentado en el pasado hacer una muestra mínima del tipo de rotura que puedes esperar cuando TForm.Scaled es verdadero, y cuando Delphi forma escalado tiene una falla. Estos fallos técnicos no siempre se desencadenan solo por un valor de DPI distinto de 96. No he podido determinar una lista completa de otras cosas, que incluye cambios en el tamaño de fuente de Windows XP. Pero dado que la mayoría de estos fallos técnicos solo aparecen en mis propias aplicaciones, en situaciones bastante complejas, he decidido mostrarles algunas pruebas de que pueden verificarse.
Delphi XE tiene este aspecto cuando configuras DPI Scaling en "Fonts @ 200%" en Windows 7, y Delphi XE2 también se rompe en Windows 7 y 8, pero estas fallas técnicas parecen estar solucionadas a partir de Delphi XE4:
Estos son en su mayoría controles de VCL estándar que se comportan mal a un nivel alto de DPI. Tenga en cuenta que la mayoría de las cosas no han sido escaladas en absoluto, por lo que los desarrolladores de Delphi IDE han decidido ignorar el conocimiento de DPI, así como también desactivar la virtualización de DPI. Una elección tan interesante.
Desactive la virtualización DPI solo si desea esta nueva fuente adicional de dolor y opciones difíciles. Te sugiero que lo dejes en paz. Tenga en cuenta que los controles comunes de Windows parecen funcionar bien. Tenga en cuenta que el control Delphi data-explorer es un contenedor C # WinForms alrededor de un control común estándar de Windows Tree. Esa es una falla pura de microsoft, y corregirlo podría requerir que Embarcadero reescriba un control de árbol nativo .Net para su explorador de datos, o escribir algún código DPI-check-and-modify-properties para cambiar las alturas de los elementos en el control. Ni siquiera microsoft WinForms puede manejar DPI alta de manera limpia, automática y sin código de kludge personalizado.
Actualización: Factoid interesante: si bien el delphi IDE parece no estar "virtualizado", no está utilizando el contenido de manifiesto que muestra David para lograr "virtualización sin DPI". Tal vez esté usando alguna función API en tiempo de ejecución.
Actualización 2: en respuesta a cómo apoyaría 100% / 125% DPI, se me ocurriría un plan de dos fases. La fase 1 es inventariar mi código para controles personalizados que deben ser reparados para DPI alto, y luego hacer un plan para solucionarlos o eliminarlos gradualmente. La fase 2 consistiría en tomar algunas áreas de mi código que están diseñadas como formularios sin gestión de diseño y cambiarlas a formularios que utilizan algún tipo de gestión de diseño para que los DPI o los cambios de altura de fuente puedan funcionar sin recorte. Sospecho que este trabajo de diseño "intercontroles" sería mucho más complejo en la mayoría de las aplicaciones que el trabajo "intracontrolar".
Actualización: en 2016, la última Delphi 10.1 Berlin está funcionando bien en mi estación de trabajo de 150 ppp.
Su configuración en el archivo .dfm se ampliará correctamente, siempre que Scaled
sea True
.
Si está configurando dimensiones en el código, entonces necesita escalarlas por Screen.PixelsPerInch
dividido por Form.PixelsPerInch
. Usa MulDiv
para hacer esto.
function TMyForm.ScaleDimension(const X: Integer): Integer;
begin
Result := MulDiv(X, Screen.PixelsPerInch, PixelsPerInch);
end;
Esto es lo que hace el marco de persistencia de formularios cuando Scaled
es True
.
De hecho, puede hacer un argumento convincente para reemplazar esta función con una versión que codifica con un valor de 96 para el denominador. Esto le permite usar valores de dimensión absoluta y no preocuparse por el cambio de significado si cambia la escala de fuente en su máquina de desarrollo y vuelve a guardar el archivo .dfm. El motivo que importa es que la propiedad PixelsPerInch
almacenada en el archivo .dfm es el valor de la máquina en la que se guardó por última vez el archivo .dfm.
const
SmallFontsPixelsPerInch = 96;
function ScaleFromSmallFontsDimension(const X: Integer): Integer;
begin
Result := MulDiv(X, Screen.PixelsPerInch, SmallFontsPixelsPerInch);
end;
Entonces, continuando con el tema, otra cosa de la que hay que desconfiar es que si su proyecto se desarrolla en varias máquinas con diferentes valores de DPI, encontrará que la escala que utiliza Delphi al guardar archivos .dfm genera controles que deambulan por una serie de ediciones . En mi lugar de trabajo, para evitar esto, tenemos una política estricta de que los formularios solo se editan a 96dpi (escala del 100%).
De hecho, mi versión de ScaleFromSmallFontsDimension
también permite la posibilidad de que la fuente del formulario difiera en tiempo de ejecución de ese conjunto en designtime. En las máquinas XP, los formularios de mi aplicación usan 8pt Tahoma. En Vista y hasta 9pt se usa Segoe UI. Esto proporciona otro grado de libertad. La escala debe tener esto en cuenta porque se supone que los valores de dimensión absoluta utilizados en el código fuente son relativos a la línea base de 8pt Tahoma a 96 ppp.
Si usa imágenes o glifos en su UI, estos también necesitan escalar. Un ejemplo común sería los glifos que se usan en barras de herramientas y menús. Deberá proporcionar estos glifos como recursos de iconos vinculados a su ejecutable. Cada icono debe contener un rango de tamaños y luego, en tiempo de ejecución, debe elegir el tamaño más apropiado y cargarlo en una lista de imágenes. Algunos detalles sobre ese tema se pueden encontrar aquí: ¿Cómo cargo iconos de un recurso sin sufrir alias?
Otro truco útil es definir las dimensiones en unidades relativas, relativas a TextWidth
o TextHeight
. Por lo tanto, si desea que algo tenga alrededor de 10 líneas verticales de tamaño, puede usar 10*Canvas.TextHeight(''Ag'')
. Esta es una métrica muy aproximada y lista porque no permite el espaciado entre líneas, etc. Sin embargo, a menudo todo lo que necesita hacer es organizar que la GUI se PixelsPerInch
correctamente con PixelsPerInch
.
También debe marcar su aplicación como de alto DPI consciente . La mejor forma de hacerlo es a través del manifiesto de la aplicación. Dado que las herramientas de compilación de Delphi no te permiten personalizar el manifiesto que usas, esto te obliga a vincular tu propio recurso de manifiesto.
<?xml version=''1.0'' encoding=''UTF-8'' standalone=''yes''?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
El script de recursos se ve así:
1 24 "Manifest.txt"
donde Manifest.txt
contiene el manifiesto real. También necesitaría incluir la sección comctl32 v6 y establecer requestedExecutionLevel
en asInvoker
. A continuación, vincula este recurso compilado a su aplicación y se asegura de que Delphi no intente hacer lo mismo con su manifiesto. En Delphi moderno lo logra estableciendo la opción del proyecto Temas de tiempo de ejecución en Ninguno.
El manifiesto es la forma correcta de declarar que tu aplicación tiene un alto reconocimiento de DPI. Si solo quiere probarlo rápidamente sin interferir con su manifiesto, llame a SetProcessDPIAware
. Hazlo como lo primero que haces cuando se ejecuta tu aplicación. Preferiblemente en una de las primeras secciones de inicialización de la unidad, o como la primera cosa en su archivo .dpr.
Si no declaras que tu aplicación tiene un alto reconocimiento de DPI, entonces Vista y arriba lo renderizarán en un modo heredado para cualquier escala de fuente superior al 125%. Esto se ve bastante terrible. Intenta evitar caer en esa trampa.
Windows 8.1 por actualización de monitor de DPI
A partir de Windows 8.1, ahora existe compatibilidad con el sistema operativo para la configuración de DPI por monitor ( http://msdn.microsoft.com/en-ca/magazine/dn574798.aspx ). Este es un gran problema para los dispositivos modernos que pueden tener pantallas diferentes conectadas con capacidades muy diferentes. Es posible que tenga una pantalla de portátil DPI muy alta y un proyector externo de PPP bajo. Apoyar tal escenario requiere aún más trabajo que el descrito anteriormente.
También es importante tener en cuenta que respetar el DPI del usuario es solo un subconjunto de su trabajo real:
honrando el tamaño de fuente del usuario
Durante décadas, Windows ha resuelto este problema con la idea de realizar diseño utilizando unidades de diálogo , en lugar de píxeles. Se define una "unidad de diálogo" para que el carácter promedio de la fuente sea
- 4 unidades de diálogo (dlus) de ancho, y
- 8 unidades de diálogo (clus) alto
Delphi se envía con una noción (con errores) de Scaled
, donde una forma intenta ajustar automáticamente en función de la
- Configuración de Windows DPI del usuario, versos
- la configuración de DPI en la máquina del desarrollador que guardó por última vez el formulario
Eso no resuelve el problema cuando el usuario usa una fuente diferente a la que diseñó el formulario, por ejemplo:
- el desarrollador diseñó el formulario con MS Sans Serif 8pt (donde el carácter promedio es
6.21px x 13.00px
, a 96dpi) usuario corriendo con Tahoma 8pt (donde el personaje promedio es
5.94px x 13.00px
, a 96dpi)Como fue el caso con cualquier persona que desarrolla una aplicación para Windows 2000 o Windows XP.
o
- el desarrollador diseñó el formulario con ** Tahoma 8pt * (donde el personaje promedio es
5.94px x 13.00px
, a 96dpi) - un usuario corriendo con Segoe UI 9pt (donde el personaje promedio es
6.67px x 15px
, a 96dpi)
Como buen desarrollador, respetará las preferencias de fuente de su usuario. Esto significa que también necesita escalar todos los controles en su formulario para que coincida con el nuevo tamaño de fuente:
- expanda todo horizontalmente en 12.29% (6.67 / 5.94)
- estirar todo verticalmente en 15.38% (15/13)
Scaled
no manejará esto por ti.
Empeora cuando:
- diseñó su formulario en Segoe UI 9pt (Windows Vista, Windows 7, Windows 8 por defecto)
- el usuario está ejecutando Segoe UI 14pt , (por ejemplo, mi preferencia) que es
10.52px x 25px
Ahora tienes que escalar todo
- horizontalmente por 57.72%
- verticalmente por 66.66%
Scaled
no manejará esto por ti.
Si eres inteligente, puedes ver cómo honrar DPI es irrelavent:
- formulario diseñado con Segoe UI 9pt @ 96dpi (6.67px x 15px)
- usuario corriendo con Segoe UI 9pt @ 150dpi (10.52px x 25px)
No debería mirar la configuración de PPP del usuario, debería ver su tamaño de fuente . Dos usuarios corriendo
- IU de Segoe 14pt a 96dpi (10.52px x 25px)
- Segoe UI 9pt @ 150dpi (10.52px x 25px)
están ejecutando la misma fuente . DPI es solo una cosa que afecta el tamaño de fuente; las preferencias del usuario son la otra.
StandardizeFormFont
Clovis notó que hago referencia a una función StandardizeFormFont
que corrige la fuente en un formulario, y lo escala al nuevo tamaño de fuente. No es una función estándar, sino un conjunto completo de funciones que logran la tarea simple que Borland nunca manejó.
function StandardizeFormFont(AForm: TForm): Real;
var
preferredFontName: string;
preferredFontHeight: Integer;
begin
GetUserFontPreference({out}preferredFontName, {out}preferredFontHeight);
//e.g. "Segoe UI",
Result := Toolkit.StandardizeFormFont(AForm, PreferredFontName, PreferredFontHeight);
end;
Windows tiene 6 fuentes diferentes; no hay una sola "configuración de fuente" en Windows.
Pero sabemos por experiencia que nuestros formularios deben seguir la configuración de Fuente de título de icono
procedure GetUserFontPreference(out FaceName: string; out PixelHeight: Integer);
var
font: TFont;
begin
font := Toolkit.GetIconTitleFont;
try
FaceName := font.Name; //e.g. "Segoe UI"
//Dogfood testing: use a larger font than we''re used to; to force us to actually test it
if IsDebuggerPresent then
font.Size := font.Size+1;
PixelHeight := font.Height; //e.g. -16
finally
font.Free;
end;
end;
Una vez que conozcamos el tamaño de la fuente, escalaremos el formulario, obtenemos la altura de la fuente actual del formulario ( en píxeles ) y aumentamos ese factor.
Por ejemplo, si estoy configurando el formulario en -16
, y el formulario está actualmente en -11
, entonces tenemos que escalar el formulario completo de la siguiente manera:
-16 / -11 = 1.45454%
La estandarización ocurre en dos fases. Primero escale la forma por la proporción de los tamaños de fuente nuevos: antiguos. Entonces cambie los controles (recursivamente) para usar la nueva fuente.
function StandardizeFormFont(AForm: TForm; FontName: string; FontHeight: Integer): Real;
var
oldHeight: Integer;
begin
Assert(Assigned(AForm));
if (AForm.Scaled) then
begin
OutputDebugString(PChar(''WARNING: StandardizeFormFont: Form "''+GetControlName(AForm)+''" is set to Scaled. Proper form scaling requires VCL scaling to be disabled, unless you implement scaling by overriding the protected ChangeScale() method of the form.''));
end;
if (AForm.AutoScroll) then
begin
if AForm.WindowState = wsNormal then
begin
OutputDebugString(PChar(''WARNING: StandardizeFormFont: Form "''+GetControlName(AForm)+''" is set to AutoScroll. Form designed size will be suseptable to changes in Windows form caption height (e.g. 2000 vs XP).''));
if IsDebuggerPresent then
Windows.DebugBreak; //Some forms would like it (to fix maximizing problem)
end;
end;
if (not AForm.ShowHint) then
begin
AForm.ShowHint := True;
OutputDebugString(PChar(''INFORMATION: StandardizeFormFont: Turning on form "''+GetControlName(AForm)+''" hints. (ShowHint := True)''));
if IsDebuggerPresent then
Windows.DebugBreak; //Some forms would like it (to fix maximizing problem)
end;
oldHeight := AForm.Font.Height;
//Scale the form to the new font size
// if (FontHeight <> oldHeight) then For compatibility, it''s safer to trigger a call to ChangeScale, since a lot of people will be assuming it always is called
begin
ScaleForm(AForm, FontHeight, oldHeight);
end;
//Now change all controls to actually use the new font
Toolkit.StandardizeFont_ControlCore(AForm, g_ForceClearType, FontName, FontHeight,
AForm.Font.Name, AForm.Font.Size);
//Return the scaling ratio, so any hard-coded values can be multiplied
Result := FontHeight / oldHeight;
end;
Este es el trabajo de escalar realmente un formulario. Funciona alrededor de errores en el propio método Form.ScaleBy
Borland. Primero tiene que deshabilitar todos los anclajes en el formulario, luego realizar la escala y luego volver a habilitar los anclajes:
TAnchorsArray = array of TAnchors;
procedure ScaleForm(const AForm: TForm; const M, D: Integer);
var
aAnchorStorage: TAnchorsArray;
RectBefore, RectAfter: TRect;
x, y: Integer;
monitorInfo: TMonitorInfo;
workArea: TRect;
begin
if (M = 0) and (D = 0) then
Exit;
RectBefore := AForm.BoundsRect;
SetLength(aAnchorStorage, 0);
aAnchorStorage := DisableAnchors(AForm);
try
AForm.ScaleBy(M, D);
finally
EnableAnchors(AForm, aAnchorStorage);
end;
RectAfter := AForm.BoundsRect;
case AForm.Position of
poScreenCenter, poDesktopCenter, poMainFormCenter, poOwnerFormCenter,
poDesigned: //i think i really want everything else to also follow the nudging rules...why did i exclude poDesigned
begin
//This was only nudging by one quarter the difference, rather than one half the difference
// x := RectAfter.Left - ((RectAfter.Right-RectBefore.Right) div 2);
// y := RectAfter.Top - ((RectAfter.Bottom-RectBefore.Bottom) div 2);
x := RectAfter.Left - ((RectAfter.Right-RectAfter.Left) - (RectBefore.Right-RectBefore.Left)) div 2;
y := RectAfter.Top - ((RectAfter.Bottom-RectAfter.Top)-(RectBefore.Bottom-RectBefore.Top)) div 2;
end;
else
//poDesigned, poDefault, poDefaultPosOnly, poDefaultSizeOnly:
x := RectAfter.Left;
y := RectAfter.Top;
end;
if AForm.Monitor <> nil then
begin
monitorInfo.cbSize := SizeOf(monitorInfo);
if GetMonitorInfo(AForm.Monitor.Handle, @monitorInfo) then
workArea := monitorInfo.rcWork
else
begin
OutputDebugString(PChar(SysErrorMessage(GetLastError)));
workArea := Rect(AForm.Monitor.Left, AForm.Monitor.Top, AForm.Monitor.Left+AForm.Monitor.Width, AForm.Monitor.Top+AForm.Monitor.Height);
end;
// If the form is off the right or bottom of the screen then we need to pull it back
if RectAfter.Right > workArea.Right then
x := workArea.Right - (RectAfter.Right-RectAfter.Left); //rightEdge - widthOfForm
if RectAfter.Bottom > workArea.Bottom then
y := workArea.Bottom - (RectAfter.Bottom-RectAfter.Top); //bottomEdge - heightOfForm
x := Max(x, workArea.Left); //don''t go beyond left edge
y := Max(y, workArea.Top); //don''t go above top edge
end
else
begin
x := Max(x, 0); //don''t go beyond left edge
y := Max(y, 0); //don''t go above top edge
end;
AForm.SetBounds(x, y,
RectAfter.Right-RectAfter.Left, //Width
RectAfter.Bottom-RectAfter.Top); //Height
end;
y luego tenemos que recursivamente usar la nueva fuente:
procedure StandardizeFont_ControlCore(AControl: TControl; ForceClearType: Boolean;
FontName: string; FontSize: Integer;
ForceFontIfName: string; ForceFontIfSize: Integer);
const
CLEARTYPE_QUALITY = 5;
var
i: Integer;
RunComponent: TComponent;
AControlFont: TFont;
begin
if not Assigned(AControl) then
Exit;
if (AControl is TStatusBar) then
begin
TStatusBar(AControl).UseSystemFont := False; //force...
TStatusBar(AControl).UseSystemFont := True; //...it
end
else
begin
AControlFont := Toolkit.GetControlFont(AControl);
if not Assigned(AControlFont) then
Exit;
StandardizeFont_ControlFontCore(AControlFont, ForceClearType,
FontName, FontSize,
ForceFontIfName, ForceFontIfSize);
end;
{ If a panel has a toolbar on it, the toolbar won''t paint properly. So this idea won''t work.
if (not Toolkit.IsRemoteSession) and (AControl is TWinControl) and (not (AControl is TToolBar)) then
TWinControl(AControl).DoubleBuffered := True;
}
//Iterate children
for i := 0 to AControl.ComponentCount-1 do
begin
RunComponent := AControl.Components[i];
if RunComponent is TControl then
StandardizeFont_ControlCore(
TControl(RunComponent), ForceClearType,
FontName, FontSize,
ForceFontIfName, ForceFontIfSize);
end;
end;
Con los anclajes siendo deshabilitados recursivamente:
function DisableAnchors(ParentControl: TWinControl): TAnchorsArray;
var
StartingIndex: Integer;
begin
StartingIndex := 0;
DisableAnchors_Core(ParentControl, Result, StartingIndex);
end;
procedure DisableAnchors_Core(ParentControl: TWinControl; var aAnchorStorage: TAnchorsArray; var StartingIndex: Integer);
var
iCounter: integer;
ChildControl: TControl;
begin
if (StartingIndex+ParentControl.ControlCount+1) > (Length(aAnchorStorage)) then
SetLength(aAnchorStorage, StartingIndex+ParentControl.ControlCount+1);
for iCounter := 0 to ParentControl.ControlCount - 1 do
begin
ChildControl := ParentControl.Controls[iCounter];
aAnchorStorage[StartingIndex] := ChildControl.Anchors;
//doesn''t work for set of stacked top-aligned panels
// if ([akRight, akBottom ] * ChildControl.Anchors) <> [] then
// ChildControl.Anchors := [akLeft, akTop];
if (ChildControl.Anchors) <> [akTop, akLeft] then
ChildControl.Anchors := [akLeft, akTop];
// if ([akTop, akBottom] * ChildControl.Anchors) = [akTop, akBottom] then
// ChildControl.Anchors := ChildControl.Anchors - [akBottom];
Inc(StartingIndex);
end;
//Add children
for iCounter := 0 to ParentControl.ControlCount - 1 do
begin
ChildControl := ParentControl.Controls[iCounter];
if ChildControl is TWinControl then
DisableAnchors_Core(TWinControl(ChildControl), aAnchorStorage, StartingIndex);
end;
end;
Y los anclajes se vuelven a habilitar recursivamente:
procedure EnableAnchors(ParentControl: TWinControl; aAnchorStorage: TAnchorsArray);
var
StartingIndex: Integer;
begin
StartingIndex := 0;
EnableAnchors_Core(ParentControl, aAnchorStorage, StartingIndex);
end;
procedure EnableAnchors_Core(ParentControl: TWinControl; aAnchorStorage: TAnchorsArray; var StartingIndex: Integer);
var
iCounter: integer;
ChildControl: TControl;
begin
for iCounter := 0 to ParentControl.ControlCount - 1 do
begin
ChildControl := ParentControl.Controls[iCounter];
ChildControl.Anchors := aAnchorStorage[StartingIndex];
Inc(StartingIndex);
end;
//Restore children
for iCounter := 0 to ParentControl.ControlCount - 1 do
begin
ChildControl := ParentControl.Controls[iCounter];
if ChildControl is TWinControl then
EnableAnchors_Core(TWinControl(ChildControl), aAnchorStorage, StartingIndex);
end;
end;
Con el trabajo de cambiar realmente una fuente de controles a la izquierda para:
procedure StandardizeFont_ControlFontCore(AControlFont: TFont; ForceClearType: Boolean;
FontName: string; FontSize: Integer;
ForceFontIfName: string; ForceFontIfSize: Integer);
const
CLEARTYPE_QUALITY = 5;
var
CanChangeName: Boolean;
CanChangeSize: Boolean;
lf: TLogFont;
begin
if not Assigned(AControlFont) then
Exit;
{$IFDEF ForceClearType}
ForceClearType := True;
{$ELSE}
if g_ForceClearType then
ForceClearType := True;
{$ENDIF}
//Standardize the font if it''s currently
// "MS Shell Dlg 2" (meaning whoever it was opted into the ''change me'' system
// "MS Sans Serif" (the Delphi default)
// "Tahoma" (when they wanted to match the OS, but "MS Shell Dlg 2" should have been used)
// "MS Shell Dlg" (the 9x name)
CanChangeName :=
(FontName <> '''')
and
(AControlFont.Name <> FontName)
and
(
(
(ForceFontIfName <> '''')
and
(AControlFont.Name = ForceFontIfName)
)
or
(
(ForceFontIfName = '''')
and
(
(AControlFont.Name = ''MS Sans Serif'') or
(AControlFont.Name = ''Tahoma'') or
(AControlFont.Name = ''MS Shell Dlg 2'') or
(AControlFont.Name = ''MS Shell Dlg'')
)
)
);
CanChangeSize :=
(
//there is a font size
(FontSize <> 0)
and
(
//the font is at it''s default size, or we''re specifying what it''s default size is
(AControlFont.Size = 8)
or
((ForceFontIfSize <> 0) and (AControlFont.Size = ForceFontIfSize))
)
and
//the font size (or height) is not equal
(
//negative for height (px)
((FontSize < 0) and (AControlFont.Height <> FontSize))
or
//positive for size (pt)
((FontSize > 0) and (AControlFont.Size <> FontSize))
)
and
//no point in using default font''s size if they''re not using the face
(
(AControlFont.Name = FontName)
or
CanChangeName
)
);
if CanChangeName or CanChangeSize or ForceClearType then
begin
if GetObject(AControlFont.Handle, SizeOf(TLogFont), @lf) <> 0 then
begin
//Change the font attributes and put it back
if CanChangeName then
StrPLCopy(Addr(lf.lfFaceName[0]), FontName, LF_FACESIZE);
if CanChangeSize then
lf.lfHeight := FontSize;
if ForceClearType then
lf.lfQuality := CLEARTYPE_QUALITY;
AControlFont.Handle := CreateFontIndirect(lf);
end
else
begin
if CanChangeName then
AControlFont.Name := FontName;
if CanChangeSize then
begin
if FontSize > 0 then
AControlFont.Size := FontSize
else if FontSize < 0 then
AControlFont.Height := FontSize;
end;
end;
end;
end;
Eso es mucho más código de lo que pensaste que iba a ser; Lo sé. Lo triste es que no hay un desarrollador de Delphi en la tierra, a excepción de mí, que realmente hace que sus aplicaciones sean correctas.
Estimado desarrollador de Delphi : configure su fuente de Windows para Segoe UI 14pt y solucione su error de aplicación
Nota : Cualquier código se libera en el dominio público. No se requiere atribución.