GroupBox とパネル内のコントロールに対して RightToLeftLayout を機能させるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/147657

  •  02-07-2019
  •  | 
  •  

質問

MSDN によると

form.RightToLeftLayout = True;
form.RightToLeft = ifWeWantRTL() ? RightToLeft.True : RightToLeft.False;

RTL 言語のフォーム コンテンツをミラーリングするには十分です。

ただし、コントロールの配置はフォーム上のコントロールに対してのみミラーリングされます。
GroupBox またはPanel 内のそれら ミラーリングされていません, 最初にそれらを TableLayoutPanel または FlowLayoutPanel に配置しない限り。

これは、各グループボックス内にTableLayOutPanelを配置し、特にコントロールを再配置するための多くの手動作業です(テーブルセル、パディング、マージンなど)コントロール(1つのコントロール)

すべてのコントロールに対してミラーリングを機能させる簡単な方法はありますか?

少なくとも、フォームの数が多いと再配置の手順が非常に大変なため、再配置の手順を​​回避するにはどうすればよいでしょうか?


編集:フォーム上の各コントロールの RightToLeft プロパティはデフォルトで継承されます。
したがって、パネルとグループボックスには常に必要な RightToLeft 設定があります。
それにもかかわらず、プログラムとデザイナーの両方でそれを再割り当てしようとしましたが、役に立ちませんでした。

役に立ちましたか?

解決

かなり厄介な問題を抱えていることがわかります。しばらく遊んでみて、次のことを思いつきました。

ちょっとした再帰を利用すると、すべてのコントロールを実行し、パンネルとグループボックスにトラップされたコントロールの手動 RTL 変換を行うことができます。

これは 素早い 私がまとめたコードの小さなモック。これを BaseForm に入れて (これらのいずれかがあることを願っています)、ベース フォームのロードを呼び出すことをお勧めします。

private void SetRTL (bool setRTL)
{
    ApplyRTL(setRTL, this);
}

private void ApplyRTL(bool yes, Control startControl)
{
    if ((startControl is Panel ) || (startControl is GroupBox))
    {
        foreach (Control control in startControl.Controls)
        {
            control.Location = CalculateRTL(control.Location, startControl.Size, control.Size);
        }
    }

    foreach (Control control in startControl.Controls)
        ApplyRTL(yes, control);
}

private Point CalculateRTL (Point currentPoint, Size parentSize, Size currentSize)
{
    return new Point(parentSize.Width - currentSize.Width - currentPoint.X, currentPoint.Y);
}

他のヒント

CreateParamsのオーバーライドに関する最初のヒントを見た場所を覚えていませんが、ここにいます;) 最速かつ最も簡単な方法は、パネル、グループボックスまたはユーザーコントロールから継承することです CreateParamsプロパティをオーバーライドします

    protected override CreateParams CreateParams
    {
        get
        {
            return Control_RTF(base.CreateParams, base.RightToLeft);
        }
    }

    private CreateParams Control_RTF(CreateParams CP, RightToLeft rightToLeft)
    {
        if (rightToLeft == System.Windows.Forms.RightToLeft.Yes)
            CP.ExStyle = ((CP.ExStyle | 0x400000) | 0x100000);
        return CP;
    }

記事によると Visual Studio 2005:アラビア語Windowsフォームアプリケーションの開発 選択肢は2つしかありません

  • TableLayoutPanelのあちこちへの追加を続けます
  • RTLの子コントロールの位置を変更すると自分自身が変更されます

そのようにしなければならないのは本当に残念です。

子コントロール( ContainerControl など)を含むControlから派生したクラスがある場合、次のコードを追加して、親フォームの RightToLeftLayout はtrueに設定され、コントロールの RightToLeft RightToLeft.Yes に設定されている場合。

protected override CreateParams CreateParams
{
    get
    {
        CreateParams createParams = base.CreateParams;
        Form parent = this.FindForm();
        bool parentRightToLeftLayout = parent != null ? parent.RightToLeftLayout : false;
        if ((this.RightToLeft == RightToLeft.Yes) && parentRightToLeftLayout)
        {
            createParams.ExStyle |= 0x500000; // WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT
            createParams.ExStyle &= ~0x7000; // WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR
        }
        return createParams;
    }
}

protected override void OnRightToLeftChanged(EventArgs e)
{
    base.OnRightToLeftChanged(e);
    RecreateHandle();
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top