创建不规则形状的Control

Delphi使用GDI+制作任意图片形状窗口 Delphi使用GDI+制作任意图片形状(PGN图形)窗口 立即下载

最近接了一个单子,开发一个产品的教学软件(汗,程序员开始变成美工了,没办法要混饭吃,只好堕落了)。按照领导(老婆)的说法,工期紧、任务重,所以,只能拿起我最擅长的Delphi作为开发利器,Delphi好是好,最困难的在于界面设计,这样的软件,脸面最重要,但是,Delphi的弱点(别砸我,我话还没有说完)也在于此,灰不拉鸡的界面在现在几乎等同于Dos的黑底白字一样不受欢迎(郁闷,这不是很好吗!整天装嫩,什么都要Q,连软件都不放过,发廊妹妹说自己昨天18岁生日,你也要装!)。言归正传,看来只能用TImage混合PhotoShop、CoreDraw做出来的图片了。做出来一看,还行,就是不会动,要动?很简单,弄个透明的Bebvl当作按钮不就可以啦!不行啊!都是方的怎么行,人家的机器上的按钮都是很复杂的形状,都是方的怎么半呢?有办法,我不说,我不说干吗写这篇文章?开玩笑。其实很简单,如果不是TwinControl继承下来的,而是从TControl继承下来的可以做到对于鼠标动作在任意形状区域的响应,TwinControl当然也可以,我比较懒啦!TwinControl怎么作,MSDN上肯定有,无非就是把窗口和一个区域联系起来(关键API连接,SetWindowRgn),当然也可以是响应消息,不过那样窗口不能透明了。Tcontrol实现起来更加简单,关键在一个消息,CM_HITTEST,这是Delphi自定义的消息,别去MSDN查,肯定查不到。这个消息表示测试x,Y是不是落在Control的范围里面,如果你响应这个消息,那么你就可以告诉VCL鼠标是不是落在你的Control范围里面,这样你就可以在矩形之中定义你的Control的任意形状,只要你在响应这个消息的时候“告诉”VCL。这个消息的格式:

  TWMNCHitTest = packed record
    Msg: Cardinal;
    Unused: Longint;
    case Integer of
      0: (
        XPos: Smallint;
        YPos: Smallint);
      1: (
        Pos: TSmallPoint;
        Result: Longint);
  end;

  TCMHitTest = TWMNCHitTest;
这个消息其实就是一个Windows消息的翻版。Result表示返回值,HTCLIENT就是在,HTNOWHERE就是不在。还有其他很多的返回值,有兴趣你可以根据情况多返回一些(没事找事:))。

下面就是这个组件的源代码,这个组件只能接受Bitmap,根据0,0的像素决定透明色彩,同时决定区域,Transparent属性表明是否透明,影响鼠标动作区域,不透明就是整个矩形。当鼠标移动进入的时候,图像颜色会变成高亮,高亮的算法是RGB色彩空间转换到HSL色彩空间,HSL色彩空间,H表示色度,S表示饱和度,L表示亮度,所以改变L就可以改变整个图片的亮度,改变以后再转换回RGB色彩空间。祝各位愉快。

unit HotTrackImage;

interface

uses
  SysUtils, Classes, Controls, Windows, Messages, Graphics, Math, Forms;

const
   MaxPixelCount = 65536;

type
  pRGBTripleArray = ^TRGBTripleArray;
  TRGBTripleArray = array[0..MaxPixelCount - 1] of TRGBTriple;
 
  THotTrackEvent = procedure(Sender:TObject) of object;

  THotTrackImage = class(TGraphicControl)
  private
    { Private declarations }
    {FSearching:Boolean;
    FSearching1:Boolean;
    FSearching2:Boolean;
    FSearching3:Boolean;
    FSearching4:Boolean;
    FSearching5:Boolean;
    FSearching6:Boolean;}
    FPicture: TBitmap;
    FHotPicture: TBitmap;
    FOnProgress: TProgressEvent;
    FStretch: Boolean;
    FCenter: Boolean;
    FIncrementalDisplay: Boolean;
    FDrawing: Boolean;
    FProportional: Boolean;
    FOnHotTrackLeave: THotTrackEvent;
    FOnHotTrackEnter: THotTrackEvent;
    FIsHoted: Boolean;
    FLightAdd: Integer;
    FTransparent: Boolean;
    function GetCanvas: TCanvas;
    procedure SetHoted(Hoted:Boolean);
    procedure DoLightBitmap;
    procedure PictureChanged(Sender: TObject);
    procedure SetCenter(Value: Boolean);
    procedure SetPicture(Value: TBitmap);
    procedure SetStretch(Value: Boolean);
    procedure SetProportional(Value: Boolean);
    procedure SetLightAdd(const Value: Integer);
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    //procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;
    procedure CMHitTest(var Message: TCMHitTest); message CM_HITTEST;
    procedure SetTransparent(const Value: Boolean);
  protected
    { Protected declarations }
    function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
    function DestRect: TRect;
    function DoPaletteChange: Boolean;
    function GetPalette: HPALETTE; override;
    procedure Paint; override;
    procedure Progress(Sender: TObject; Stage: TProgressStage;
      PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string); dynamic;
    //procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
    //  X, Y: Integer); override;
    //procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
    //  X, Y: Integer); override;
    //procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure DoHotTrackEnter;
    procedure DoHotTrackLeave;
    //procedure Click; override;
    //procedure DblClick; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Canvas: TCanvas read GetCanvas;
  published
    { Published declarations }
    property Align;
    property Anchors;
    property AutoSize;
    property Center: Boolean read FCenter write SetCenter default False;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property IncrementalDisplay: Boolean read FIncrementalDisplay write FIncrementalDisplay default False;
    property ParentShowHint;
    property Picture: TBitmap read FPicture write SetPicture;
    property PopupMenu;
    property Proportional: Boolean read FProportional write SetProportional default false;
    property ShowHint;
    property Stretch: Boolean read FStretch write SetStretch default False;
    property Visible;
    property IsHoted:Boolean read FIsHoted;
    property LightAdd:Integer read FLightAdd write SetLightAdd;
    property Transparent: Boolean read FTransparent write SetTransparent default True;
    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
    property OnStartDock;
    property OnStartDrag;
    property OnHotTrackEnter:THotTrackEvent read FOnHotTrackEnter write FOnHotTrackEnter;
    property OnHotTrackLeave:THotTrackEvent read FOnHotTrackLeave write FOnHotTrackLeave;
  end;

procedure Register;

implementation

procedure HSLtoRGB(H, S, L: Double; var R, G, B: Integer);
//hsl颜色空间到rgb空间的转换
var //类似于返回多个值的函数
   Sat, Lum: Double;
begin
   R := 0;
   G := 0;
   B := 0;
   if (H < 360) and (H >= 0) and (S <= 100) and (S >= 0) and (L <= 100) and (L
      >=
      0) then
      begin
         if H <= 60 then
            begin
               R := 255;
               G := Round((255 / 60) * H);
               B := 0;
            end
         else if H <= 120 then
            begin
               R := Round(255 - (255 / 60) * (H - 60));
               G := 255;
               B := 0;
            end
         else if H <= 180 then
            begin
               R := 0;
               G := 255;
               B := Round((255 / 60) * (H - 120));
            end
         else if H <= 240 then
            begin
               R := 0;
               G := Round(255 - (255 / 60) * (H - 180));
               B := 255;
            end
         else if H <= 300 then
            begin
               R := Round((255 / 60) * (H - 240));
               G := 0;
               B := 255;
            end
         else if H < 360 then
            begin
               R := 255;
               G := 0;
               B := Round(255 - (255 / 60) * (H - 300));
            end;

         Sat := Abs((S - 100) / 100);
         R := Round(R - ((R - 128) * Sat));
         G := Round(G - ((G - 128) * Sat));
         B := Round(B - ((B - 128) * Sat));

         Lum := (L - 50) / 50;
         if Lum > 0 then
            begin
               R := Round(R + ((255 - R) * Lum));
               G := Round(G + ((255 - G) * Lum));
               B := Round(B + ((255 - B) * Lum));
            end
         else if Lum < 0 then
            begin
               R := Round(R + (R * Lum));
               G := Round(G + (G * Lum));
               B := Round(B + (B * Lum));
            end;
      end;
end;

procedure RGBtoHSL(R, G, B: Integer; var H, S, L: Double);
// RGB空间到HSL空间的转换
var
   Delta: Double;
   CMax, CMin: Double;
   Red, Green, Blue, Hue, Sat, Lum: Double;
begin
   Red := R / 255;
   Green := G / 255;
   Blue := B / 255;
   CMax := Max(Red, Max(Green, Blue));
   CMin := Min(Red, Min(Green, Blue));
   Lum := (CMax + CMin) / 2;
   if CMax = CMin then
      begin
         Sat := 0;
         Hue := 0;
      end
   else
      begin
         if Lum < 0.5 then
            Sat := (CMax - CMin) / (CMax + CMin)
         else
            Sat := (cmax - cmin) / (2 - cmax - cmin);
         delta := CMax - CMin;
         if Red = CMax then
            Hue := (Green - Blue) / Delta
         else if Green = CMax then
            Hue := 2 + (Blue - Red) / Delta
         else
            Hue := 4.0 + (Red - Green) / Delta;
         Hue := Hue / 6;
         if Hue < 0 then
            Hue := Hue + 1;
      end;
   H := (Hue * 360);
   S := (Sat * 100);
   L := (Lum * 100);
end;

procedure Register;
begin
  RegisterComponents('Custom', [THotTrackImage]);
end;

{ THotTrackImage }

function THotTrackImage.CanAutoSize(var NewWidth,
  NewHeight: Integer): Boolean;
begin
  Result := True;
  if not (csDesigning in ComponentState) or (FPicture.Width > 0) and
    (FPicture.Height > 0) then
  begin
    if Align in [alNone, alLeft, alRight] then
      NewWidth := FPicture.Width;
    if Align in [alNone, alTop, alBottom] then
      NewHeight := FPicture.Height;
  end;
end;

{procedure THotTrackImage.Click;

  procedure ReSearch;
  var
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching3 then
        begin
          THotTrackImage(TempHK).Click();
          Exit;
        end;
      end;
    end;
  end;

begin
  if not FSearching3 then
  begin
    FSearching3:=True;
    try
      if FIsHoted then
      begin
        inherited;
      end else
      begin
        ReSearch;
      end;
    finally
      FSearching3:=False;
    end;
  end;
end;}

{procedure THotTrackImage.CMHintShow(var Message: TMessage);

  procedure ReSearch;
  var
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching5 then
        begin
          if THotTrackImage(TempHK).ShowHint then
          begin
            TCMHintShow(Message).HintInfo^.HintStr:=THotTrackImage(TempHK).Hint;
            THotTrackImage(TempHK).CMHintShow(Message);
            Exit;
          end;
        end;
      end;
    end;
  end;

begin
  if not FSearching5 then
  begin
    FSearching5:=True;
    try
      if FIsHoted then
      begin
        inherited;
      end else
      begin
        ReSearch;
      end;
    finally
      FSearching5:=False;
    end;
  end;
end;}

procedure THotTrackImage.CMMouseEnter(var Message: TMessage);
begin
  inherited;
  SetHoted(True);
end;

procedure THotTrackImage.CMMouseLeave(var Message: TMessage);
begin
  inherited;
  SetHoted(False);
end;

constructor THotTrackImage.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csReplicatable];
  FPicture := TBitmap.Create;
  FHotPicture := TBitmap.Create;
  FPicture.Transparent:=False;
  FPicture.TransparentMode:=tmAuto;
  FHotPicture.Transparent:=False;
  FHotPicture.TransparentMode:=tmAuto;
  FPicture.OnChange := PictureChanged;
  FPicture.OnProgress := Progress;
  Height := 105;
  Width := 105;
  FIsHoted:=False;
  FLightAdd:=8;
  FTransparent:=True;
  {FSearching:=False;
  FSearching1:=False;
  FSearching2:=False;
  FSearching3:=False;
  FSearching4:=False;
  FSearching5:=False;
  FSearching6:=False;}
end;

{procedure THotTrackImage.DblClick;

  procedure ReSearch;
  var
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching4 then
        begin
          THotTrackImage(TempHK).DblClick();
          Exit;
        end;
      end;
    end;
  end;

begin
  if not FSearching4 then
  begin
    FSearching4:=True;
    try
      if FIsHoted then
      begin
        inherited;
      end else
      begin
        ReSearch;
      end;
    finally
      FSearching4:=False;
    end;
  end;
end;}

function THotTrackImage.DestRect: TRect;
var
  w, h, cw, ch: Integer;
  xyaspect: Double;
begin
  w := Picture.Width;
  h := Picture.Height;
  cw := ClientWidth;
  ch := ClientHeight;
  if Stretch or (Proportional and ((w > cw) or (h > ch))) then
  begin
 if Proportional and (w > 0) and (h > 0) then
 begin
      xyaspect := w / h;
      if w > h then
      begin
        w := cw;
        h := Trunc(cw / xyaspect);
        if h > ch then  // woops, too big
        begin
          h := ch;
          w := Trunc(ch * xyaspect);
        end;
      end
      else
      begin
        h := ch;
        w := Trunc(ch * xyaspect);
        if w > cw then  // woops, too big
        begin
          w := cw;
          h := Trunc(cw / xyaspect);
        end;
      end;
    end
    else
    begin
      w := cw;
      h := ch;
    end;
  end;

  with Result do
  begin
    Left := 0;
    Top := 0;
    Right := w;
    Bottom := h;
  end;

  if Center then
 OffsetRect(Result, (cw - w) div 2, (ch - h) div 2);
