列表显示;没有RTL布局的工具提示

时间:2019-07-02 04:57:44

标签: windows listview delphi tooltip

我已使用下面的代码将TListView设置为RTL(从右到左)布局。现在我意识到没有显示工具提示。如果我删除了WS_EX_LAYOUTRTL(因此控制不再是RTL),问题就解决了,并显示工具提示。

我希望在Listview处于RTL布局时显示工具提示。

我认为也许一种解决方案是也将工具提示窗口(如果有窗口)也更改为RTL布局,但是我不知道如何。

procedure SetControlLayout(Control: TWinControl; RTL: Boolean);
const
  LVM_FIRST = $1000;
  LVM_GETHEADER = LVM_FIRST + 31;   // ListView header messages
var
  Header: thandle;
  NewLong: NativeInt;
begin
  if Control is TListView then
  begin
    Header:= SendMessage(Control.Handle, LVM_GETHEADER, 0, 0);
    if RTL then
      NewLong:= GetWindowLong (Header, GWL_EXSTYLE) or WS_EX_LAYOUTRTL
        //or WS_EX_NOINHERITLAYOUT
    else
      NewLong:= 0;

    SetWindowLongPtr(Header, GWL_EXSTYLE, NewLong);
  end;

  if RTL then
    NewLong:= GetWindowLong(Control.Handle, GWL_EXSTYLE)  or
      WS_EX_LAYOUTRTL or
      WS_EX_RTLREADING or
      WS_EX_LEFT
      //or WS_EX_NOINHERITLAYOUT
  else
    NewLong:= 0;

  SetWindowLongPtr(Control.Handle, GWL_EXSTYLE, NewLong );

  Control.invalidate; 
end;

1 个答案:

答案 0 :(得分:0)

我看到的一个问题是,当RTL为假时,您正在将GWL_EXSTYLE设置为0,从而清除了所有扩展窗口样式,包括LVS_EX_INFOTIP。您需要保留对更改不感兴趣的样式,例如:

procedure SetControlLayout(Control: TWinControl; RTL: Boolean);
const
  LVM_FIRST = $1000;
  LVM_GETHEADER = LVM_FIRST + 31; // ListView header messages
  HeaderRTLStyles = WS_EX_LAYOUTRTL
    //or WS_EX_NOINHERITLAYOUT
    ;
  ControlRTLStyles = WS_EX_LAYOUTRTL
    or WS_EX_RTLREADING
    or WS_EX_LEFT
    //or WS_EX_NOINHERITLAYOUT
    ;
var
  Header: HWND;
  ExStyles: LONG_PTR;
begin
  if Control is TListView then
  begin
    Header := SendMessage(Control.Handle, LVM_GETHEADER, 0, 0);
    if Header <> 0 then
    begin
      ExStyles := GetWindowLongPtr(Header, GWL_EXSTYLE);
      if RTL then
        ExStyles := ExStyles or HeaderRTLStyles
      else
        ExStyles := ExStyles and not HeaderRTLStyles;

      SetWindowLongPtr(Header, GWL_EXSTYLE, ExStyles);
    end;
  end;

  ExStyles := GetWindowLongPtr(Control.Handle, GWL_EXSTYLE);
  if RTL then
    ExStyles := ExStyles or ControlRTLStyles
  else
    ExStyles := ExStyles and not ControlRTLStyles;

  SetWindowLongPtr(Control.Handle, GWL_EXSTYLE, ExStyles);

  Control.Invalidate;
end;

我看到的另一个问题是WS_EX_LAYOUTRTLLVS_EX_TRANSPARENTBKGND具有相同的数值。无法使用CreateWindow/Ex()SetWindowLong/Ptr(GWL_EXSTYLE)设置ListView扩展窗口样式,而必须使用LVM_SETEXTENDEDLISTVIEWSTYLE窗口消息进行设置。因此,设置LVS_EX_INFOTIP后,您可能必须重新启用WS_EX_LAYOUTRTL样式:

procedure SetControlLayout(Control: TWinControl; RTL: Boolean);
const
  LVM_FIRST = $1000;
  LVM_GETHEADER = LVM_FIRST + 31; // ListView header messages
  HeaderRTLStyles = WS_EX_LAYOUTRTL
    //or WS_EX_NOINHERITLAYOUT
    ;
  ControlRTLStyles = WS_EX_LAYOUTRTL
    or WS_EX_RTLREADING
    or WS_EX_LEFT
    //or WS_EX_NOINHERITLAYOUT
    ;
var
  IsListView: boolean;
  Header: HWND;
  ExStyles: LONG_PTR;
begin
  IsListView := Control is TListView;
  if IsListView then
  begin
    Header := SendMessage(Control.Handle, LVM_GETHEADER, 0, 0);
    if Header <> 0 then
    begin
      ExStyles := GetWindowLongPtr(Header, GWL_EXSTYLE);
      if RTL then
        ExStyles := ExStyles or HeaderRTLStyles
      else
        ExStyles := ExStyles and not HeaderRTLStyles;

      SetWindowLongPtr(Header, GWL_EXSTYLE, ExStyles);
    end;
  end;

  ExStyles := GetWindowLongPtr(Control.Handle, GWL_EXSTYLE);
  if RTL then
    ExStyles := ExStyles or ControlRTLStyles
  else
    ExStyles := ExStyles and not ControlRTLStyles;

  SetWindowLongPtr(Control.Handle, GWL_EXSTYLE, ExStyles);

  if IsListView then
    Control.Perform(LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_INFOTIP, LVS_EX_INFOTIP);

  Control.Invalidate;
end;