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

Delphi控件源码

开发平台:

Delphi

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