end;

destructor THotTrackImage.Destroy;
begin
  FPicture.Free;
  FHotPicture.Free;
  inherited Destroy;
end;

procedure THotTrackImage.DoHotTrackEnter;
begin
  if Assigned(FOnHotTrackEnter) then
    FOnHotTrackEnter(Self);
end;

procedure THotTrackImage.DoHotTrackLeave;
begin
  if Assigned(FOnHotTrackLeave) then
    FOnHotTrackEnter(Self);
end;

procedure THotTrackImage.DoLightBitmap;
var
   x, y, ScanlineBytes: integer;
   p: prgbtriplearray;
   RVALUE, bvalue, gvalue: integer;
   hVALUE, sVALUE, lVALUE: Double;
begin
  FHotPicture.Assign(FPicture);
  if not FHotPicture.Empty then
  begin
    FHotPicture.PixelFormat:=pf24bit;
    p := FHotPicture.ScanLine[0];
    ScanlineBytes := integer(FHotPicture.ScanLine[1]) - integer(FHotPicture.ScanLine[0]);
    for y := 0 to FHotPicture.Height - 1 do
    begin
      for x := 0 to FHotPicture.Width - 1 do
      begin
        RVALUE := p[x].rgbtRed;
        gVALUE := p[x].rgbtGreen;
        bVALUE := p[x].rgbtBlue;
        RGBtoHSL(RVALUE, gVALUE, bVALUE, hVALUE, sVALUE, lVALUE);
        lVALUE := min(100, lVALUE + FLightAdd);
        HSLtorgb(hVALUE, sVALUE, lVALUE, rVALUE, gVALUE, bVALUE);
        p[x].rgbtRed := RVALUE;
        p[x].rgbtGreen := gVALUE;
        p[x].rgbtBlue := bVALUE;
      end;
      inc(integer(p), ScanlineBytes);
    end;
  end;
end;

function THotTrackImage.DoPaletteChange: Boolean;
var
  ParentForm: TCustomForm;
  Tmp: TGraphic;
begin
  Result := False;
  Tmp := FPicture;
  if Visible and (not (csLoading in ComponentState)) and (Tmp <> nil) and
 (Tmp.PaletteModified) then
  begin
 if (Tmp.Palette = 0) then
   Tmp.PaletteModified := False
 else
 begin
   ParentForm := GetParentForm(Self);
   if Assigned(ParentForm) and ParentForm.Active and Parentform.HandleAllocated then
   begin
  if FDrawing then
    ParentForm.Perform(wm_QueryNewPalette, 0, 0)
  else
    PostMessage(ParentForm.Handle, wm_QueryNewPalette, 0, 0);
  Result := True;
  Tmp.PaletteModified := False;
   end;
 end;
  end;
end;

function THotTrackImage.GetCanvas: TCanvas;
begin
 Result := FPicture.Canvas;
end;

function THotTrackImage.GetPalette: HPALETTE;
begin
 Result := FPicture.Palette;
end;

