none
派生クラスのローカライズでフォントが変更されてしまう RRS feed

  • 質問

  •  

    初めて投稿させていただきます。

    「UI画面のローカライズでコントロールの位置がずれる」

    という投稿と似ているのですが、未回答な状態ですので投稿させていただきます。

     

    Visual Studio 2005 C#でプログラムを行っています。

    ユーザコントロールを継承してFormコントロールを作成しているのですが、ローカライズしてビルドを行った際にフォントが勝手に変更されてしまいます。

    下記のような手順でこの現象が発生しています。

    何かわかる方がいらっしゃいましたらご教授お願いいたします。

     

    【手順】

    ①基本クラスの作成。

    ユーザコントロール

    Localizablefalse

    FontMS UI Gothic, 11.25pt

    AutoScaleModeTrue

     

    ②派生クラスにコントロールを配置。

    Localizablefalse

    FontMS UI Gothic, 11.25pt

    AutoScaleModeTrue

     

    ③LocalizabletrueLanguageを英語(米)に変更し、***.en-US.resxを作成する。

     

    テキストを英語化した後、ビルドするとFontMS UI Gothic, 9ptに変更してしまう。

     

    その後、Fontを設定しなおしてビルドすれば元に戻るのですが、編集する度にFont9ptに変更されてしまい、困っています。

     

    ビルド時に***.Desigener.cs内で

     

    this.Font = null;

     

    と指定されてしまうことが原因だと思うのですが、この現象が起こる理由、また、回避する方法がありましたらご教授お願いいたします。

    2008年2月27日 7:30

回答

  • たとえば、AutoScaleMode プロパティを AutoScaleMode.Dpi などにしてみたら如何でしょう。たぶん、今は AutoScaleMode.Font になっているのでは?

    2008年2月27日 15:11
  • 良さそうな方法がありました。

    # またズレた話になっていなければ良いですが…。

     

    上の私の投稿での1の手順で作成したコントロールを UserControl1、2の手順で作成したコントロールを UserControl2 とした場合、以下のようなプロパティの定義を UserControl1 側に行います。

     

    方法1と方法2の2通りありますが、方法1の方は UserControl2 側でのフォントの変更までもが記録されなくなるので、方法2の方が良いと思います。

    # 方法1の方は上で1度書いてますが、おそらく UserControl2 側に実装されたのではないかと考えています。

     

    ◆ 方法1

    Code Snippet
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override Font Font
    {
        get { return base.Font; }
        set { base.Font = value; }
    }

     

    ◆ 方法2

    Code Snippet

    public override Font Font
    {
        get { return base.Font; }
        set
        {

            // null の代入は無視する。
            if (this.Font != value && value != null)
                base.Font = value;
        }
    }

     

    2008年2月29日 13:35

すべての返信

  • たとえば、AutoScaleMode プロパティを AutoScaleMode.Dpi などにしてみたら如何でしょう。たぶん、今は AutoScaleMode.Font になっているのでは?

    2008年2月27日 15:11
  •  

    回答ありがとうございます。

    AutoScaleMode.Dpiに変更して試してみました。

    サイズは変わらなくなるのですが、やはりフォントは変わってしまいます。

    また、解像度でスケールが決まらないようにフォント基準にしているため、AutoScaleMode.Fontを変えることが出来ません。

    2008年2月28日 1:32
  • ユーザーコントロール内にあるコントロールに対し、個別にフォントを設定すると、この問題は発生しないようです。
    ただしそれでは全然解決になりませんね。

     

    どこで変になるのかを、以下のように確認してみましたところ、「B地点」でフォントが元に戻ってしまっているようでした。
    # 以下、Form1 が ユーザーコントロールを貼り付けているフォーム、
    # UserControl1 がユーザーコントロールの型、userControl11 がそのインスタンス変数です。

     

    Code Snippet

    private void InitializeComponent()
    {
        System.ComponentModel.ComponentResourceManager resources =

            new System.ComponentModel.ComponentResourceManager(typeof(Form1));


     

        this.userControl11 = new WindowsApplication1.UserControl1();
        // ◆フォント確認◆
        System.Diagnostics.Debug.WriteLine("A地点:" + this.userControl11.Font.ToString());

     

        this.SuspendLayout();
        //
        // userControl11
        //
        resources.ApplyResources(this.userControl11, "userControl11");
        // ◆フォント確認◆
        System.Diagnostics.Debug.WriteLine("B地点:" + this.userControl11.Font.ToString());


        this.userControl11.Name = "userControl11";
       
        ・・・
    }

     

    Form1 のリソースを確認してみると、たしかに「userControl11.Font」のリソースが存在しますので、単純にユーザーコントロールのフォントが反映されないという訳ではないですね…。

     

    ということで、しかたがないので以下のようにしてみたところ、期待する結果になった感じです。
    何か弊害がなければ良いですが…。

     

    Code Snippet

    public Form1()
    {
        InitializeComponent();

     

        // ユーザーコントロール自身のローカライズを適用しなおす

        System.ComponentModel.ComponentResourceManager resources =
            new System.ComponentModel.ComponentResourceManager(typeof(UserControl1));
        // (UserControl1 のリソースでの "$this" は、UserControl1 自身を示す)
        resources.ApplyResources(userControl11, "$this");
    }

     

    ちなみに、Visual Studio 2008 でも同様でした。

    単純なバグという訳ではないと思いますので、直らない可能性があるかもしれませんね。

    2008年2月28日 2:18
  • 回答ありがとうございます。

     

    コンストラクタで再度適用しなおすと、設定したいFontとすることが出来ました。

     

    ただ、デザイナで9ptと指定した後、コンストラクタで11ptと指定しなおしているためか、

    ビルドを繰り返しているうちにコントロールの配置がずれてしまう現象が発生しました。

    (SplitContainerを使用している部分です。)

     

    デザイナレベルで指定したいポイントに設定できる方法はありませんでしょうか?

    2008年2月28日 9:07
  • ビルド時にはフォームのコンストラクタのコードは実行されませんので、配置がずれる原因は別かもしれません。

    (追記:あ、InitializeComponent 内で 11pt→9pt になっているので関係あるのかもしれません。)
    以前、ローカライズしていない普通のフォームで、プロジェクトを開く度にタブコントロール内のコントロールの配置がずれることを経験したことがあります。

     

    デザイナレベルの件ですが、ユーザーコントロール自身の Font プロパティをオーバーライドし、DesignerSerializationVisibilityAttribute を付加すると良さそうです。
    また、フォーム側ではユーザーコントロールの Font を変更することに意味はなくなりますので、一応 BrowsableAttribute も付けてみました。

     

    こうすることで、フォーム側のリソースにはユーザーコントロールの Font 情報が記録されなくなるため、元に戻されてしまう(フォーム側での指定フォントになってしまう)ことはなくなります。
    # 先ほどのコンストラクタ内のコードは不要です。
    # これで配置がずれる件も回避できればいいですが。

     

    Code Snippet

    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }

     

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Font Font
        {
            get { return base.Font; }
            set { base.Font = value; }
        }
    }

     

    2008年2月28日 9:55
  • 少しわかったことを書かせてもらいます。

     

    「UI画面のローカライズでコントロールの位置がずれる」のスレを見てみました。
    まず、そこで書かれている再現方法をもう少し単純にしました。

     

    1. フォームに SplitContainer を配置する。
    2. SplitContainer の BorderStyle を Fixed3D にする。
    3. Panel を SplitContainer の Panel2 へ配置する。
    4. 配置した Panel の Anchor を Top,Bottom,Left,Right にする。
    5. フォームの Language を切り替える。

     

    手順5を繰り返すと配置した Panel のサイズは徐々に小さくなります。
    手順3で配置するコントロールは Panel でなくても同じです。

     

    ポイントは上記手順の2と4だと思いますが、
    nSnowBear さんの状況は、上記再現条件に当てはまりますでしょうか?

     

    ~.Designer.cs の中身を見ると、BorderStyle はローカライズ対象にはなっていませんでした。
    そこで試しに以下のような BorderStyle をローカライズ対象にしたコントロールを作成し、これを使って上記再現手順を行ってみましたところ、小さくなることはありませんでした。

     

    Code Snippet

    public class SplitContainerEx : SplitContainer
    {
        [Localizable(true)]
        public new BorderStyle BorderStyle
        {
            get { return base.BorderStyle; }
            set { base.BorderStyle = value; }
        }
    }

     

    ただ、この結果が何を意味するのか(直接的な原因)は、わかりませんでした。
    とても惜しいところまでは来たような気がするのですが…。
    なお、この件の原因は、先ほど私が書いた体験談や解像度の件とは、別なような気がしています。

    2008年2月28日 12:27
  • 回答ありがとうございます。

     

    ずれてしまうのはビルド時に派生クラスのFontが変わってしまうためだと思います。

    確認してみたところ、

    BorderStyleはNoneでしたので上記にはあてはまりませんでした。

     

    また、Font プロパティをオーバーライドし、DesignerSerializationVisibilityAttribute を付加する方法を試してみたのですが、

    上手くいきませんでした。

    やはり、InitializeComponent 内でthis.Font = null.となり、9ptに変更されてしまいました。

    2008年2月29日 9:29
  • すいません!
    全然検討外れな確認をしてました。
    nSnowBear さんの状況は

     

    1. [ユーザー コントロール] の作成
    2. [継承されたユーザー コントロール] を、1のコントロールを継承して作成

     

    なんですね。
    この場合、確かにそうなりました。
    こちらでは2を行っていませんでした。
    # nSnowBear さんの最初の投稿の②の手順は、コントロールを追加する手順だと思ってしまいました。

    # しかも、似た不都合現象を、たまたま発見してしまいましたので。

     

    this.Font = null;
    となる理由の想像ですが、上記2のコントロールとしては、Font の変更はない状態のため、デフォルトに戻っても良いという意味合いで null の代入になるのかなと思います。
    これをなんとか属性の指定で制御できないかと思い、試行錯誤してみたのですが、どうにもなりませんでした。
    明日、もう少しあがいてみようと思っていますが、私には期待しないでください…。

    2008年2月29日 11:43
  • 良さそうな方法がありました。

    # またズレた話になっていなければ良いですが…。

     

    上の私の投稿での1の手順で作成したコントロールを UserControl1、2の手順で作成したコントロールを UserControl2 とした場合、以下のようなプロパティの定義を UserControl1 側に行います。

     

    方法1と方法2の2通りありますが、方法1の方は UserControl2 側でのフォントの変更までもが記録されなくなるので、方法2の方が良いと思います。

    # 方法1の方は上で1度書いてますが、おそらく UserControl2 側に実装されたのではないかと考えています。

     

    ◆ 方法1

    Code Snippet
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public override Font Font
    {
        get { return base.Font; }
        set { base.Font = value; }
    }

     

    ◆ 方法2

    Code Snippet

    public override Font Font
    {
        get { return base.Font; }
        set
        {

            // null の代入は無視する。
            if (this.Font != value && value != null)
                base.Font = value;
        }
    }

     

    2008年2月29日 13:35
  • こんにちは。中川俊輔 です。

     

    囚人さん、TH01さん、回答ありがとうございます。

     

    nSnowBearさん、フォーラムのご利用ありがとうございます。

    その後いかがでしょうか?

    有用な情報と思われたため、勝手ながら囚人さん、TH01さんの回答へ回答済みチェックをつけさせていただきました。

    追加の質問等ありましたら是非投稿してください!

     

    回答済みチェックが付くことにより、有用な情報を探している方が情報を見つけやすくなります。
    有用な情報と思われる回答があった場合は、なるべく回答済みボタンを押してチェックを付けてください。

    nSnowBearさんはチェックを解除することもできますので、ご確認ください。

     

    それでは!

    2008年3月6日 8:52
  • 申し訳ありません。

    長期で不在としていたため、確認・返信をすることができませんでした。

     

    確認してみたところ、上記の方法で期待通りの結果を得ることができました。

     

    説明不足な点もあり、お手数おかけしました。

    今後も何かありましたらよろしくお願いいたします。

    2008年3月10日 0:41