高見知英のかいはつにっし(β)

高見知英のアプリケーション開発日誌 のほか、地域活動などの活動報告ブログ。

PictureBoxのちらつき

 フォームの上にPictureBoxをおき、そこに更新が頻繁な画像を描画させるようにする 当然ながら背景塗りつぶしが入るせいで、ちらつきが発生します。PictureBoxのSetStyleメソッドで、ControlStyles.AllPaintingInWmPaintあたりでも使えば直るかなと思い、面倒なのでInvokeMemberを使って強制的にアクセスし、値を変更。
…しかし、ちらつきは一向に収まらない。ControlStyles.DoubleBufferdやControlStyles.UserPaintも当然追加しましたが、ちらついたままです。

 調べてみると、PictureBoxでは、最初からControlStyles.AllPaintingInWmPaintが設定されているようです。同じように、UserPaintなども、最初から宣言されていました。しかし、背景は描画されているようです。最初の一回くらいは勝手に動くのかもしれませんが、なぜでしょうね?
親のWM_ERASEBKGNDもあるかなと思い、親フォームのOnPaintBackGroundで、コントロールのある場所の矩形を抜かしたリージョンだけに塗りつぶしを施してみたものの、効果なし。依然としてちらつき続けてます。
場所によっては、背景塗りつぶしに、ControlStyles.Opaqueを使用しているところもあります。SetBkMode APIの代替(Microsoft Win32 と Microsoft .NET Framework API との対応より)だとすると、これはあんまり関係ない気がするんですが…、実際にやってみると、有効みたいです。でも、ちらつきを抑えるまでには至らなかった。
どうもうまくいかないようです。フォームに直接描画するだけなら、上の三つだけでも十分なのになぁ…。


 それとさらに気づいたことですが、InvokeMemberはTypeクラスのメソッドですので、呼び出しにはobject.GetType().InvokeMemberなどとしなければいけません。ここで、InvokeMemberを呼び出す時点では、Typeが"どのオブジェクトから得られたのか"などということは分からないので、InvokeMemberをすると、フォーム上の(アセンブリ上かも)すべてのPictureBoxの同じメソッドが呼び出されてしまうのです。なので、上の場合は、ぜんPictureBoxにControlStyles.Opaqueフラグをつけてしまったりしていたようで。だからといってそれがバグの元になる理由が分かりませんが…。
 素直に継承コンポーネントを作れとでも、言われているのかな(今回はPaintさえ出来ればいいので、Labelなんかでも何とか出来そうですが)?