none
スクロールバーが消えない RRS feed

  • 質問

  • PanelのAutoScrollプロパティをtrueにして、スクロールバーを表示させています。別のボタンを押すとスクロールバーが無くなるような内容にPanel内を変更しています。

    この時、スクロールバーにマウスを重ねるとWindows7では薄い青色に変化し、マウスを外すと青色がフェードアウトして元の色に戻るのですが、フェードアウトが完了する前に素早くスクロールバーを非表示にすると、マウスを重ねていたスクロールバーが見かけ上表示されてしまいます。

    OSの設定をクラシック表示にしたり、コントロールパネルの「コンピュータを見やすくします」のところで「必要のないアニメーションは無効にします(可能な場合)」にチェックを入れたりすれば上記の現象は発生しません。
    また、Spy++で見るとスクロールバーは無くなっているようです。
    十分な時間を空けてから(秒に近いオーダー)Refreshをかけたり、自分で画面の外にウィンドウを移動させてから画面内に戻すと消えます。

    スクロールバーを消す良い方法はないでしょうか。
    .Net 4 Client Profile です。よろしくお願いします。

    2011年11月7日 1:56

回答

  • 強引ですが、レイアウトの変更後に下記コードを実行するのはいかがでしょうか?
    PerformLayout しているのは、スクロールバーが表示された場合のつまみサイズの再計算のためです。
    // using System.Reflection;
    var mi = typeof(Panel).GetMethod("RecreateHandle", BindingFlags.Instance | BindingFlags.NonPublic);
    if (mi != null) mi.Invoke(panel1, null);
    panel1.PerformLayout();
    

    • 回答としてマーク iwims 2011年11月9日 3:14
    2011年11月7日 10:25

すべての返信

  • この現象は複数の環境で発生しますか?

    個人的に推測すると低スペックなマシンによる描画遅延の問題のように思えますが、OSやCPU・グラフィックボードは何をお使いでしょうか?


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2011年11月7日 5:36
    モデレータ
  • レスありがとうございます。

    複数の環境で発生するのでスペックのせいでは無いと思いますが。。。

    自分の環境はCore i5 M450@2.40GHz  NVIDIA GeForce GT 330M です。

    再現方法はAutoScrollをtrueにしたPanelをフォームに適当に配置し、その中にスクロールバーが表示されるような位置にLabel等なんでもいいので配置します。

    後は適当なButtonのクリックイベントで例えば下記のようにしてスクロールバーの表示、非表示を切り替えれば再現します。

    private void button1_Click(object sender, EventArgs e) {
        panel1.AutoScroll = !panel1.AutoScroll;
    }

    2011年11月7日 6:42
  • 複数の環境で発生するのでスペックのせいでは無いと思いますが。。。

    自分の環境はCore i5 M450@2.40GHz  NVIDIA GeForce GT 330M です。

    再現方法はAutoScrollをtrueにしたPanelをフォームに適当に配置し、その中にスクロールバーが表示されるような位置にLabel等なんでもいいので配置します。

    後は適当なButtonのクリックイベントで例えば下記のようにしてスクロールバーの表示、非表示を切り替えれば再現します。

    private void button1_Click(object sender, EventArgs e) {
        panel1.AutoScroll = !panel1.AutoScroll;
    }


    試してみました。

    Windows 7 64bit SP1・Core i7-2600 3.40GHz・メモリ12.0GB・GeForce GT 530

    ・・・こちらでも再現しますね (^^;

    いろいろ試してみましたが、どうにも厄介な現象のようです。フィードバックに報告しといた方がいいかもしれません。

    https://connect.microsoft.com/VisualStudio/content/content.aspx?ContentID=25941

    # ちなみに旧日本語版フィードバックは暫定的に見れるようになったみたいです。
    # https://connect.microsoft.com/site550


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2011年11月7日 7:45
    モデレータ
  • とりあえず回避はできるんじゃないかなぁ

    bool hVisible;
    bool vVisible;
    hVisible = panel1.HorizontalScroll.Visible;
    vVisible=panel1.VerticalScroll.Visible;
    
    panel1.VerticalScroll.Visible = false;
    panel1.HorizontalScroll.Visible = false;
    
    panel1.AutoScroll = !panel1.AutoScroll;
    
    panel1.VerticalScroll.Visible = vVisible;
    panel1.HorizontalScroll.Visible = hVisible;
    

    エフェクトの描画でWM_TIMERが飛んできてるのを無駄に反応して描画しちゃってるみたいですね。
    スクロールバーが表示されている状態だとエフェクトが発動するので、スクロールバーを一時的に消してからAutoScrollを変更すればエフェクトを描画することがなくなるので、この現象は回避できそうです。

    #他にも同じ原因の描画ミスはありそう

     

    追記:
    Visibleにfalseを入れなくてもAutoScroll変更後に変更前のVisibleを戻すだけでよさそう。
    動作検証 Vista 32bitデスクトップ + 7 64bitノート


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
    • 編集済み gekkaMVP 2011年11月7日 13:34
    2011年11月7日 8:59
  • とりあえず回避はできるんじゃないかなぁ

    ・・・・(中略)・・・・・

    スクロールバーが表示されている状態だとエフェクトが発動するので、スクロールバーを一時的に消してからAutoScrollを変更すればエフェクトを描画することがなくなるので、この現象は回避できそうです。

    同様の手段は試してみましたが、残念ながらこちらの環境ではうまくいかないですね。上記コードも試してみましたが、AutoScroll が true のままか、もしくは false にしても描画が残ったままです。

    そもそもこんな対処せねばならない時点で、十分フィードバック行きだと思う(汗


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2011年11月7日 9:13
    モデレータ
  • 強引ですが、レイアウトの変更後に下記コードを実行するのはいかがでしょうか?
    PerformLayout しているのは、スクロールバーが表示された場合のつまみサイズの再計算のためです。
    // using System.Reflection;
    var mi = typeof(Panel).GetMethod("RecreateHandle", BindingFlags.Instance | BindingFlags.NonPublic);
    if (mi != null) mi.Invoke(panel1, null);
    panel1.PerformLayout();
    

    • 回答としてマーク iwims 2011年11月9日 3:14
    2011年11月7日 10:25
  • いろいろ試してみましたが、どうにも厄介な現象のようです。フィードバックに報告しといた方がいいかもしれません。

    https://connect.microsoft.com/VisualStudio/content/content.aspx?ContentID=25941


    Not Found になります。こちらでよろしいでしょうか?Visual Studio Feedback
    それとも、フィードバックに投稿した内容?



    Jitta@わんくま同盟
    • 編集済み Jitta 2011年11月7日 11:52 変換ミス(--;
    2011年11月7日 11:51

  • gekka様、TH01様、ひらぽん様、Jitta様
    レス感謝いたします。

    gekka様とTH01様のコードを取りあえずダミーのプログラムで試してみたところ私の環境ではうまくうまく動いているようでした。ひらぽん様の環境ではうまくいかないとの事なので、明日別の環境でも試してみようと思います。
    取り急ぎ御礼申し上げます。

    ところでフィードバックの投稿の仕方が分かったら投稿しようと思います(汗

    2011年11月7日 12:57
  • いろいろ試してみましたが、どうにも厄介な現象のようです。フィードバックに報告しといた方がいいかもしれません。

    https://connect.microsoft.com/VisualStudio/content/content.aspx?ContentID=25941

    Not Found になります。こちらでよろしいでしょうか?Visual Studio Feedback
    それとも、フィードバックに投稿した内容?


    英語版のサイトで報告するしかなさそうですね。

    https://connect.microsoft.com/site550

    には

    日本語 Visual Studio フィードバックのホームページはこちらに移動しました。新しいフィードバックはこちらから送信してください」

    と書いてあるのに・・・ダメじゃん(汗


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2011年11月7日 23:13
    モデレータ
  • 以前に似た状況になった時の回避策で gekka さん指摘のような処理を行いましたが、一個だけ追加しないと回避できませんでした。

    スクロールバーを一時的に消してからAutoScrollを変更すれば...

    ビジュアルスタイル表示時のみでしたが、一時的に消す前に各 Scroll.Value に0を指定しないと表示が残りましたね。

     Framework 2.0 の頃なので直ってるかもしれませんが・・・。


    • 編集済み kyano30 2011年11月8日 10:51 追記
    2011年11月8日 10:42
  • TH01様の回答で解決しました。

    gekka様の回答でサンプルプログラムはうまくいったのですが、実際のプログラムでは何故かうまくいきませんでした。またkyano30様の回答は有効でしたが、元が0の時に0を代入してもうまくいかないことがあったのでValueを違う値に変更するのが要ではないでしょうか。

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

    2011年11月9日 3:29