トップ回答者
AnimateWindowを使用してFormを表示させると、Controlが描画されずに表示される

質問
-
標題の通りなのですが、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); }
よろしくお願いします。
回答
-
コントロールは、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); }
-
「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
すべての返信
-
コントロールは、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); }
-
「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
-
有難うございます。
確認しました。期待通りの動作です。一点追加で質問です。
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どちらでも変わらないです。
-
>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 の件は、軽くググっても見当たらないので現状は、何も見解を出せません。
# トリッキーなことをしている(と私は思っている)ので、最悪解決策ないということもあり得るかも。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなりま -
従って、Application.Run を実行する前・後にかかわらず、現象は起きることになり、Application.Run をやらないことが原因ではないということを主張するものです。
確かにその通りですね。その部分、撤回します。
Showが、Loadイベント発生以前にしていることを実行できればコントロールの描画も出来そうですが…内部状態不正の可能性を考えると、LoadイベントとかWM_SHOWWINDOWメッセージの時に呼ぶのが妥当かもしれませんね。
じゃぁその時は大丈夫なのかといわれると、またそれはそれでなんとも言えないのですが…ComboBoxについてはよくわかりませんでした。
AnimateWindow後にRefreshすれば薄い境界線に戻るようですが、フォームが読み込まれるときとRefresh時とで違う表示になるのは不思議です。 -
RichEditだと、Client Areaの背景が描画されないですね。調べるには時間がかかりそうです。
昨晩、調べていた際に見かけたページの話題でしょうか?
このページでは、VisibleChanged で Capture して Update して Refresh してといろいろとこなしているようですが、効果の有無は確認していません。
http://stackoverflow.com/questions/3507355/animatewindow-api-transparency-problem-with-richtextboxただ、こういった回避は、あくまで回避であり、長続きしないものと理解するべきだと思っています。
Windows のバージョンに依存するとかありそうですし…。# ビジネスであれば、本当にその仕様が必要かも含めて見直すべきかもしれませんね。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。