none
AnimateWindowを使用してFormを表示させると、Controlが描画されずに表示される RRS feed

  • 質問

  • 標題の通りなのですが、AnimateWindowを利用してFormをSlide表示させると、
    Controlが描画されずFormのみがSlideされて表示されます。

    その後、Formが表示しきった後にControlが描画されます。
    Controlも一緒にSlide表示されるのがAnimateWindowだと思うのですが、
    これに対応するためにはどうすればよいでしょうか?

    ・AnimateWindow用のClass

      class Win32
      {
        [Flags]
        public enum AnimateWindowFlags
        {
          AW_HOR_POSITIVE = 0x00000001,
          AW_HOR_NEGATIVE = 0x00000002,
          AW_VER_POSITIVE = 0x00000004,
          AW_VER_NEGATIVE = 0x00000008,
          AW_CENTER = 0x00000010,
          AW_HIDE = 0x00010000,
          AW_ACTIVATE = 0x00020000,
          AW_SLIDE = 0x00040000,
          AW_BLEND = 0x00080000
        }
    
        [DllImport("user32")]
        public static extern bool AnimateWindow(IntPtr hwnd, int time, AnimateWindowFlags flags);
      }
    
    

    ・Main

        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
    
          Form1 form1 = new Form1();
          Win32.AnimateWindow(form1.Handle, 1000,
              Win32.AnimateWindowFlags.AW_ACTIVATE | Win32.AnimateWindowFlags.AW_SLIDE | Win32.AnimateWindowFlags.AW_VER_POSITIVE);
          form1.Show();
          Application.Run(form1);
        }
    
    

     よろしくお願いします。

     

    2011年4月6日 9:19

回答

  • コントロールは、Application.Runの後(メッセージループの開始後?)にやらないと描画されないようです。
    というわけでもないようです。

    フォームのLoadイベントでAnimateWindowを行うとうまく動きます。

    [STAThread]
    static void Main()
    {
    	Application.EnableVisualStyles();
    	Application.SetCompatibleTextRenderingDefault(false);
    
    	var form1 = new Form1();
    	form1.Load += new EventHandler(form1_Load);
    	Application.Run(form1);
    }
    
    static void form1_Load(object sender, EventArgs e)
    {
    	Win32.AnimateWindow((sender as Form1).Handle, 1000,
    		Win32.AnimateWindowFlags.AW_ACTIVATE |
    		Win32.AnimateWindowFlags.AW_SLIDE |
    		Win32.AnimateWindowFlags.AW_VER_POSITIVE);
    }
    • 編集済み ShTair 2011年4月7日 4:15
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月6日 13:08
  • 「AnimateWindow C# Windows Forms」
    http://www.google.co.jp/#hl=ja&source=hp&biw=1138&bih=769&q=AnimateWindow+C%23+Windows+Forms&aq=f&aqi=&aql=&oq=&fp=79ec1216c12fdddc

    この最初の検索結果である下記のページで事足りませんか?
    http://calc33.blog57.fc2.com/blog-entry-1.html
    (WM_SHOWWINDOW のタイミングで AnimateWindow を呼ぶ)

    推測ですが、AnimateWindow によって Windows Forms のあずかり知らぬところで ShowWindow が呼ばれてしまうことで、内部状態が不正になっているのではないでしょうか。
    Windows Forms で表示処理をしていないから、中身のコントロールも描画されていないという推測も無茶ではありません。

    蛇足ですが、Application.Run が回避条件ではないようです。
    Application.Run 以降に開くフォームで実験した際にうまく表示されない現象を確認しました。
    (Windows 7 SP1 (x86) において)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月6日 13:26
    モデレータ
  • 昔、処理していた時の記憶の限りですが、アニメーションしたいフォームの SetVisibleCore みたいな名前のメソッドを override して、そこで呼び出していた気がします。
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月7日 10:16

