2015-10-20 14 views
0

Я пытался установить направление TListView элемента управления к RTL по следующей функции:TListView прокрутки ошибка при использовании VCL стилей - Delphi X Е8

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 Styles:

1: Vertical scrollbar не появляется, не нажимая на него.

enter image description here

2: Когда я изменить размер столбцов ListView и horizontal scrollbar нажата, отображается следующее сообщение об ошибке: Источник

enter image description here

Исключение: Vcl.ComCtrls.TListViewStyleHook.WMMouseMove

enter image description here

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; 

Как решить эту проблему?

Спасибо.

+1

Вы пробовали это, не используя стиль VCL? Очевидно, что исключение связано со стилями, поэтому сначала нужно изолировать его, увидев, что происходит, когда вы его не используете. Также ваш снимок экрана отсекает часть математики, которая делает разделение, поэтому никто не может смотреть на нее и посмотреть, что это за ошибка. –

+0

Пожалуйста, покажите код вместо скриншотов. –

+0

@BrandonStaggs Да, после моего сообщения, у меня есть проблемы только тогда, когда я использую 'VCL-Style', и нет проблем без' VCL-Style'. – smartiz

ответ

5

Существует множество проблем с вашим подходом. Быстрый ответ:

Не делайте этого. Вместо этого установите для элемента управления BiDiMode значение bdRightToLeft. Если я что-то не упустил, это даст вам поведение, в котором вы нуждаетесь, и я протестировал его сейчас, поэтому нет проблем с прокруткой тем.

Есть две большие проблемы с тем, как вы привязывания сделать это:

  1. Вы не можете гарантировать контроль будет держать настройки вы вынуждаете в него. В первый раз, когда VCL должен воссоздать Окно для элемента управления, ваши настройки будут стерты.

  2. Вы считаете, что VCL не нужно каким-либо образом учитывать этот параметр. Ясно, что это происходит, потому что вы плохо себя чувствуете, пытаясь подорвать VCL и отправить стиль непосредственно в окно. Если вы действительно хотите напрямую управлять стилем окна, вам нужно создать свой собственный потомок класса управления и обработать все, что связано в соответствующих местах, - вы не можете просто выбрать любое старое время, когда хотите изменить элемент управления RTL с вызовом Windows API (а не свойствами управления) и ожидайте, что элемент управления продолжит работу.

+0

'BiDiMode = bdRightToLeft' Не работает на элементах' TListView' и 'TTreeView'. – smartiz

+0

это ошибка в 'VCL-Styles'. Благодарю. – smartiz

+0

Я согласен с тем, что крючок стиля никогда не должен делиться на ноль, но проблема в том, что вы меняете стили окон, не позволяя элементу управления делать что-либо для его учета. Как я сказал в своем ответе, это не работает, независимо от стиля. VCL часто нуждается в воссоздании окон, и в первый раз, когда ваши настройки, которые вы применили через вызовы API, исчезнут. Если у элемента управления VCL есть багги-реализация BiDiMode, вам нужно будет создать свой собственный элемент управления с исправленным поведением (или опубликовать отчет об ошибке QA и дождаться их исправления). –