如何制作具有透明背景的TScrollBox?

时间:2012-07-06 16:47:50

标签: delphi user-interface delphi-2006

我有一个TFrame,背景为TImage

这个框架作为我放在主TForm的有限空间内的其他框架的祖先。 所以它只是其他框架的用户界面基础。

我需要在这些框架中放置许多控件,因为它们将处理大型数据库表单。

由于主要表单的空间有限,我需要在标题栏以外的所有TScrollBox空格中加TFrame。但这涵盖了背景图像。

如何让此ScrollBar变为背景透明?

或者,制作具有该功能的新组件以及如何做更好?

我在其他网站上看到了一些示例,但它们在运行时出现错误

谢谢!

EDIT2:

我从LMD Inovative中找到了来自ElPack的TElScrollBox。 这是透明背景,允许我们将图像作为背景。 但同样的问题出现了:当我们在运行时滚动它时,它会将祖先的背景移动到它的效果区域。

EDIT1:

我试图制作一个后代但滚动条只显示当我们将鼠标悬停在它应该位于的位置时,当我们滚动它时,表单的背景在滚动框内移动。 而且,它内部的控件会出现一些油漆错误......

interface

uses
  Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, StdCtrls, ExtCtrls;

type
  TTransScrollBox = class(TScrollBox)
  private
    { Private declarations }
  protected
    procedure CreateParams(var params: TCreateParams); override;
    procedure WMEraseBkGnd(var msg: TWMEraseBkGnd); message WM_ERASEBKGND;
  public
    { Public declarations }
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Eduardo', [TTransScrollBox]);
end;

procedure TTransScrollBox.CreateParams(var params: TCreateParams);
begin
  inherited CreateParams(params);
  params.ExStyle := params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TTransScrollBox.WMEraseBkGnd(var Msg: TWMEraseBkGnd); 
begin
  SetBkMode (Msg.DC, TRANSPARENT);
  Msg.Result := 1;
end;

2 个答案:

答案 0 :(得分:3)

如果你不希望图像滚动你将不得不滚动自己的卷轴,这不是太难(在英格兰仍在下雨,所以我很无聊!)

要测试,请创建框架,将图像打开并对照客户端。 将框架上的滚动条设置为垂直并向右对齐。 在设计时放大框架。 将控件放在任何地方,然后缩小它,使一些不可见(在底部下方)。 在表单show(用于测试)的主窗体上,或者在创建新帧时调用Frame.BeforeShow来进行设置。

[LATER]编辑正在下雨&还是很无聊所以我为你完成了它!

unit ScrollingBaseFrameU;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, jpeg, ExtCtrls, StdCtrls, contnrs, Generics.Collections, Grids,
  DBGrids;

const
  MaxLargeSteps = 5; // maximum large scroll clicks to scroll to max
  IgnoreTag = 99;   // Controls with this tag value are igored for scrolling
  TitleHeight = 23; // Height of title bar as we are dealing with the image mouse co-ordinates
  RightMargin = 25; // space after right-most control
  BottomMargin = 25; // space after bottom-most control
  StrControl = 'ControlName';  // prefix for controls with no name

