sma*_*tiz 0 delphi listview bidi right-to-left vcl-styles
我试图通过以下功能设置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;
Run Code Online (Sandbox Code Playgroud)
但是当项目使用时,我有两个问题如下VCL Styles:
1:Vertical scrollbar没有点击它就不会出现.
2:当我更改ListView列的大小并horizontal scrollbar单击时,将显示以下错误消息:
例外来源: Vcl.ComCtrls.TListViewStyleHook.WMMouseMove
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;
Run Code Online (Sandbox Code Playgroud)
这个问题应该如何解决?
谢谢.
您的方法存在多个问题.快速回答是:
不要这样做.而是将控件的BiDiMode属性设置为bdRightToLeft. 除非我遗漏了某些东西,否则这将为您提供所需的行为并且我现在对其进行了测试,以这种方式滚动主题没有任何问题.
你想要做到这一点的方式存在两个大问题:
您不能保证控件将保持您强制进入的设置.VCL第一次需要为控件重新创建窗口时,您的设置将被删除.
您假设VCL不需要以某种方式考虑此设置.显然它确实如此,因为当你试图削弱VCL并将样式直接发送到Window时,你会遇到不良行为.如果你真的想直接控制窗口样式,你需要创建自己的控件类后代并处理在适当位置相关的所有内容 - 你不能只选择你想要将控件改为RTL的任何旧时代Windows API调用(而不是控件的属性)并期望控件将继续正常工作.
| 归档时间: |
|
| 查看次数: |
682 次 |
| 最近记录: |