none
DataGridView スクロール中の画面遷移(画面更新) RRS feed

  • 質問

  •  

    DataGridViewのスクロールバーが表示されている状態で、スクロール中(※)にデータの更新による画面更新や、Alt+Tabなどで画面を切り替えると、スクロールバーが壊れてしまう現象が発生しています。

     

    ※縦スクロールであれば「▼」、横スクロールであれば「右向き」押下によるスクロールです。

     

    回避方法を知っている方がいらっしゃれば、ご教示ください。

    2008年4月17日 7:17

回答

  • VScrollBar コントロールでも発生しますので、DataGridView 自体の問題ではなく、スクロールバーの問題のようです。また、Main メソッド内の Application.EnableVisualStyles(); をコメントにすると問題は起きないため、これは VScrollBar コントロール自体の問題でもなく、Windows XP の LUNA スタイルのスクロールバークラスの問題のようです(ComCtl32.dll バージョン6?)。Vista では問題ありませんでした(若干おかしそう)。
    Visual Studio の IDE や Excel などのスクロールバーでも再現します。TreeView コントロールやメモ帳などは問題ありませんが、これは、Spy++ で確認すると、Windows のスクロールバークラスは使用されていないためでした。

     

    対処としては、ビジュアルスタイルをあきらめるか、Windows XP の問題として修正されるのを待つしかないと思います。

     

    ここからは蛇足になります。

    以下のような感じで強制的にスクロールバーの再生成を行ってみたところ、壊れたスクロールバーは元に戻りました。ただし、この方法での副作用の有無はわかりません。

     

    Code Snippet

    //using System.Reflection;
    private void Form1_Deactivate(object sender, EventArgs e)
    {

        foreach (Control c in dataGridView1.Controls)
        {
            if (!(c is ScrollBar)) continue;

            Type type = c.GetType();
            MethodInfo mi =
                type.GetMethod(
                    "RecreateHandle", BindingFlags.Instance | BindingFlags.NonPublic);
            if (mi != null) mi.Invoke(c, null);
        }
    }

     

    ※ 投稿後、コードを変更しました。

    2008年4月17日 10:19
  •  TH01さんこんばんは。

     確かに書いていただいたコードで回避できました。たったあれだけの現象からよくこんなことがわかりますね。

     再帰的にControlsをサーチしていくようにしてみました。VBですが。

     ありがとうございました。

     

    Code Snippet

      Private Sub RecreateScrollBar(ByVal controls As IEnumerable)
        For Each c As Control In controls
          RecreateScrollBar(c.Controls)
          If TypeOf c Is ScrollBar Then
            Dim type As Type = c.GetType()
            Dim mi As Reflection.MethodInfo = type.GetMethod("RecreateHandle", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
            If mi IsNot Nothing Then mi.Invoke(c, Nothing)
          End If
        Next
      End Sub

     

     

     

    2008年4月17日 12:26
  •  TH01 さんからの引用

    VScrollBar コントロールでも発生しますので、DataGridView 自体の問題ではなく、スクロールバーの問題のようです。また、Main メソッド内の Application.EnableVisualStyles(); をコメントにすると問題は起きないため、これは VScrollBar コントロール自体の問題でもなく、Windows XP の LUNA スタイルのスクロールバークラスの問題のようです(ComCtl32.dll バージョン6?)。Vista では問題ありませんでした(若干おかしそう)。

    そうです。ComCtl32.dllのバージョン6系の不具合です。(Vistaバージョンはぱっと見た感じ起きないように見えました)

    不具合の原因自体には.NET Frameworkとは関係ありません。ネイティブアプリでも発生します。

     

    ただ、単体のVScrollBarやHScrollBarを使用した場合のみであり、AutoScrollで出てくるスクロールバーはこの現象が発生しません。

    (WS_HSCROLL等のスタイルで出てくるスクロールバーは影響しないという意味)


     TH01 さんからの引用

    対処としては、ビジュアルスタイルをあきらめるか、Windows XP の問題として修正されるのを待つしかないと思います。

    望み薄かなと考えます。

    Hotfixとしてリリースされたところで、ユーザ環境にそのHotfixのインストールを求めるのは難しいですし。

     

     

    DataGridViewについては諦めるか、VisualStyleを辞めるか、外から再生成という邪道を取るかですね。

    自作のコントロールやフォームについては極力AutoScrollを検討すべきです。

    2008年4月17日 13:19
    モデレータ

すべての返信

  •   さいふじさんこんにちは。
     回避方法はわかりませんが、現象を確認しました。ボタンが消えてしまって、まともに表示されなくなります。 
     visual studio 2005 sp1, Windows XP SP2

    2008年4月17日 7:32
  • 三輪の牛さん、こんにちは。

     

    検証、ありがとうございます。

    一度、壊れてしまうと復旧もできないみたいで、根本原因なども一切分からずに困っています。

     

    他のコントロールでは壊れないので、DataGridViewの不具合だと思うのですが。

    困りました。。

    2008年4月17日 8:02
  • VScrollBar コントロールでも発生しますので、DataGridView 自体の問題ではなく、スクロールバーの問題のようです。また、Main メソッド内の Application.EnableVisualStyles(); をコメントにすると問題は起きないため、これは VScrollBar コントロール自体の問題でもなく、Windows XP の LUNA スタイルのスクロールバークラスの問題のようです(ComCtl32.dll バージョン6?)。Vista では問題ありませんでした(若干おかしそう)。
    Visual Studio の IDE や Excel などのスクロールバーでも再現します。TreeView コントロールやメモ帳などは問題ありませんが、これは、Spy++ で確認すると、Windows のスクロールバークラスは使用されていないためでした。

     

    対処としては、ビジュアルスタイルをあきらめるか、Windows XP の問題として修正されるのを待つしかないと思います。

     

    ここからは蛇足になります。

    以下のような感じで強制的にスクロールバーの再生成を行ってみたところ、壊れたスクロールバーは元に戻りました。ただし、この方法での副作用の有無はわかりません。

     

    Code Snippet

    //using System.Reflection;
    private void Form1_Deactivate(object sender, EventArgs e)
    {

        foreach (Control c in dataGridView1.Controls)
        {
            if (!(c is ScrollBar)) continue;

            Type type = c.GetType();
            MethodInfo mi =
                type.GetMethod(
                    "RecreateHandle", BindingFlags.Instance | BindingFlags.NonPublic);
            if (mi != null) mi.Invoke(c, null);
        }
    }

     

    ※ 投稿後、コードを変更しました。

    2008年4月17日 10:19
  •  TH01さんこんばんは。

     確かに書いていただいたコードで回避できました。たったあれだけの現象からよくこんなことがわかりますね。

     再帰的にControlsをサーチしていくようにしてみました。VBですが。

     ありがとうございました。

     

    Code Snippet

      Private Sub RecreateScrollBar(ByVal controls As IEnumerable)
        For Each c As Control In controls
          RecreateScrollBar(c.Controls)
          If TypeOf c Is ScrollBar Then
            Dim type As Type = c.GetType()
            Dim mi As Reflection.MethodInfo = type.GetMethod("RecreateHandle", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
            If mi IsNot Nothing Then mi.Invoke(c, Nothing)
          End If
        Next
      End Sub

     

     

     

    2008年4月17日 12:26
  •  TH01 さんからの引用

    VScrollBar コントロールでも発生しますので、DataGridView 自体の問題ではなく、スクロールバーの問題のようです。また、Main メソッド内の Application.EnableVisualStyles(); をコメントにすると問題は起きないため、これは VScrollBar コントロール自体の問題でもなく、Windows XP の LUNA スタイルのスクロールバークラスの問題のようです(ComCtl32.dll バージョン6?)。Vista では問題ありませんでした(若干おかしそう)。

    そうです。ComCtl32.dllのバージョン6系の不具合です。(Vistaバージョンはぱっと見た感じ起きないように見えました)

    不具合の原因自体には.NET Frameworkとは関係ありません。ネイティブアプリでも発生します。

     

    ただ、単体のVScrollBarやHScrollBarを使用した場合のみであり、AutoScrollで出てくるスクロールバーはこの現象が発生しません。

    (WS_HSCROLL等のスタイルで出てくるスクロールバーは影響しないという意味)


     TH01 さんからの引用

    対処としては、ビジュアルスタイルをあきらめるか、Windows XP の問題として修正されるのを待つしかないと思います。

    望み薄かなと考えます。

    Hotfixとしてリリースされたところで、ユーザ環境にそのHotfixのインストールを求めるのは難しいですし。

     

     

    DataGridViewについては諦めるか、VisualStyleを辞めるか、外から再生成という邪道を取るかですね。

    自作のコントロールやフォームについては極力AutoScrollを検討すべきです。

    2008年4月17日 13:19
    モデレータ
  • TH01さん、三輪の牛さん、Azuleanさん

     

    とても参考になる回答ありがとうございました。

    今回の回答を元に色々と対応策を検討してみます。

     

    以上、ありがとうございました。
    2008年4月18日 2:49