type
  TControlPos = class(Tobject) // Little object to save initial control positions
  public
    Name: string;
    X,
    Y: Integer;
  end;

  TScrollingBaseFrame = class(TFrame)
    BackGroundImage: TImage;
    HorzScrollBar: TScrollBar;
    VertScrollBar: TScrollBar;
    pnlTitle: TPanel;
    procedure VertScrollBarChange(Sender: TObject);
    procedure BackGroundImageMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FrameResize(Sender: TObject);
    procedure HorzScrollBarChange(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ShowHScroller,
    ShowVScroller : Boolean;       // scroller needed at all?
    PosList: TList<TControlPos>;   // list of initial positions
    procedure BeforeShow; virtual; // override in descendants for specific behaviour
    procedure BeforeClose; virtual; // override in descendants for specific behaviour
    function IndexOfPos(AName:string): Integer;
  end;

implementation

{$R *.dfm}

procedure TScrollingBaseFrame.BeforeClose;
// Clean up
var
  p: TControlPos;
begin
  for p in PosList do
    p.free;
  PosList.Free;
end;

procedure TScrollingBaseFrame.BeforeShow;
//Setup scroller and save initial control positions
var
  i,XMax,YMax,Idx: Integer;
  AControl: TControl;
begin
  pnlTitle.Height := TitleHeight;
  PosList := TList<TControlpos>.Create;
  XMax := 0;
  YMax := 0;
  for i := 0 to ComponentCount - 1 do
  begin
    if Components[i] is TControl then
    begin
      AControl := TControl(Components[i]);
      if Acontrol.Tag <> IgnoreTag then
      begin
        Idx := PosList.Add(TcontrolPos.Create);
        if AControl.Name = '' then  // deal with empty names
          AControl.Name :=  StrControl + IntToStr(i);
        PosList[Idx].Name := AControl.Name;
        PosList[Idx].X := AControl.Left;
        PosList[Idx].Y := AControl.Top;
        if YMax < AControl.Top + AControl.Height then
         YMax := AControl.Top + AControl.Height;
        if XMax < AControl.Left + AControl.Width then
         XMax := AControl.Left + AControl.Width;
      end; // Ignored
    end; // is control
  end; // count
   VertScrollBar.Max := (YMax + BottomMargin) - Height; // bit of a bottom margin :)
   VertScrollBar.LargeChange := VertScrollBar.Max div MaxLargeSteps;
   ShowVScroller := VertScrollBar.Max > BottomMargin;
   VertScrollBar.Visible := ShowVScroller;
   HorzScrollBar.Max := (XMax + RightMargin) - Width; // bit of a Right margin :)
   HorzScrollBar.LargeChange := HorzScrollBar.Max div MaxLargeSteps;
   ShowHScroller := HorzScrollBar.Max > RightMargin;
   HorzScrollBar.Visible := ShowHScroller;
end;

procedure TScrollingBaseFrame.FrameResize(Sender: TObject);
begin
  BackGroundImage.Width := Width;
  BackGroundImage.Height := Height;
end;

procedure TScrollingBaseFrame.HorzScrollBarChange(Sender: TObject);
// Move the controls left and right relative to thier initail positions
var
  i,j: Integer;
  AControl: TControl;
begin
  for i := 0 to ComponentCount - 1 do
   begin
     if Components[i] is TControl then
     begin
       AControl :=  TControl(Components[i]);
       j := IndexOfPos(AControl.Name);
       if j >= 0 then  // could be ignored or the background image
         Acontrol.Left := PosList[j].X  - HorzScrollBar.Position;
     end;
   end;
end;

procedure TScrollingBaseFrame.BackGroundImageMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
// Show/Hide the scrollbars using mouse position
var
  ScrollBarWidth: Integer;
begin
  ScrollBarWidth := GetSystemmetrics(SM_CXVSCROLL);  // assume the same for horizontal
  VertScrollBar.Visible := (X > Width - ScrollBarWidth) and ShowVScroller;
  HorzScrollBar.Visible := (Y > (Height - TitleHeight) - ScrollBarWidth) and ShowHScroller;
end;

function TScrollingBaseFrame.IndexOfPos(AName:string): Integer;
// Find a control position in the list by name
var
  Idx: Integer;
begin
  Result := -1;
  Idx := 0;
  while (Result < 0) and (Idx < PosList.Count) do
  begin
    if PosList[idx].Name = AName then
      Result := idx;
    inc(idx);
  end;
end;

procedure TScrollingBaseFrame.VertScrollBarChange(Sender: TObject);
// Move the controls Up and down relative to thier initail positions
var
  i,j: Integer;
  AControl: TControl;
begin
  for i := 0 to ComponentCount - 1 do
   begin
     if Components[i] is TControl then
     begin
       AControl :=  TControl(Components[i]);
       j := IndexOfPos(AControl.Name);
       if j >= 0 then  // could be ignored
         Acontrol.Top := PosList[j].Y  - VertScrollBar.Position;
     end;
   end;
end;

end.

和DFM的完整性:

object ScrollingBaseFrame: TScrollingBaseFrame
  Left = 0
  Top = 0
  Width = 830
  Height = 634
  DoubleBuffered = True
  ParentDoubleBuffered = False
  TabOrder = 0
  OnResize = FrameResize
  object BackGroundImage: TImage
    Tag = 99
    Left = 0
    Top = 23
    Width = 813
    Height = 594
    Align = alClient
    Picture.Data = { **Removed as it was so big!**}
    Transparent = True
    OnMouseMove = BackGroundImageMouseMove
    ExplicitTop = 0
    ExplicitWidth = 1600
    ExplicitHeight = 1200
  end
  object HorzScrollBar: TScrollBar
    Tag = 99
    Left = 0
    Top = 617
    Width = 830
    Height = 17
    Align = alBottom
    PageSize = 0
    TabOrder = 0
    OnChange = HorzScrollBarChange
    ExplicitLeft = 231
    ExplicitTop = 293
    ExplicitWidth = 121
  end
  object VertScrollBar: TScrollBar
    Tag = 99
    Left = 813
    Top = 23
    Width = 17
    Height = 594
    Align = alRight
    Kind = sbVertical
    PageSize = 0
    TabOrder = 1
    OnChange = VertScrollBarChange
    ExplicitTop = 29
  end
  object pnlTitle: TPanel
    Tag = 99
    Left = 0
    Top = 0
    Width = 830
    Height = 23
    Align = alTop
    Caption = 'pnlTitle'
    TabOrder = 2
    ExplicitLeft = 184
    ExplicitTop = 3
    ExplicitWidth = 185
  end
end

[2ND编辑] 好吧,不想让我的业余时间浪费,下面的内容应该适用于Delphi 6。

unit ScrollingBaseFrameU;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, jpeg, ExtCtrls, StdCtrls, contnrs, Grids,
  DBGrids;

const
  MaxLargeSteps = 5; // maximum large scroll clicks to scroll to max
  IgnoreTag = 99;   // Controls with this tag value are igored for scrolling
  TitleHeight = 23; // Height of title bar as we are dealing with the image mouse co-ordinates
  RightMargin = 25; // space after right-most control
  BottomMargin = 25; // space after bottom-most control
  StrControl = 'ControlName';  // prefix for controls with no name

type
  TControlPos = class(Tobject) // Little object to save initial control positions
  public
    Name: string;
    X,
    Y: Integer;
  end;

  TControlPosList = class(TObject)
  private
    function GetCount: Integer;
    function GetItems(Index: Integer): TControlPos;
    procedure SetItems(Index: Integer; const Value: TControlPos);
  public
   TheList: TObjectList;
   Constructor Create; virtual;
   Destructor Destroy; override;
   function Add(APos: TControlPos): Integer;
   function IndexOfPos(AName: string): Integer;
   property Count: Integer read GetCount;
   property Items[Index: Integer]: TControlPos read GetItems write SetItems; default;
  end;

  TScrollingBaseFrame = class(TFrame)
    BackGroundImage: TImage;
    HorzScrollBar: TScrollBar;
    VertScrollBar: TScrollBar;
    pnlTitle: TPanel;
    procedure VertScrollBarChange(Sender: TObject);
    procedure BackGroundImageMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FrameResize(Sender: TObject);
    procedure HorzScrollBarChange(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ShowHScroller,
    ShowVScroller : Boolean;       // scroller needed at all?
    PosList: TControlPosList;   // list of initial positions
    procedure BeforeShow; virtual; // override in descendants for specific behaviour
    procedure BeforeClose; virtual; // override in descendants for specific behaviour
  end;

implementation

{$R *.dfm}

procedure TScrollingBaseFrame.BeforeClose;
// Clean up
begin
  PosList.Free;
end;

procedure TScrollingBaseFrame.BeforeShow;
//Setup scroller and save initial control positions
var
  i,XMax,YMax,Idx: Integer;
  AControl: TControl;
begin
  pnlTitle.Height := TitleHeight;
  PosList := TControlPosList.Create;
  XMax := 0;
  YMax := 0;
  for i := 0 to ComponentCount - 1 do
  begin
    if Components[i] is TControl then
    begin
      AControl := TControl(Components[i]);
      if Acontrol.Tag <> IgnoreTag then
      begin
        Idx := PosList.Add(TcontrolPos.Create);
        if AControl.Name = '' then  // deal with empty names
          AControl.Name :=  StrControl + IntToStr(i);
        PosList[Idx].Name := AControl.Name;
        PosList[Idx].X := AControl.Left;
        PosList[Idx].Y := AControl.Top;
        if YMax < AControl.Top + AControl.Height then
         YMax := AControl.Top + AControl.Height;
        if XMax < AControl.Left + AControl.Width then
         XMax := AControl.Left + AControl.Width;
      end; // Ignored
    end; // is control
  end; // count
   VertScrollBar.Max := (YMax + BottomMargin) - Height; // bit of a bottom margin :)
   VertScrollBar.LargeChange := VertScrollBar.Max div MaxLargeSteps;
   ShowVScroller := VertScrollBar.Max > BottomMargin;
   VertScrollBar.Visible := ShowVScroller;
   HorzScrollBar.Max := (XMax + RightMargin) - Width; // bit of a Right margin :)
   HorzScrollBar.LargeChange := HorzScrollBar.Max div MaxLargeSteps;
   ShowHScroller := HorzScrollBar.Max > RightMargin;
   HorzScrollBar.Visible := ShowHScroller;
end;

procedure TScrollingBaseFrame.FrameResize(Sender: TObject);
begin
  BackGroundImage.Width := Width;
  BackGroundImage.Height := Height;
end;

procedure TScrollingBaseFrame.HorzScrollBarChange(Sender: TObject);
// Move the controls left and right relative to thier initail positions
var
  i,j: Integer;
  AControl: TControl;
begin
  for i := 0 to ComponentCount - 1 do
   begin
     if Components[i] is TControl then
     begin
       AControl :=  TControl(Components[i]);
       j := PosList.IndexOfPos(AControl.Name);
       if j >= 0 then  // could be ignored
         Acontrol.Left := PosList[j].X  - HorzScrollBar.Position;
     end;
   end;
end;

procedure TScrollingBaseFrame.BackGroundImageMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
// Show/Hide the scrollbars using mouse position
var
  ScrollBarWidth: Integer;
begin
  ScrollBarWidth := GetSystemmetrics(SM_CXVSCROLL);  // assume the same for horizontal
  VertScrollBar.Visible := (X > Width - ScrollBarWidth) and ShowVScroller;
  HorzScrollBar.Visible := (Y > (Height - TitleHeight) - ScrollBarWidth) and ShowHScroller;
end;


procedure TScrollingBaseFrame.VertScrollBarChange(Sender: TObject);
// Move the controls Up and down relative to thier initail positions
var
  i,j: Integer;
  AControl: TControl;
begin
  for i := 0 to ComponentCount - 1 do
   begin
     if Components[i] is TControl then
     begin
       AControl :=  TControl(Components[i]);
       j := PosList.IndexOfPos(AControl.Name);
       if j >= 0 then  // could be ignored
         Acontrol.Top := PosList[j].Y  - VertScrollBar.Position;
     end;
   end;
end;

{ TcontrolPosList }

function TControlPosList.Add(APos: TControlPos): Integer;
begin
  Result := TheList.Add(APos);
end;

constructor TControlPosList.Create;
begin
  TheList := TObjectList.Create;
  TheList.OwnsObjects := True;
end;

destructor TControlPosList.Destroy;
begin
  TheList.Free;
  inherited;
end;

function TControlPosList.GetCount: Integer;
begin
  Result := TheList.Count;
end;

function TControlPosList.GetItems(Index: Integer): TControlPos;
begin
  Result := TControlPos(TheList[Index]);
end;

function TControlPosList.IndexOfPos(AName: string): Integer;
// Find a control position in the list by name
var
  Idx: Integer;
begin
  Result := -1;
  Idx := 0;
  while (Result < 0) and (Idx < TheList.Count) do
  begin
    if Items[idx].Name = AName then
      Result := idx;
    inc(idx);
  end;
end;

procedure TControlPosList.SetItems(Index: Integer; const Value: TControlPos);
begin
  TheList[Index] := Value;
end;

end.

答案 1 :(得分:0)

撤销基础框架上的顺序:)

打开ScrollBox,然后将图像放在Scrollbox上(对齐客户端)并使其透明。然后将控件放在它上面,它允许滚动...

我相信你会尝试这个,所以是什么让你有问题......