{procedure THotTrackImage.MouseDown(Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

  procedure ReSearch;
  var
    P:TPoint;
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching1 then
        begin
          P.X:=X;
          P.Y:=Y;
          P:=THotTrackImage(TempHK).ScreenToClient(ClientToScreen(P));
          THotTrackImage(TempHK).MouseDown(Button,Shift,P.X,P.Y);
          Exit;
        end;
      end;
    end;
  end;

begin
  if not FSearching1 then
  begin
    FSearching1:=True;
    try
      if (X>=0)and(X<FPicture.Width)and(Y>=0)and(Y<FPicture.Height) then
      begin
        if FPicture.Canvas.Pixels[X,Y]=FPicture.Canvas.Pixels[0,0] then
        begin
          ReSearch;
        end else
        begin
          inherited;
        end;
      end else
      begin
        ReSearch;
      end;
    finally
      FSearching1:=False;
    end;
  end;
end;}

{procedure THotTrackImage.MouseMove(Shift: TShiftState; X, Y: Integer);

  procedure ReSearch;
  var
    P:TPoint;
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching then
        begin
          P.X:=X;
          P.Y:=Y;
          P:=THotTrackImage(TempHK).ScreenToClient(ClientToScreen(P));
          THotTrackImage(TempHK).MouseMove(Shift,P.X,P.Y);
          Exit;
        end;
      end;
    end;
  end;

  procedure Slicen;
  var
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK<>Self then
      begin
        THotTrackImage(TempHK).SetHoted(False);
      end;
    end;
  end;

begin
  if not FSearching then
  begin
    FSearching:=True;
    try
      if (X>=0)and(X<FPicture.Width)and(Y>=0)and(Y<FPicture.Height) then
      begin
        if FPicture.Canvas.Pixels[X,Y]=FPicture.Canvas.Pixels[0,0] then
        begin
          SetHoted(False);
          ReSearch;
        end else
        begin
          SetHoted(True);
          Slicen;
          inherited;
        end;
      end else
      begin
        SetHoted(False);
        ReSearch;
      end;
    finally
      FSearching:=False;
    end;
  end;
end;}

{procedure THotTrackImage.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);

  procedure ReSearch;
  var
    P:TPoint;
    I:Integer;
    TempHK:TControl;
  begin
    for I:=0 to Parent.ControlCount-1 do
    begin
      TempHK:=Parent.Controls[I];
      if TempHK is THotTrackImage then
      begin
        if not THotTrackImage(TempHK).FSearching2 then
        begin
          P.X:=X;
          P.Y:=Y;
          P:=THotTrackImage(TempHK).ScreenToClient(ClientToScreen(P));
          THotTrackImage(TempHK).MouseUp(Button,Shift,P.X,P.Y);
          Exit;
        end;
      end;
    end;
  end;

begin
  if not FSearching2 then
  begin
    FSearching2:=True;
    try
      if (X>=0)and(X<FPicture.Width)and(Y>=0)and(Y<FPicture.Height) then
      begin
        if FPicture.Canvas.Pixels[X,Y]=FPicture.Canvas.Pixels[0,0] then
        begin
          ReSearch;
        end else
        begin
          inherited;
        end;
      end else
      begin
        ReSearch;
      end;
    finally
      FSearching2:=False;
    end;
  end;
end;}

procedure THotTrackImage.Paint;
var
  Save: Boolean;
begin
  if csDesigning in ComponentState then
 with inherited Canvas do
 begin
   Pen.Style := psDash;
   Brush.Style := bsClear;
   Rectangle(0, 0, Width, Height);
 end;
  Save := FDrawing;
  FDrawing := True;
  try
   with inherited Canvas do
    begin
      if FIsHoted and not(csDesigning in ComponentState) then
       StretchDraw(DestRect, FHotPicture)
      else
       StretchDraw(DestRect, FPicture);
    end;
  finally
   FDrawing := Save;
  end;
end;

procedure THotTrackImage.PictureChanged(Sender: TObject);
begin
  Picture.Transparent:=FTransparent;
  if AutoSize and (FPicture.Width > 0) and (FPicture.Height > 0) then
 SetBounds(Left, Top, FPicture.Width, FPicture.Height);
  if FTransparent then
    ControlStyle := ControlStyle - [csOpaque]
  else
    ControlStyle := ControlStyle + [csOpaque];
  DoLightBitmap;
  if DoPaletteChange and FDrawing then Update;
  if not FDrawing then Invalidate;
end;

procedure THotTrackImage.Progress(Sender: TObject; Stage: TProgressStage;
  PercentDone: Byte; RedrawNow: Boolean; const R: TRect;
  const Msg: string);
begin
  if FIncrementalDisplay and RedrawNow then
  begin
 if DoPaletteChange then Update
 else Paint;
  end;
  if Assigned(FOnProgress) then FOnProgress(Sender, Stage, PercentDone, RedrawNow, R, Msg);
end;

procedure THotTrackImage.SetCenter(Value: Boolean);
begin
  if FCenter <> Value then
  begin
 FCenter := Value;
 PictureChanged(Self);
  end;
end;

procedure THotTrackImage.CMHitTest(var Message: TCMHitTest);
var
  X,Y:Integer;
begin
  if (Message.XPos>=0)and(Message.XPos<FPicture.Width)and(Message.YPos>=0)and(Message.YPos<FPicture.Height)then
  begin
    if FTransparent then
    begin
      X:=Round(Message.XPos*Picture.Height/Height);
      Y:=Round(Message.YPos*Picture.Height/Height);
      if(FPicture.Canvas.Pixels[X,Y]<>FPicture.Canvas.Pixels[0,0]) then
        Message.Result := HTCLIENT
      else
        Message.Result := HTNOWHERE
    end else
      Message.Result := HTCLIENT;
  end else
    Message.Result := HTNOWHERE;
end;