すべての返信

  • コントロールは、Application.Runの後(メッセージループの開始後?)にやらないと描画されないようです。
    というわけでもないようです。

    フォームのLoadイベントでAnimateWindowを行うとうまく動きます。

    [STAThread]
    static void Main()
    {
    	Application.EnableVisualStyles();
    	Application.SetCompatibleTextRenderingDefault(false);
    
    	var form1 = new Form1();
    	form1.Load += new EventHandler(form1_Load);
    	Application.Run(form1);
    }
    
    static void form1_Load(object sender, EventArgs e)
    {
    	Win32.AnimateWindow((sender as Form1).Handle, 1000,
    		Win32.AnimateWindowFlags.AW_ACTIVATE |
    		Win32.AnimateWindowFlags.AW_SLIDE |
    		Win32.AnimateWindowFlags.AW_VER_POSITIVE);
    }
    • 編集済み ShTair 2011年4月7日 4:15
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月6日 13:08
  • 「AnimateWindow C# Windows Forms」
    http://www.google.co.jp/#hl=ja&source=hp&biw=1138&bih=769&q=AnimateWindow+C%23+Windows+Forms&aq=f&aqi=&aql=&oq=&fp=79ec1216c12fdddc

    この最初の検索結果である下記のページで事足りませんか?
    http://calc33.blog57.fc2.com/blog-entry-1.html
    (WM_SHOWWINDOW のタイミングで AnimateWindow を呼ぶ)

    推測ですが、AnimateWindow によって Windows Forms のあずかり知らぬところで ShowWindow が呼ばれてしまうことで、内部状態が不正になっているのではないでしょうか。
    Windows Forms で表示処理をしていないから、中身のコントロールも描画されていないという推測も無茶ではありません。

    蛇足ですが、Application.Run が回避条件ではないようです。
    Application.Run 以降に開くフォームで実験した際にうまく表示されない現象を確認しました。
    (Windows 7 SP1 (x86) において)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月6日 13:26
    モデレータ
  • 有難うございます。
    確認しました。期待通りの動作です。

    一点追加で質問です。
    Form1にComboBoxを追加して、ドロップダウンスタイルをシンプルにします。
    Buildして実行すると、SlideしながらFormがComboBoxとともに表示されます。

    この時、ComboBoxのList部分のBorderが彫りが深いBorderになっています。
    この状態でCursorをList部分に持って行くと、Borderが薄いBorderに変わります。

    彫りが深いBorderはVisal Style Offの時の凹んだ3D Borderです。
    薄いBorderはVisal Style Onの時のBorderです。

    Visal Style Onの時はSlideしながら表示される時も、薄いBorderで描画されるのが正しいと思うのですが、
    この現象はどのように回避するのでしょうか?

    CursorをList部分に持って行くと何故Borderが薄いBorderに変わるのかよく分からないです。

    現象が発生する状況は、Visal Style Onの時です。DWMはOn/Offどちらでも変わらないです。

    2011年4月6日 13:28
  • 有難うございます。
    確認しました。WM_SHOWWINDOWでも動作しますね。

    >Application.Run 以降に開くフォームで実験した際にうまく表示されない現象を確認しました。
    この状況を教えてもらえないでしょうか?
    WM_SHOWWINDOWでAnimateWindowした状況でしょうか?

    2011年4月6日 14:09
  • >Application.Run 以降に開くフォームで実験した際にうまく表示されない現象を確認しました。
    この状況を教えてもらえないでしょうか?
    WM_SHOWWINDOWでAnimateWindowした状況でしょうか?

    「Application.Runの後(メッセージループの開始後?)にやらないと描画されないようです」という説に対して、否定する意味で書いたものです。

    手元の Windows 7 SP1 + .NET 3.5.1 で実験した結果、Application.Run(new Form1()) で普通に表示し、button1_Click などでもう一つ Form1 を作り、それを AnimateWindow → Show() としたときに、アニメーションはするが、コントロールが描画されない問題が再現しました。
    従って、Application.Run を実行する前・後にかかわらず、現象は起きることになり、Application.Run をやらないことが原因ではないということを主張するものです。

    Load イベント、あるいは WM_SHOWWINDOW メッセージのタイミングで AnimateWindow をするやり方であれば、特に影響ない話になります。

    # ComboBox の件は、軽くググっても見当たらないので現状は、何も見解を出せません。
    # トリッキーなことをしている(と私は思っている)ので、最悪解決策ないということもあり得るかも。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなりま
    2011年4月6日 14:29
    モデレータ
  • 有難うございます。

    >「Application.Runの後(メッセージループの開始後?)にやらないと描画されないようです」という説に対して、否定する意味で書いたものです。
    はい。
    現象を確認されたとのことで、私の環境においてもその状況や手順を確認したかったため、現象発生時の状況を伺いました。
    明日確認してみます。

    2011年4月6日 15:10
  • 従って、Application.Run を実行する前・後にかかわらず、現象は起きることになり、Application.Run をやらないことが原因ではないということを主張するものです。

    確かにその通りですね。その部分、撤回します。

    Showが、Loadイベント発生以前にしていることを実行できればコントロールの描画も出来そうですが…内部状態不正の可能性を考えると、LoadイベントとかWM_SHOWWINDOWメッセージの時に呼ぶのが妥当かもしれませんね。
    じゃぁその時は大丈夫なのかといわれると、またそれはそれでなんとも言えないのですが…

    ComboBoxについてはよくわかりませんでした。
    AnimateWindow後にRefreshすれば薄い境界線に戻るようですが、フォームが読み込まれるときとRefresh時とで違う表示になるのは不思議です。

    2011年4月7日 4:02
  • RichEditだと、Client Areaの背景が描画されないですね。調べるには時間がかかりそうです。
    2011年4月7日 8:46
  • 昔、処理していた時の記憶の限りですが、アニメーションしたいフォームの SetVisibleCore みたいな名前のメソッドを override して、そこで呼び出していた気がします。
    • 回答としてマーク kozz 2011年4月8日 10:39
    2011年4月7日 10:16
  • RichEditだと、Client Areaの背景が描画されないですね。調べるには時間がかかりそうです。


    昨晩、調べていた際に見かけたページの話題でしょうか?
    このページでは、VisibleChanged で Capture して Update して Refresh してといろいろとこなしているようですが、効果の有無は確認していません。
    http://stackoverflow.com/questions/3507355/animatewindow-api-transparency-problem-with-richtextbox

    ただ、こういった回避は、あくまで回避であり、長続きしないものと理解するべきだと思っています。
    Windows のバージョンに依存するとかありそうですし…。

    # ビジネスであれば、本当にその仕様が必要かも含めて見直すべきかもしれませんね。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年4月7日 13:46
    モデレータ
  • Windows APIで作成したApplicationでTestしても同じ結果になるため、Controlの不具合であると結論付けました。
    対応策は自分で描画するしかありません。

    C#だとP/Invokeに手間がかかるため、その処理のみC++/CLIで行い現象を回避する方法で検討することにしました。
    (ただ、この要件に見合うだけのCostなのだろうか、ということも考え判断します。)

    有難うございました。

    2011年4月8日 10:38