1 unit CustomDrawn_WinXP;
2 
3 {$mode objfpc}{$H+}
4 
5 interface
6 
7 uses
8   // RTL
9   Classes, SysUtils, Types, fpcanvas, fpimage,
10   // LCL -> Use only TForm, TWinControl, TCanvas and TLazIntfImage
11   Graphics, Controls, LCLType,
12   //
13   customdrawndrawers, customdrawn_common;
14 
15 type
16 
17   { TCDDrawerWinXP }
18 
19   TCDDrawerWinXP = class(TCDDrawerCommon)
20   public
21     // General
GetMeasuresnull22     function GetMeasures(AMeasureID: Integer): Integer; override;
GetMeasuresExnull23     //function GetMeasuresEx(ADest: TCanvas; AMeasureID: Integer;
24       //AState: TCDControlState; AStateEx: TCDControlStateEx): Integer; override;
25     //
26     function GetDrawStyle: TCDDrawStyle; override;
27     procedure LoadFallbackPaletteColors; override;
28     // General drawing routines
29     {procedure DrawFocusRect(ADest: TCanvas; ADestPos: TPoint; ASize: TSize); override;
30     procedure DrawRaisedFrame(ADest: TCanvas; ADestPos: TPoint; ASize: TSize); override;
31     procedure DrawSunkenFrame(ADest: TCanvas; ADestPos: TPoint; ASize: TSize); override;
32     procedure DrawShallowSunkenFrame(ADest: TCanvas; ADestPos: TPoint; ASize: TSize); override;}
33     procedure DrawTickmark(ADest: TFPCustomCanvas; ADestPos: TPoint; AState: TCDControlState); override;
34     {procedure DrawSlider(ADest: TCanvas; ADestPos: TPoint; ASize: TSize; AState: TCDControlState); override;
35     procedure DrawCompactArrow(ADest: TCanvas; ADestPos: TPoint; ADirection: TCDControlState); override;}
36     // ===================================
37     // Standard Tab
38     // ===================================
39     // TCDButton
40     procedure DrawButton(ADest: TFPCustomCanvas; ADestPos: TPoint; ASize: TSize;
41       AState: TCDControlState; AStateEx: TCDButtonStateEx); override;
42     // TCDEdit
43     procedure DrawEditFrame(ADest: TCanvas; ADestPos: TPoint; ASize: TSize;
44       AState: TCDControlState; AStateEx: TCDEditStateEx); override;
45     // TCDCheckBox
46     procedure DrawCheckBoxSquare(ADest: TCanvas; ADestPos: TPoint; ASize: TSize;
47       AState: TCDControlState; AStateEx: TCDControlStateEx); override;
48   end;
49 
50 implementation
51 
52 const
53 
54   // Button
55 
56   WINXP_BUTTON_BODY_TOP = $00FFFFFF;
57   WINXP_BUTTON_BODY_BOTTOM = $00EAF0F0;
58 
59   WINXP_BUTTON_BODY_LINES_PREPRELAST = $00E6EBEC;
60   WINXP_BUTTON_BODY_LINES_PRELAST = $00D6DFE2;
61   WINXP_BUTTON_BODY_LINES_LAST = $00C5D0D6;
62 
63   WINXP_BUTTON_SUNKEN_BODY_BOTTOM = $00E3E9EA;
64 
65   WINXP_BUTTON_FRAME_DARK_BLUE = $00743C00;
66   WINXP_BUTTON_FRAME_MED_DARK_BLUE = $00A27055;
67   WINXP_BUTTON_FRAME_MEDIUM_BLUE = $00A8957A;
68   WINXP_BUTTON_FRAME_LIGHT_BLUE = $00DDCFC0;
69 
70   WINXP_BUTTON_DISABLED_BODY = $00EAF4F5;
71 
72   WINXP_BUTTON_FRAME_DARK_DISABLED = $00BAC7C9;
73   WINXP_BUTTON_FRAME_MEDIUM_DISABLED = $00CAD6D8;
74   WINXP_BUTTON_FRAME_LIGHT_DISABLED = $00E2EDEE;
75 
76   WINXP_BUTTON_FOCUS_TOP = $00FFE7CE;
77   WINXP_BUTTON_FOCUS_TOP_GRAD = $00F6D4BC;
78   WINXP_BUTTON_FOCUS_BOTTOM_GRAD = $00E4AD89;
79   WINXP_BUTTON_FOCUS_BOTTOM = $00EF8269;
80 
81   WINXP_BUTTON_MOUSEOVER_TOP = $00CFF0FF;
82   WINXP_BUTTON_MOUSEOVER_TOP_GRAD = $0089D8FD;
83   WINXP_BUTTON_MOUSEOVER_BOTTOM_GRAD = $0030B3F8;
84   WINXP_BUTTON_MOUSEOVER_BOTTOM = $000097E5;
85 
86   // CheckBox
87 
88   WINXP_CHECKBOX_GRADIENT_1 = $00D6DED6;
89   WINXP_CHECKBOX_GRADIENT_2 = $00CED6D6;
90   WINXP_CHECKBOX_GRADIENT_3 = $00D6DED6;
91   WINXP_CHECKBOX_GRADIENT_4 = $00D6D6D6;
92   WINXP_CHECKBOX_GRADIENT_5 = $00DEE7DE;
93   WINXP_CHECKBOX_GRADIENT_6 = $00D6DEDE;
94   WINXP_CHECKBOX_GRADIENT_7 = $00E7E7DE;
95   WINXP_CHECKBOX_GRADIENT_8 = $00DEE7E7;
96   WINXP_CHECKBOX_GRADIENT_9 = $00EFEFE7;
97   WINXP_CHECKBOX_GRADIENT_10 = $00E7E7E7;
98 
99   WINXP_CHECKBOX_GRADIENT_DIAGONAL = $00D6DED6; // The biggest diagonal
100 
101   WINXP_CHECKBOX_GRADIENT_11 = $00EFEFF7;
102   WINXP_CHECKBOX_GRADIENT_12 = $00F7EFEF;
103   WINXP_CHECKBOX_GRADIENT_13 = $00EFEFEF;
104   WINXP_CHECKBOX_GRADIENT_14 = $00F7FFF7;
105   WINXP_CHECKBOX_GRADIENT_15 = $00F7F7FF;
106   WINXP_CHECKBOX_GRADIENT_16 = $00FFF7F7;
107   WINXP_CHECKBOX_GRADIENT_17 = $00F7F7F7;
108   WINXP_CHECKBOX_GRADIENT_18 = $00F7FFF7;
109   WINXP_CHECKBOX_GRADIENT_19 = $00F7F7FF;
110   WINXP_CHECKBOX_GRADIENT_20 = $00FFF7F7;
111 
112   WINXP_TICKMARK = $0021A521;
113   WINXP_GRAY_TICKMARK = $0099A8AC;
114 
115   WINXP_FRAME_BLUE = $00B99D7F;
116   WINXP_FORM       = $00D8E9EC;
117 
118 { TCDDrawerWinXP }
119 
GetMeasuresnull120 function TCDDrawerWinXP.GetMeasures(AMeasureID: Integer): Integer;
121 begin
122   case AMeasureID of
123   TCDCHECKBOX_SQUARE_HALF_HEIGHT: Result := 6;
124   TCDCHECKBOX_SQUARE_HEIGHT: Result := 13;
125   else
126     Result:=inherited GetMeasures(AMeasureID);
127   end;
128 end;
129 
TCDDrawerWinXP.GetDrawStylenull130 function TCDDrawerWinXP.GetDrawStyle: TCDDrawStyle;
131 begin
132   Result := dsWinXP;
133 end;
134 
135 procedure TCDDrawerWinXP.LoadFallbackPaletteColors;
136 begin
137   Palette.ScrollBar := $C8D0D4;
138   Palette.Background := $984E00;
139   Palette.ActiveCaption := $E35400;
140   Palette.InactiveCaption := $DF967A;
141   Palette.Menu := $FFFFFF;
142   Palette.Window := clWhite; // The inside of a Edit control, for example
143   Palette.WindowFrame := $0;
144   Palette.MenuText := $0;
145   Palette.WindowText := $0;
146   Palette.CaptionText := $FFFFFF;
147   Palette.ActiveBorder := $C8D0D4;
148   Palette.InactiveBorder := $C8D0D4;
149   Palette.AppWorkspace := $808080;
150   Palette.Highlight := $C56A31;
151   Palette.HighlightText := $FFFFFF;
152   Palette.BtnFace := WINXP_FORM;
153   Palette.BtnShadow := $99A8AC;
154   Palette.GrayText := $99A8AC;
155   Palette.BtnText := $0;
156   Palette.InactiveCaptionText := $F8E4D8;
157   Palette.BtnHighlight := $FFFFFF;
158   Palette.color3DDkShadow := $646F71;
159   Palette.color3DLight := $E2EFF1;
160   Palette.InfoText := $0;
161   Palette.InfoBk := $E1FFFF;
162     //
163   Palette.HotLight := $800000;
164   Palette.GradientActiveCaption := $FF953D;
165   Palette.GradientInactiveCaption := $EBB99D;
166   Palette.MenuHighlight := $C56A31;
167   Palette.MenuBar := $D8E9EC;
168   Palette.Form := WINXP_FORM;
169 end;
170 
171 procedure TCDDrawerWinXP.DrawTickmark(ADest: TFPCustomCanvas; ADestPos: TPoint; AState: TCDControlState);
172 var
173   i: Integer;
174 begin
175   if csfPartiallyOn in AState then ADest.Pen.FPColor := TColorToFPColor(WINXP_GRAY_TICKMARK)
176   else ADest.Pen.FPColor := TColorToFPColor(WINXP_TICKMARK);
177   ADest.Pen.Style := psSolid;
178   // 3 lines going down and to the right
179   for i := 0 to 2 do
180     ADest.Line(ADestPos.X+i, ADestPos.Y+i, ADestPos.X+i, ADestPos.Y+3+i);
181   // Now 4 lines going up and to the right
182   for i := 3 to 6 do
183     ADest.Line(ADestPos.X+i, ADestPos.Y+4-i, ADestPos.X+i, ADestPos.Y+3+4-i);
184 end;
185 
186 procedure TCDDrawerWinXP.DrawButton(ADest: TFPCustomCanvas;
187   ADestPos: TPoint; ASize: TSize; AState: TCDControlState; AStateEx: TCDButtonStateEx);
188 var
189   lDest: TCanvas absolute ADest;
190   Str: string;
191   lColor: TColor;
192   lRect: TRect;
193   lFrameDark, lFrameMedDark, lFrameMedium, lFrameLight: TColor;
194   lSelTop, lSelTopGrad, lSelBottomGrad, lSelBottom: TColor;
195 begin
196   // Background corners
197   lColor := AStateEx.ParentRGBColor;
198   lDest.Pixels[0, 0] := lColor;
199   lDest.Pixels[ASize.cx-1, 0] := lColor;
200   lDest.Pixels[0, ASize.cy-1] := lColor;
201   lDest.Pixels[ASize.cx-1, ASize.cy-1] := lColor;
202 
203   // Main body
204   if csfSunken in AState then
205   begin
206     ADest.Brush.Style := bsSolid;
207     lDest.Brush.Color := WINXP_BUTTON_SUNKEN_BODY_BOTTOM;
208     lDest.Pen.Color := WINXP_BUTTON_SUNKEN_BODY_BOTTOM;
209     ADest.Rectangle(1, 1, ASize.cx-1, ASize.cy-1);
210   end
211   else if csfEnabled in AState then
212   begin
213     // First the gradient
214     lRect := Bounds(1, 1, ASize.cx-4, ASize.cy-5);
215     lDest.GradientFill(lRect, WINXP_BUTTON_BODY_TOP, WINXP_BUTTON_BODY_BOTTOM, gdVertical);
216     // Now the extra lines which make the bottom-right
217     lDest.Pen.Color := WINXP_BUTTON_BODY_LINES_PREPRELAST;
218     ADest.Line(1, ASize.cy-4, ASize.cx-3, ASize.cy-4);
219     ADest.Line(ASize.cx-3, ASize.cy-4, ASize.cx-3, 1);
220     lDest.Pen.Color := WINXP_BUTTON_BODY_LINES_PRELAST;
221     ADest.Line(2, ASize.cy-3, ASize.cx-2, ASize.cy-3);
222     ADest.Line(ASize.cx-2, ASize.cy-3, ASize.cx-2, 2);
223     lDest.Pen.Color := WINXP_BUTTON_BODY_LINES_LAST;
224     ADest.Line(3, ASize.cy-1, ASize.cx-3, ASize.cy-1);
225   end
226   else // disabled
227   begin
228     ADest.Brush.Style := bsSolid;
229     lDest.Brush.Color := WINXP_BUTTON_DISABLED_BODY;
230     lDest.Pen.Color := WINXP_BUTTON_DISABLED_BODY;
231     ADest.Rectangle(1, 1, ASize.cx-1, ASize.cy-1);
232   end;
233 
234   // Now the frame
235   if csfEnabled in AState then
236   begin
237     lFrameDark := WINXP_BUTTON_FRAME_DARK_BLUE;
238     lFrameMedDark := WINXP_BUTTON_FRAME_MED_DARK_BLUE;
239     lFrameMedium := WINXP_BUTTON_FRAME_MEDIUM_BLUE;
240     lFrameLight := WINXP_BUTTON_FRAME_LIGHT_BLUE;
241   end
242   else
243   begin
244     lFrameDark := WINXP_BUTTON_FRAME_DARK_DISABLED;
245     lFrameMedDark := WINXP_BUTTON_FRAME_MEDIUM_DISABLED;
246     lFrameMedium := WINXP_BUTTON_FRAME_MEDIUM_DISABLED;
247     lFrameLight := WINXP_BUTTON_FRAME_LIGHT_DISABLED;
248   end;
249 
250   lDest.Pixels[1, 0] := lFrameMedium;
251   lDest.Pixels[0, 1] := lFrameMedium;
252   lDest.Pixels[1, 1] := lFrameMedDark;
253   lDest.Pixels[2, 1] := lFrameLight;
254   lDest.Pixels[1, 2] := lFrameLight;
255 
256   lDest.Pixels[ASize.cx-2, 0] := lFrameMedium;
257   lDest.Pixels[ASize.cx-1, 1] := lFrameMedium;
258   lDest.Pixels[ASize.cx-2, 1] := lFrameMedDark;
259   lDest.Pixels[ASize.cx-3, 1] := lFrameLight;
260   lDest.Pixels[ASize.cx-2, 2] := lFrameLight;
261 
262   lDest.Pixels[1, ASize.cy-1] := lFrameMedium;
263   lDest.Pixels[0, ASize.cy-2] := lFrameMedium;
264   lDest.Pixels[1, ASize.cy-2] := lFrameMedDark;
265   lDest.Pixels[2, ASize.cy-2] := lFrameLight;
266   lDest.Pixels[1, ASize.cy-3] := lFrameLight;
267 
268   lDest.Pixels[ASize.cx-2, ASize.cy-1] := lFrameMedium;
269   lDest.Pixels[ASize.cx-1, ASize.cy-2] := lFrameMedium;
270   lDest.Pixels[ASize.cx-2, ASize.cy-2] := lFrameMedDark;
271   lDest.Pixels[ASize.cx-3, ASize.cy-2] := lFrameLight;
272   lDest.Pixels[ASize.cx-2, ASize.cy-3] := lFrameLight;
273 
274   lDest.Pen.Color := lFrameDark;
275   lDest.Line(2, 0, ASize.cx-2, 0);
276   lDest.Line(2, ASize.cy-1, ASize.cx-2, ASize.cy-1);
277   lDest.Line(0, 2, 0, ASize.cy-2);
278   lDest.Line(ASize.cx-1, 2, ASize.cx-1, ASize.cy-2);
279 
280   // Now focus / mouseover indication, note that both disappear when sunked in WinXP
281   if ((csfHasFocus in AState) or (csfMouseOver in AState)) and not (csfSunken in AState) then
282   begin
283     if (csfHasFocus in AState) then
284     begin
285       lSelTop := WINXP_BUTTON_FOCUS_TOP;
286       lSelTopGrad := WINXP_BUTTON_FOCUS_TOP_GRAD;
287       lSelBottomGrad := WINXP_BUTTON_FOCUS_BOTTOM_GRAD;
288       lSelBottom := WINXP_BUTTON_FOCUS_BOTTOM;
289     end
290     else
291     begin
292       lSelTop := WINXP_BUTTON_MOUSEOVER_TOP;
293       lSelTopGrad := WINXP_BUTTON_MOUSEOVER_TOP_GRAD;
294       lSelBottomGrad := WINXP_BUTTON_MOUSEOVER_BOTTOM_GRAD;
295       lSelBottom := WINXP_BUTTON_MOUSEOVER_BOTTOM;
296     end;
297 
298     // Top
299     lDest.Pen.Color := lSelTop;
300     ADest.Line(2, 1, ASize.cx-2, 1);
301     lDest.Pen.Color := lSelTopGrad;
302     ADest.Line(1, 2, ASize.cx-1, 2);
303     // Gradient
304     lRect := Bounds(1, 2, 2, ASize.cy-4);
305     lDest.GradientFill(lRect, lSelTopGrad, lSelBottomGrad, gdVertical);
306     lRect := Bounds(ASize.cx-3, 2, 2, ASize.cy-4);
307     lDest.GradientFill(lRect, lSelTopGrad, lSelBottomGrad, gdVertical);
308     // Bottom
309     lDest.Pen.Color := lSelBottomGrad;
310     ADest.Line(1, ASize.cy-3, ASize.cx-1, ASize.cy-3);
311     lDest.Pen.Color := lSelBottom;
312     ADest.Line(2, ASize.cy-2, ASize.cx-2, ASize.cy-2);
313   end;
314 
315   // Button text, note that it doesn't move downwards when clicked in WinXP
316   ADest.Font.Assign(AStateEx.Font);
317   ADest.Brush.Style := bsClear;
318   ADest.Pen.Style := psSolid;
319   Str := AStateEx.Caption;
320   lDest.TextOut((ASize.cx - lDest.TextWidth(Str)) div 2,
321     (ASize.cy - lDest.TextHeight(Str)) div 2, Str);
322 end;
323 
324 procedure TCDDrawerWinXP.DrawEditFrame(ADest: TCanvas; ADestPos: TPoint;
325   ASize: TSize; AState: TCDControlState; AStateEx: TCDEditStateEx);
326 begin
327   // The frame
328   ADest.Brush.Style := bsClear;
329   ADest.Pen.Color := WINXP_FRAME_BLUE;
330   ADest.Pen.Style := psSolid;
331   ADest.Rectangle(0, 0, ASize.cx, ASize.cy);
332 end;
333 
334 procedure TCDDrawerWinXP.DrawCheckBoxSquare(ADest: TCanvas; ADestPos: TPoint;
335   ASize: TSize; AState: TCDControlState; AStateEx: TCDControlStateEx);
336 begin
337   ADest.Pen.Style := psSolid;
338   ADest.Brush.Style := bsClear;
339   ADest.Pen.Color := clBlack;
340   ADest.Rectangle(0,0,13,13);
341   ADest.Pixels[1,1] := WINXP_CHECKBOX_GRADIENT_1;
342   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_2;
343   ADest.Line(1,2,3,0);
344   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_3;
345   ADest.Line(1,3,4,0);
346   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_4;
347   ADest.Line(1,4,5,0);
348   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_5;
349   ADest.Line(1,5,6,0);
350   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_6;
351   ADest.Line(1,6,7,0);
352   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_7;
353   ADest.Line(1,7,8,0);
354   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_8;
355   ADest.Line(1,8,9,0);
356   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_9;
357   ADest.Line(1,9,10,0);
358   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_10;
359   ADest.Line(1,10,11,0);
360   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_DIAGONAL;
361   ADest.Line(1,11,12,0);
362   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_11;
363   ADest.Line(2,11,12,1);
364   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_12;
365   ADest.Line(3,11,12,2);
366   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_13;
367   ADest.Line(4,11,12,3);
368   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_14;
369   ADest.Line(5,11,12,4);
370   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_15;
371   ADest.Line(6,11,12,5);
372   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_16;
373   ADest.Line(7,11,12,6);
374   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_17;
375   ADest.Line(8,11,12,7);
376   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_18;
377   ADest.Line(9,11,12,8);
378   ADest.Pen.Color := WINXP_CHECKBOX_GRADIENT_19;
379   ADest.Line(10,11,12,9);
380   ADest.Pixels[11,11] := WINXP_CHECKBOX_GRADIENT_20;
381 end;
382 
383 initialization
384   RegisterDrawer(TCDDrawerWinXP.Create, dsWinXP);
385 end.
386 
387