我有一个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;
答案 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上(对齐客户端)并使其透明。然后将控件放在它上面,它允许滚动...
我相信你会尝试这个,所以是什么让你有问题......