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

Delphi控件源码

开发平台:

Delphi

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