tslediter/funcext/tvclib/tcustomscrollcontrol.tsf

390 lines
11 KiB
Plaintext

type tcustomscrollcontrol = class(TCustomControl)
{**
@explan(说明)带滚动条的窗口类 %%
**}
uses utslvclmemstruct;
{**
@explan(说明) 带滚动条的自绘制窗口 %%
**}
private
FLocalX;//水平基准
FLocalXold;
FLocalY;//垂直基准
FLocalYold;
FSI; //滚动条结构
FAutoScroll; //自动滚动条
FThumbTrack; //thunmtrack
FWhileStep ;//滚动步长
function SetAutoScroll(v);
begin
if(v in array(0,1,2,3))and v <> FAutoScroll then
begin
FAutoScroll := v;
InitialScroll();
end
end
function SetWhileStep(v);
begin
if not(v>=1) then return ;
nv := integer(v);
if FWhileStep=nv then return ;
FWhileStep := nv;
end
protected
function GetXScrollDelta();virtual; //x间隔
begin
{**
@explan(说明) 获得x间隔 %%
**}
return 10;
end
function GetYScrollDelta();virtual; //y 间隔
begin
{**
@explan(说明) 获得y间隔 %%
**}
return 10;
end
function GetClientXCapacity();virtual; //宽度容量
begin
{**
@explan(说明) 客户区x容量 %%
**}
return 0;
end
function GetClientYCapacity();virtual; //高度容量
begin
{**
@explan(说明) 客户区y容量 %%
**}
return 0; //integer((yClient) / FDeltaY);
end
function GetClientXCount();virtual; //宽度间隔
begin
{**
@explan(说明) 客户区x数量 %%
**}
return 0;
end
function GetClientYCount();virtual; //高度项
begin
{**
@explan(说明) 客户区y数量 %%
**}
return 0;
end
function PositionChanged();virtual; //基准点改变
begin
{**
@explan(说明) 基准点改变回调 %%
**}
end
function GetDeltaXpos();virtual; //水平变化
begin
r := FLocalX-FLocalXold;
FLocalXold := FLocalX;
return r;
end
function GetDeltaYpos();virtual; //垂直变化
begin
r := FLocalY-FLocalYold;
FLocalYold := FLocalY;
return r;
end
function GetXPos();virtual;
begin
return FLocalX;
end
function GetYPos();virtual;
begin
return FLocalY;
end
function SetXpos(x);virtual;
begin
nx := integer(x);
if not HandleAllocated()then return FLocalX := nx;
if nx <> FLocalX then
begin
hwnd := Handle;
FSI.fMask := SIF_POS; //SIF_ALL;
_wapi.GetScrollInfo(hwnd,SB_HORZ,FSI._getptr_);
ypos := FSI.nPos;
hwnd := Handle;
FSI.fMask := SIF_POS;
FSI.nPos := nx;
_wapi.SetScrollInfo(hwnd,SB_HORZ,FSI._getptr_,TRUE);
// 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
_wapi.GetScrollInfo(hwnd,SB_HORZ,FSI._getptr_);
if FSI.nPos <> ypos then
begin
FLocalXold := FLocalX;
FLocalX := FSI.nPos;
PositionChanged();
end
end
end
function SetYpos(y);virtual;
begin
nx := integer(y);
if not HandleAllocated()then return FLocalY := nx;
if nx <> FLocalY then
begin
hwnd := Handle;
FSI.fMask := SIF_POS; //SIF_ALL;
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
ypos := FSI.nPos;
FSI.nPos := nx;
FSI.fMask := SIF_POS;
_wapi.SetScrollInfo(hwnd,SB_VERT,FSI._getptr_,TRUE);
// 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
if FSI.nPos <> ypos then
begin
FLocalYold := FLocalY;
FLocalY := FSI.nPos;
PositionChanged();
end
end
end
function InitialScroll();virtual;
begin
if not HandleAllocated()then return;
hwnd := Handle;
// 设置垂直滚动条范围和页面大小(设置页面大小将决定滑块的粗细)
FSI.fMask := SIF_POS .| SIF_RANGE .| SIF_PAGE;
FSI.nMin := 0;
FSI.nPos := FLocalY; //20200709
FSI.nMax :=(FAutoScroll .& 1)?(GetClientYCount()):0;
FSI.nPage := GetClientYCapacity();
_wapi.SetScrollInfo(hwnd,SB_VERT,FSI._getptr_,true);
{if FSI.nMax>FSI.nPage then
begin
FLocalYold := FLocalY;
FLocalY := 0;
end else
begin }
FSI.fMask := SIF_POS;
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
FLocalYold := FLocalY;
FLocalY := FSI.nPos;
//end
// 设置水平滚动条范围和页面大小(设置页面大小将决定滑块的粗细)
FSI.cbSize := FSI._size_;
FSI.fMask := SIF_RANGE .| SIF_PAGE .| SIF_POS;
FSI.nMin := 0;
FSI.nPos := FLocalX;
FSI.nMax :=(FAutoScroll .& 2)?(GetClientXCount()):0;
FSI.nPage := GetClientXCapacity();
_wapi.SetScrollInfo(hwnd,SB_HORZ,FSI._getptr_,TRUE);
{if FSI.nMax>FSI.nPage then
begin
FLocalXold := FLocalX;
FLocalX := 0;
end else
begin }
FSI.fMask := SIF_POS;
_wapi.GetScrollInfo(hwnd,SB_HORZ,FSI._getptr_);
FLocalXold := FLocalX;
FLocalX := FSI.nPos;
//end
PositionChanged();
end
function DoVScroll(o,e);override;
begin
// 获得垂直滚动条的所有信息
if csDesigning in ComponentState then return;
FSI.fMask := SIF_ALL;
hwnd := e.hwnd;
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
// 保存当前滑块位置,迟些进行比较
yPos := FSI.nPos;
case e.lowparam of
// 用户点击键盘 Home 按键
SB_TOP:
begin
FSI.nPos := FSI.nMin;
end
// 用户点击键盘 End 按键
SB_BOTTOM:
begin
FSI.nPos := FSI.nMax;
end
// 用户点击滚动条上边的三角形
SB_LINEUP:
begin
FSI.nPos -= 1;
end
// 用户点击滚动条下边的三角形
SB_LINEDOWN:
begin
FSI.nPos += 1;
end
// 用户点击滑块上边的滚动条轴
SB_PAGEUP:
begin
//return ;
FSI.nPos -= FSI.nPage;
end
// 用户点击滑块下边的滚动条轴
SB_PAGEDOWN:
begin
//return ;
FSI.nPos += FSI.nPage;
end
// 用户拖动滚动条
SB_THUMBTRACK:
begin
if FThumbTrack then
begin
FSI.nPos := FSI.nTrackPos;
end
end
SB_THUMBPOSITION:
begin
FSI.nPos := FSI.nTrackPos;
end
end
// 设置滚动条滑块的新位置
if FSI.nPos=yPos then return;
return SetYpos(FSI.nPos);
FSI.fMask := SIF_POS;
_wapi.SetScrollInfo(hwnd,SB_VERT,FSI._getptr_,TRUE);
// 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
// 与此前的保存的值进行比较,如果不同则滚动窗口
FLocalY := FSI.nPos;
if(FSI.nPos <> yPos)then
begin
PositionChanged();
end
return 0;
end
function DoHScroll(o,e);override;
begin
if csDesigning in ComponentState then return;
FSI.fMask := SIF_ALL;
_wapi.GetScrollInfo(e.hwnd,SB_HORZ,FSI._getptr_);
// 保存当前滑块位置,迟些进行比较
xPos := FSI.nPos;
case e.lowparam of
// 用户点击滚动条左边的三角形
SB_LEFT:
begin
FSI.nPos := FSI.nMin;
end
SB_RIGHT:
begin
FSI.nPos := FSI.nMax;
end
SB_LINELEFT:
begin
FSI.nPos -= 1;
end
// 用户点击滚动条右边的三角形
SB_LINERIGHT:
begin
FSI.nPos += 1;
end
// 用户点击滑块左边的滚动条轴
SB_PAGELEFT:
begin
FSI.nPos -= FSI.nPage;
end
// 用户点击滑块右边的滚动条轴
SB_PAGERIGHT:
begin
FSI.nPos += FSI.nPage;
end
// 用户拖动滚动条
SB_THUMBTRACK:
begin
if FThumbTrack then
begin
FSI.nPos := FSI.nTrackPos;
end
end
SB_THUMBPOSITION:
begin
//return ;
FSI.nPos := FSI.nTrackPos;
end
end;
if FSI.nPos=xPos then return;
return SetXpos(FSI.nPos);
// 设置滚动条滑块的新位置
FSI.fMask := SIF_POS;
_wapi.SetScrollInfo(e.hwnd,SB_HORZ,FSI._getptr_,TRUE);
// 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
_wapi.GetScrollInfo(e.hwnd,SB_HORZ,FSI._getptr_);
// 与此前的保存的值进行比较,如果不同则滚动窗口
FLocalX := FLocalX;
FLocalX := FSI.nPos;
if(FSI.nPos <> xPos)then
begin
PositionChanged();
end
end
function DoMouseWheel(o,e);override;
begin
if csDesigning in ComponentState then return;
hwnd := self.Handle;
FSI.fMask := SIF_ALL;
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
// 保存当前滑块位置,迟些进行比较
yPos := FSI.nPos;
dd := 0;
edelta := e.delta;
ew := abs(round(edelta/120));
if edelta<0 and FSI.nMax>yPos then
begin
//dd++;
dd += FWhileStep*ew;
end
if edelta>0 and FSI.nMin<yPos then
begin
//dd--;
dd -= FWhileStep*ew;
end
if not dd then return;
FSI.fMask := SIF_POS;
FSI.nPos := yPos+dd;
_wapi.SetScrollInfo(hwnd,SB_VERT,FSI._getptr_,TRUE);
// 获得滚动条滑块的位置,由于窗口调整,它可能不是同一个值
_wapi.GetScrollInfo(hwnd,SB_VERT,FSI._getptr_);
dd := yPos-FSI.nPos;
FLocalYold := FLocalY;
FLocalY := FSI.nPos;
if dd then
begin
PositionChanged();
end
end
public
function Create(AOwner);override;
begin
FWhileStep := 3;
inherited;
end
function AfterConstruction();override;
begin
inherited;
FThumbTrack := true;
FLocalX := 0;
FLocalY := 0;
FLocalXold := 0;
FLocalYold := 0;
FAutoScroll := 0;
FSI := new TScrollinfo();
FSI.cbSize := FSI._size_;
end
property AutoScroll:integer read FAutoScroll write SetAutoScroll;
property ThumbTrack:bool read FThumbTrack write FThumbTrack;
property WhileStep:integer read FWhileStep write SetWhileStep; //滚动步长
{**
@param(AutoScroll)(integer) 0,1,2,3 滚动条模式 %%
@param(ThumbTrack)(bool) 拖动按钮 %%
@param(WhileStep)(integer) 滚动步长 %%
**}
end