これいつも忘れるのでメモ。

IsHitTestVisible="False"

WinFormsでスクロール処理を行うと言うと、ScrollableControlの派生クラスを作ってAutoScrollMinSizeでコンテンツのサイズを指定するのが定石だと思うのですが、このAutoScrollMinSizeが上手いこと反映されない事がたまにあります。

以下、無理矢理再現させたコードです。

namespace ScrollTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            if (ClientSize == Size.Empty)
            {
                AutoScrollMinSize = new Size(8000, 8000);
            }
            else
            {
                AutoScrollMinSize = new Size(10, 10);
            }
            Debug.WriteLine("AutoScrollMinSize= {0}", AutoScrollMinSize);
        }
    }
}

見たとおりですがフォームを最小化した瞬間に、AutoScrollMinSizeを{8000, 8000}にし、元のサイズに戻したときには{10, 10}に設定します。
実行して最小化→元のサイズに戻すと、AutoScrollMinSizeが{8000, 8000}だった頃のスクロールバー状態のままになっています。

Edge2

この条件だけでしたら、ClientSize == Size.EmptyのときにはAutoScrollMinSizeを変更しない事で回避できますが、他にも何パターンか有るような気がします。
この症状について何か情報をお持ちの方がいらっしゃいましたらご連絡ください。

何故かDebug.WriteLineで出力ペインに出力されなくなりました。
当然デバッグ実行ですし、プロジェクトの設定でDEBUG定数の定義にチェックは入っています。
イミディエイトウィンドウへのリダイレクト機能もオフにしてあります。

一応いろいろやってみたのですが

Debug.WriteLine("Debug.WriteLine");
Trace.WriteLine("Trace.WriteLine");
Console.WriteLine("Console.WriteLine");

Console.WriteLineは動作するので今はこれで代用しています。
ただ、気持ちが悪いので解決策をご存知の方がいらっしゃいましたらご教授ください。
(VS2010再インストールしかないかな・・・。いろいろアンインストールした時期があるので、間違って何か消しちゃったのかも。)

解決しました。

出力ペインの右クリックメニューで、プログラム出力がオフになってました・・・。
何かの拍子に触ってしまったようです。

  • ある画像をマルチスレッド(分割統治法など)で事前にレンダリングしておき、キャッシュする。
  • OnPaintでそのキャッシュを使う。

なんて事をしようと思いまして、スレッドプールを使って処理をさせ、レンダリングが終わったらワーカースレッド側でManualResetEventのSet()を呼び出し、メインスレッド側ではWaitOneで各ワーカースレッドが終わるのを待つ・・・・というような処理を書きました。

で、たまに描画結果が期待したものにならない事がありまして調べてみると、
どうやらWaitOneで待っている間にOnPaintが呼ばれてしまう事があるようなのです。
(当然その段階ではキャッシュは作り終わっていないので、描画がおかしくなるというわけです。)

このような挙動は過去にMFCなどでネイティブアプリを作っている時には起こり得なかったため、特定に時間がかかりました。

WinFormsはそういう作りになっているそうです。
参考:
http://stackoverflow.com/questions/4540244/how-is-this-possible-onpaint-processed-while-in-waitone

ただ、WaitOneだけならともかく、他にもメインスレッドを待つ処理だったり、.NETのフレームワークの一部の機能を使ったとき(例えばクリップボードに格納されているデータを確認するとき)のような意図しない時にもOnPaintが呼ばれるのが厄介です。
(ツールバーの「貼り付け」ボタンの状態を更新しようとしたらOnPaintが呼ばれる、なんて事もありえます。)

こうした場合、

  • マルチスレッドで画像をレンダリングするのを止める(^^;
  • キャッシュを使わないようにする
  • OnPaintの中でキャッシュを作るようにする
  • フラグでなんとか回避する

などなど、注意してプログラムする必要がありそうです。

何か良いアイディアをご存知の方がいらっしゃいましたら、ご連絡くださいm(_ _)m
(先の参考サイトだとMutexなら起こらないとか書かれていますが、今回のケースだと使えないような?)

カスタムコントロールを作ってデザイナへ貼り付けても、InitializeComponent()内でnewされず、実行するとエラーになるケースが頻発しました。

これどうやら、カスタムコントロールのコンストラクタがpublicでないと起こるみたいです。
http://stackoverflow.com/questions/5684784/custom-user-control-not-initialized-in-auto-generated-code

interfaceの実装もpublic固定ですし、デザイナで表示させるプロパティもpublicである必要がありますし(うろ覚え)、データバインディングを行わせるためのプロパティもpublicでないといけません。

外部に公開する気は無いのでinternalをよく使っているのですが、結構こういう制限があって統一しきれないのが残念です。

記事検索

アーカイブ