TListView在使用VCL样式时出现滚动错误-Delphi XE8
我尝试通过以下功能将TListView在使用VCL样式时出现滚动错误-Delphi XE8,delphi,listview,right-to-left,vcl-styles,bidi,Delphi,Listview,Right To Left,Vcl Styles,Bidi,我尝试通过以下功能将TListView控件的方向设置为RTL: procedure RTL_LV(lv:TListView); const LVM_FIRST = $1000; LVM_GETHEADER = LVM_FIRST + 31; var header: THandle; begin header:= SendMessage (lv.Handle, LVM_GETHEADER, 0, 0); SetWindowLong (header, GWL_EXSTYLE,
TListView
控件的方向设置为RTL
:
procedure RTL_LV(lv:TListView);
const
LVM_FIRST = $1000;
LVM_GETHEADER = LVM_FIRST + 31;
var
header: THandle;
begin
header:= SendMessage (lv.Handle, LVM_GETHEADER, 0, 0);
SetWindowLong (header, GWL_EXSTYLE,
GetWindowLong (header, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
SetWindowLong (lv.Handle, GWL_EXSTYLE,
GetWindowLong (lv.Handle, GWL_EXSTYLE) or
WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT);
lv.invalidate;
end;
但是当项目使用VCL样式时,我有两个问题,如下所示:
1:垂直滚动条
未单击就不会出现
2:当我更改ListView列的大小并单击水平滚动条时,将显示以下错误消息:
异常源:Vcl.ComCtrls.TListViewStyleHook.WMMouseMove
过程TListViewStyleHook.WMMouseMove(var消息:TWMMouse);
变量
SF:TScrollInfo;
SPos:整数;
R:TRect;
开始
如果VertSliderState=TSThumbTnVertPressed,则
开始
SF.fMask:=SIF_ALL;
SF.cbSize:=SizeOf(SF);
GetScrollInfo(句柄、SB_VERT、SF);
ScrollPos:=ScrollPos+(SF.nMax-SF.nMin)*((Mouse.CursorPos.Y-PrevScrollPos)/VertTrackRect.Height);
PrevScrollPos:=Mouse.CursorPos.Y;
如果控件为TCustomListView,则
开始
PostMessage(Handle,WM_VSCROLL,Integer(SmallPoint(SB_THUMBTRACK,Round(ScrollPos))),0);
如果TCustomListView(Control).ViewStyle=vsReport,则
开始
如果(Abs(滚动位置-列表位置)>=1)或
((ScrollPos=SF.nMin)和(ListPos ScrollPos))或
((ScrollPos=SF.nMax)和(ListPos-ScrollPos))然后
开始
如果TCustomListView(Control).GroupView,则
开始
SPO:=圆形(滚动位置-列表位置);
如果SF.nPos+SPos<0,则SPos:=-SF.nPos;
结束
其他的
开始
ListView_GetItemRect(句柄、0、R、LVIR_边界);
SPos:=圆形((滚动位置-列表位置)*垂直高度);
结束;
ListView_滚动(句柄、0、SPos);
ListPos:=ScrollPos;
结束;
结束
其他的
开始
如果Abs(滚动位置-列表位置)>=1,则
开始
ListView_滚动(手柄,0,圆形((ScrollPos-ListPos));
ListPos:=ScrollPos;
结束;
结束;
结束
其他的
PostMessage(Handle,WM_VSCROLL,Integer(SmallPoint(SB_拇指位置,Round(ScrollPos))),0);
画卷;
已处理:=真;
出口
结束;
如果按HorzSliderState=TSThumbTnHorz,则
开始
SF.fMask:=SIF_ALL;
SF.cbSize:=SizeOf(SF);
GeTScrollInfo(手柄,SB_HORZ,SF);
ScrollPos:=ScrollPos+(SF.nMax-SF.nMin)*((Mouse.CursorPos.X-PrevScrollPos)/HorzTrackRect.Width);
如果滚动位置SF.nMax,则
ScrollPos:=SF.nMax;
PrevScrollPos:=Mouse.CursorPos.X;
如果控件为TCustomListView,则
开始
如果TCustomListView(Control).ViewStyle=vsReport,则
开始
如果Abs(滚动位置-列表位置)>=1,则
开始
ListView_滚动(手柄,圆形((ScrollPos-ListPos)),0);
ListPos:=ScrollPos;
结束;
结束
其他的
开始
如果Abs(滚动位置-列表位置)>=0.5,则
开始
ListView_滚动(手柄,圆形((ScrollPos-ListPos)),0);
ListPos:=ScrollPos;
结束;
结束;
结束
其他的
PostMessage(Handle,WM_HSCROLL,Integer(SmallPoint(SB_拇指位置,Round(ScrollPos))),0);
画卷;
已处理:=真;
出口
结束;
如果(HorzSliderState TsThumbTnhorzPressed)和(HorzSliderState=TsThumbTnhorzhot),则
开始
HorzSliderState:=TsThumbTnHorznormal;
画卷;
结束;
如果(VertSliderState TsThumbTnvertPressed)和(VertSliderState=TsThumbTnverTot),则
开始
VertSliderState:=TSThumbTnVertNormal;
画卷;
结束;
如果(HorzUpState tsArrowBtnLeftPressed)和(HorzUpState=tsArrowBtnLeftHot),则
开始
水平状态:=tsarrowbtnleeftnormal;
画卷;
结束;
如果(HorzDownState tsArrowBtnRightPressed)和(HorzDownState=tsArrowBtnRightHot),则
开始
HorzDownState:=tsArrowBtnRightNormal;
画卷;
结束;
如果(VertUpState tsArrowBtnUpPressed)和(VertUpState=tsArrowBtnUpHot),则
开始
垂直向上状态:=tsArrowBtnUpNormal;
画卷;
结束;
如果(VertdowState TsarrowbtDownpressed)和(VertdowState=TsarrowbtDownhot),则
开始
垂直下降状态:=TsarrowbtDownNormal;
画卷;
结束;
CallDefaultProc(TMessage(Message));
如果是LeftButtonDown,那么
画卷;
已处理:=真;
结束;
这个问题应该如何解决
谢谢。您的方法存在多个问题。快速的答案是:
不要这样做。相反,将控件的BiDiMode
属性设置为bdrightoleft
。除非我遗漏了一些东西,这将使您获得所需的行为,并且我现在已经测试了它,否则以这种方式滚动主题不会有任何问题
你的捆绑方式有两个大问题:
您不能保证控件将保留您强制输入的设置。VCL第一次需要为控件重新创建窗口时,您的设置将被删除
您假设VCL不需要以某种方式考虑此设置。显然是这样,因为当你试图削弱VCL并将样式直接发送到窗口时,你会有不良行为。如果你真的想直接控制窗口样式,你需要创建你自己的控件类的后代,并在适当的地方处理所有相关的事情——你不能选择任何你想通过Windows API调用(而不是控件的属性)将控件更改为RTL的旧时间并期望控制将继续正常工作
您的方法存在多个问题。快速的答案是:
不要这样做。相反,将控件的BiDiMode
属性设置为bdrightoleft
。除非我遗漏了什么,否则这会让你做出你需要的行为
procedure TListViewStyleHook.WMMouseMove(var Message: TWMMouse);
var
SF: TScrollInfo;
SPos: Integer;
R: TRect;
begin
if VertSliderState = tsThumbBtnVertPressed then
begin
SF.fMask := SIF_ALL;
SF.cbSize := SizeOf(SF);
GetScrollInfo(Handle, SB_VERT, SF);
ScrollPos := ScrollPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.Y - PrevScrollPos) / VertTrackRect.Height);
PrevScrollPos := Mouse.CursorPos.Y;
if Control is TCustomListView then
begin
PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBTRACK, Round(ScrollPos))), 0);
if TCustomListView(Control).ViewStyle = vsReport then
begin
if (Abs(ScrollPos - ListPos) >= 1) or
((ScrollPos = SF.nMin) and (ListPos <> ScrollPos)) or
((ScrollPos = SF.nMax) and (ListPos <> ScrollPos)) then
begin
if TCustomListView(Control).GroupView then
begin
SPos := Round(ScrollPos - ListPos);
if SF.nPos + SPos < 0 then SPos := -SF.nPos;
end
else
begin
ListView_GetItemRect(Handle, 0, R, LVIR_BOUNDS);
SPos := Round((ScrollPos - ListPos) * R.Height);
end;
ListView_Scroll(Handle, 0, SPos);
ListPos := ScrollPos;
end;
end
else
begin
if Abs(ScrollPos - ListPos) >= 1 then
begin
ListView_Scroll(Handle, 0, Round((ScrollPos - ListPos)));
ListPos := ScrollPos;
end;
end;
end
else
PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(ScrollPos))), 0);
PaintScroll;
Handled := True;
Exit;
end;
if HorzSliderState = tsThumbBtnHorzPressed then
begin
SF.fMask := SIF_ALL;
SF.cbSize := SizeOf(SF);
GeTScrollInfo(Handle, SB_HORZ, SF);
ScrollPos := ScrollPos + (SF.nMax - SF.nMin) * ((Mouse.CursorPos.X - PrevScrollPos) / HorzTrackRect.Width);
if ScrollPos < SF.nMin then
ScrollPos := SF.nMin;
if ScrollPos > SF.nMax then
ScrollPos := SF.nMax;
PrevScrollPos := Mouse.CursorPos.X;
if Control is TCustomListView then
begin
if TCustomListView(Control).ViewStyle = vsReport then
begin
if Abs(ScrollPos - ListPos) >= 1 then
begin
ListView_Scroll(Handle, Round((ScrollPos - ListPos)), 0);
ListPos := ScrollPos;
end;
end
else
begin
if Abs(ScrollPos - ListPos) >= 0.5 then
begin
ListView_Scroll(Handle, Round((ScrollPos - ListPos)), 0);
ListPos := ScrollPos;
end;
end;
end
else
PostMessage(Handle, WM_HSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(ScrollPos))), 0);
PaintScroll;
Handled := True;
Exit;
end;
if (HorzSliderState <> tsThumbBtnHorzPressed) and (HorzSliderState = tsThumbBtnHorzHot) then
begin
HorzSliderState := tsThumbBtnHorzNormal;
PaintScroll;
end;
if (VertSliderState <> tsThumbBtnVertPressed) and (VertSliderState = tsThumbBtnVertHot) then
begin
VertSliderState := tsThumbBtnVertNormal;
PaintScroll;
end;
if (HorzUpState <> tsArrowBtnLeftPressed) and (HorzUpState = tsArrowBtnLeftHot) then
begin
HorzUpState := tsArrowBtnLeftNormal;
PaintScroll;
end;
if (HorzDownState <> tsArrowBtnRightPressed) and (HorzDownState =tsArrowBtnRightHot) then
begin
HorzDownState := tsArrowBtnRightNormal;
PaintScroll;
end;
if (VertUpState <> tsArrowBtnUpPressed) and (VertUpState = tsArrowBtnUpHot) then
begin
VertUpState := tsArrowBtnUpNormal;
PaintScroll;
end;
if (VertDownState <> tsArrowBtnDownPressed) and (VertDownState = tsArrowBtnDownHot) then
begin
VertDownState := tsArrowBtnDownNormal;
PaintScroll;
end;
CallDefaultProc(TMessage(Message));
if LeftButtonDown then
PaintScroll;
Handled := True;
end;