Prevent RTL TListView from mirroring check boxes and/or graphics
I'm trying to make columns of a ListView appear from right to left. This has already been asked and answered. But the problem is about icons and check boxes. When I make a ListView RTL using SetWindowLong
, it mirrors graphics and checkboxes as well, wich is not wanted. I can mirror graphics using editing tools, bothering but doable, but I don't know how to handle check boxes.
I think both of them have same reason, so I searched about it and found an entire article about RTL layout in Microsoft Docs. In Activating Mirroring per Device Context section it points out the graphics problem. It suggests to change layout style of DC with LAYOUT_RTL
and LAYOUT_BITMAPORIENTATIONPRESERVED
flags.
This is the function I implemented with combining methods suggested in the article and the answer mentioned above:
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
But it doesn't change anything. I tried blocking either of them, changing order of them and changing different places to call it, but no success.
Now the question is, how to make columns of a ListView appear from right to left, without mirroring graphics or checkboxes?
I'm using Win10 x64 and Delphi 2010.
here is my delphi codes if you want to reproduce the problem:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
LAYOUT_RTL = 1;
LAYOUT_BTT = 2;
LAYOUT_VBH = 4;
LAYOUT_ORIENTATIONMASK = LAYOUT_RTL or LAYOUT_BTT or LAYOUT_VBH;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
end.
dfm:
object Form1: TForm1
Left = 0
Top = 0
BiDiMode = bdLeftToRight
Caption = 'Form1'
ClientHeight = 169
ClientWidth = 353
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style =
OldCreateOrder = False
ParentBiDiMode = False
OnActivate = FormActivate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 277
Top = 128
Width = 47
Height = 26
Cursor = crHandPoint
Alignment = taCenter
Caption = 'graphics by Icons8'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = [fsUnderline]
ParentFont = False
WordWrap = True
OnClick = Label1Click
end
object ListView1: TListView
Left = 8
Top = 8
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
LargeImages = ImageList1
SmallImages = ImageList1
TabOrder = 0
ViewStyle = vsReport
end
object ListView2: TListView
Left = 8
Top = 87
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
SmallImages = ImageList1
TabOrder = 1
ViewStyle = vsReport
end
object Button1: TButton
Left = 264
Top = 8
Width = 75
Height = 25
Caption = 'RTL'
TabOrder = 2
OnClick = Button1Click
end
object ImageList1: TImageList
ColorDepth = cd32Bit
DrawingStyle = dsTransparent
Left = 272
Top = 40
Bitmap = {
494C0101020008003C0010001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000001000000001002000000000000010
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000618062C0E3E0E741557159F1557159F0E3F0E730617062B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E218A
21FE218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218A21FE1455149C00000000000000000000000000000000000000000107
010D145814A1218A21FE218B21FF218B21FF218B21FF218B21FF218A21FE1557
159F0207020C0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC000000000000000000000000000000000107010D1B71
1BCF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1A701ACE0207020C00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000000000000165816A2218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF1456149E00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF124E128F000100010929094B208720F8218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000005160528218A21FD218B
21FF218B21FF114A1187000000000722073E208520F4218B21FF218B21FF218B
21FF218B21FF218A21FD05150526000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0000000000000000000000000F430F7B218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0F410F78000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF0000000000000000000000001557159F218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF1456149E000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF0000000000000000000000001456149E218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF1456149D000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A691AC00006000B0925
0944208620F6218B21FF0000000000000000000000001044107C218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB010901110722
073E208420F3218B21FF10421079000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218B21FF0000000000000000000000000519052D218A21FE218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218A21FE0617062B000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF218B21FF00000000000000000000000000000000165E16AC218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF155C15A800000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC00000000000000000000000000000000020902101B72
1BD1218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1B711BD00108010F00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E2188
21F9218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218821F91455149C00000000000000000000000000000000000000000209
0210165E16AD218B21FF218B21FF218B21FF218B21FF218B21FF218A21FE165D
16AB0108010F0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000061A062F10471082155915A4155915A4114611810519052E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000424D3E000000000000003E000000
2800000040000000100000000100010000000000800000000000000000000000
000000000000000000000000FFFFFF0000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000}
end
end
listview delphi winapi gdi+ right-to-left
add a comment |
I'm trying to make columns of a ListView appear from right to left. This has already been asked and answered. But the problem is about icons and check boxes. When I make a ListView RTL using SetWindowLong
, it mirrors graphics and checkboxes as well, wich is not wanted. I can mirror graphics using editing tools, bothering but doable, but I don't know how to handle check boxes.
I think both of them have same reason, so I searched about it and found an entire article about RTL layout in Microsoft Docs. In Activating Mirroring per Device Context section it points out the graphics problem. It suggests to change layout style of DC with LAYOUT_RTL
and LAYOUT_BITMAPORIENTATIONPRESERVED
flags.
This is the function I implemented with combining methods suggested in the article and the answer mentioned above:
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
But it doesn't change anything. I tried blocking either of them, changing order of them and changing different places to call it, but no success.
Now the question is, how to make columns of a ListView appear from right to left, without mirroring graphics or checkboxes?
I'm using Win10 x64 and Delphi 2010.
here is my delphi codes if you want to reproduce the problem:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
LAYOUT_RTL = 1;
LAYOUT_BTT = 2;
LAYOUT_VBH = 4;
LAYOUT_ORIENTATIONMASK = LAYOUT_RTL or LAYOUT_BTT or LAYOUT_VBH;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
end.
dfm:
object Form1: TForm1
Left = 0
Top = 0
BiDiMode = bdLeftToRight
Caption = 'Form1'
ClientHeight = 169
ClientWidth = 353
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style =
OldCreateOrder = False
ParentBiDiMode = False
OnActivate = FormActivate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 277
Top = 128
Width = 47
Height = 26
Cursor = crHandPoint
Alignment = taCenter
Caption = 'graphics by Icons8'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = [fsUnderline]
ParentFont = False
WordWrap = True
OnClick = Label1Click
end
object ListView1: TListView
Left = 8
Top = 8
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
LargeImages = ImageList1
SmallImages = ImageList1
TabOrder = 0
ViewStyle = vsReport
end
object ListView2: TListView
Left = 8
Top = 87
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
SmallImages = ImageList1
TabOrder = 1
ViewStyle = vsReport
end
object Button1: TButton
Left = 264
Top = 8
Width = 75
Height = 25
Caption = 'RTL'
TabOrder = 2
OnClick = Button1Click
end
object ImageList1: TImageList
ColorDepth = cd32Bit
DrawingStyle = dsTransparent
Left = 272
Top = 40
Bitmap = {
494C0101020008003C0010001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000001000000001002000000000000010
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000618062C0E3E0E741557159F1557159F0E3F0E730617062B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E218A
21FE218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218A21FE1455149C00000000000000000000000000000000000000000107
010D145814A1218A21FE218B21FF218B21FF218B21FF218B21FF218A21FE1557
159F0207020C0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC000000000000000000000000000000000107010D1B71
1BCF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1A701ACE0207020C00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000000000000165816A2218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF1456149E00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF124E128F000100010929094B208720F8218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000005160528218A21FD218B
21FF218B21FF114A1187000000000722073E208520F4218B21FF218B21FF218B
21FF218B21FF218A21FD05150526000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0000000000000000000000000F430F7B218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0F410F78000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF0000000000000000000000001557159F218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF1456149E000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF0000000000000000000000001456149E218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF1456149D000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A691AC00006000B0925
0944208620F6218B21FF0000000000000000000000001044107C218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB010901110722
073E208420F3218B21FF10421079000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218B21FF0000000000000000000000000519052D218A21FE218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218A21FE0617062B000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF218B21FF00000000000000000000000000000000165E16AC218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF155C15A800000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC00000000000000000000000000000000020902101B72
1BD1218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1B711BD00108010F00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E2188
21F9218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218821F91455149C00000000000000000000000000000000000000000209
0210165E16AD218B21FF218B21FF218B21FF218B21FF218B21FF218A21FE165D
16AB0108010F0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000061A062F10471082155915A4155915A4114611810519052E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000424D3E000000000000003E000000
2800000040000000100000000100010000000000800000000000000000000000
000000000000000000000000FFFFFF0000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000}
end
end
listview delphi winapi gdi+ right-to-left
add a comment |
I'm trying to make columns of a ListView appear from right to left. This has already been asked and answered. But the problem is about icons and check boxes. When I make a ListView RTL using SetWindowLong
, it mirrors graphics and checkboxes as well, wich is not wanted. I can mirror graphics using editing tools, bothering but doable, but I don't know how to handle check boxes.
I think both of them have same reason, so I searched about it and found an entire article about RTL layout in Microsoft Docs. In Activating Mirroring per Device Context section it points out the graphics problem. It suggests to change layout style of DC with LAYOUT_RTL
and LAYOUT_BITMAPORIENTATIONPRESERVED
flags.
This is the function I implemented with combining methods suggested in the article and the answer mentioned above:
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
But it doesn't change anything. I tried blocking either of them, changing order of them and changing different places to call it, but no success.
Now the question is, how to make columns of a ListView appear from right to left, without mirroring graphics or checkboxes?
I'm using Win10 x64 and Delphi 2010.
here is my delphi codes if you want to reproduce the problem:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
LAYOUT_RTL = 1;
LAYOUT_BTT = 2;
LAYOUT_VBH = 4;
LAYOUT_ORIENTATIONMASK = LAYOUT_RTL or LAYOUT_BTT or LAYOUT_VBH;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
end.
dfm:
object Form1: TForm1
Left = 0
Top = 0
BiDiMode = bdLeftToRight
Caption = 'Form1'
ClientHeight = 169
ClientWidth = 353
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style =
OldCreateOrder = False
ParentBiDiMode = False
OnActivate = FormActivate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 277
Top = 128
Width = 47
Height = 26
Cursor = crHandPoint
Alignment = taCenter
Caption = 'graphics by Icons8'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = [fsUnderline]
ParentFont = False
WordWrap = True
OnClick = Label1Click
end
object ListView1: TListView
Left = 8
Top = 8
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
LargeImages = ImageList1
SmallImages = ImageList1
TabOrder = 0
ViewStyle = vsReport
end
object ListView2: TListView
Left = 8
Top = 87
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
SmallImages = ImageList1
TabOrder = 1
ViewStyle = vsReport
end
object Button1: TButton
Left = 264
Top = 8
Width = 75
Height = 25
Caption = 'RTL'
TabOrder = 2
OnClick = Button1Click
end
object ImageList1: TImageList
ColorDepth = cd32Bit
DrawingStyle = dsTransparent
Left = 272
Top = 40
Bitmap = {
494C0101020008003C0010001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000001000000001002000000000000010
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000618062C0E3E0E741557159F1557159F0E3F0E730617062B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E218A
21FE218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218A21FE1455149C00000000000000000000000000000000000000000107
010D145814A1218A21FE218B21FF218B21FF218B21FF218B21FF218A21FE1557
159F0207020C0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC000000000000000000000000000000000107010D1B71
1BCF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1A701ACE0207020C00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000000000000165816A2218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF1456149E00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF124E128F000100010929094B208720F8218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000005160528218A21FD218B
21FF218B21FF114A1187000000000722073E208520F4218B21FF218B21FF218B
21FF218B21FF218A21FD05150526000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0000000000000000000000000F430F7B218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0F410F78000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF0000000000000000000000001557159F218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF1456149E000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF0000000000000000000000001456149E218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF1456149D000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A691AC00006000B0925
0944208620F6218B21FF0000000000000000000000001044107C218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB010901110722
073E208420F3218B21FF10421079000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218B21FF0000000000000000000000000519052D218A21FE218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218A21FE0617062B000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF218B21FF00000000000000000000000000000000165E16AC218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF155C15A800000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC00000000000000000000000000000000020902101B72
1BD1218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1B711BD00108010F00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E2188
21F9218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218821F91455149C00000000000000000000000000000000000000000209
0210165E16AD218B21FF218B21FF218B21FF218B21FF218B21FF218A21FE165D
16AB0108010F0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000061A062F10471082155915A4155915A4114611810519052E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000424D3E000000000000003E000000
2800000040000000100000000100010000000000800000000000000000000000
000000000000000000000000FFFFFF0000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000}
end
end
listview delphi winapi gdi+ right-to-left
I'm trying to make columns of a ListView appear from right to left. This has already been asked and answered. But the problem is about icons and check boxes. When I make a ListView RTL using SetWindowLong
, it mirrors graphics and checkboxes as well, wich is not wanted. I can mirror graphics using editing tools, bothering but doable, but I don't know how to handle check boxes.
I think both of them have same reason, so I searched about it and found an entire article about RTL layout in Microsoft Docs. In Activating Mirroring per Device Context section it points out the graphics problem. It suggests to change layout style of DC with LAYOUT_RTL
and LAYOUT_BITMAPORIENTATIONPRESERVED
flags.
This is the function I implemented with combining methods suggested in the article and the answer mentioned above:
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
But it doesn't change anything. I tried blocking either of them, changing order of them and changing different places to call it, but no success.
Now the question is, how to make columns of a ListView appear from right to left, without mirroring graphics or checkboxes?
I'm using Win10 x64 and Delphi 2010.
here is my delphi codes if you want to reproduce the problem:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
LAYOUT_RTL = 1;
LAYOUT_BTT = 2;
LAYOUT_VBH = 4;
LAYOUT_ORIENTATIONMASK = LAYOUT_RTL or LAYOUT_BTT or LAYOUT_VBH;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
var
DC: HDC;
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
DC := GetWindowDC(Handle);
if DC <> 0 then
SetLayout(DC, GetLayout(DC) or LAYOUT_RTL or LAYOUT_ORIENTATIONMASK);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
end.
dfm:
object Form1: TForm1
Left = 0
Top = 0
BiDiMode = bdLeftToRight
Caption = 'Form1'
ClientHeight = 169
ClientWidth = 353
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style =
OldCreateOrder = False
ParentBiDiMode = False
OnActivate = FormActivate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 277
Top = 128
Width = 47
Height = 26
Cursor = crHandPoint
Alignment = taCenter
Caption = 'graphics by Icons8'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = [fsUnderline]
ParentFont = False
WordWrap = True
OnClick = Label1Click
end
object ListView1: TListView
Left = 8
Top = 8
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
LargeImages = ImageList1
SmallImages = ImageList1
TabOrder = 0
ViewStyle = vsReport
end
object ListView2: TListView
Left = 8
Top = 87
Width = 250
Height = 73
Checkboxes = True
Columns = <
item
Caption = 'Cap'
Width = 100
end
item
Caption = 'Sub1'
Width = 100
end>
Items.ItemData = {
03620000000200000000000000FFFFFFFFFFFFFFFF01000000FFFFFFFF000000
00054900740065006D00310005500072006F007000310001000000FFFFFFFFFF
FFFFFF01000000FFFFFFFF00000000054900740065006D00320005500072006F
0070003200FFFFFFFF}
SmallImages = ImageList1
TabOrder = 1
ViewStyle = vsReport
end
object Button1: TButton
Left = 264
Top = 8
Width = 75
Height = 25
Caption = 'RTL'
TabOrder = 2
OnClick = Button1Click
end
object ImageList1: TImageList
ColorDepth = cd32Bit
DrawingStyle = dsTransparent
Left = 272
Top = 40
Bitmap = {
494C0101020008003C0010001000FFFFFFFF2110FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000001000000001002000000000000010
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000618062C0E3E0E741557159F1557159F0E3F0E730617062B0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E218A
21FE218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218A21FE1455149C00000000000000000000000000000000000000000107
010D145814A1218A21FE218B21FF218B21FF218B21FF218B21FF218A21FE1557
159F0207020C0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC000000000000000000000000000000000107010D1B71
1BCF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1A701ACE0207020C00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000000000000165816A2218B
21FF218B21FF218B21FF155915A4208520F4218B21FF218B21FF218B21FF218B
21FF218B21FF1456149E00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF124E128F000100010929094B208720F8218B21FF218B21FF218B
21FF218B21FF218B21FF00000000000000000000000005160528218A21FD218B
21FF218B21FF114A1187000000000722073E208520F4218B21FF218B21FF218B
21FF218B21FF218A21FD05150526000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0000000000000000000000000F430F7B218B21FF218B
21FF114A1187000000000D3B0D6C010901110722073E208520F4218B21FF218B
21FF218B21FF218B21FF0F410F78000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF0000000000000000000000001557159F218B21FF1A6B
1AC400000000114A1187218B21FF1B6F1BCC010901110722073E208420F3218B
21FF218B21FF218B21FF1456149E000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF0000000000000000000000001456149E218B21FF218B
21FF196919C1218B21FF218B21FF218B21FF1B6F1BCC010901110722073E2084
20F3218B21FF218B21FF1456149D000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A691AC00006000B0925
0944208620F6218B21FF0000000000000000000000001044107C218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB010901110722
073E208420F3218B21FF10421079000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218B21FF0000000000000000000000000519052D218A21FE218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF1A6F1ACB0310
031E1B711BD0218A21FE0617062B000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218B21FF218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF218B21FF00000000000000000000000000000000165E16AC218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF2087
20F8218B21FF155C15A800000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000218A21FD218B
21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218B21FF218921FC00000000000000000000000000000000020902101B72
1BD1218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF1B711BD00108010F00000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000001456149E2188
21F9218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B21FF218B
21FF218821F91455149C00000000000000000000000000000000000000000209
0210165E16AD218B21FF218B21FF218B21FF218B21FF218B21FF218A21FE165D
16AB0108010F0000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000061A062F10471082155915A4155915A4114611810519052E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000424D3E000000000000003E000000
2800000040000000100000000100010000000000800000000000000000000000
000000000000000000000000FFFFFF0000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000}
end
end
listview delphi winapi gdi+ right-to-left
listview delphi winapi gdi+ right-to-left
edited Dec 29 '18 at 22:57
saastn
asked Dec 29 '18 at 10:47
saastnsaastn
1,2511129
1,2511129
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
The reason your calls doesn't have an effect is that the device context you retrieved is not used in any way at all. You should suspect this since, in your current design, you can't even call ReleaseDC
and the DC leaks.
All painting is done in a painting cycle when the system triggers it by sending a paint message. You can intercept the message to modify the layout of the device context to be used - VCL design allows that you retrieve the context first.
Below is your full example code accordingly modified, using an interposer class to modify listview's message handling.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TListView = class(comctrls.TListView)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
{ TListView }
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
procedure TListView.WMPaint(var Message: TWMPaint);
var
Layout: DWORD;
PS: TPaintStruct;
begin
Message.DC := BeginPaint(Handle, PS);
Layout := GetLayout(Message.DC);
if (Layout and LAYOUT_RTL) <> 0 then
SetLayout(Message.DC, Layout or LAYOUT_BITMAPORIENTATIONPRESERVED);
inherited;
EndPaint(Handle, PS);
end;
end.
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53968824%2fprevent-rtl-tlistview-from-mirroring-check-boxes-and-or-graphics%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The reason your calls doesn't have an effect is that the device context you retrieved is not used in any way at all. You should suspect this since, in your current design, you can't even call ReleaseDC
and the DC leaks.
All painting is done in a painting cycle when the system triggers it by sending a paint message. You can intercept the message to modify the layout of the device context to be used - VCL design allows that you retrieve the context first.
Below is your full example code accordingly modified, using an interposer class to modify listview's message handling.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TListView = class(comctrls.TListView)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
{ TListView }
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
procedure TListView.WMPaint(var Message: TWMPaint);
var
Layout: DWORD;
PS: TPaintStruct;
begin
Message.DC := BeginPaint(Handle, PS);
Layout := GetLayout(Message.DC);
if (Layout and LAYOUT_RTL) <> 0 then
SetLayout(Message.DC, Layout or LAYOUT_BITMAPORIENTATIONPRESERVED);
inherited;
EndPaint(Handle, PS);
end;
end.
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
add a comment |
The reason your calls doesn't have an effect is that the device context you retrieved is not used in any way at all. You should suspect this since, in your current design, you can't even call ReleaseDC
and the DC leaks.
All painting is done in a painting cycle when the system triggers it by sending a paint message. You can intercept the message to modify the layout of the device context to be used - VCL design allows that you retrieve the context first.
Below is your full example code accordingly modified, using an interposer class to modify listview's message handling.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TListView = class(comctrls.TListView)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
{ TListView }
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
procedure TListView.WMPaint(var Message: TWMPaint);
var
Layout: DWORD;
PS: TPaintStruct;
begin
Message.DC := BeginPaint(Handle, PS);
Layout := GetLayout(Message.DC);
if (Layout and LAYOUT_RTL) <> 0 then
SetLayout(Message.DC, Layout or LAYOUT_BITMAPORIENTATIONPRESERVED);
inherited;
EndPaint(Handle, PS);
end;
end.
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
add a comment |
The reason your calls doesn't have an effect is that the device context you retrieved is not used in any way at all. You should suspect this since, in your current design, you can't even call ReleaseDC
and the DC leaks.
All painting is done in a painting cycle when the system triggers it by sending a paint message. You can intercept the message to modify the layout of the device context to be used - VCL design allows that you retrieve the context first.
Below is your full example code accordingly modified, using an interposer class to modify listview's message handling.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TListView = class(comctrls.TListView)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
{ TListView }
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
procedure TListView.WMPaint(var Message: TWMPaint);
var
Layout: DWORD;
PS: TPaintStruct;
begin
Message.DC := BeginPaint(Handle, PS);
Layout := GetLayout(Message.DC);
if (Layout and LAYOUT_RTL) <> 0 then
SetLayout(Message.DC, Layout or LAYOUT_BITMAPORIENTATIONPRESERVED);
inherited;
EndPaint(Handle, PS);
end;
end.
The reason your calls doesn't have an effect is that the device context you retrieved is not used in any way at all. You should suspect this since, in your current design, you can't even call ReleaseDC
and the DC leaks.
All painting is done in a painting cycle when the system triggers it by sending a paint message. You can intercept the message to modify the layout of the device context to be used - VCL design allows that you retrieve the context first.
Below is your full example code accordingly modified, using an interposer class to modify listview's message handling.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ImgList, StdCtrls, CommCtrl, ShellAPI;
type
TListView = class(comctrls.TListView)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
ListView2: TListView;
Button1: TButton;
Label1: TLabel;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Label1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetLayout(DC: HDC): DWORD; stdcall; external 'gdi32.dll';
function SetLayout(DC: HDC; dwLayout: DWORD): DWORD; stdcall; external 'gdi32.dll';
procedure MakeRTL(const Handle: HWND);
begin
SetWindowLong(Handle, GWL_EXSTYLE,
GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);
InvalidateRect(Handle, nil, True);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MakeRTL(ListView_GetHeader(ListView1.Handle));
MakeRTL(ListView1.Handle);
end;
procedure TForm1.FormActivate(Sender: TObject);
var
I: Integer;
begin
for I := 0 to ListView1.Items.Count - 1 do
begin
ListView1.Items[I].Checked := True;
ListView2.Items[I].Checked := True;
end;
end;
procedure TForm1.Label1Click(Sender: TObject);
begin
ShellExecute(0, 'open', 'https://icons8.com/icons/set/check', '', '', SW_SHOWNORMAL);
end;
{ TListView }
const
LAYOUT_RTL = 1;
LAYOUT_BITMAPORIENTATIONPRESERVED = 8;
procedure TListView.WMPaint(var Message: TWMPaint);
var
Layout: DWORD;
PS: TPaintStruct;
begin
Message.DC := BeginPaint(Handle, PS);
Layout := GetLayout(Message.DC);
if (Layout and LAYOUT_RTL) <> 0 then
SetLayout(Message.DC, Layout or LAYOUT_BITMAPORIENTATIONPRESERVED);
inherited;
EndPaint(Handle, PS);
end;
end.
answered Dec 29 '18 at 13:17
Sertac AkyuzSertac Akyuz
48k372127
48k372127
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
add a comment |
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
Thanks Sertac. Reading that article I really didn't think it could be something that needs to be done on every single paint! It's such a pain to make an application completely RTL.
– saastn
Dec 29 '18 at 17:54
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53968824%2fprevent-rtl-tlistview-from-mirroring-check-boxes-and-or-graphics%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown