DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C#でBitBot関数を使用しピクチャーボックスへ描画

環境/言語:[VC2008 C#]
分類:[.NET]

C#にて、BitBit関数を使用してピクチャーボックスに描画したいのですが、
なかなかうまくいきません。

ビットマップファイルを読み込んでその一部をピクチャーボックスに表示するのが目的です。
BiBit関数以外では読み込めましたが、大きな画像を扱うためさらに高速化したいために試行錯誤しております。

あまりDCなど扱ったことがないのでなかなかうまくいきません。
アドバイスいただければと思います。
よろしくお願いいたします。

以下途中まで作成したものになります。(何かが間違っていますが)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public const int SRCCOPY = 0xcc0020;

        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(
            IntPtr hdcDst,
            int xDst,
            int yDst,
            int width,
            int height,
            IntPtr hdcSrc,
            int xSrc,
            int ySrc,
            int rasterOp
            );

        [DllImport("user32.dll")]
        static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern IntPtr CreateCompatibleDC(IntPtr hdc);
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern bool DeleteDC(IntPtr hdc);
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);


        public Form1()
        {
            InitializeComponent();
            String filename = @"C:\Users\PC\Desktop\test.bmp"

            // 画像ファイルの読み込み
            Bitmap bmp = new Bitmap(filename);
            Graphics mapGfx = Graphics.FromImage(this.pictureBox1.Image);
            IntPtr srcDC = mapGfx.GetHdc();
            IntPtr destDC = mapGfx.GetHdc();
            IntPtr hsrc = CreateCompatibleDC(hdc); 
            IntPtr porg = SelectObject(hsrc, bmp.GetHbitmap());

            BitBlt(destDC, 80, 30, bmp.Width, bmp.Height, hsrc, 0, 0, SRCCOPY); 

            mapGfx.ReleaseHdc(destDC); 
            mapGfx.Dispose();
            src.Dispose();
        }
    }
}
■No30772に返信(kintonさんの記事)
> C#にて、BitBit関数を使用してピクチャーボックスに描画したいのですが、
> なかなかうまくいきません。

掲載のコードは狙っている効果を出せないと思います。
PictureBox が画面に表示される際には結局、PictureBox.Image の画像が内部の Paint イベントで DrawImage によって描画されるためです。(正確には Paint イベントそのものではありませんが)

本当に BitBlt で画面に描きたいなら、PictureBox.Image プロパティを使うことはありませんし、コンストラクタに書くことでもありません。
Paint イベントで描くなどの対応が必要でしょうね。

> ビットマップファイルを読み込んでその一部をピクチャーボックスに表示するのが目的です。
> BiBit関数以外では読み込めましたが、大きな画像を扱うためさらに高速化したいために試行錯誤しております。

BitBlt 関数を使えば速くなるとお考えなのはなぜでしょうか。

> 以下途中まで作成したものになります。(何かが間違っていますが)

いろいろと問題があります…。

・srcDC が使われていない、後処理がされていない。
・hdc と src が存在しないのに使われている。
・GetHbitmap で取得した IntPtr が解放されていない。
・bmp、hsrc が解放されていない。

コンパイルが通らない問題、解放漏れの問題が散見されます。
これらを修正しても、前述のように実際の描画は DrawImage を使っているので BitBlt 関数は読み込み時に位置をずらすぐらいの効果に限られますので、狙っている高速化が期待できるかはわかりません。

DOBON.NET | プログラミング道 | プログラミング掲示板