procedure THotTrackImage.SetHoted(Hoted: Boolean);
begin
  if FIsHoted<>Hoted then
  begin
    FIsHoted:=Hoted;
    Invalidate;
    if Hoted then
    begin
      //SetCaptureControl(Self);
      DoHotTrackEnter;
    end else
    begin
      //SetCaptureControl(nil);
      DoHotTrackLeave;
    end;
  end;
end;

procedure THotTrackImage.SetLightAdd(const Value: Integer);
begin
  FLightAdd := Value;
  DoLightBitmap;
  if FIsHoted then
    Invalidate;
end;

procedure THotTrackImage.SetPicture(Value: TBitmap);
begin
  if Value<>nil then
  begin
    Value.Transparent:=FTransparent;
    Value.TransparentMode:=tmAuto;
  end;
  FPicture.Assign(Value);
end;

procedure THotTrackImage.SetProportional(Value: Boolean);
begin
  if FProportional <> Value then
  begin
 FProportional := Value;
 PictureChanged(Self);
  end;
end;

procedure THotTrackImage.SetStretch(Value: Boolean);
begin
  if Value <> FStretch then
  begin
 FStretch := Value;
 PictureChanged(Self);
  end;
end;

procedure THotTrackImage.SetTransparent(const Value: Boolean);
begin
  if FTransparent<>Value then
  begin
    FTransparent := Value;
   PictureChanged(Self);
  end;
end;

end.

仿微信不规则形状图片 仿照微信发送和显示图片为不规则的泡泡型图片,找了好久的 立即下载

相关推荐

不规则图片切换特效

插件描述:TweenMax不规则图片切换特效. 参考示例:http://www.jq22.com/jquery-info6215

delphi根据不同图片生成不规则窗口的实现(仅限于BMP格式)

