source: tags/1.0.0/Packages/Common/UScaleDPI.pas

Last change on this file was 3, checked in by chronos, 8 years ago
  • Added: Remember last form position.
File size: 8.6 KB
Line 
1unit UScaleDPI;
2
3{ See: http://wiki.lazarus.freepascal.org/High_DPI }
4
5{$mode delphi}{$H+}
6
7interface
8
9uses
10 Classes, Forms, Graphics, Controls, ComCtrls, LCLType, SysUtils, StdCtrls,
11 Contnrs;
12
13type
14
15 { TControlDimension }
16
17 TControlDimension = class
18 BoundsRect: TRect;
19 AuxSize: TPoint;
20 FontHeight: Integer;
21 Controls: TObjectList; // TList<TControlDimension>
22 constructor Create;
23 destructor Destroy; override;
24 end;
25
26 { TScaleDPI }
27
28 TScaleDPI = class(TComponent)
29 private
30 FAutoDetect: Boolean;
31 FDesignDPI: TPoint;
32 FDPI: TPoint;
33 procedure SetAutoDetect(AValue: Boolean);
34 procedure SetDesignDPI(AValue: TPoint);
35 procedure SetDPI(AValue: TPoint);
36 public
37 procedure StoreDimensions(Control: TControl; Dimensions: TControlDimension);
38 procedure RestoreDimensions(Control: TControl; Dimensions: TControlDimension);
39 procedure ScaleDimensions(Control: TControl; Dimensions: TControlDimension);
40 procedure ApplyToAll(FromDPI: TPoint);
41 procedure ScaleControl(Control: TControl; FromDPI: TPoint);
42 procedure ScaleImageList(ImgList: TImageList; FromDPI: TPoint);
43 function ScalePoint(APoint: TPoint; FromDPI: TPoint): TPoint;
44 function ScaleRect(ARect: TRect; FromDPI: TPoint): TRect;
45 function ScaleX(Size: Integer; FromDPI: Integer): Integer;
46 function ScaleY(Size: Integer; FromDPI: Integer): Integer;
47 constructor Create(AOwner: TComponent); override;
48 property DesignDPI: TPoint read FDesignDPI write SetDesignDPI;
49 property DPI: TPoint read FDPI write SetDPI;
50 published
51 property AutoDetect: Boolean read FAutoDetect write SetAutoDetect;
52 end;
53
54procedure Register;
55
56
57implementation
58
59resourcestring
60 SWrongDPI = 'Wrong DPI [%d,%d]';
61
62procedure Register;
63begin
64 RegisterComponents('Common', [TScaleDPI]);
65end;
66
67{ TControlDimension }
68
69constructor TControlDimension.Create;
70begin
71 Controls := TObjectList.Create;
72end;
73
74destructor TControlDimension.Destroy;
75begin
76 Controls.Free;
77 inherited Destroy;
78end;
79
80procedure TScaleDPI.SetAutoDetect(AValue: Boolean);
81begin
82 if FAutoDetect = AValue then Exit;
83 FAutoDetect := AValue;
84 if AValue then begin
85 DPI := Point(ScreenInfo.PixelsPerInchX, ScreenInfo.PixelsPerInchY);
86 end;
87end;
88
89procedure TScaleDPI.SetDesignDPI(AValue: TPoint);
90begin
91 if (FDesignDPI.X = AValue.X) and (FDesignDPI.Y = AValue.Y) then Exit;
92 if (AValue.X <= 0) or (AValue.Y <= 0) then
93 raise Exception.Create(Format(SWrongDPI, [AValue.X, AValue.Y]));
94 FDesignDPI := AValue;
95end;
96
97procedure TScaleDPI.SetDPI(AValue: TPoint);
98begin
99 if (FDPI.X = AValue.X) and (FDPI.Y = AValue.Y) then Exit;
100 if (AValue.X <= 0) or (AValue.Y <= 0) then
101 raise Exception.Create(Format(SWrongDPI, [AValue.X, AValue.Y]));
102 FDPI := AValue;
103end;
104
105procedure TScaleDPI.StoreDimensions(Control: TControl;
106 Dimensions: TControlDimension);
107var
108 NewControl: TControlDimension;
109 I: Integer;
110begin
111 Dimensions.BoundsRect := Control.BoundsRect;
112 Dimensions.FontHeight := Control.Font.GetTextHeight('Hg');
113 Dimensions.Controls.Clear;
114 if Control is TToolBar then
115 Dimensions.AuxSize := Point(TToolBar(Control).ButtonWidth, TToolBar(Control).ButtonHeight);
116
117 if Control is TWinControl then
118 for I := 0 to TWinControl(Control).ControlCount - 1 do begin
119 if TWinControl(Control).Controls[I] is TControl then begin
120 NewControl := TControlDimension.Create;
121 Dimensions.Controls.Add(NewControl);
122 StoreDimensions(TWinControl(Control).Controls[I], NewControl);
123 end;
124 end;
125end;
126
127procedure TScaleDPI.RestoreDimensions(Control: TControl;
128 Dimensions: TControlDimension);
129var
130 I: Integer;
131begin
132 Control.BoundsRect := Dimensions.BoundsRect;
133 Control.Font.Height := Dimensions.FontHeight;
134 if Control is TToolBar then begin
135 TToolBar(Control).ButtonWidth := Dimensions.AuxSize.X;
136 TToolBar(Control).ButtonHeight := Dimensions.AuxSize.Y;
137 end;
138 if Control is TWinControl then
139 for I := 0 to TWinControl(Control).ControlCount - 1 do begin
140 if TWinControl(Control).Controls[I] is TControl then begin
141 RestoreDimensions(TWinControl(Control).Controls[I], TControlDimension(Dimensions.Controls[I]));
142 end;
143 end;
144end;
145
146procedure TScaleDPI.ScaleDimensions(Control: TControl;
147 Dimensions: TControlDimension);
148var
149 I: Integer;
150begin
151 Control.BoundsRect := ScaleRect(Dimensions.BoundsRect, DesignDPI);
152 Control.Font.Height := ScaleY(Dimensions.FontHeight, DesignDPI.Y);
153 if Control is TToolBar then begin
154 TToolBar(Control).ButtonWidth := ScaleX(Dimensions.AuxSize.X, DesignDPI.X);
155 TToolBar(Control).ButtonHeight := ScaleY(Dimensions.AuxSize.Y, DesignDPI.Y);
156 end;
157 if Control is TWinControl then
158 for I := 0 to TWinControl(Control).ControlCount - 1 do begin
159 if TWinControl(Control).Controls[I] is TControl then begin
160 ScaleDimensions(TWinControl(Control).Controls[I], TControlDimension(Dimensions.Controls[I]));
161 end;
162 end;
163end;
164
165procedure TScaleDPI.ApplyToAll(FromDPI: TPoint);
166var
167 I: Integer;
168begin
169 for I := 0 to Screen.FormCount - 1 do begin
170 ScaleControl(Screen.Forms[I], FromDPI);
171 end;
172end;
173
174procedure TScaleDPI.ScaleImageList(ImgList: TImageList; FromDPI: TPoint);
175var
176 TempBmp: TBitmap;
177 Temp: array of TBitmap;
178 NewWidth, NewHeight: integer;
179 I: Integer;
180begin
181 NewWidth := ScaleX(ImgList.Width, FromDPI.X);
182 NewHeight := ScaleY(ImgList.Height, FromDPI.Y);
183
184 SetLength(Temp, ImgList.Count);
185 TempBmp := TBitmap.Create;
186 for I := 0 to ImgList.Count - 1 do
187 begin
188 ImgList.GetBitmap(I, TempBmp);
189 //TempBmp.PixelFormat := pfDevice;
190 Temp[I] := TBitmap.Create;
191 Temp[I].SetSize(NewWidth, NewHeight);
192 Temp[I].TransparentColor := TempBmp.TransparentColor;
193 //Temp[I].TransparentMode := TempBmp.TransparentMode;
194 Temp[I].Transparent := True;
195 Temp[I].Canvas.Brush.Style := bsSolid;
196 Temp[I].Canvas.Brush.Color := Temp[I].TransparentColor;
197 Temp[I].Canvas.FillRect(0, 0, Temp[I].Width, Temp[I].Height);
198
199 if (Temp[I].Width = 0) or (Temp[I].Height = 0) then Continue;
200 Temp[I].Canvas.StretchDraw(Rect(0, 0, Temp[I].Width, Temp[I].Height), TempBmp);
201 end;
202 TempBmp.Free;
203
204 ImgList.Clear;
205 ImgList.Width := NewWidth;
206 ImgList.Height := NewHeight;
207
208 for I := 0 to High(Temp) do
209 begin
210 ImgList.Add(Temp[I], nil);
211 Temp[i].Free;
212 end;
213end;
214
215function TScaleDPI.ScaleX(Size: Integer; FromDPI: Integer): Integer;
216begin
217 Result := MulDiv(Size, DPI.X, FromDPI);
218end;
219
220function TScaleDPI.ScaleY(Size: Integer; FromDPI: Integer): Integer;
221begin
222 Result := MulDiv(Size, DPI.Y, FromDPI);
223end;
224
225function TScaleDPI.ScalePoint(APoint: TPoint; FromDPI: TPoint): TPoint;
226begin
227 Result.X := ScaleX(APoint.X, FromDPI.X);
228 Result.Y := ScaleY(APoint.Y, FromDPI.Y);
229end;
230
231function TScaleDPI.ScaleRect(ARect: TRect; FromDPI: TPoint): TRect;
232begin
233 Result.TopLeft := ScalePoint(ARect.TopLeft, FromDPI);
234 Result.BottomRight := ScalePoint(ARect.BottomRight, FromDPI);
235end;
236
237constructor TScaleDPI.Create(AOwner: TComponent);
238begin
239 inherited;
240 DPI := Point(96, 96);
241 DesignDPI := Point(96, 96);
242end;
243
244procedure TScaleDPI.ScaleControl(Control: TControl; FromDPI: TPoint);
245var
246 I: Integer;
247 WinControl: TWinControl;
248 ToolBarControl: TToolBar;
249 OldAnchors: TAnchors;
250 OldAutoSize: Boolean;
251begin
252 //if Control is TMemo then Exit;
253 //if Control is TForm then
254 // Control.DisableAutoSizing;
255 with Control do begin
256 //OldAutoSize := AutoSize;
257 //AutoSize := False;
258 //Anchors := [];
259 Left := ScaleX(Left, FromDPI.X);
260 Top := ScaleY(Top, FromDPI.Y);
261 //if not (akRight in Anchors) then
262 Width := ScaleX(Width, FromDPI.X);
263 //if not (akBottom in Anchors) then
264 Height := ScaleY(Height, FromDPI.Y);
265 {$IFDEF LCL Qt}
266 Font.Size := 0;
267 {$ELSE}
268 Font.Height := ScaleY(Font.GetTextHeight('Hg'), FromDPI.Y);
269 {$ENDIF}
270 //Anchors := OldAnchors;
271 //AutoSize := OldAutoSize;
272 end;
273
274
275
276 if Control is TToolBar then begin
277 ToolBarControl := TToolBar(Control);
278 with ToolBarControl do begin
279 ButtonWidth := ScaleX(ButtonWidth, FromDPI.X);
280 ButtonHeight := ScaleY(ButtonHeight, FromDPI.Y);
281 end;
282 end;
283
284 //if not (Control is TCustomPage) then
285 if Control is TWinControl then begin
286 WinControl := TWinControl(Control);
287 if WinControl.ControlCount > 0 then begin
288 for I := 0 to WinControl.ControlCount - 1 do begin
289 if WinControl.Controls[I] is TControl then begin
290 ScaleControl(WinControl.Controls[I], FromDPI);
291 end;
292 end;
293 end;
294 end;
295 //if Control is TForm then
296 // Control.EnableAutoSizing;
297end;
298
299end.
Note: See TracBrowser for help on using the repository browser.