zoukankan      html  css  js  c++  java
  • 自定义hint框

    unit Danhint;
    
    interface
    
    uses
      SysUtils, Windows, Messages, Classes, Graphics, Controls,
      Forms, Dialogs;
    
    type
      THintDirection = (hdUpRight, hdUpLeft, hdDownRight, hdDownLeft);
      TOnSelectHintDirection = procedure(HintControl: TControl; var HintDirection:
        THintDirection) of object;
    
      TDanHint = class(TComponent)
      private
        {   Private   declarations   }
        FHintDirection: THintDirection;
        FHintColor: TColor;
        FHintShadowColor: TColor;
        FHintFont: TFont;
        FHintPauseTime: Integer;
        FOnSelectHintDirection: TOnSelectHintDirection;
        procedure SetHintDirection(Value: THintDirection);
        procedure SetHintColor(Value: TColor);
        procedure SetHintShadowColor(Value: TColor);
        procedure SetHintFont(Value: TFont);
        procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
        procedure SetHintPauseTime(Value: Integer);
      protected
        {   Protected   declarations   }
      public
        {   Public   declarations   }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure Loaded; override;
        procedure SetNewHintFont;
      published
        {   Published   declarations   }
        property HintDirection: THintDirection read FHintDirection write
          SetHintDirection default hdUpRight;
        property HintColor: TColor read FHintColor write SetHintColor default
          clYellow;
        property HintShadowColor: TColor read FHintShadowColor write
          SetHintShadowColor default clPurple;
        property HintFont: TFont read FHintFont write SetHintFont;
        property HintPauseTime: Integer read FHintPauseTime write SetHintPauseTime
          default 600;
        property OnSelectHintDirection: TOnSelectHintDirection read
          FOnSelectHintDirection write FOnSelectHintDirection;
      end;
    
      TNewHint = class(THintWindow)
      private
        {   Private   declarations   }
        FDanHint: TDanHint;
        FHintDirection: THintDirection;
        procedure SelectProperHintDirection(ARect: TRect);
        procedure CheckUpRight(Spot: TPoint);
        procedure CheckUpLeft(Spot: TPoint);
        procedure CheckDownRight(Spot: TPoint);
        procedure CheckDownLeft(Spot: TPoint);
        function FindDanHint: TDanHint;
        function FindCursorControl: TControl;
      protected
        {   Protected   declarations   }
        procedure Paint; override;
        procedure CreateParams(var Params: TCreateParams); override;
      public
        {   Public   declarations   }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure ActivateHint(Rect: TRect; const AHint: string); override;
        property HintDirection: THintDirection read FHintDirection write
          FHintDirection default hdUpRight;
      published
        {   Published   declarations   }
      end;
    
    procedure Register;
    
    var
      NewHint : TNewHint;
    
    implementation
    
    const
      SHADOW_WIDTH = 6;
      N_PIXELS = 5;
    var
      MemBmp: TBitmap;
      UpRect, DownRect: TRect;
      SelectHintDirection: THintDirection;
      ShowPos: TPoint;
    
    procedure Register;
    begin
      RegisterComponents('standard', [TDanHint]);
    end;
    
    procedure TDanHint.SetNewHintFont;
    var
      I: Integer;
    begin
      for I := 0 to Application.ComponentCount - 1 do
        if Application.Components[I] is TNewHint then
        begin
          TNewHint(Application.Components[I]).Canvas.Font.Assign(FHintFont);
          Exit;
        end;
    end;
    
    constructor TDanHint.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      FHintDirection := hdUpRight;
      FHintColor := clYellow;
      {   $0080FFFF   is   Delphi's   original   setting   }
      FHintShadowColor := clPurple;
      FHintPauseTime := 600;
      Application.HintPause := FHintPauseTime;
      FHintFont := TFont.Create;
      FHintFont.Name := 'MS   Sans   Serif';
      FHintFont.Size := 12;
      FHintFont.Color := clBlue;
      FHintFont.Pitch := fpDefault;
      FHintFont.Style := FHintFont.Style + [fsBold, fsItalic];
    
      if not (csDesigning in ComponentState) then
      begin
        HintWindowClass := TNewHint;
        Application.ShowHint := not Application.ShowHint;
        Application.ShowHint := not Application.ShowHint;
        {   in   TApplication's   SetShowHint,   the   private
            FHintWindow   is   allocated   according   to
            HintWindowClass,   so   here   do   so   actions   to
            call   SetShowHint   and   keep   ShowHint   property
            the   same   value   }
        SetNewHintFont;
      end;
    end;
    
    destructor TDanHint.Destroy;
    begin
      FHintFont.Free;
      inherited Destroy;
    end;
    
    procedure TDanHint.Loaded;
    begin
      if not (csDesigning in ComponentState) then
      begin
        inherited Loaded;
        HintWindowClass := TNewHint;
        Application.ShowHint := not Application.ShowHint;
        Application.ShowHint := not Application.ShowHint;
        {   to   activate   to   allocate   a   new   Hint   Window   }
        SetNewHintFont;
      end;
    end;
    
    procedure TDanHint.SetHintDirection(Value: THintDirection);
    begin
      FHintDirection := Value;
    end;
    
    procedure TDanHint.SetHintColor(Value: TColor);
    begin
      FHintColor := Value;
    end;
    
    procedure TDanHint.SetHintShadowColor(Value: TColor);
    begin
      FHintShadowColor := Value;
    end;
    
    procedure TDanHint.SetHintFont(Value: TFont);
    begin
      FHintFont.Assign(Value);
      Application.ShowHint := not Application.ShowHint;
      Application.ShowHint := not Application.ShowHint;
      {   to   activate   to   allocate   a   new   Hint   Window   }
      SetNewHintFont;
    end;
    
    procedure TDanHint.CMFontChanged(var Message: TMessage);
    begin
      inherited;
      Application.ShowHint := not Application.ShowHint;
      Application.ShowHint := not Application.ShowHint;
      {   to   activate   to   allocate   a   new   Hint   Window   }
      SetNewHintFont;
    end;
    
    procedure TDanHint.SetHintPauseTime(Value: Integer);
    begin
      if (Value <> FHintPauseTime) then
      begin
        FHintPauseTime := Value;
        Application.HintPause := Value;
      end;
    end;
    
    function TNewHint.FindDanHint: TDanHint;
    var
      I: Integer;
    begin
      Result := nil;
      for I := 0 to Application.MainForm.ComponentCount - 1 do
        if Application.MainForm.Components[I] is TDanHint then
        begin
          Result := TDanHint(Application.MainForm.Components[I]);
          Exit;
        end;
    end;
    
    constructor TNewHint.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      {if   (Application<>nil)   and   (Application.MainForm<>nil)   then
            FDanHint:=FindDanHint;}
      ControlStyle := ControlStyle - [csOpaque];
      with Canvas do
      begin
        {   Font.Name:='MS   Sans   Serif';
          Font.Size:=10;}
          {if   (FDanHint<>nil)   then   Font.Assign(FDanHint.HintFont);}
        Brush.Style := bsClear;
        Brush.Color := clBackground;
        Application.HintColor := clBackground;
      end;
      FHintDirection := hdUpRight;
    end;
    
    destructor TNewHint.Destroy;
    begin
      inherited Destroy;
    end;
    
    procedure TNewHint.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      with Params do
      begin
        {Style   :=   WS_POPUP   or   WS_BORDER   or   WS_DISABLED;}
        Style := Style - WS_BORDER;
        {ExStyle:=ExStyle   or   WS_EX_TRANSPARENT;}
        {Add   the   above   makes   the   beneath   window   overlap   hint}
        WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
      end;
    end;
    
    procedure TNewHint.Paint;
    var
      R: TRect;
      CCaption: array[0..255] of Char;
      FillRegion, ShadowRgn: HRgn;
      AP: array[0..2] of TPoint; {   Points   of   the   Arrow   }
      SP: array[0..2] of TPoint; {   Points   of   the   Shadow   }
      X, Y: Integer;
      AddNum: Integer; {   Added   num   for   hdDownXXX   }
    begin
      R := ClientRect;
      {   R   is   for   Text   output   }
      Inc(R.Left, 5 + 3);
      Inc(R.Top, 3);
      AddNum := 0;
      if FHintDirection >= hdDownRight then
        AddNum := 15;
      Inc(R.Top, AddNum);
    
      case HintDirection of
        hdUpRight:
          begin
            AP[0] := Point(10, Height - 15);
            AP[1] := Point(20, Height - 15);
            AP[2] := Point(0, Height);
            SP[0] := Point(12, Height - 15);
            SP[1] := Point(25, Height - 15);
            SP[2] := Point(12, Height);
          end;
        hdUpLeft:
          begin
            AP[0] := Point(Width - SHADOW_WIDTH - 20, Height - 15);
            AP[1] := Point(Width - SHADOW_WIDTH - 10, Height - 15);
            AP[2] := Point(Width - SHADOW_WIDTH, Height);
            SP[0] := Point(Width - SHADOW_WIDTH - 27, Height - 15);
            SP[1] := Point(Width - SHADOW_WIDTH - 5, Height - 15);
            SP[2] := Point(Width - SHADOW_WIDTH, Height);
          end;
        hdDownRight:
          begin
            AP[0] := Point(10, 15);
            AP[1] := Point(20, 15);
            AP[2] := Point(0, 0);
            {   for   hdDownXXX,   SP   not   used   now   }
            SP[0] := Point(12, Height - 15);
            SP[1] := Point(25, Height - 15);
            SP[2] := Point(12, Height);
          end;
        hdDownLeft:
          begin
            AP[0] := Point(Width - SHADOW_WIDTH - 20, 15);
            AP[1] := Point(Width - SHADOW_WIDTH - 10, 15);
            AP[2] := Point(Width - SHADOW_WIDTH, 0);
            {   for   hdDownXXX,   SP   not   used   now   }
            SP[0] := Point(12, Height - 15);
            SP[1] := Point(25, Height - 15);
            SP[2] := Point(12, Height);
          end;
      end;
    
      {   Draw   Shadow   of   the   Hint   Rect}
      if (FHintDirection <= hdUpLeft) then
      begin
        ShadowRgn := CreateRoundRectRgn(0 + 10, 0 + 8, Width, Height - 9, 8, 8);
        {   8   is   for   RoundRect's   corner   }
        for X := Width - SHADOW_WIDTH - 8 to Width do
          for Y := 8 to Height - 14 do
          begin
            if (Odd(X) = Odd(Y)) and PtInRegion(ShadowRgn, X, Y) then
              MemBmp.Canvas.Pixels[X, Y] := FDanHint.HintShadowColor;
          end;
        for X := 10 to Width do
          for Y := Height - 14 to Height - 9 do
          begin
            if (Odd(X) = Odd(Y)) and PtInRegion(ShadowRgn, X, Y) then
              MemBmp.Canvas.Pixels[X, Y] := FDanHint.HintShadowColor;
          end;
      end
      else {   for   hdDownXXX   }
      begin
        ShadowRgn := CreateRoundRectRgn(0 + 10, 0 + 8 + 15, Width, Height - 2, 8,
          8);
        for X := Width - SHADOW_WIDTH - 8 to Width do
          for Y := 23 to Height - 8 do
          begin
            if (Odd(X) = Odd(Y)) and PtInRegion(ShadowRgn, X, Y) then
              MemBmp.Canvas.Pixels[X, Y] := FDanHint.HintShadowColor;
          end;
        for X := 10 to Width do
          for Y := Height - 8 to Height - 2 do
          begin
            if (Odd(X) = Odd(Y)) and PtInRegion(ShadowRgn, X, Y) then
              MemBmp.Canvas.Pixels[X, Y] := FDanHint.HintShadowColor;
          end;
      end;
      DeleteObject(ShadowRgn);
    
      {   Draw   the   shadow   of   the   arrow   }
      if (HintDirection <= hdUpLeft) then
      begin
        ShadowRgn := CreatePolygonRgn(SP, 3, WINDING);
        for X := SP[0].X to SP[1].X do
          for Y := SP[0].Y to SP[2].Y do
          begin
            if (Odd(X) = Odd(Y)) and PtInRegion(ShadowRgn, X, Y) then
              MemBmp.Canvas.Pixels[X, Y] := FDanHint.HintShadowColor;
          end;
        DeleteObject(ShadowRgn);
      end;
    
      {   Draw   HintRect   }
      MemBmp.Canvas.Pen.Color := clBlack;
      MemBmp.Canvas.Pen.Style := psSolid;
      MemBmp.Canvas.Brush.Color := FDanHint.HintColor;
    
      MemBmp.Canvas.Brush.Style := bsSolid;
      if (FHintDirection <= hdUpLeft) then
        MemBmp.Canvas.RoundRect(0, 0, Width - SHADOW_WIDTH, Height - 14, 9, 9)
      else
        MemBmp.Canvas.RoundRect(0, 0 + AddNum, Width - SHADOW_WIDTH, Height - 14 +
          6, 9, 9);
      {   Draw   Hint   Arrow   }
      MemBmp.Canvas.Pen.Color := FDanHint.HintColor;
      MemBmp.Canvas.MoveTo(AP[0].X, AP[0].Y);
      MemBmp.Canvas.LineTo(AP[1].X, AP[1].Y);
      MemBmp.Canvas.Pen.Color := clBlack;
      FillRegion := CreatePolygonRgn(AP, 3, WINDING);
      FillRgn(MemBmp.Canvas.Handle, FillRegion, MemBmp.Canvas.Brush.Handle);
      DeleteObject(FillRegion);
      MemBmp.Canvas.LineTo(AP[2].X, AP[2].Y);
      MemBmp.Canvas.LineTo(AP[0].X, AP[0].Y);
    
      {   SetBkMode   makes   DrawText's   text   be   transparent   }
      SetBkMode(MemBmp.Canvas.Handle, TRANSPARENT);
      MemBmp.Canvas.Font.Assign(FDanHint.HintFont);
      DrawText(MemBmp.Canvas.Handle, StrPCopy(CCaption, Caption), -1, R,
        DT_LEFT or DT_NOPREFIX or DT_WORDBREAK);
      Canvas.CopyMode := cmSrcCopy;
      Canvas.CopyRect(ClientRect, MemBmp.Canvas, ClientRect);
      MemBmp.Free;
    end;
    
    procedure TNewHint.CheckUpLeft(Spot: TPoint);
    var
      Width, Height: Integer;
    begin
      Dec(Spot.Y, N_PIXELS);
      Width := UpRect.Right - UpRect.Left;
      Height := UpRect.Bottom - UpRect.Top;
      SelectHintDirection := hdUpLeft;
      if (Spot.X + SHADOW_WIDTH - Width) < 0 then
      begin
        Inc(Spot.Y, N_PIXELS); {back   tp   original}
        CheckUpRight(Spot);
        Exit;
      end;
      if (Spot.Y - Height) < 0 then
      begin
        Inc(Spot.Y, N_PIXELS);
        CheckDownLeft(Spot);
        Exit;
      end;
      ShowPos.X := Spot.X + SHADOW_WIDTH - Width;
      ShowPos.Y := Spot.Y - Height;
    end;
    
    procedure TNewHint.CheckUpRight(Spot: TPoint);
    var
      Width, Height: Integer;
    begin
      Dec(Spot.Y, N_PIXELS);
      Width := UpRect.Right - UpRect.Left;
      Height := UpRect.Bottom - UpRect.Top;
      SelectHintDirection := hdUpRight;
      if (Spot.X + Width) > Screen.Width then
      begin
        Inc(Spot.Y, N_PIXELS);
        CheckUpLeft(Spot);
        Exit;
      end;
      if (Spot.Y - Height) < 0 then
      begin
        Inc(Spot.Y, N_PIXELS);
        CheckDownRight(Spot);
        Exit;
      end;
      ShowPos.X := Spot.X;
      ShowPos.Y := Spot.Y - Height;
    end;
    
    procedure TNewHint.CheckDownRight(Spot: TPoint);
    var
      Width, Height: Integer;
    begin
      Inc(Spot.Y, N_PIXELS * 3);
      Width := DownRect.Right - DownRect.Left;
      Height := DownRect.Bottom - DownRect.Top;
      SelectHintDirection := hdDownRight;
      if (Spot.X + Width) > Screen.Width then
      begin
        Dec(Spot.Y, N_PIXELS * 3);
        CheckDownLeft(Spot);
        Exit;
      end;
      if (Spot.Y + Height) > Screen.Height then
      begin
        Dec(Spot.Y, N_PIXELS * 3);
        CheckUpRight(Spot);
        Exit;
      end;
      ShowPos.X := Spot.X;
      ShowPos.Y := Spot.Y;
    end;
    
    procedure TNewHint.CheckDownLeft(Spot: TPoint);
    var
      Width, Height: Integer;
    begin
      Inc(Spot.Y, N_PIXELS * 3);
      Width := DownRect.Right - DownRect.Left;
      Height := DownRect.Bottom - DownRect.Top;
      SelectHintDirection := hdDownLeft;
      if (Spot.X + SHADOW_WIDTH - Width) < 0 then
      begin
        Dec(Spot.Y, N_PIXELS * 3);
        CheckDownRight(Spot);
        Exit;
      end;
      if (Spot.Y + Height) > Screen.Height then
      begin
        Dec(Spot.Y, N_PIXELS * 3);
        CheckUpLeft(Spot);
        Exit;
      end;
      ShowPos.X := Spot.X + SHADOW_WIDTH - Width;
      ShowPos.Y := Spot.Y;
    end;
    
    function TNewHint.FindCursorControl: TControl;
    begin
      {ControlAtPos}
    end;
    
    procedure TNewHint.SelectProperHintDirection(ARect: TRect);
    var
      Spot: TPoint;
      OldHintDirection, SendHintDirection: THintDirection;
      HintControl: TControl;
    begin
      GetCursorPos(Spot);
      HintCOntrol := FindDragTarget(Spot, True);
      Inc(ARect.Right, 10 + SHADOW_WIDTH);
      Inc(ARect.Bottom, 20);
      UpRect := ARect;
      Inc(ARect.Bottom, 9);
      DownRect := ARect;
      OldHintDirection := FDanHint.HintDirection;
      SendHintDirection := FDanHint.HintDirection;
      {   Tricky,   why   here   can't   use   FDanHint.OnSe...?   }
      if Assigned(FDanHint.FOnSelectHintDirection) then
      begin
        FDanHint.FOnSelectHintDirection(HintControl, SendHintDirection);
        FDanHint.HintDirection := SendHintDirection;
      end;
      case FDanHint.HintDirection of
        hdUpRight: CheckUpRight(Spot);
        hdUpLeft: CheckUpLeft(Spot);
        hdDownRight: CheckDownRight(Spot);
        hdDownLeft: CheckDownLeft(Spot);
      end;
      FDanHint.HintDirection := OldHintDirection;
    end;
    
    procedure TNewHint.ActivateHint(Rect: TRect; const AHint: string);
    var
      ScreenDC: HDC;
      LeftTop: TPoint;
      tmpWidth, tmpHeight: Integer;
    begin
      MemBmp := TBitmap.Create;
      Caption := AHint;
      {   add   by   Dan   from   Here   }
      FDanHint := FindDanHint;
    
      SelectProperHintDirection(Rect);
      HintDirection := SelectHintDirection;
      {   if   the   following   changes,   make   sure   to   modify
          SelectProperHintDirection   also   }
      Inc(Rect.Right, 10 + SHADOW_WIDTH);
      Inc(Rect.Bottom, 20);
      if (FHintDirection >= hdDownRight) then
        Inc(Rect.Bottom, 9);
      {   to   expand   the   rect   }
      tmpWidth := Rect.Right - Rect.Left;
      tmpHeight := Rect.Bottom - Rect.Top;
      Rect.Left := ShowPos.X;
      Rect.Top := ShowPos.Y;
      Rect.Right := Rect.Left + tmpWidth;
      Rect.Bottom := Rect.Top + tmpHeight;
      BoundsRect := Rect;
    
      MemBmp.Width := Width;
      MemBmp.Height := Height;
    
      ScreenDC := CreateDC('DISPLAY', nil, nil, nil);
      LeftTop.X := 0;
      LeftTop.Y := 0;
      LeftTop := ClientToScreen(LeftTop);
      {   use   MemBmp   to   store   the   original   bitmap
          on   screen   }
      //BitBlt(MemBmp.Canvas.Handle, 0, 0, Width, Height, ScreenDC, LeftTop.X, LeftTop.Y, SRCCOPY);
      {       SetBkMode(Canvas.Handle,TRANSPARENT);}
    
      SetWindowPos(Handle, HWND_TOPMOST, ShowPos.X, ShowPos.Y, 0,
        0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
      BitBlt(Canvas.Handle, 0, 0, Width, Height, MemBmp.Canvas.Handle,
        0, 0, SRCCOPY);
      DeleteDC(ScreenDC);
    end;
    
    initialization
    
     
    
    end.

    盒子论坛:http://bbs.2ccc.com/topic.asp?topicid=289749

  • 相关阅读:
    python 自定义去掉空行
    JavaScript 获取时间函数
    python 自定义ssh
    python 去掉空行
    python roboot解析 output.xml
    语音识别-windows
    python 自定义request模块调试
    python 自定义装饰器
    python 自定义Server酱模块编写
    python 自定义exception模块
  • 原文地址:https://www.cnblogs.com/shuaixf/p/2828731.html
Copyright © 2011-2022 走看看