0

次の関数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;

しかし、プロジェクトで を使用する場合、次の 2 つの問題があります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;

この問題はどのように解決されるべきですか?

ありがとう。

4

1 に答える 1

5

あなたのアプローチには複数の問題があります。簡単な答えは次のとおりです。

こんなことしないで。代わりに、コントロールのBiDiModeプロパティをに設定しますbdRightToLeft 何か不足していない限り、必要な動作が得られます。現在テストしましたが、この方法でテーマをスクロールしても問題はありません。

これを行う方法には、2 つの大きな問題があります。

  1. コントロールが、強制している設定を保持することを保証することはできません。VCL がコントロールのウィンドウを初めて再作成する必要がある場合、設定は消去されます。

  2. VCL が何らかの方法でこの設定を考慮する必要はないと想定しています。VCL をアンダーカットしてスタイルを Window に直接送信しようとすると、悪い動作が発生するため、明らかにそうです。本当にウィンドウ スタイルを直接制御したい場合は、コントロール クラスの独自の子孫を作成し、適切な場所で関連するすべてを処理する必要があります。 (コントロールのプロパティではなく) Windows API 呼び出しを呼び出し、コントロールが引き続き適切に機能することを期待します。

于 2015-10-20T18:07:01.023 に答える