SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C#でフォームを擬似的にロックする方法

Formのバックグランド処理中にコントロールの更新を見えさせなくするテクニック

ダウンロード サンプルコード (22.6 KB)

コントロールを描画した画像でフタをする方法

 バックグラウンドで時間のかかる処理を行った場合、前述の方法だと、フォームの移動時にPaintイベントが発生しないため、コントロールがフォームから消え去る現象が生じます。

 アニメ「キャッツ・アイ」では、監視カメラの真ん前に無人状態の風景写真を貼り付け、監視員がモニターに映ったその写真を実際の映像だと勘違いしている間に、カメラの前を横切るというシーンがありました。ここではそんな偽の画像を用いることで、コントロール処理を隠す方法を解説します。

 .NET Framework 2.0にはフォームのスクリーンショットを取得するためのメソッドControl.DrawToBitmapが用意されていますが、このメソッドはWebBrowserコントロールなどのActiveXコントロールを反映されないため、ここではWindows XPから追加されたAPI「PrintWindow」を用い、この関数で取得した画像をフォームの最前面に貼り付けています。

[DllImport("user32")]
private static extern bool PrintWindow(
    IntPtr hwnd,    // イメージを取得する対象ウィンドウ(HWND)
    IntPtr hdcBlt,  // イメージの保存先(HDC)
    uint nFlags     // オプションフラッグ:
                    // PW_CLIENTONLY(=0x1)でクライアント領域のみ取得
    );

private Bitmap screen = null;
private PictureBox pctbox = null;

private void button1_Click(object sender, EventArgs e)
{
    // 有効状態であるクライアント領域のイメージをキャプチャ

    // ※Windows XPではPrintWindowの第3引数に
    //  PW_CLIENTONLYを指定しても正しくキャプチャされないため、
    //  引数0x0でウィンドウ全体を取得した後で、
    //  クライアント領域部分をコピーするようにしている
    Bitmap winimg = new Bitmap(Width, Height);
    Graphics g = Graphics.FromImage(winimg);
    IntPtr hDC = g.GetHdc();
    PrintWindow(this.Handle, hDC, 0x0);
    g.ReleaseHdc(hDC);
    g.Dispose();

    // クライアント領域の相対位置を取得
    Rectangle r1 = this.Bounds; r1.X = r1.Y = 0;
    Rectangle r2 = this.ClientRectangle;
    Rectangle r3 = new Rectangle(
        (r1.Width - r2.Width) / 2,
        (r1.Height - r2.Height - SystemInformation.CaptionHeight) / 2 + SystemInformation.CaptionHeight,
        r2.Width, r2.Height);

    // クライアント部分をコピーする
    screen = new Bitmap(ClientSize.Width, ClientSize.Height);
    g = Graphics.FromImage(screen);
    g.DrawImage(winimg, ClientRectangle, r3, GraphicsUnit.Pixel);
    g.Dispose();
    winimg.Dispose();


    // 「フタ」を作成
    pctbox = new PictureBox();
    pctbox.Paint += new PaintEventHandler(pctbox_Paint);
    pctbox.Bounds = this.ClientRectangle;
    pctbox.BackgroundImage = screen;
    this.Controls.Add(pctbox);
    pctbox.BringToFront();

    panel1.Enabled = false;

    timer1.Start();

    // バックグラウンド処理の開始
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    // 編集可能な状態に復帰する
    panel1.Enabled = true;

    // 偽装フォームを廃棄して本来のフォームを表示
    if (pctbox != null) pctbox.Dispose();
}

 PictureBox.OnPaintイベントに描画処理を追加すれば、Web 2.0でよく見られるようなウェイト処理を再現することも可能です(サンプルファイルを参照)。

Web 2.0のようなバックグラウンド処理

最後に

 「フタ」テクニックは、フォームの中央に半透明で「お待ち下さい」といったメッセージを簡単に描画できるので、アイデア次第で多彩なウェイト処理を実装できるでしょう。更新中にコントロールにアクセスされては困るようなタイプのソフトウェア――特にデータベースソフトウェアにおすすめします。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

TNKソフトウェア(ティーエヌケーソフトウェア)

 フリーソフト/シェアウェア作家。小学生の頃ゴミ捨て場から拾ってきたPC-6001によってプログラミングに目覚める。大学生時代に開発したフリーのカード型データベースが好評価を得たのを機に、オンラインソフトウェア開発に積極的に取り組むようになる。 www.tnksoft.com

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3407 2009/01/26 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー