MMForm.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:49k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 19.02.98 - 16:04:37 $                                        =}
  24. {========================================================================}
  25. unit MMForm;
  26. {$I COMPILER.INC}
  27. {$D+,L+}
  28. interface
  29. uses
  30.     Windows,
  31.     Messages,
  32.     SysUtils,
  33.     Classes,
  34.     Graphics,
  35.     Controls,
  36.     Forms,
  37.     Dialogs,
  38.     StdCtrls,
  39.     ExtCtrls,
  40.     ShellApi,
  41.     MMObj,
  42.     MMUtils,
  43.     MMHook;
  44. type
  45.   TMMFormStyler = class;
  46.   TMMFontKind    = (fkCustom, fkSystem, fkSystemI, fkSystemB, fkSystemBI, fkAutoHeight);
  47.   {== TMMCompanyText ==========================================================}
  48.   TMMCompanyText = class(TPersistent)
  49.   private
  50.     FCaption      : String;
  51.     FColorActive  : TColor;
  52.     FColorInactive: TColor;
  53.     FFont         : TFont;
  54.     FFontKind     : TMMFontKind;
  55.     FOwner        : TMMFormStyler;
  56.     FVisible      : Boolean;
  57.     function  StoreFont: Boolean;
  58.     procedure SetColorActive(Value: TColor);
  59.     procedure SetColorInactive(Value: TColor);
  60.     procedure SetCaption(Value: String); virtual;
  61.     procedure SetFont(Value: TFont);
  62.     procedure SetFontKind(Value: TMMFontKind);
  63.     procedure SetVisible(Value: Boolean);
  64.     procedure SetFontKind_NoRedraw(Value: TMMFontKind);
  65.   public
  66.     constructor Create(AOwner: TMMFormStyler); virtual;
  67.     destructor  Destroy; override;
  68.   published
  69.     property Caption: String read FCaption write SetCaption;
  70.     property ColorActive: TColor read FColorActive write SetColorActive default clCaptionText;
  71.     property ColorInactive: TColor read FColorInactive write SetColorInactive default clInactiveCaptionText;
  72.     property Font: TFont read FFont write SetFont stored StoreFont;
  73.     property FontKind: TMMFontKind read FFontKind write SetFontKind;
  74.     property Visible: Boolean read FVisible write SetVisible;
  75.   end;
  76.   TMMAppNameText = class(TMMCompanyText)
  77.   end;
  78.   TMMCaptionText = class(TMMCompanyText)
  79.   protected
  80.     function  GetCaption: String; virtual;
  81.   published
  82.     property Caption : String read GetCaption write SetCaption;
  83.   end;
  84.   {== TMMFormStyler ===========================================================}
  85.   TMMGradientColors  = 2..236;
  86.   TMMGradientOptions = (goAlways, goNever, goActive, goSmart);
  87.   TMMFormStyler = class(TMMWndProcComponent)
  88.   private
  89.     FHandle           : THandle;
  90.     FAppNameText      : TMMAppNameText;
  91.     FCaptionText      : TMMCaptionText;
  92.     FCompanyText      : TMMCompanyText;
  93.     FClrLeftActive    : TColor;
  94.     FClrLeftInActive  : TColor;
  95.     FClrRightActive   : TColor;
  96.     FClrRightInActive : TColor;
  97.     FOptions          : TMMGradientOptions;
  98.     FNumColors        : TMMGradientColors;
  99.     FAlignment        : TAlignment;
  100.     FSystemFont       : TFont;
  101.     FWindowActive     : Boolean;
  102.     FActiveDefined    : Boolean;
  103.     FRecreating       : Boolean;
  104.     procedure SetColors(index: integer; aValue: TColor);
  105.     procedure SetAlignment(aValue: TAlignment);
  106.     procedure SetNumColors(aValue: TMMGradientColors);
  107.     procedure SetOptions(aValue: TMMGradientOptions);
  108.     function  GetVisibleButtons: TBorderIcons;
  109.     procedure ExcludeBtnRgn (var R: TRect);
  110.     procedure GetSystemFont(Font: TFont);
  111.     function  GetTextRect: TRect;
  112.     function  GetTitleBarRect: TRect;
  113.     function  MeasureText(DC: HDC; R: TRect; Text: TMMCompanyText): integer;
  114.     procedure NewCaptionText;
  115.     procedure PaintMenuIcon(DC: HDC; var R: TRect);
  116.     procedure PaintCaptionText(DC: HDC; var R: TRect; Text: TMMCompanyText; Active: Boolean);
  117.     procedure PaintCaptionButtons(DC: HDC; var Rect: TRect);
  118.     procedure PerformNCPaint(var AMsg: TMessage);
  119.     procedure PerformNCActivate(var AMsg: TMessage);
  120.     function  HandleWMSetCursor(var Msg: TWMSetCursor): Boolean;
  121.     procedure SetAutoFontHeight(Font: TFont);
  122.     function  WindowIsActive: Boolean;
  123.   protected
  124.     procedure Loaded; override;
  125.     procedure HookWndProc(var Message: TMessage); override;
  126.     procedure HookAppWndProc(var AMsg: TMessage);
  127. {$IFDEF BUILD_ACTIVEX}
  128.     procedure ChangeDesigning(Value: Boolean); override;
  129.     function GetOwnerCaption: string;
  130.     procedure HookOwner; override;
  131.     procedure UnhookOwner; override;
  132.     procedure CMEnabledChanged(var M: TMessage); message CM_ENABLEDCHANGED;
  133. {$ELSE}
  134.     procedure ChangeDesigning(Value: Boolean);
  135. {$ENDIF}
  136.   public
  137.     constructor Create(AOwner: TComponent);  override;
  138.     destructor  Destroy; override;
  139.     procedure   UpdateCaption;
  140.     function    DrawCaption(Active: Boolean): TRect;
  141.   published
  142. {$IFDEF BUILD_ACTIVEX}
  143.     property Enabled;
  144. {$ENDIF}
  145.     property AppNameText: TMMAppNameText read FAppNameText write FAppNameText;
  146.     property CaptionText: TMMCaptionText read FCaptionText write FCaptionText;
  147.     property CompanyText: TMMCompanyText read FCompanyText write FCompanyText;
  148.     property ClrLeftActive   : TColor index 0 read FClrLeftActive write SetColors default clBlack;
  149.     property ClrLeftInActive : TColor index 1 read FClrLeftInActive write SetColors default clBlack;
  150.     property ClrRightActive  : TColor index 2 read FClrRightActive write SetColors default clActiveCaption;
  151.     property ClrRightInActive: TColor index 3 read FClrRightInActive write SetColors default clInActiveCaption;
  152.     property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
  153.     property Options  : TMMGradientOptions read FOptions write SetOptions default goSmart;
  154.     property NumColors: TMMGradientColors read FNumColors write SetNumColors default 64;
  155.   end;
  156. implementation
  157. {$IFDEF DELPHI3} resourcestring {$ELSE} const {$ENDIF}
  158.   SSecondStyler = 'Only one FormStyler is allowed per Form';
  159. const
  160.    ControlList: TList = nil;
  161.    WordSpacing        = 3;
  162.    MM_RecreateNotify  = WM_USER + 12621;
  163. {== TMMCompanyText ============================================================}
  164. constructor TMMCompanyText.Create(AOwner: TMMFormStyler);
  165. begin
  166.    inherited Create;
  167.    FOwner := AOwner;
  168.    FColorActive := (clCaptionText);
  169.    FColorInactive := (clInactiveCaptionText);
  170.    FFont := TFont.Create;
  171.    FFontKind := fkSystem;
  172.    FFont.Assign(FOwner.FSystemFont);
  173.    FVisible := true;
  174.    FCaption := '';
  175. end;
  176. {-- TMMCompanyText ------------------------------------------------------------}
  177. destructor TMMCompanyText.Destroy;
  178. begin
  179.    FFont.Free;
  180.    inherited destroy;
  181. end;
  182. {-- TMMCompanyText ------------------------------------------------------------}
  183. procedure TMMCompanyText.SetColorActive(Value: TColor);
  184. begin
  185.    FColorActive := value;
  186.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  187. end;
  188. {-- TMMCompanyText ------------------------------------------------------------}
  189. procedure TMMCompanyText.SetColorInactive(Value: TColor);
  190. begin
  191.    FColorInactive := value;
  192.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  193. end;
  194. {-- TMMCompanyText ------------------------------------------------------------}
  195. procedure TMMCompanyText.SetCaption(Value: String);
  196. begin
  197.    if FCaption = Value then exit;
  198.    FCaption := Value;
  199.    FOwner.NewCaptionText;
  200.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  201. end;
  202. {-- TMMCompanyText ------------------------------------------------------------}
  203. procedure TMMCompanyText.SetFont(Value: TFont);
  204. begin
  205.    FFont.Assign(Value);
  206.    if FFontKind = fkAutoHeight then
  207.       FOwner.SetAutoFontHeight(FFont)
  208.    else
  209.       FFontKind := fkCustom;
  210.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  211. end;
  212. {-- TMMCompanyText ------------------------------------------------------------}
  213. function TMMCompanyText.Storefont : Boolean;
  214. begin
  215.    Result := not (FFontKind in [fkSystem, fkSystemB, fkSystemBI, fkSystemI]);
  216. end;
  217. {-- TMMCompanyText ------------------------------------------------------------}
  218. procedure TMMCompanyText.SetFontKind(Value: TMMFontKind);
  219. begin
  220.    SetFontKind_NoRedraw(Value);
  221.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  222. end;
  223. {-- TMMCompanyText ------------------------------------------------------------}
  224. procedure TMMCompanyText.SetFontKind_NoRedraw(Value: TMMFontKind);
  225. begin
  226.    FFontKind := Value;
  227.    case FFontKind of
  228.       fkCustom : { do nothing special };
  229.       fkSystem : FFont.Assign(FOwner.FSystemFont);
  230.       fkSystemI:
  231.       begin
  232.          FFont.Assign(FOwner.FSystemFont);
  233.          FFont.Style := FFont.Style + [fsItalic];
  234.       end;
  235.       fkSystemB:
  236.       begin
  237.          FFont.Assign(FOwner.FSystemFont);
  238.          FFont.Style := FFont.Style + [fsBold];
  239.       end;
  240.       fkSystemBI:
  241.       begin
  242.          FFont.Assign(FOwner.FSystemFont);
  243.          FFont.Style := FFont.Style + [fsItalic, fsBold];
  244.       end;
  245.       fkAutoHeight: FOwner.SetAutoFontHeight(FFont);
  246.    end;
  247. end;
  248. {-- TMMCompanyText ------------------------------------------------------------}
  249. procedure TMMCompanyText.SetVisible(Value: Boolean);
  250. begin
  251.    if FVisible = Value then exit;
  252.    FVisible := Value;
  253.    FOwner.NewCaptionText;
  254.    if csDesigning in FOwner.ComponentState then FOwner.UpdateCaption;
  255. end;
  256. {== TMMCaptionText ============================================================}
  257. function TMMCaptionText.GetCaption: String;
  258. var
  259.    temp : string;
  260.    found: integer;
  261. begin
  262.    try
  263. {$IFNDEF BUILD_ACTIVEX}
  264.       if FOwner.OwnerForm = nil then
  265.       begin
  266.          Result := '';
  267.          exit;
  268.       end;
  269.       temp := FOwner.OwnerForm.Caption;
  270. {$ELSE}
  271.       if FOwner.HookWnd = 0 then
  272.       begin
  273.         Result := '';
  274.         exit;
  275.       end;
  276.       temp := FOwner.GetOwnerCaption;
  277. {$ENDIF}
  278.       if FOwner.FCompanyText.Visible then
  279.       begin
  280.          Found := Pos(FOwner.FCompanyText.Caption, Temp);
  281.          if found <> 0 then temp := Copy(temp, found + length(FOwner.FCompanyText.Caption), maxint);
  282.          if length(temp) > 0 then if temp[1] = ' ' then temp := Copy(temp, 2, maxint);
  283.       end;
  284.       if FOwner.FAppNameText.Visible then
  285.       begin
  286.          found := Pos(FOwner.FAppNameText.Caption, Temp);
  287.          if found <> 0 then temp := Copy(temp, found + length(FOwner.FAppNameText.Caption), maxint);
  288.          if length(temp) > 0 then if temp[1] = ' ' then temp := Copy(temp, 2, maxint);
  289.       end;
  290.       Result := temp;
  291.    except
  292.       Result := '';
  293.    end;
  294. end;
  295. {------------------------------------------------------------------------}
  296. procedure AddStyler(Comp: TMMFormStyler);
  297. begin
  298.    if (ControlList = nil) then ControlList := TList.Create;
  299.    ControlList.Add(Comp);
  300. end;
  301. {------------------------------------------------------------------------}
  302. procedure RemoveStyler(Comp: TMMFormStyler);
  303. begin
  304.    ControlList.Remove(Comp);
  305.    if (ControlList.Count = 0) then
  306.    begin
  307.       ControlList.Free;
  308.       ControlList := nil;
  309.    end;
  310. end;
  311. {------------------------------------------------------------------------}
  312. function FindStylerForWindow(Wnd: HWND): TMMFormStyler;
  313. var
  314.    i: Integer;
  315. begin
  316.    { It is no sense to have multiple different designers for one window }
  317.    if (ControlList <> nil) and (ControlList.Count > 0) then
  318.    for i := 0 to ControlList.Count-1 do
  319.    begin
  320.       with TMMFormStyler(ControlList[i]) do
  321. {$IFNDEF BUILD_ACTIVEX}
  322.       if ((OwnerForm.Handle = Wnd) or IsChild(OwnerForm.Handle, Wnd)) then
  323. {$ELSE}
  324.       if ((HookWnd = Wnd) or IsChild(HookWnd, Wnd)) then
  325. {$ENDIF}
  326.       begin
  327.          Result := TMMFormStyler(ControlList[i]);
  328.          Exit;
  329.       end;
  330.    end;
  331.    Result := nil;
  332. end;
  333. {== TMMFormStyler =============================================================}
  334. constructor TMMFormStyler.Create(AOwner: TComponent);
  335. begin
  336.    inherited Create(AOwner);
  337. {$IFNDEF BUILD_ACTIVEX}
  338.    if (FindStylerForWindow(TForm(Owner).Handle) <> nil) then
  339.       raise Exception.Create(SSecondStyler);
  340. {$ELSE}
  341.   // Oops! it's an early place to check for the neighbor...
  342. {$ENDIF}
  343.    FWindowActive  := True;  { assumption }
  344.    FActiveDefined := False;
  345.    FSystemFont := TFont.Create;
  346.    try
  347.       GetSystemFont(FSystemFont);
  348.    except
  349.       FSystemFont.Free;
  350.       FSystemFont := nil;
  351.       raise;
  352.    end;
  353.    FCompanyText := TMMCompanyText.Create(self);
  354.    FAppNameText := TMMAppNameText.Create(self);
  355.    FCaptionText := TMMCaptionText.Create(self);
  356.    FClrLeftActive    := clBlack;
  357.    FClrLeftInActive  := clBlack;
  358.    FClrRightActive   := clActiveCaption;
  359.    FClrRightInActive := clInActiveCaption;
  360.    FAlignment        := taLeftJustify;
  361.    FOptions          := goSmart;
  362.    FNumColors        := 64;
  363.    FHandle           := AllocateHwnd(HookAppWndProc);
  364.    FRecreating       := False;
  365.    HookOwner;
  366.    AddStyler(Self);
  367. {$IFNDEF BUILD_ACTIVEX}
  368.    if (csdesigning in ComponentState) and not
  369.       (csReadingState in OwnerForm.ControlState) then
  370.      ChangeDesigning(True);
  371. {$ENDIF}
  372. end;
  373. {-- TMMFormStyler -------------------------------------------------------------}
  374. destructor TMMFormStyler.Destroy;
  375. begin
  376.    if FormOK then
  377.      UnHookOwner;
  378.    RemoveStyler(Self);
  379. {$IFNDEF BUILD_ACTIVEX}
  380.    { update caption if the parent form is not being destroyed }
  381.    if (FCaptionText <> nil) and not
  382.       (csDestroying in OwnerForm.ComponentState) then
  383.    begin
  384.       OwnerForm.Caption := FCaptionText.Caption;
  385.       UpdateCaption;
  386.    end;
  387. {$ENDIF}
  388.    if FAppNameText <> nil then FAppNameText.Free;
  389.    if FCaptionText <> nil then FCaptionText.Free;
  390.    if FCompanyText <> nil then FCompanyText.Free;
  391.    if FSystemFont <> nil then FSystemFont.Free;
  392.    if (FHandle <> 0) then DeallocateHwnd(FHandle);
  393.    inherited Destroy;
  394. end;
  395. {$IFDEF BUILD_ACTIVEX}
  396. function TMMFormStyler.GetOwnerCaption: string;
  397. begin
  398.   if HookWnd <> 0 then
  399.   begin
  400.     SetLength(Result, 255);
  401.     GetWindowText(HookWnd, PChar(Result), 255);
  402.     SetLength(Result, StrLen(PChar(Result)));
  403.   end else
  404.     Result := '';
  405. end;
  406. {$ENDIF}
  407. procedure TMMFormStyler.ChangeDesigning(Value: Boolean);
  408. begin
  409.   if Value then
  410.   begin
  411.     { Set default fonts unless stored user settings are being loaded }
  412.     FCompanyText.FCaption := 'SwiftSoft';
  413.     FAppNameText.FCaption := 'MMTools -';
  414. {$IFDEF BUILD_ACTIVEX}
  415.     FCaptionText.FCaption := GetOwnerCaption;
  416. {$ELSE}
  417.     FCaptionText.FCaption := OwnerForm.Caption;
  418. {$ENDIF}
  419.     NewCaptionText;
  420.     FCaptionText.SetFontKind_noRedraw(fkSystem);
  421.     FAppNameText.SetFontkind_noRedraw(fkSystemB);  { system + bold }
  422.     FCompanyText.SetFontkind_noRedraw(fkSystemBI); { system + bold + italic }
  423.     DrawCaption(WindowIsActive);   { do the first-time draw }
  424.   end;
  425.   inherited;
  426. end;
  427. {-- TMMFormStyler -------------------------------------------------------------}
  428. procedure TMMFormStyler.Loaded;
  429. begin
  430.   inherited Loaded;
  431.   { some people have reported problems with TForm's position being poScreenCenter.
  432.     this removes the problem (I believe - I've never replicated the problem so I
  433.     can't test it). }
  434. {$IFNDEF BUILD_ACTIVEX}
  435.   if (HookWnd <> OwnerForm.Handle) then
  436.   begin
  437.      UnhookOwner;
  438.      HookOwner;
  439.   end;
  440. {$ENDIF}
  441. end;
  442. {-- TMMFormStyler -------------------------------------------------------------}
  443. function TMMFormStyler.WindowIsActive: Boolean;
  444. begin
  445.    if FActiveDefined then
  446.    begin
  447.       Result := FWindowActive;
  448.       exit;
  449.    end;
  450.    Result := (HookWnd = GetActiveWindow);
  451.    if Assigned(OwnerForm) and (OwnerForm.FormStyle = fsMDIChild) then
  452.        if Application <> nil then
  453.           if Application.Mainform <> nil then
  454.              if OwnerForm = Application.Mainform.ActiveMDIChild then
  455.                 if Application.Mainform.HandleAllocated then
  456.                    if Application.Mainform.Handle = GetActiveWindow then Result := True;
  457. end;
  458. {-- TMMFormStyler -------------------------------------------------------------}
  459. procedure TMMFormStyler.PerformNCPaint(var AMsg: TMessage);
  460. var
  461.   R, WR : TRect;
  462.   MyRgn : HRgn;
  463.   DC : HDC;
  464. begin
  465.    R := DrawCaption(WindowIsActive);
  466.    DC := GetWindowDC(HookWnd);
  467.    GetWindowRect(HookWnd, WR);
  468.    MyRgn := CreateRectRgnIndirect(WR);
  469.    try
  470.       if SelectClipRgn(DC, AMsg.wParam) = ERROR then
  471.          SelectClipRgn(DC, MyRgn);
  472.       OffsetClipRgn(DC, -WR.Left, -WR.Top);
  473.       ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
  474.       OffsetClipRgn(DC, WR.Left, WR.Top);
  475.       GetClipRgn(DC, MyRgn);
  476.       AMsg.Result := CallPrevWndProc(AMsg.Msg, MyRgn, AMsg.lParam);
  477.    finally
  478.       DeleteObject(MyRgn);
  479.       ReleaseDC(HookWnd, DC);
  480.    end;
  481. end;
  482. {-- TMMFormStyler -------------------------------------------------------------}
  483. procedure TMMFormStyler.PerformNCActivate(var AMsg: TMessage);
  484. var
  485.    R: TRect;
  486. begin
  487.    FWindowActive := TWMNCActivate(AMsg).Active;
  488.    FActiveDefined := true;
  489.    if (not NewStyleControls) then
  490.        AMsg.Result := CallPrevWndProc(AMsg.Msg, AMsg.wParam, AMsg.lParam)
  491.    else if Assigned(OwnerForm) and (OwnerForm.FormStyle = fsMDIChild) then { cover up hassles with minimized MDI children borders and button redrawing }
  492.             AMsg.Result := CallPrevWndProc(AMsg.Msg, AMsg.wParam, AMsg.lParam);
  493.    if Assigned(OwnerForm) and (OwnerForm.FormStyle = fsMDIForm) then
  494.       if Application <> nil then
  495.          if Application.Mainform <> nil then
  496.             if Application.Mainform.ActiveMDIChild <> nil then
  497.                PostMessage(Application.Mainform.ActiveMDIChild.Handle, WM_NCACTIVATE, longint(TWMNCActivate(AMsg).Active), 0);
  498.    R := GetTitleBarRect;
  499.    { cause a nc_Paint message to occur (immediately) }
  500.    ReDrawWindow(HookWnd,@R,0,RDW_FRAME or RDW_INVALIDATE or RDW_UPDATENOW);
  501.    AMsg.Result := 1;
  502.    AMsg.wParam := 1;   { Tell windows that we have handled the message }
  503. end;
  504. {-- TMMFormStyler -------------------------------------------------------------}
  505. procedure TMMFormStyler.HookWndProc(var Message: TMessage);
  506. begin
  507.    if Message.Msg = WM_NCPAINT then
  508.    begin
  509.       PerformNCPaint(Message);
  510.       exit;
  511.    end; { NCPaint is handled for win32 }
  512.    if Message.Msg = WM_NCACTIVATE then
  513.    begin
  514.       PerformNCActivate(Message);
  515.       exit;
  516.    end; { NCActivate is handled for win32 }
  517.    if Message.Msg = WM_SETCURSOR then
  518.    begin
  519.       if HandleWMSetCursor(TWMSetCursor(Message)) then
  520.       exit;
  521.    end; { SetCursor is handled for win32 }
  522.    if Message.Msg = WM_DESTROY then
  523.    begin
  524.       {Note: WM_DESTROY is trapped here when the form itself is destroyed,
  525.        and whenever the RecreateWnd method of the form is called }
  526.       if not (csDestroying in ComponentState) then
  527.       begin
  528.          { We must unhook the WindowProc, and then rehook it later }
  529.          FRecreating := True;
  530.          UnHookOwner;
  531.          { Notify WordCap to rehook the form. A message must be posted so that this
  532.            can be done once the form has completed the recreation process. }
  533.          PostMessage(FHandle, MM_RecreateNotify, 0, Longint(Self));
  534.          { don't exit.  Allow default processing to still occur }
  535.       end;
  536.    end;
  537.    { now handle all other calls }
  538.    inherited;
  539.    if Message.Msg = WM_SETICON then DrawCaption(WindowIsActive);
  540.    if ((Message.Msg = WM_DISPLAYCHANGE)  or
  541.        (Message.Msg = WM_SysColorChange) or
  542.        (Message.Msg = WM_WININICHANGE) or
  543.        (Message.Msg = WM_SETTINGCHANGE)) then
  544.    begin
  545.       GetSystemFont(FSystemFont);  { update systemfont }
  546.       FAppNameText.SetFontkind_noRedraw(FAppNameText.FFontkind);
  547.       FCaptionText.SetFontKind_noRedraw(FCaptionText.FFontKind);
  548.       FCompanyText.SetFontkind_noRedraw(FCompanyText.FFontkind);
  549.       UpdateCaption;  {force a NC region redraw};
  550.    end;
  551. end;
  552. {-- TMMFormStyler -------------------------------------------------------------}
  553. procedure TMMFormStyler.HookAppWndProc(var AMsg: TMessage);
  554. begin
  555.    if AMsg.Msg = MM_RecreateNotify then
  556.    begin
  557.       if AMsg.LParam <> longint(self) then exit;    { did the message come from this instance or another instance? }
  558.       HookOwner;  { Rehook the form }
  559.       if GetActiveWindow = HookWnd then FWindowActive := True;
  560.       UpdateCaption;
  561.    end;
  562. end;
  563. {-- TMMFormStyler -------------------------------------------------------------}
  564. procedure TMMFormStyler.UpdateCaption;
  565. begin
  566.    if FormOK then
  567.    begin
  568.       SetWindowPos(HookWnd, 0, 0, 0, 0, 0,
  569.                    SWP_FRAMECHANGED or SWP_DRAWFRAME or
  570.                    SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
  571.    end;
  572. end;
  573. {-- TMMFormStyler -------------------------------------------------------------}
  574. procedure TMMFormStyler.GetSystemFont(Font: TFont);
  575. var
  576.   FNONCLIENTMETRICS : TNONCLIENTMETRICS;
  577. begin
  578.    Font.Handle := GetStockObject(SYSTEM_FONT);
  579.    FNONCLIENTMETRICS.cbSize := Sizeof(TNONCLIENTMETRICS);
  580.    if Boolean(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0,
  581.                                    @FNONCLIENTMETRICS, 0)) then
  582.    begin
  583.       { work now with FNonClientMetrics.lfCaptionFont }
  584.       Font.Name := FNonClientMetrics.lfCaptionFont.lfFacename;
  585.       if FNonClientMetrics.lfCaptionFont.lfHeight > 0 then
  586.          Font.Size := FNonClientMetrics.lfCaptionFont.lfHeight
  587.       else
  588.          Font.Height := FNonClientMetrics.lfCaptionFont.lfHeight;
  589.       Font.Style := [];
  590.       if FNonClientMetrics.lfCaptionFont.lfItalic <> 0 then
  591.          Font.Style := Font.Style + [fsItalic];
  592.       if FNonClientMetrics.lfCaptionFont.lfWeight > FW_MEDIUM then
  593.          Font.Style := Font.Style + [fsBold];
  594.       Font.Pitch := fpDefault;
  595.    end;
  596. end;
  597. {-- TMMFormStyler -------------------------------------------------------------}
  598. procedure TMMFormStyler.NewCaptionText;
  599. var
  600.    temp: string;
  601. begin
  602.    LockWindowUpdate(HookWnd);
  603.    temp := '';
  604.    if FCompanyText.Visible then temp := temp + FCompanyText.FCaption;
  605.    if FCompanyText.Visible and (FCompanyText.Caption <> '') and
  606.       (FAppNameText.Visible or FCaptionText.Visible) then temp := temp + ' ';
  607.    if FAppNameText.Visible then temp := temp + FAppNameText.FCaption;
  608.    if FAppNameText.Visible and (FAppNameText.Caption <> '') and FCaptionText.Visible then temp := temp + ' ';
  609.    if FCaptionText.Visible then temp := temp + FCaptionText.FCaption;
  610. {$IFNDEF BUILD_ACTIVEX}
  611.    OwnerForm.Caption := temp;
  612. {$ELSE}
  613.    SetWindowText(HookWnd, PChar(temp));
  614. {$ENDIF}
  615.    LockWindowUpdate(0);
  616. end;
  617. const
  618.    // depends upon WS_EX_TOOLWINDOW
  619.   smcCaptionY: array[Boolean] of Integer = (SM_CYCAPTION, SM_CYSMCAPTION);
  620.   smcButtonX: array[Boolean] of Integer = (SM_CXSIZE, SM_CXSMSIZE);
  621.   smcButtonY: array[Boolean] of Integer = (SM_CYSIZE, SM_CYSMSIZE);
  622.    // depends upon WS_THICKFRAME
  623.   smcFrameX: array[Boolean] of Integer = (SM_CXFIXEDFRAME, SM_CXSIZEFRAME);
  624.   smcFrameY: array[Boolean] of Integer = (SM_CYFIXEDFRAME, SM_CYSIZEFRAME);
  625. {-- TMMFormStyler -------------------------------------------------------------}
  626. function TMMFormStyler.GetTitleBarRect: TRect;
  627. var
  628.   Style, ExStyle: Integer;
  629.   SizeFrame, ToolWindow: Boolean;
  630. begin
  631.   Style := GetWindowLong(HookWnd, GWL_STYLE);
  632.   ExStyle := GetWindowLong(HookWnd, GWL_EXSTYLE);
  633. {$IFNDEF BUILD_ACTIVEX}
  634.   if csDesigning in ComponentState then
  635.   begin
  636.     Style := WS_CAPTION or WS_THICKFRAME;
  637.     ExStyle := 0;
  638.   end;
  639. {$ENDIF}
  640.    { if we have no border style, then just set the rectangle empty. }
  641.   if Style and WS_BORDER = 0 then
  642.   begin
  643.     SetRectEmpty(Result);
  644.     exit;
  645.   end;
  646.   GetWindowRect(HookWnd, Result);
  647.    { Convert rect from screen (absolute) to client (0 based) coordinates. }
  648.   OffsetRect(Result, -Result.Left, -Result.Top);
  649.    { Shrink rectangle to allow for window border.  We let Windows paint the border. }
  650.    { this catches drawing MDI minimised windows caption bars in Win95 }
  651.   if IsIconic(HookWnd) then
  652.   begin
  653.     InflateRect(Result, -GetSystemMetrics(SM_CXFIXEDFRAME),
  654.                         -GetSystemMetrics(SM_CYFIXEDFRAME));
  655.     if not NewStyleControls then
  656.       InflateRect(Result, -GetSystemMetrics(SM_CYBORDER),
  657.                           -GetSystemMetrics(SM_CYBORDER));
  658.   end else
  659.   begin
  660.     SizeFrame := Style and WS_THICKFRAME <> 0;
  661.     InflateRect(Result, -GetSystemMetrics(smcFrameX[SizeFrame]),
  662.                         -GetSystemMetrics(smcFrameY[SizeFrame]));
  663.   end;
  664.   { Set the appropriate height of caption bar. }
  665.   ToolWindow := ExStyle and WS_EX_TOOLWINDOW <> 0;
  666.   with Result do
  667.     Bottom := Top + GetSystemMetrics(smcCaptionY[ToolWindow]) - 1;
  668. end;
  669. {-- TMMFormStyler -------------------------------------------------------------}
  670. function TMMFormStyler.GetVisibleButtons: TBorderIcons;
  671. {$IFNDEF BUILD_ACTIVEX}
  672. var
  673.    BS: TFormBorderStyle;
  674. begin
  675.    Result := [];
  676.    if csDesigning in ComponentState then
  677.    begin
  678.       Result := [biSystemMenu, biMaximize, biMinimize];
  679.       exit;
  680.    end;
  681.    BS:= OwnerForm.BorderStyle;
  682.    if BS = bsNone then exit;
  683.    if not (biSystemMenu in OwnerForm.BorderIcons) then exit;  { none will be visible }
  684.    if BS in [bsToolWindow, bsSizeToolWin] then
  685.    begin
  686.       Result := [biSystemMenu];  { close icon only }
  687.       exit;
  688.    end;
  689.    if (NewStyleControls and (biSystemMenu in OwnerForm.BorderIcons)) then
  690.        Result := [biSystemMenu];  { close icon - this is OS dependant }
  691.    if ((BS = bsDialog) and (biHelp in OwnerForm.BorderIcons) and
  692.        (biSystemMenu in OwnerForm.BorderIcons)) then
  693.       Result := Result + [biHelp];  { help icon }
  694.    if ((BS = bsSingle) and (biHelp in OwnerForm.BorderIcons) and
  695.        (not(biMinimize in OwnerForm.BorderIcons)) and
  696.        (not(biMaximize in OwnerForm.BorderIcons))) then
  697.       Result := Result + [biHelp];  { help icon }
  698.    if ((BS = bsSizeable) and (biHelp in OwnerForm.BorderIcons) and
  699.        (not(biMinimize in OwnerForm.BorderIcons)) and
  700.        (not(biMaximize in OwnerForm.BorderIcons))) then
  701.       Result := Result + [biHelp];  { help icon }
  702.    if BS = bsDialog then exit;  { no chance of Min&Max buttons }
  703.    if NewStyleControls then
  704.    begin
  705.       if ((biMinimize in OwnerForm.BorderIcons) or (biMaximize in OwnerForm.BorderIcons)) then
  706.          Result := Result + [biMinimize, biMaximize];  { minimise and maximise button }
  707.    end
  708.    else
  709.    begin
  710.       if (biMinimize in OwnerForm.BorderIcons) then
  711.          Result := Result + [biMinimize];  { minimise button }
  712.       if (biMaximize in OwnerForm.BorderIcons) then
  713.          Result := Result + [biMaximize];  { maximise button }
  714.    end;
  715. {$ELSE}
  716. var
  717.   Style, ExStyle: Integer;
  718. begin
  719.   Style := GetWindowLong(HookWnd, GWL_STYLE);
  720.   ExStyle := GetWindowLong(HookWnd, GWL_EXSTYLE);
  721.   Result := [];
  722.   if not Style and (WS_BORDER or WS_SYSMENU) = 0 then
  723.     if ExStyle and WS_EX_TOOLWINDOW = 0 then
  724.     begin
  725.       if NewStyleControls then
  726.         Include(Result, biSystemMenu); { close icon - this is OS dependant }
  727.       if ExStyle and WS_EX_CONTEXTHELP <> 0 then
  728.         Include(Result, biHelp);
  729.       if (Style and DS_MODALFRAME = 0) and (ExStyle and WS_EX_DLGMODALFRAME = 0) then
  730.       begin
  731.         if Style and WS_MINIMIZEBOX <> 0 then
  732.           Include(Result, biMinimize);
  733.         if Style and WS_MAXIMIZEBOX <> 0 then
  734.           Include(Result, biMaximize);
  735.         if NewStyleControls and (Result * [biMinimize, biMaximize] <> []) then
  736.           Result := Result + [biMinimize, biMaximize];
  737.       end
  738.     end else
  739.       Result := [biSystemMenu]; { close icon only }
  740. {$ENDIF}
  741. end;
  742. {-- TMMFormStyler -------------------------------------------------------------}
  743. procedure TMMFormStyler.ExcludeBtnRgn (var R: TRect);
  744. {$IFNDEF BUILD_ACTIVEX}
  745. var
  746.    BtnWidth: integer;
  747.    BI: TBorderIcons;
  748. begin
  749.    if ((OwnerForm.BorderStyle = bsNone) and
  750.        (not(csDesigning in ComponentState))) then exit;
  751.    if ((OwnerForm.BorderStyle in [bsToolWindow, bsSizeToolWin]) and
  752.       (not(csDesigning in ComponentState))) then
  753.       BtnWidth := GetSystemMetrics(SM_CXSMSIZE)
  754.    else
  755.       BtnWidth := GetSystemMetrics(SM_CXSIZE);
  756.   BI := GetVisibleButtons;
  757.   if (biSystemMenu in BI) then R.Right := R.Right - BtnWidth - 2; { close icon }
  758.   if (biMinimize in BI) then R.Right := R.Right - BtnWidth;  { minimize icon }
  759.   if (biMaximize in BI) then R.Right := R.Right - BtnWidth;  { maximize icon }
  760.   if (biHelp in BI) then R.Right := R.Right - BtnWidth - 2;  { help icon }
  761.   if not NewStyleControls then
  762.      if (((biSystemMenu in OwnerForm.BorderIcons) and
  763.           (OwnerForm.BorderStyle in [bsSingle, bsSizeable])) or
  764.           (csDesigning in ComponentState)) then
  765.         R.Left := R.Left + BtnWidth;  { let windows do the system icon in win3 style }
  766. {$ELSE}
  767. var
  768.   BtnWidth,
  769.   Style, ExStyle: Integer;
  770.   BI: TBorderIcons;
  771. begin
  772.   Style := GetWindowLong(HookWnd, GWL_STYLE);
  773.   ExStyle := GetWindowLong(HookWnd, GWL_EXSTYLE);
  774.   if Style and WS_BORDER <> 0 then
  775.   begin
  776.     BtnWidth := GetSystemMetrics(smcButtonX[ExStyle and WS_EX_TOOLWINDOW <> 0]);
  777.     BI := GetVisibleButtons;
  778.     if (biSystemMenu in BI) then
  779.       if NewStyleControls
  780.         then Dec(R.Right, BtnWidth + 2) { close icon }
  781.         else Inc(R.Left, BtnWidth);  { let windows do the system icon in win3 style }
  782.     if (biMinimize in BI)   then Dec(R.Right, BtnWidth);     { minimize icon }
  783.     if (biMaximize in BI)   then Dec(R.Right, BtnWidth);     { maximize icon }
  784.     if (biHelp in BI)       then Dec(R.Right, BtnWidth + 2); { help icon }
  785.   end;
  786. {$ENDIF}
  787. end;
  788. {-- TMMFormStyler -------------------------------------------------------------}
  789. function TMMFormStyler.GetTextRect: TRect;
  790. begin
  791.    Result := GetTitleBarRect;
  792.    ExcludeBtnRgn(result);
  793.    if Result.Right <= Result.Left then {error}
  794.       Result.Right := Result.Left+2;  { right must be greater than left- otherwise system resources get lost }
  795. end;
  796. {-- TMMFormStyler -------------------------------------------------------------}
  797. procedure TMMFormStyler.PaintMenuIcon(DC: HDC; var R: TRect);
  798. const
  799.   LR_COPYFROMRESOURCE = $4000; { Missing from WINDOWS.PAS! }
  800. var
  801.   IconHandle: HIcon;
  802.   NewIconHandle: HIcon;
  803.   IconNeedsDestroying : Boolean;
  804.   IconX, IconY : integer;
  805. begin
  806.    if not NewStyleControls then exit;  { a safety catch - shouldn't be needed }
  807.    Inc(R.Left, 1);
  808.    IconNeedsDestroying := False;
  809.    { Does the form (or application) have an icon assigned to it? }
  810. {$IFDEF BUILD_ACTIVEX}
  811.    if HookWnd <> 0 then
  812.      IconHandle := GetClassLong(HookWnd, GCL_HICON);
  813.    if IconHandle = 0 then
  814. {$ELSE}
  815.    if OwnerForm.Icon.Handle <> 0 then
  816.       IconHandle := OwnerForm.Icon.Handle
  817.    else
  818. {$ENDIF}
  819.      if Application.Icon.Handle <> 0 then
  820.        IconHandle := Application.Icon.Handle
  821.    else
  822.    begin
  823.       IconHandle := LoadIcon(0, IDI_APPLICATION);  { system defined application icon. }
  824.       IconNeedsDestroying := True;
  825.    end;
  826.    IconX := GetSystemMetrics(SM_CXSMICON);
  827.    if IconX = 0 then IconX := GetSystemMetrics(SM_CXSIZE);
  828.    IconY := GetSystemMetrics(SM_CYSMICON);
  829.    if IconY = 0 then IconY := GetSystemMetrics(SM_CYSIZE);
  830.    NewIconHandle := CopyImage(IconHandle,
  831.                               IMAGE_ICON,  { what is it's value??? }
  832.                               IconX, IconY,
  833.                               LR_COPYFROMRESOURCE);
  834.    DrawIconEx(DC, R.Left+1, R.Top+1,
  835.               NewIconHandle,
  836.               0, 0, 0, 0, DI_NORMAL);
  837.    DestroyIcon(NewIconHandle);
  838.    if IconNeedsDestroying then DestroyIcon(IconHandle);
  839.    Inc(R.Left, GetSystemMetrics(SM_CXSMICON)+1);
  840. end;
  841. {-- TMMFormStyler -------------------------------------------------------------}
  842. procedure TMMFormStyler.PaintCaptionText(DC: HDC; var R: TRect; Text: TMMCompanyText; Active: Boolean);
  843. var
  844.    OldColor: TColorRef;
  845.    OldBkMode: integer;
  846.    OldFont: HFont;
  847.    P: ^string;
  848.    S:String;
  849.    RTemp: TRect;
  850. begin
  851.    Inc(R.Left, WordSpacing);
  852.    RTemp:= R;
  853.    if Active then
  854.       OldColor := SetTextColor(DC, ColorToRGB(Text.FColorActive))
  855.    else
  856.       OldColor := SetTextColor(DC, ColorToRGB(Text.FColorInActive));
  857.    OldBkMode := SetBkMode(DC, TRANSPARENT);  { paint text transparently - so gradient can show through }
  858.    { Select in the required font for this text. }
  859.    if Text.FFont.Handle <> 0 then
  860.       OldFont := SelectObject(DC, Text.FFont.Handle)
  861.    else
  862.       OldFont := 0;
  863.    try
  864.       { Draw the text making it left aligned, centered vertically, allowing no line breaks. }
  865.       S := Text.FCaption + #0;
  866.       P := @S[1];
  867.       DrawText(DC, PChar(P), -1, RTemp, DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_CALCRECT);
  868.       DrawText(DC, PChar(P), -1, R, DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS);
  869.       R.Left := RTemp.Right;
  870.    finally
  871.       { Clean up all the drawing objects. }
  872.       if OldFont <> 0 then
  873.          SelectObject(DC, OldFont);
  874.       SetBkMode(DC, OldBkMode);
  875.       SetTextColor(DC, OldColor);
  876.    end;
  877. end;
  878. {-- TMMFormStyler -------------------------------------------------------------}
  879. procedure TMMFormStyler.PaintCaptionButtons(DC: HDC; var Rect: TRect);
  880. {$IFNDEF BUILD_ACTIVEX}
  881. var
  882.   BtnWidth: integer;
  883.   Flag    : UINT;
  884.   SrcRect : TRect;
  885.   Btns    : TBorderIcons;
  886. begin
  887.    SrcRect := Rect;
  888.    InflateRect(SrcRect, -2, -2);
  889.    Btns := GetVisibleButtons;
  890.    BtnWidth := GetSystemMetrics(SM_CXSIZE)-2;
  891.    if ((OwnerForm.BorderStyle in [bsToolWindow, bsSizeToolWin]) and
  892.        (not (csDesigning in ComponentState))) then
  893.       BtnWidth := GetSystemMetrics(SM_CXSMSIZE)-2;
  894.    SrcRect.Left := SrcRect.Right - BtnWidth;
  895.    { Close button }
  896.    if biSystemMenu in Btns then
  897.    begin
  898.       DrawFrameControl(DC, SrcRect, DFC_CAPTION, DFCS_CAPTIONCLOSE);
  899.       OffsetRect(SrcRect, -BtnWidth-2, 0);
  900.       Dec(Rect.Right,BtnWidth+2);
  901.    end;
  902.    { Maximize button }
  903.    if biMaximize in Btns then
  904.    begin
  905.       if IsZoomed(HookWnd) then
  906.          Flag := DFCS_CAPTIONRESTORE
  907.       else
  908.          Flag := DFCS_CAPTIONMAX;
  909.       { if it doesn't have max in style, then it shows up disabled }
  910.       if not (biMaximize in OwnerForm.BorderIcons) then
  911.          Flag := Flag or DFCS_INACTIVE;
  912.       DrawFrameControl(DC, SrcRect, DFC_CAPTION, Flag);
  913.       OffsetRect(SrcRect, -BtnWidth, 0);
  914.       Dec(Rect.Right,BtnWidth);
  915.    end;
  916.    { Minimize button }
  917.    if biMinimize in Btns then
  918.    begin
  919.       if IsIconic(HookWnd) then
  920.          Flag := DFCS_CAPTIONRESTORE
  921.       else
  922.          Flag := DFCS_CAPTIONMIN;
  923.       { if it doesn't have min in style, then it shows up disabled }
  924.       if not (biMinimize in OwnerForm.BorderIcons) then
  925.          Flag := Flag or DFCS_INACTIVE;
  926.       DrawFrameControl(DC, SrcRect, DFC_CAPTION, Flag);
  927.       OffsetRect(SrcRect, -BtnWidth, 0);
  928.       Dec(Rect.Right,BtnWidth);
  929.    end;
  930.    { Help button }
  931.    if (biHelp in Btns) then
  932.    begin
  933.       DrawFrameControl(DC, SrcRect, DFC_CAPTION, DFCS_CAPTIONHELP);
  934.       Dec(Rect.Right,BtnWidth);
  935.    end;
  936.    Dec(Rect.Right, 3);
  937. {$ELSE}
  938. var
  939.   BtnWidth: integer;
  940.   Flag: UINT;
  941.   SrcRect: TRect;
  942.   Style, ExStyle: Integer;
  943.   BI: TBorderIcons;
  944. begin
  945.   Style := GetWindowLong(HookWnd, GWL_STYLE);
  946.   ExStyle := GetWindowLong(HookWnd, GWL_EXSTYLE);
  947.   SrcRect := Rect;
  948.   InflateRect(SrcRect, -2, -2);
  949.   BI := GetVisibleButtons;
  950.   BtnWidth := GetSystemMetrics(smcButtonX[ExStyle and WS_EX_TOOLWINDOW <> 0]) - 2;
  951.   SrcRect.Left := SrcRect.Right - BtnWidth;
  952.    { Close button }
  953.   if biSystemMenu in BI then
  954.   begin
  955.     DrawFrameControl(DC, SrcRect, DFC_CAPTION, DFCS_CAPTIONCLOSE);
  956.     OffsetRect(SrcRect, -BtnWidth-2, 0);
  957.     Dec(Rect.Right, BtnWidth+2);
  958.   end;
  959.    { Maximize button }
  960.   if biMaximize in BI then
  961.   begin
  962.     if IsZoomed(HookWnd)
  963.       then Flag := DFCS_CAPTIONRESTORE
  964.       else Flag := DFCS_CAPTIONMAX;
  965.      { if it doesn't have max in style, then it shows up disabled }
  966.     if Style and WS_MAXIMIZEBOX = 0 then
  967.       Flag := Flag or DFCS_INACTIVE;
  968.     DrawFrameControl(DC, SrcRect, DFC_CAPTION, Flag);
  969.     OffsetRect(SrcRect, -BtnWidth, 0);
  970.     Dec(Rect.Right,BtnWidth);
  971.   end;
  972.    { Minimize button }
  973.   if biMinimize in BI then
  974.   begin
  975.     if IsIconic(HookWnd)
  976.       then Flag := DFCS_CAPTIONRESTORE
  977.       else Flag := DFCS_CAPTIONMIN;
  978.      { if it doesn't have min in style, then it shows up disabled }
  979.     if Style and WS_MINIMIZEBOX = 0 then
  980.       Flag := Flag or DFCS_INACTIVE;
  981.     DrawFrameControl(DC, SrcRect, DFC_CAPTION, Flag);
  982.     OffsetRect(SrcRect, -BtnWidth, 0);
  983.     Dec(Rect.Right,BtnWidth);
  984.   end;
  985.    { Help button }
  986.   if (biHelp in BI) then
  987.   begin
  988.     DrawFrameControl(DC, SrcRect, DFC_CAPTION, DFCS_CAPTIONHELP);
  989.     Dec(Rect.Right,BtnWidth);
  990.   end;
  991.   Dec(Rect.Right, 3);
  992. {$ENDIF}
  993. end;
  994. {-- TMMFormStyler -------------------------------------------------------------}
  995. function TMMFormStyler.MeasureText(DC: HDC; R: TRect; Text: TMMCompanyText): integer;
  996. var
  997.   OldFont: HFont;
  998.   P: ^string;
  999.   S: String;
  1000. begin
  1001.    { Select in the required font for this text. }
  1002.    if Text.FFont.Handle <> 0 then
  1003.       OldFont := SelectObject(DC, Text.FFont.Handle)
  1004.    else
  1005.       OldFont := 0;
  1006.    try     { Measure the text making it left aligned, centered vertically, allowing no line breaks. }
  1007.       S := Text.FCaption + #0;
  1008.       P := @S[1];
  1009.       DrawText(DC, PChar(P), -1, R, DT_LEFT or DT_VCENTER or DT_SINGLELINE or DT_CALCRECT);
  1010.       Result := R.Right + WordSpacing - R.Left {-1};
  1011.    finally
  1012.       { Clean up all the drawing objects. }
  1013.       if OldFont <> 0 then SelectObject(DC, OldFont);
  1014.    end;
  1015. end;
  1016. {-- TMMFormStyler -------------------------------------------------------------}
  1017. function TMMFormStyler.DrawCaption(Active: Boolean): TRect;
  1018. var
  1019.    DC,OrigDC     : HDC;
  1020.    rcText        : TRect;
  1021.    rcCaption     : TRect;
  1022.    rgbColorLeft  : TColor;
  1023.    rgbColorRight : TColor;
  1024.    rgbColorPlain : TColor;
  1025.    OldBmp        : HBitmap;
  1026.    Bmp           : HBitmap;
  1027.    TotalTextWidth: longint;
  1028.    SpaceForCompanyText : Boolean;
  1029.    SpaceForAppNameText : Boolean;
  1030.    NumColors     : longint;
  1031.    Shaded        : Boolean;
  1032. begin
  1033.    Result := Rect(0,0,0,0);
  1034. {$IFNDEF BUILD_ACTIVEX}
  1035.    if ((OwnerForm.BorderStyle = bsNone) and (not (csdesigning in ComponentState))) then
  1036. {$ELSE}
  1037.    if GetWindowLong(HookWnd, GWL_STYLE) and WS_BORDER = 0 then
  1038. {$ENDIF}
  1039.         exit;
  1040.    OrigDC := GetWindowDC(HookWnd);
  1041.    if OrigDC = 0 then exit;
  1042.    DC := CreateCompatibleDC(OrigDC);
  1043.    if DC = 0 then
  1044.    begin
  1045.       ReleaseDC(HookWnd, OrigDC);
  1046.       exit;
  1047.    end;
  1048.    rcText := GetTextRect;
  1049.    rcCaption := GetTextRect;
  1050.    if NewStyleControls then rcCaption := GetTitleBarRect;
  1051.    Bmp := CreateCompatibleBitmap(OrigDC, rcCaption.Right, rcCaption.Bottom);
  1052.    if Bmp = 0 then
  1053.    begin
  1054.       ReleaseDC(HookWnd, OrigDC);
  1055.       DeleteDC(DC);
  1056.       exit;
  1057.    end;
  1058.    OldBmp := SelectObject(DC, Bmp);
  1059.    try
  1060.       Result := rcCaption;
  1061.       if Active then
  1062.          rgbColorPlain := ColorToRGB(clActiveCaption)
  1063.       else
  1064.          rgbColorPlain := ColorToRGB(clInActiveCaption);
  1065.       if Active then
  1066.          rgbColorRight := ColorToRGB(ClrRightActive)
  1067.       else
  1068.          rgbColorRight := ColorToRGB(ClrRightInactive);
  1069.       if Active then
  1070.          rgbColorLeft  := ColorToRGB(ClrLeftActive)
  1071.       else
  1072.          rgbColorLeft  := ColorToRGB(ClrLeftInactive);
  1073.       case FOptions of
  1074.           goAlways : Shaded := True;
  1075.           goNever  : Shaded := False;
  1076.           goActive : Shaded := Active;
  1077.           goSmart  :
  1078.           begin
  1079.              NumColors := GetDeviceCaps(DC, BITSPIXEL);
  1080.              if Active then
  1081.                 Shaded := NumColors >= 8
  1082.              else
  1083.                 Shaded := NumColors > 8;
  1084.           end;
  1085.           else Shaded := False;
  1086.       end;
  1087.       if NewStyleControls then
  1088.       begin
  1089.          if Shaded then
  1090.             FillSolid(DC, rgbColorRight, rcCaption)
  1091.          else
  1092.             FillSolid(DC, rgbColorPlain, rcCaption);
  1093.       end;
  1094.       if Shaded then
  1095.          FillGradient(DC, rgbColorLeft, rgbColorRight, FNumColors, rcText)
  1096.       else
  1097.          FillSolid(DC, rgbColorPlain, rcText);
  1098. {$IFNDEF BUILD_ACTIVEX}
  1099.       if NewStyleControls then
  1100.          if (((biSystemMenu in OwnerForm.BorderIcons) and
  1101.              (OwnerForm.BorderStyle in [bsSingle, bsSizeable])) or
  1102.              (csDesigning in ComponentState)) then
  1103. {$ELSE}
  1104.       if NewStyleControls then
  1105.          if (GetWindowLong(HookWnd, GWL_STYLE) and WS_SYSMENU <> 0) and
  1106.             (GetWindowLong(HookWnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW = 0) then
  1107. {$ENDIF}
  1108.             PaintMenuIcon(DC, rcText);
  1109.       if NewStyleControls then
  1110.          PaintCaptionButtons(DC, rcCaption);
  1111.       {------------------------------------------------------------------------}
  1112.       {Determine if there is sufficient space for the CompanyName text and the }
  1113.       {CompanyName text and the standard caption text to be all drawn onto the }
  1114.       {working Bitmap (i.e. the caption).  If not, is there enough room for    }
  1115.       {the AppName text and the standard caption?                              }
  1116.       {------------------------------------------------------------------------}
  1117.       FCaptionText.FCaption := FCaptionText.Caption; { safety - catches MDI changes }
  1118.       TotalTextWidth := MeasureText(DC,rcText,FCompanyText)*Ord(FCompanyText.Visible)
  1119.                                     + MeasureText(dc,rcText,FAppNameText) * ord(FAppNameText.Visible)
  1120.                                     + MeasureText(dc,rcText,FCaptionText) * ord(FCaptionText.Visible);
  1121.       SpaceForCompanyText := (TotalTextWidth < (rcText.Right - rcText.Left));
  1122.       if SpaceForCompanyText then
  1123.          SpaceForAppNameText := True { space for company ==> space for appname }
  1124.       else
  1125.       begin
  1126.          TotalTextWidth := MeasureText(DC,rcText,FAppNameText) * ord(FAppNameText.Visible)
  1127.                                        + MeasureText(dc,rcText,FCaptionText) * ord(FCaptionText.Visible);
  1128.          SpaceForAppNameText := (TotalTextWidth < (rcText.Right - rcText.Left));
  1129.       end;
  1130.       if not SpaceForAppNameText then
  1131.          TotalTextWidth := MeasureText(DC,rcText,FCaptionText);
  1132.       case FAlignment of
  1133.         taLeftJustify  : { do nothing at all - it is already setup for this default };
  1134.         taCenter       : if (TotalTextWidth < rcText.right - rcText.left) then
  1135.                              rcText.Left := rcText.left + ((rcText.right - rcText.left - TotalTextWidth) div 2);
  1136.         taRightJustify : if (TotalTextWidth < rcText.right - rcText.left) then
  1137.                              rcText.Left := rcText.left + (rcText.right - rcText.left - TotalTextWidth);
  1138.       end;
  1139.       {------------------------------------------------------------------------}
  1140.       { Actually draw the CompanyText, AppNameText, and CaptionText.           }
  1141.       {------------------------------------------------------------------------}
  1142.       if (SpaceForCompanyText and (FCompanyText.FCaption <> '') and (FCompanyText.FVisible)) then
  1143.           PaintCaptionText(DC, rcText, FCompanyText, Active);
  1144.       if ((SpaceForAppNameText) and (FAppNameText.FCaption <> '') and (FAppNameText.FVisible)) then
  1145.            PaintCaptionText(DC, rcText, FAppNameText, Active);
  1146.       { Truncate the window caption text, until it will fit into the caption bar.}
  1147.       if FCaptionText.FVisible then
  1148.          PaintCaptionText(DC, rcText, FCaptionText, Active);
  1149.       { copy from temp DC, onto the actual window Caption }
  1150.       BitBlt(OrigDC, Result.Left, Result.Top, Result.Right-Result.Left,
  1151.                      Result.Bottom-Result.Top,
  1152.              DC, Result.Left, Result.Top, SRCCOPY);
  1153.    finally
  1154.       { Clean up device context & free memory}{ Release the working bitmap resources }
  1155.       Bmp := SelectObject(DC, OldBmp);
  1156.       DeleteObject(Bmp);
  1157.       DeleteDC(DC);
  1158.       ReleaseDC(HookWnd, OrigDC);
  1159.    end;
  1160. end;
  1161. {-- TMMFormStyler -------------------------------------------------------------}
  1162. procedure TMMFormStyler.SetAutoFontHeight(Font: TFont);
  1163. var
  1164.    FTextHeight    : longint;
  1165.    FSysTextHeight : longint;
  1166.    FTextMetrics   : TTextMetric;
  1167.    FSysTextMetrics: TTextMetric;
  1168.    WrkBMP         : TBitmap;
  1169. begin
  1170.    WrkBmp := TBitmap.Create;
  1171.    try
  1172.       WrkBmp.Width := 10;
  1173.       WrkBmp.Height := 10;
  1174.       WrkBMP.Canvas.Font.Assign(Font);
  1175.       GetTextMetrics(WrkBmp.Canvas.Handle, FTextMetrics);
  1176.       WrkBMP.Canvas.Font.Assign(FSystemFont);
  1177.       GetTextMetrics(WrkBmp.Canvas.Handle, FSysTextMetrics);
  1178.       FTextHeight := FTextMetrics.tmHeight - FTextMetrics.tmInternalLeading;
  1179.       FSysTextHeight := FSysTextMetrics.tmHeight - FSysTextMetrics.tmInternalLeading;
  1180.       Font.Height:= Font.Height + FTextHeight - FSysTextHeight;
  1181.       WrkBMP.Canvas.Font.Assign(Font);
  1182.       GetTextMetrics(WrkBmp.Canvas.Handle, FTextMetrics);
  1183.       FTextHeight := FTextMetrics.tmHeight - FTextMetrics.tmInternalLeading;
  1184.       if (FTextHeight > FSysTextHeight) then
  1185.           Font.Height := Font.Height + FTextHeight - FSysTextHeight;
  1186.    finally
  1187.        Wrkbmp.Free;
  1188.    end;
  1189. end;
  1190. {-- TMMFormStyler -------------------------------------------------------------}
  1191. procedure TMMFormStyler.SetColors(index: integer; aValue: TColor);
  1192. begin
  1193.    case index of
  1194.        0: if (aValue = FClrLeftActive) then exit else FClrLeftActive := aValue;
  1195.        1: if (aValue = FClrLeftInActive) then exit else FClrLeftInActive := aValue;
  1196.        2: if (aValue = FClrRightActive) then exit else FClrRightActive := aValue;
  1197.        3: if (aValue = FClrRightInActive) then exit else FClrRightInActive := aValue;
  1198.    end;
  1199.    if csDesigning in ComponentState then UpdateCaption;
  1200. end;
  1201. {-- TMMFormStyler -------------------------------------------------------------}
  1202. procedure TMMFormStyler.SetOptions(aValue: TMMGradientOptions);
  1203. begin
  1204.    if (aValue <> FOptions) then
  1205.    begin
  1206.       FOptions := aValue;
  1207.       if csDesigning in ComponentState then UpdateCaption;
  1208.    end;
  1209. end;
  1210. {-- TMMFormStyler -------------------------------------------------------------}
  1211. procedure TMMFormStyler.SetAlignment(aValue: TAlignment);
  1212. begin
  1213.    if (aValue <> FAlignment) then
  1214.    begin
  1215.       FAlignment := aValue;
  1216.       if csDesigning in ComponentState then UpdateCaption;
  1217.    end;
  1218. end;
  1219. {-- TMMFormStyler -------------------------------------------------------------}
  1220. procedure TMMFormStyler.SetNumColors(aValue: TMMGradientColors);
  1221. begin
  1222.    if (aValue <> FNumColors) then
  1223.    begin
  1224.       FNumColors := aValue;
  1225.       if csDesigning in ComponentState then UpdateCaption;
  1226.    end;
  1227. end;
  1228. {-- TMMFormStyler -------------------------------------------------------------}
  1229. function TMMFormStyler.HandleWMSetCursor(var Msg: TWMSetCursor): Boolean;
  1230. begin
  1231.    Msg.Result := 1;
  1232.    { Load and display the correct cursor for the border area being hit }
  1233.    case Msg.HitTest of
  1234.        HTTOP,
  1235.        HTBOTTOM     : SetCursor(LoadCursor(0, MakeIntResource(IDC_SIZENS)));
  1236.        HTLEFT,
  1237.        HTRIGHT      : SetCursor(LoadCursor(0, MakeIntResource(IDC_SIZEWE)));
  1238.        HTTOPRIGHT,
  1239.        HTBOTTOMLEFT : SetCursor(LoadCursor(0, MakeIntResource(IDC_SIZENESW)));
  1240.        HTTOPLEFT,
  1241.        HTBOTTOMRIGHT: SetCursor(LoadCursor(0, MakeIntResource(IDC_SIZENWSE)));
  1242.      else
  1243.      begin
  1244.         Msg.Result := 0;
  1245.         inherited;
  1246.      end;
  1247.    end;
  1248.    Result := (Msg.Result = 1);
  1249. end;
  1250. {$IFDEF BUILD_ACTIVEX}
  1251. procedure TMMFormStyler.HookOwner;
  1252. var
  1253.   Styler: TMMFormStyler;
  1254. begin
  1255.   if Enabled and not (csDestroying in ComponentState) then
  1256.   begin
  1257.     Styler := FindStylerForWindow(HookWnd);
  1258.     if (Styler <> Self) and (Styler <> nil) then
  1259.     begin
  1260.       Enabled := False;
  1261.       exit; // raise Exception.Create(SSecondStyler);
  1262.     end;
  1263.     inherited;
  1264.     UpdateCaption;
  1265.   end;
  1266. end;
  1267. procedure TMMFormStyler.UnhookOwner;
  1268. var
  1269.   H: HWnd;
  1270. begin
  1271.   if FormOK then
  1272.   begin
  1273.     H := HookWnd;
  1274.     inherited;
  1275.     SetWindowText(H, PChar(FCaptionText.Caption));
  1276.     InvalidateRect(H, nil, False);
  1277.   end else
  1278.     inherited;
  1279. end;
  1280. procedure TMMFormStyler.CMEnabledChanged(var M: TMessage);
  1281. begin
  1282.   inherited;
  1283.   if Enabled then HookOwner else UnhookOwner;
  1284.   UpdateCaption;
  1285. end;
  1286. {$ENDIF}
  1287. end.