unit CreateImageForm; interface uses  Windows, SysUtils, Variants, Classes, Graphics; procedure CreatRgnForm( Bmap: TBitMap; WColor: TColor; hand:THandle); implementation procedure CreatRgnForm( Bmap:

surpaimb的专栏 3361

利用c# wpf实现各种图形绘制

利用visual studio 2010中的自带的相关引用实现各种图形的绘制,包括柱状图、曲线图、饼图等

Delphi不规则窗体实现

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, dxGDIPlusClasses, StdCtrls, Menus, ExtCtrls;type  TForm1 = class(TForm)    PopupMenu1: TP...

henreash的专栏 1405

从时序博弈到数据稳定:CS1237驱动中的信号滤波与卡尔曼实践

本文探讨了CS1237高精度ADC驱动在复杂工业环境中的信号处理挑战,重点介绍了一阶滤波与自适应卡尔曼滤波算法的实践应用。通过参数优化和动态调整策略,有效提升了数据稳定性和抗干扰能力,为嵌入式系统在噪声环境下的精密测量提供了可靠解决方案。

rnn9storyteller的博客 862

DrMOS电路仿真

将驱动电路与功率MOS集成化后既是DrMOS。把驱动芯片以及上下桥MOSFET封装在一起,这样每一相供电就有了单独的驱动芯片,并且这种高度整合的MOSFET可以通过更高的电流、发热比传统的MOSFET也小很多且更节能 自举升压同步BUCK高低侧栅驱动电路原理及仿真 ...

Srambler的博客 5038

焕发新生——FLUKE福禄克DSP4000维修记

说起fluke福禄克 DSP4000系列的测试仪器,相信很多对福禄克产品线略有了解的都应该有所耳闻,它属于元老级的产品了,迄今为止,有差不多超过二十多年的寿命了。然而就是这样一款堪称“爷爷”级别的老古董,如今在市场上依然在某些工程验收领域发光发热,这不手头上又收到客户快递过来的一套故障机维修。 首先,这台设备用户反馈的是无法开机,电池确保电量充满的情况下,依然无法开机,没有任何反应。 按照惯例,我们要确认主板的供电电路是否正常,其次检查主板的CPU供电是否正常。在测试了P5供电脚位都有不低于7.8V的

kaianding的博客 1283

浅谈天线 - - - GNSS/BT/4G/2.4G

全球定位导航系统,最成熟的就是美利坚,我大中华,俄罗斯,还有就是欧洲的一个(太次不谈)所以我们在项目调试的时候,小尺寸的陶瓷天线上一般兼容2个频段,体积大一点的可以兼容三个频段,采用组合的形式 GPS+BD GPS+GLONASS GLONASS+BD 或者是单频段的定位天线陶瓷PATC陶瓷片:陶瓷片面积越大,介电常数越大,其共振频率越高,接收效果越高,这就是为什么都推荐使用大一点的陶瓷天线的原因银层:陶瓷天线表面的银层可以影响天线的共振频率,理想的GNSS陶瓷片频点准确落在1575.42MH

BLACKHOLE6的博客 1万+

自动超频_锐龙4000 APU还能自动超频:比标称频率再高100MHz

AMD日前发布了基于7nm新工艺、Zen 2新架构的锐龙4000U/锐龙4000H APU处理器,分别面向轻薄本、游戏本,都做到了最多8核心16线程,而热设计功耗分别控制在15W、45W。得益于新工艺新架构的支撑,锐龙4000系列不仅核心数量多,频率也不差,比如锐龙7 4800U锐龙7 4800H都能加速到4.2GHz,而且潜力还不止于此。随着锐龙4000笔记本即将陆续上市,测试工作正在全面展开,...

weixin_39907316的博客 291

Delphi开发者必备:CEF4Delphi跨平台浏览器嵌入实战指南(含Lazarus适配)

本文详细介绍了Delphi开发者如何利用CEF4Delphi实现跨平台浏览器嵌入,包括环境配置、Lazarus适配、ARM架构优化及Firemonkey集成等实战技巧。通过Chromium引擎的强大功能,开发者可以轻松为传统桌面应用添加现代浏览器特性,提升多平台开发效率。

weixin_29233333的博客 226

DC竞赛 国能日新功率预测题 rank21 解决方案(适合新手)

DataCastle国能日新光伏功率预测 数据异常处 本题在测试集中提供了时间、辐照度、风速、风向、温度、压强、湿度、实发辐照度8个特征,以及标签**实际功率**。 而在训练集中只有前七个特征,无实发辐照度。 策略 在观察了数据之后,我们确定实发辐照度是一个强力特征,于是我们采取了stacking的策略: 1. 第一次训练以实发辐照度为标签,预测 测试集的实发辐照度 2....

yyhhlancelot的博客 7294

华为p40论坛_预算4000+,华为、苹果、三星、小米,该如何选择?

同等价位,你会买苹果、三星、华为、小米还是其他什么品牌的手机?查看全部 6,005 个回答邀请回答查看回答之润扬人类迷惑行为鉴赏师第一次认真写回答,要准备买手机的 朋友可以参考参考。同等价位,首先要明确是哪一档的价位,这个很有必要。众所周知,三星苹果4000元以下的机型国内是很少的,三星还有几款,苹果刚刚发布的se2算一款,所以,4000元以下不讨论三星苹果机型。那么4000元以上,这四个品牌该怎...

weixin_39735509的博客 307

时频分析之短时傅里叶变换(STFT)

本文利用MATLAB自带的spectrogram函数对信号做短时傅里叶变换。首先介绍了短时傅里叶变换(STFT)的背景及意义;其次,对spectrogram函数的用法以及变量的含义做了详细的解释;最后,利用MATLAB编写程序实现了信号的STFT。

总结论文中的算法并给出论文的复现代码 7万+

惠普辞退4000员工,今后如何走

电脑市场的竞争越来越强,惠普正在改革自己的方针,虽然是PC市场的老大,但现在联想一步不接近惠普的市场。惠普的历史很深远,如今不断涌现的新市场占领惠普的市场,惠普现在面临的危机也越来越大。 惠普辞退了4000名员工,在第三财政季度下降的速度要比最初预料快,削减人员是为了削减其开支。惠普的首席执行官MegWhitman(梅格·惠特曼)透露,更新后的数字会在一个业...

weixin_34004750的博客 102

ORB-SLAM3算法2之EuRoc开源数据集运行ORB-SLAM3生成轨迹并用evo工具评估轨迹

ORB-SLAM3算法1 已成功编译安装ORB-SLAM3到本地,本篇目的是用EuRoc开源数据来运行ORB-SLAM3,并生成轨迹,最后用evo评估工具来评估ORB-SLAM3生成的轨迹和真值轨迹。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 3761

A2B V1.0协议学习笔记(A2B System Specification V1.0)

A2B全称是 Automotive Audio Bus 汽车音频总线,主要是解决传统音频总线线多、线重、成本贵等问题。本文是以A2B V1.0规范为准,现在ADI又推出了A2B V2.0,物理层不兼容,采用了QPSK编码方式,后续有时间再更新。A2B总线的优点:支持1主多从的架构(最多10个子节点)支持50Mbps(具体是49.152 Mbps)的高带宽传输以及

qflook的博客 4425

bwl老二吃嘲讽吗_盘点国内十个老大和老二“打架”导致老三消失的案例

国内市场非常大,所以一种业务火了之后就会有很多企业跟进,多家企业做同一种业务,意味着竞争的开始,正所谓商场如战场,为了获得更多用户量,竞争过程中少不了烧钱,烧不起的企业自然会退出,甚至一些企业本身已经站稳了脚跟,然而不久后却被一些新加入的巨头企业烧钱将其边缘化。值得一提的是,我们常常会看到老大和老二“打架”的过程中,老三就会消失或者被边缘化。接下来就盘点国内十个老大和老二“打架”导致老三...

weixin_35928736的博客 403

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

每月4000元我仍然选择辞职,我准备去当农民【并与女友分手在平安夜】

分手在平安夜原文 http://www.zuola.com/weblog/?p=357如果我没有判断错误的话,我应该已经是一个至少有四百个观众的自我表演者,一心描述自己的BT的生活。我真的很BT,很猥琐,但在网上却是另一个模样,我想我还应该还是聪明的善于选择公众面具的人,我看上去知道如何迎合观众的口味,我知道哪些东西说起好玩,并且吸引人。我知道哪些不应该在BLOG里说,比如工作上的事和感情上的事,

FreeXploiT 4242

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

AI老大哥,正在看着你

郭一璞 发自 凹非寺量子位 报道 | 公众号 QbitAI太可怕了。远程办公的疫情期间,除了Zoom这类会议软件,另一种办公软件也火了:云监工软件,还是AI来监工的那种。只是,被监工的对...

量子位 698

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

世事无常:盛极一时的行业老大,如今却寄人篱下

最近刷到一则关注度不是很高的新闻,标题叫《谷歌硅谷斥巨资拿地,这次连雅虎总部都买下了》,看完这个新闻到不是感慨谷歌的财大气粗,毕竟人家现在就是有这个资本和地位,让我心生感...

239

新浪互联星空网站的体系结构(4000万动态pv-6台服务器)

这个博文于2007年12月17号发表,我认为:开源的宗旨:就在于技术的传播,让更多的人知道。我再把这个翻出来。以下是对原文的引用(注:以下的第一人称“我”指作者-张宴)。另外提示一下大家,很多的技术内幕不在公司的主页上,往往在技术主创人员的blog中。很多的牛牛的blog都是大家关注的目标(像mysql大牛:jay pipe, jcole,Jeremy Zawodny,还有很多,不一一列出)付本文

cnbird's blog 1481

格式排版不再熬大夜:Paperxie 4000 + 高校模板,让毕业论文一键变规范

毕业论文是本科与研究生生涯的最后一份答卷,它的核心价值在于内容的学术性与创新性,而不是格式的完美无缺。但繁琐的格式要求,却让无数学生在毕业季里陷入「为格式而活」的困境,消耗了本该用来享受毕业时光、准备答辩的精力。Paperxie 的格式排版功能,正是为了打破这一困境而生。把时间留给内容创作,而非机械的格式修改;把精力留给学术思考,而非琐碎的细节调整;把心情留给毕业喜悦,而非无尽的格式焦虑。在这个毕业季,不妨放下对格式的恐惧,打开 Paperxie,体验「一键排版」的高效与便捷。

355

阿里巴巴斥资4000万在美国打广告 为上市铺路

        在美国大选期,美国国家广播公司(CNBC)的黄金时段,一家中国公司正在花大价钱展开广告轰炸。  记者昨天获悉,正在中央电视台狂打广告的阿里巴巴,已与美国主流媒体CNBC签了一年的广告协议。  从本月开始,阿里巴巴在CNBC滚动播出,以展示中国企业为主体的广告。据可靠消息,阿里巴巴头两个月的广告支出将超过4000万元人民币。  阿里巴巴拒绝透露美国大选期间广告投放的经费,只含糊地透露

piner的专栏 2540

4000亿农夫山泉的生意经

配图来自Canva “农夫山泉有点甜”、“我们不生产水,我们只是大自然的搬运工。”多年来,这些耳熟能详的广告词,已经深入人心。与这些广告词一道深入人心的,还有农夫山泉这家通过“卖水”建立起来的饮品帝国。 在农夫山泉早期,营销先行可以说是其品牌能够迅速崛起的不二法门,也是农夫山泉多次在市场中获胜的重要原因。此外,农夫山泉在成立后的20多年时间里面,先后打造了一批诸如农夫山泉、茶π、尖叫等爆款饮品矩阵,正是这些爆款饮品品牌,构建起了如今的农夫山泉饮品帝国。 农夫山泉深入人心的品牌影响力,让它在首次公开..

liukuang110的博客 304
上一篇: 面对对象的思考(二)
下一篇: 软件质量管理
BlueTrees
博客等级 码龄26年 44粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值