390 lines
11 KiB
Plaintext
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 |