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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       BusinessSkinForm                                            }
  5. {       Version 2.90                                                }  
  6. {                                                                   }
  7. {       Copyright (c) 2000-2004 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. {$P+,S-,W-,R-}
  15. {$WARNINGS OFF}
  16. {$HINTS OFF}
  17. unit bsSkinHint;
  18. interface
  19. uses
  20.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  21.   bsSkinData, ExtCtrls;
  22. type
  23.   TbsSkinHint = class;
  24.   TbsSkinHintWindow = class(THintWindow)
  25.   private
  26.     NewClRect: TRect;
  27.     NewLTPoint, NewRTPoint,
  28.     NewLBPoint, NewRBPoint: TPoint;
  29.     FspHint: TbsSkinHint;
  30.     DrawBuffer: TBitMap;
  31.     FSD:  TbsSkinData;
  32.     FRgn: HRGN;
  33.     FOldAlphaBlend: Boolean;
  34.     FOldAlphaBlendValue: Byte;
  35.     procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;
  36.     procedure WMEraseBkGnd(var Msg: TWMEraseBkgnd); message WM_EraseBkgnd;
  37.     function FindHintComponent: TBSSKINHINT;
  38.     procedure CalcHintSize(Cnvs: TCanvas; S: String; var W, H: Integer);
  39.   protected
  40.     procedure SetHintWindowRegion;
  41.     procedure CreateParams(var Params: TCreateParams); override;
  42.     procedure Paint; override;
  43.   public
  44.     constructor Create(AOwner: TComponent); override;
  45.     destructor Destroy; override;
  46.     procedure ActivateHint(Rect: TRect; const AHint: string); override;
  47.   end;
  48.   TbsSkinHint = class(TComponent)
  49.   private
  50.     FOnShowHint: TShowHintEvent;
  51.     FActive: Boolean;
  52.     FSD: TbsSkinData;
  53.     HW: TbsSkinHintWindow;
  54.     FAlphaBlend: Boolean;
  55.     FAlphaBlendValue: Byte;
  56.     FDefaultFont: TFont;
  57.     FUseSkinFont: Boolean;
  58.     HintTimer: TTimer;
  59.     HintText: String;
  60.     procedure SetActive(Value: Boolean);
  61.     procedure SetDefaultFont(Value: TFont);
  62.     procedure HintTime1(Sender: TObject);
  63.     procedure HintTime2(Sender: TObject);
  64.   protected
  65.     procedure Notification(AComponent: TComponent;
  66.       Operation: TOperation); override;
  67.     procedure SetSkinData(Value: TbsSkinData);
  68.     procedure SelfOnShowHint(var HintStr: string;
  69.                              var CanShow: Boolean; var HintInfo: THintInfo);
  70.   public
  71.     constructor Create(AOwner: TComponent); override;
  72.     destructor Destroy; override;
  73.     function GetCursorHeightMargin: Integer;
  74.     procedure ActivateHint(P: TPoint; const AHint: string);
  75.     procedure ActivateHint2(const AHint: string);
  76.     function IsVisible: Boolean;
  77.     procedure HideHint; 
  78.   published
  79.     property SkinData: TbsSkinData read FSD write SetSkinData;
  80.     property Active: Boolean read FActive write SetActive;
  81.     property AlphaBlend: Boolean read FAlphaBlend write FAlphaBlend;
  82.     property AlphaBlendValue: Byte read FAlphaBlendValue write FAlphaBlendValue;  
  83.     property DefaultFont: TFont read FDefaultFont write SetDefaultFont;
  84.     property UseSkinFont: Boolean read FUseSkinFont write FUseSkinFont;
  85.     property OnShowHint: TShowHintEvent read FOnShowHint write FOnShowHint;
  86.   end;
  87. implementation
  88.   Uses bsUtils;
  89. const
  90.   CS_DROPSHADOW_ = $20000;
  91. constructor TbsSkinHintWindow.Create(AOwner: TComponent);
  92. begin
  93.   inherited Create(AOwner);
  94.   FRgn := 0;
  95.   FOldAlphaBlend := False;
  96.   FOldAlphaBlendValue := 0;
  97. end;
  98. destructor TbsSkinHintWindow.Destroy;
  99. begin
  100.   inherited Destroy;
  101.   if FRgn <> 0 then DeleteObject(FRgn);
  102. end;
  103. procedure TbsSkinHintWindow.WMNCPaint(var Message: TMessage);
  104. begin
  105. end;
  106. procedure TbsSkinHintWindow.SetHintWindowRegion;
  107. var
  108.   TempRgn: HRgn;
  109.   MaskPicture: TBitMap;
  110. begin
  111.   if (FSD <> nil) and (FSD.HintWindow.MaskPictureIndex <> -1)
  112.   then
  113.     begin
  114.       TempRgn := FRgn;
  115.       with FSD.HintWindow do
  116.       begin
  117.         MaskPicture := TBitMap(FSD.FActivePictures[MaskPictureIndex]);
  118.         CreateSkinRegion
  119.           (FRgn, LTPoint, RTPoint, LBPoint, RBPoint, ClRect,
  120.            NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint, NewClRect,
  121.            MaskPicture, Width, Height);
  122.       end;
  123.       SetWindowRgn(Handle, FRgn, False);
  124.       if TempRgn <> 0 then DeleteObject(TempRgn);
  125.     end
  126.   else
  127.     if FRgn <> 0 then
  128.     begin
  129.       SetWindowRgn(Handle, 0, False);
  130.       DeleteObject(FRgn);
  131.       FRgn := 0;
  132.     end;
  133. end;
  134. procedure TbsSkinHintWindow.CalcHintSize(Cnvs: TCanvas; S: String; var W, H: Integer);
  135. var
  136.   R: TRect;
  137.   PW, PH, OX, OY: Integer;
  138. begin
  139.   R := Rect(0, 0, 0, 0);
  140.   DrawText(Cnvs.Handle, PChar(S), -1, R, DT_CALCRECT or DT_LEFT);
  141.   W := RectWidth(R);
  142.   H := RectHeight(R);
  143.   if FSD <> nil
  144.   then
  145.     begin
  146.       with FSD.HintWindow do
  147.       begin
  148.         PW := TBitMap(FSD.FActivePictures[WindowPictureIndex]).Width;
  149.         PH := TBitMap(FSD.FActivePictures[WindowPictureIndex]).Height;
  150.         W := W + ClRect.Left + (PW - ClRect.Right);
  151.         H := H + ClRect.Top + (PH - ClRect.Bottom);
  152.         if W < PW then W := PW;
  153.         if H < PH then H := PH;
  154.         OX := W - PW;
  155.         OY := H - PH;
  156.         NewClRect := ClRect;
  157.         Inc(NewClRect.Right, OX);
  158.         Inc(NewClRect.Bottom, OY);
  159.         NewLTPoint := LTPoint;
  160.         NewRTPoint := Point(RTPoint.X + OX, RTPoint.Y);
  161.         NewLBPoint := Point(LBPoint.X, LBPoint.Y + OY);
  162.         NewRBPoint := Point(RBPoint.X + OX, RBPoint.Y + OY);
  163.       end;
  164.     end
  165.   else
  166.     begin
  167.       Inc(W, 4);
  168.       Inc(H, 4);
  169.     end;
  170. end;
  171. function TbsSkinHintWindow.FindHintComponent;
  172. var
  173.   i: Integer;
  174. begin
  175.   Result := nil;
  176.   if (Application.MainForm <> nil) and
  177.      (Application.MainForm.ComponentCount > 0)
  178.   then
  179.     with Application.MainForm do
  180.       for i := 0 to ComponentCount - 1 do
  181.        if (Components[i] is TbsSkinHint) and
  182.           (TbsSkinHint(Components[i]).Active)
  183.        then
  184.          begin
  185.            Result := TbsSkinHint(Components[i]);
  186.            Break;
  187.          end;
  188. end;
  189. procedure TbsSkinHintWindow.ActivateHint(Rect: TRect; const AHint: string);
  190. const
  191.   WS_EX_LAYERED = $80000;
  192.   AnimationStep = 1;
  193. var
  194.   HintWidth, HintHeight: Integer;
  195.   CanSkin: Boolean;
  196.   i: Integer;
  197. begin
  198.   FspHint := FindHintComponent;
  199.   if FspHint = nil then Exit;
  200.   if not FspHint.Active then Exit;
  201.   CanSkin := ((FspHint.FSD <> nil) and (not FspHInt.FSD.Empty) and
  202.              (FspHint.FSD.HintWindow.WindowPictureIndex <> -1));
  203.   //
  204.   if CanSkin then FSD := FspHint.FSD else FSD := nil;
  205.   if FSD <> nil
  206.   then
  207.     begin
  208.       with Canvas, FSD.HintWindow do
  209.       begin
  210.         if FspHint.UseSkinFont
  211.         then
  212.           begin
  213.             Font.Height := FontHeight;
  214.             Font.Name := FontName;
  215.             Font.Style := FontStyle;
  216.           end
  217.         else
  218.           Font.Assign(FspHint.FDefaultFont);
  219.       end;
  220.     end
  221.   else
  222.     with Canvas do
  223.     begin
  224.       Font.Assign(FspHint.FDefaultFont);
  225.     end;
  226.   if (FspHint.SkinData <> nil) and (FspHint.SkinData.ResourceStrData <> nil)
  227.   then
  228.     Canvas.Font.CharSet := FspHint.SkinData.ResourceStrData.CharSet
  229.   else
  230.     Canvas.Font.CharSet := FspHint.DefaultFont.CharSet;
  231.   Caption := AHint;
  232.   CalcHintSize(Canvas, Caption, HintWidth, HintHeight);
  233.   Rect.Right := Rect.Left + HintWidth;
  234.   Rect.Bottom := Rect.Top + HIntHeight;
  235.   //
  236.   {if Rect.Right > Screen.Width then OffsetRect(Rect, - (Rect.Right - Screen.Width), 0);
  237.   if Rect.Bottom > Screen.Height then OffsetRect(Rect, 0, - (Rect.Bottom - Screen.Height));}
  238.   if (Rect.Right > Screen.Width) then OffsetRect(Rect, -HintWidth - 2, 0);
  239.   if (Rect.Bottom > Screen.Height) then OffsetRect(Rect, 0, -HintHeight - 2);
  240.   //
  241.   BoundsRect := Rect;
  242.   //
  243.   if CheckW2KWXP
  244.   then
  245.     begin
  246.       if FspHint.AlphaBlend and not FOldAlphaBlend
  247.       then
  248.         begin
  249.           SetWindowLong(Handle, GWL_EXSTYLE,
  250.                         GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  251.         end
  252.       else
  253.       if not FspHint.AlphaBlend and FOldAlphaBlend
  254.       then
  255.         begin
  256.          SetWindowLong(Handle, GWL_EXSTYLE,
  257.             GetWindowLong(Handle, GWL_EXSTYLE) and (not WS_EX_LAYERED));
  258.         end;
  259.       FOldAlphaBlend := FspHint.AlphaBlend;
  260.       if (FOldAlphaBlendValue <> FspHint.AlphaBlendValue) and FspHint.AlphaBlend
  261.       then
  262.         begin
  263.           SetAlphaBlendTransparent(Handle, FspHint.AlphaBlendValue);
  264.           FOldAlphaBlendValue := FspHint.AlphaBlendValue;
  265.         end;
  266.     end;
  267.   //
  268.   SetHintWindowRegion;
  269.   SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, 0,
  270.     0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
  271.   Visible := True;
  272. end;
  273. procedure TbsSkinHintWindow.CreateParams(var Params: TCreateParams);
  274. begin
  275.   inherited CreateParams(Params);
  276.   Params.Style := Params.Style - WS_BORDER;
  277.   if CheckWXP
  278.   then
  279.     Params.WindowClass.Style := Params.WindowClass.style or CS_DROPSHADOW_;
  280. end;
  281. procedure TbsSkinHintWindow.Paint;
  282. var
  283.   R: TRect;
  284.   B: TBitMap;
  285.   W, H, X, Y: Integer;
  286. begin
  287.   //
  288.   DrawBuffer := TBitMap.Create;
  289.   DrawBuffer.Width := Width;
  290.   DrawBuffer.Height := Height;
  291.   //
  292.   if FSD <> nil
  293.   then
  294.     with DrawBuffer.Canvas, FSD.HintWindow do
  295.     begin
  296.       B := TBitMap(FSD.FActivePictures[WindowPictureIndex]);
  297.       CreateSkinImageBS(LTPoint, RTPoint, LBPoint, RBPoint,
  298.       CLRect, NewLTPoint, NewRTPoint, NewLBPoint, NewRBPoint,
  299.       NewClRect, DrawBuffer, B,
  300.       Rect(0, 0, B.Width, B.Height), Width, Height, True,
  301.       FSD.HintWindow.LeftStretch, FSD.HintWindow.TopStretch,
  302.       FSD.HintWindow.RightStretch, FSD.HintWindow.BottomStretch);
  303.     end
  304.   else
  305.     with DrawBuffer.Canvas do
  306.     begin
  307.       Brush.Color := clInfoBk;
  308.       FillRect(ClientRect);
  309.       R := ClientRect;
  310.       Frame3D(DrawBuffer.Canvas, R, clBtnShadow, clBtnShadow, 1);
  311.     end;
  312.   //
  313.   if FSD <> nil
  314.   then
  315.     with DrawBuffer.Canvas, FSD.HintWindow do
  316.     begin
  317.       Brush.Style := bsClear;
  318.       if FspHint.UseSkinFont
  319.       then
  320.         begin
  321.           Font.Height := FontHeight;
  322.           Font.Style := FontStyle;
  323.           Font.Name := FontName;
  324.         end
  325.       else
  326.         Font.Assign(FspHint.FDefaultFont);
  327.       if (FspHint.SkinData <> nil) and (FspHint.SkinData.ResourceStrData <> nil)
  328.       then
  329.         Font.CharSet := FspHint.SkinData.ResourceStrData.CharSet
  330.       else
  331.         Font.CharSet := FspHint.DefaultFont.CharSet;
  332.       Font.Color := FontColor;
  333.       R := Rect(0, 0, 0, 0);
  334.       DrawText(Handle, PChar(Caption), -1, R, DT_CALCRECT or DT_LEFT);
  335.       W := RectWidth(R);
  336.       H := RectHeight(R);
  337.       X := NewClRect.Left + RectWidth(NewClRect) div 2 - W div 2;
  338.       Y := NewClRect.Top + RectHeight(NewClRect) div 2 - H div 2;
  339.       R := Rect(X, Y, X + W, Y + H);
  340.       DrawText(Handle, PChar(Caption), -1, R, DT_LEFT);
  341.     end
  342.   else
  343.     with DrawBuffer.Canvas do
  344.     begin
  345.       Font.Assign(FspHint.FDefaultFont);
  346.       if (FspHint.SkinData <> nil) and (FspHint.SkinData.ResourceStrData <> nil)
  347.       then
  348.         Font.CharSet := FspHint.SkinData.ResourceStrData.CharSet
  349.       else
  350.         Font.CharSet := FspHint.DefaultFont.CharSet;
  351.       Font.Color := clInfoText;
  352.       Brush.Style := bsClear;
  353.       R := Rect(2, 2, Width - 2, Height - 2);
  354.       DrawText(Handle, PChar(Caption), -1, R, DT_LEFT);
  355.     end;
  356.   //
  357.   Canvas.Draw(0, 0, DrawBuffer);
  358.   DrawBuffer.Free;
  359. end;
  360. procedure TbsSkinHintWindow.WMEraseBkGnd(var Msg: TWMEraseBkgnd);
  361. begin
  362.   Msg.Result := 1;
  363. end;
  364. constructor TbsSkinHint.Create(AOwner: TComponent);
  365. begin
  366.   inherited Create(AOwner);
  367.   HintTimer := nil;
  368.   FSD := nil;
  369.   FDefaultFont := TFont.Create;
  370.   FActive := True;
  371.   HW := TbsSkinHintWindow.Create(Self);
  372.   HW.Visible := False;
  373.   if not (csDesigning in ComponentState)
  374.   then
  375.     begin
  376.       HintWindowClass := TbsSkinHintWindow;
  377.       with Application do begin
  378.         ShowHint := not ShowHint;
  379.         ShowHint := not ShowHint;
  380.         OnShowHint := SelfOnShowHint;
  381.         Application.HintShortPause := 100;
  382.       end;
  383.     end;
  384.   UseSkinFont := True;  
  385. end;
  386. destructor TbsSkinHint.Destroy;
  387. begin
  388.   HW.Free;
  389.   FDefaultFont.Free;
  390.   if HintTimer <> nil then HintTimer.Free;
  391.   inherited Destroy;
  392. end;
  393. procedure TbsSkinHint.SetDefaultFont(Value: TFont);
  394. begin
  395.   FDefaultFont.Assign(Value);
  396. end;
  397. procedure TbsSkinHint.SetSkinData;
  398. begin
  399.   FSD := Value;
  400. end;
  401. procedure TbsSkinHint.Notification;
  402. begin
  403.   inherited Notification(AComponent, Operation);
  404.   if (Operation = opRemove) and (AComponent = FSD) then FSD := nil;
  405. end;
  406. procedure TbsSkinHint.SetActive(Value: Boolean);
  407. var
  408.   i: Integer;
  409. begin
  410.   FActive := Value;
  411.   if FActive and (Application.MainForm <> nil)
  412.   then
  413.     with Application.MainForm do
  414.       for i := 0 to ComponentCount-1 do
  415.         if (Components[i] is TbsSkinHint) and (Components[i] <> Self)
  416.         then
  417.           if TbsSkinHint(Components[i]).Active
  418.           then TbsSkinHint(Components[i]).Active := False;
  419.   if not (csDesigning in ComponentState) and FActive
  420.   then Application.OnShowHint := SelfOnShowHint;
  421. end;
  422. procedure TbsSkinHint.SelfOnShowHint(var HintStr: string;
  423.                                  var CanShow: Boolean; var HintInfo: THintInfo);
  424. begin
  425.   if Assigned(FOnShowHint) then FOnShowHint(HintStr, CanShow, HintInfo);
  426. end;
  427. function TbsSkinHint.GetCursorHeightMargin: Integer;
  428.   var
  429.     IconInfo: TIconInfo;
  430.     BitmapInfoSize, BitmapBitsSize, ImageSize: DWORD;
  431.     Bitmap: PBitmapInfoHeader;
  432.     Bits: Pointer;
  433.     BytesPerScanline: Integer;
  434.       function FindScanline(Source: Pointer; MaxLen: Cardinal;
  435.         Value: Cardinal): Cardinal; assembler;
  436.       asm
  437.               PUSH    ECX
  438.               MOV     ECX,EDX
  439.               MOV     EDX,EDI
  440.               MOV     EDI,EAX
  441.               POP     EAX
  442.               REPE    SCASB
  443.               MOV     EAX,ECX
  444.               MOV     EDI,EDX
  445.       end;
  446.   begin
  447.     { Default value is entire icon height }
  448.     Result := GetSystemMetrics(SM_CYCURSOR);
  449.     if GetIconInfo(GetCursor, IconInfo) then
  450.     try
  451.       GetDIBSizes(IconInfo.hbmMask, BitmapInfoSize, BitmapBitsSize);
  452.       Bitmap := AllocMem(DWORD(BitmapInfoSize) + BitmapBitsSize);
  453.       try
  454.       Bits := Pointer(DWORD(Bitmap) + BitmapInfoSize);
  455.       if GetDIB(IconInfo.hbmMask, 0, Bitmap^, Bits^) and
  456.         (Bitmap^.biBitCount = 1) then
  457.       begin
  458.         { Point Bits to the end of this bottom-up bitmap }
  459.         with Bitmap^ do
  460.         begin
  461.           BytesPerScanline := ((biWidth * biBitCount + 31) and not 31) div 8;
  462.           ImageSize := biWidth * BytesPerScanline;
  463.           Bits := Pointer(DWORD(Bits) + BitmapBitsSize - ImageSize);
  464.           { Use the width to determine the height since another mask bitmap
  465.             may immediately follow }
  466.           Result := FindScanline(Bits, ImageSize, $FF);
  467.           { In case the and mask is blank, look for an empty scanline in the
  468.             xor mask. }
  469.           if (Result = 0) and (biHeight >= 2 * biWidth) then
  470.             Result := FindScanline(Pointer(DWORD(Bits) - ImageSize),
  471.             ImageSize, $00);
  472.           Result := Result div BytesPerScanline;
  473.         end;
  474.         Dec(Result, IconInfo.yHotSpot);
  475.       end;
  476.       finally
  477.         FreeMem(Bitmap, BitmapInfoSize + BitmapBitsSize);
  478.       end;
  479.     finally
  480.       if IconInfo.hbmColor <> 0 then DeleteObject(IconInfo.hbmColor);
  481.       if IconInfo.hbmMask <> 0 then DeleteObject(IconInfo.hbmMask);
  482.     end;
  483. end;
  484. procedure TbsSkinHint.HintTime1(Sender: TObject);
  485. var
  486.   R: TRect;
  487.   P: TPoint;
  488. begin
  489.   GetCursorPos(P);
  490.   P.Y := P.Y + GetCursorHeightMargin;
  491.   R := Rect(P.X, P.Y, P.X, P.Y);
  492.   HW.ActivateHint(R, HintText);
  493.   HW.Visible := True;
  494.   HintTimer.Enabled := False;
  495.   HintTimer.Interval := Application.HintHidePause;
  496.   HintTimer.OnTimer := HintTime2;
  497.   HintTimer.Enabled := True;
  498. end;
  499. procedure TbsSkinHint.HintTime2(Sender: TObject);
  500. begin
  501.   HideHint;
  502. end;
  503. procedure TbsSkinHint.ActivateHint2(const AHint: string);
  504. begin
  505.   if HintTimer <> nil then HintTimer.Free;
  506.   HintText := AHint;
  507.   HintTimer := TTimer.Create(Self);
  508.   HintTimer.Enabled := False;
  509.   HintTimer.Interval := Application.HintPause;
  510.   HintTimer.OnTimer := HintTime1;
  511.   HintTimer.Enabled := True;
  512. end;
  513. procedure TbsSkinHint.ActivateHint(P: TPoint; const AHint: string);
  514. var
  515.   R: TRect;
  516. begin
  517.   R := Rect(P.X, P.Y, P.X, P.Y);
  518.   HW.ActivateHint(R, AHint);
  519.   HW.Visible := True;
  520. end;
  521. function TbsSkinHint.IsVisible: Boolean;
  522. begin
  523.   Result := HW.Visible;
  524. end;
  525. procedure TbsSkinHint.HideHint;
  526. begin
  527.   if HintTimer <> nil
  528.   then
  529.     begin
  530.       HintTimer.Enabled := False;
  531.       HintTimer.Free;
  532.       HintTimer := nil;
  533.     end;
  534.   if HW.Visible
  535.   then
  536.     begin
  537.       HW.Visible := False;
  538.       SetWindowPos(HW.Handle, HWND_TOPMOST, 0, 0, 0,
  539.         0, SWP_HideWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
  540.     end;
  541. end;
  542. end.