GDI+について

このQ&Aのポイント
  • GDI+を使用してプログラミングをする際の利点とは何でしょうか?
  • GDIで作成した画像バッファのhdcを使用してGDI+関数で描画する方法について教えてください。
  • GDI+で画像バッファを作成し、そのデバイスコンテキストを取得することは可能でしょうか?
回答を見る
  • ベストアンサー

GDI+について

いつもお世話になっております。 今回教えていただきたいことは、GDI+についてです。 今まで GDI と OpenGL を組み合わせてプログラミングをしていましたが、GDIでは自前でアンチエリアス処理をしなければならないなど面倒な部分が多く困っていました。 そこで GDI+ を使用して楽にプログラミングしようと考えて色々とプログラムをしてみたのですが、ここにきて壁にぶち当たりましたので、先人の方にご教授していただきたいのです。 《 GDI でプログラムしていた時 》 (1)画像バッファを作成しておく  //ディスクトップのDCを取得  HDC hdcTmp = GetDC( GetDesktopWindow() );  //ビットマップのハンドルと、作成したバッファの先頭アドレスを取得  hBitmap = CreateDIBSection( hdcTmp, &bmi, DIB_RGB_COLORS, (void**)&buffer, 0, 0 );  //HBITMAPにHDCを結び付ける  hdc = CreateCompatibleDC( hdcTmp );     //DIBSection用メモリデバイスコンテキスト作成  hOldHandle = SelectObject( hdc, hBitmap );       //画像バッファ(m_hBitmap)をメモリデバイスコンテキストに選択 (GDIでも描画出来るようにするため) (2)画像バッファ上にGDIで描画する  hdcに対してGDIの関数を使用して描画 (3)BitBlt()でウィンドウに転送する  WM_PAINTのメッセージのときだけウィンドウに対して転送 上記(1)(2)(3)のようにして描画を行っていました。 ■したいこと(1)■ 今したい事は 上記(1)で作成したGDI の画像バッファのhdcを使ってGDI+関数で描画したいのです。 そうするといままで使っていたGDIの知識を生かして両方使えます。 ■したいこと(2)■ したいこと(1)がもし出来ないのであればGDI+での画像バッファがつくれるかどうか、その画像バッファのデバイスコンテキスト は取得できるのかどうか教えていただきたいと思います 情報不足かもしれませんが、ご教授よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

私も最近GDI+を使い始めて苦しんだので、わかる所を。 日本語のマニュアルを探すと.NETばかりですからね。MSDNで調べても良くわからなくて結局ヘッダを調べて作っています。 手順の(2)のところをこうして下さい。 Graphics Graph(hdc); //Graphics クラスのインスタンス これで、Grpahを使ってラインや円などを描けるようになります。 四角に塗りつぶしなら、 SolidBrush brush( Color(255,0,0,0) ); //不透明の黒 Grpah.FillRectangle(&brush,0,0,100,100); //四角形 といった感じです。

Daisuke-now
質問者

お礼

ご回答ありがとうございます、本当に助かりました。 しかし一つ不思議な事があります。 GDIではWM_CREATEメッセージの時点で描画したものが画像バッファに反映されているのですが、GDI+で同じようにWM_CREATEで、  Graphics Graph(hdc);  //Graphics クラスのインスタンス を実行してWM_CREATE内でGDI+描画するとバッファに反映されていないんです。 しかしWM_PAINTで  Graphics Graph(hdc);  //Graphics クラスのインスタンス を実行し、WM_PAINT内でバッファにGDI+で描画すると描画されます。 上記が一つ目の疑問点です。 それからもう一つ不思議な事があります。 画像バッファにGDI+で描画した図形にアンチエリアスをかけていたのですが、ウインドウを別のウィンドウで隠したりして再描画させると最初にGDI+で描画した図形にアンチエリアスがかかっていません。  Graph.SetSmoothingMode( SmoothingModeAntiAlias ); 上記のようにアンチエリアス指定してから描画しています。 普通にGDI+だけで直接ウィンドウのHDCに対してWM_PAINTで描画している時にはアンチエリアスがかかっているのですが、不思議です。 たびたびすみませんがご教授よろしくお願いいたします。

その他の回答 (1)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

日ごろMFC専門でWindowsAPIの生で組まないので、答えが間違ってるかも知れませんが。 >WM_CREATEメッセージの時点で描画したものが画像バッファに反映されているのですが タイミング的にGDI+の初期化は完了していますか? >画像バッファにGDI+で描画した図形にアンチエリアスをかけていたのですが、ウインドウを別のウィンドウで隠したりして再描画させると最初にGDI+で描画した図形にアンチエリアスがかかっていません。 それは経験したことがないですね。 Graph.SetSmoothingMode( SmoothingModeAntiAlias ); が何処かで取り消されているとしか思えません。 今回は、あくまで参考意見という事で。

関連するQ&A

  • c言語を使いダイアログにbmpを表示したい 

    はじめまして、 私は、c言語は初心者なのでが、ダイアログボックスに、画像(bmp)が表示することができません。 ソースは、 hdc = BeginPaint(hDlg, &ps); //指定ウィンドウ内での描写準備 // ビットマップをファイルからロードする hBitmap = ::LoadBitmap( NULL, _T("test.bmp") ); // ウィンドウのデバイスコンテキストハンドルを取得する hDC = GetDC( hDlg ); // メモリデバイスコンテキストを作成する hCompatDC = CreateCompatibleDC( hDC ); // ロードしたビットマップを選択する GetObject(hBitmap, sizeof(BITMAP), &bmp); // ビットマップをウィンドウに転送する(表示する) if(hBitmap != NULL){ StretchBlt( hDC, 0, 0, 100, 100, hCompatDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY ); SendDlgItemMessage( hDlg, IDC_STATIC, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); } なのですが、これはメインウィンドウでは動くのですが、ダイアログボックスでは動かずこまっています。 どうか、助言のほどよろしくお願いします。

  • GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。

    GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。 環境は、VC++のWin32プロジェクトです。 WindowのデバイスコンテキストからGraphicsオブジェクトを生成し、DrawStringとすると滑らかに描画されます。 しかし、BitmapオブジェクトからGraphicsオブジェクトを生成し、DrawStringを行うとビットマップフォントのようです。 Graphics g(hdc); g.DrawString(......); -> この場合はなめらか(画像の下の方) しかし、 Bitmap bmp(w, h, PixelFormat32bppARGB); Graphics g (&bmp); g.SetSmootingMode(SmoothingModeHighQuality); g.DrawString(...); -> ジャギが目立つ。(画像の上の方) ビットマップ(メモリ)にスムーズなテキストを描画することはできないのでしょうか? ちなみにフォントはメイリオです。

  • GetPixelに使うHDCの作り方

    ビットマップハンドルhBitmap の(x,y)の画素の色を読み取るプログラムに使うデバイスコンテキストとして、  hDC = CreateCompatibleDC(NULL);  SelectObject(hDC, hBitmap);  rgb = GetPixel(hDC, x,y);  DeleteDC(hDC); のように、NULL を指定して、画面と互換性のあるメモリデバイスコンテキストを指定したのですが、正しい色が読み出せません。hDC = GetDC(NULL);でも同じく駄目でした。hDCはどのように作ったらよいのでしょう。 なお、関数の中でGetPixel()を使いたいので、hWnd などは使えません。

  • ReadFileの読み込みエラーについて

     こんばんは Win32 APIでプログラミングをやっているのですが、そのAPIの中でReadFileというものがありますよね? この関数でエラー値が出力され、第二引数としてBITMAPINFO構造体に格納するはずの値がそのままです。 以下に一部ソースを載せます BOOL Cell_Init( HINSTANCE hInstance ) { BITMAPINFO bmi2; HANDLE hFile; DWORD dwBytes; // 作成するビットマップの情報を設定する BITMAPFILEHEADER bmpFileHeader; BITMAPINFO bmi; // ビットマップのハンドルと、作成したバッファの先頭アドレスを取得 void* pImage; HBITMAP hBitmap; // デスクトップのDCを得る HDC tmpDC = GetDC(GetDesktopWindow() ); // HBITMAPにHDCを結びつける g_hdc_cell = CreateCompatibleDC( tmpDC ); DWORD er; hFile = CreateFile("cointos.bmp", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); er = GetLastError(); if(hFile == INVALID_HANDLE_VALUE) return 0; ReadFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER), &dwBytes, NULL); er = GetLastError(); if(bmpFileHeader.bfType != 0x4D42) { MessageBox(NULL, TEXT("This is not a bitmap file"), NULL, MB_OK); return FALSE; }       //ここでbmi2に格納される値が格納されていない(そのためでかい値のまま) そのためCreateDIBSectionではエラーを起こす ReadFile(hFile, &bmi2, bmpFileHeader.bfOffBits - dwBytes, &dwBytes, NULL); er = GetLastError(); // ここの部分でエラー値998が出ます hBitmap = CreateDIBSection(tmpDC, &bmi2, DIB_RGB_COLORS, (LPVOID*)&pImage, NULL, 0); ReadFile(hFile,pImage, bmpFileHeader.bfSize - bmpFileHeader.bfOffBits, &dwBytes, NULL); SelectObject( g_hdc_cell, hBitmap ); CloseHandle(hFile); ReleaseDC(GetDesktopWindow(), tmpDC); return TRUE; } なぜこうなるんでしょうか? bmi2はBITMAPINFO構造体でローカルで宣言しています。これがポインタだと大丈夫なんですが なぜ変数ではダメなのか分かりません。 あらかじめ確保されているスタック領域の容量限界でも ないと思うのですが。 分かる方がいらっしゃったらよろしくお願いします。 開発環境はVS.2005 です。

  • OnPaint() とOnDraw()の違いについて

    OnPaint内に記述した下記コードでビットマップが描画されますが、OnDraw内だと描画されません。 どうしてなのか教えてください。 お願いします。 void CAbcView::OnPaint() { HBITMAP myDIB; // ビットマップのハンドル HBITMAP oldDIB; HDC hDC; // デバイスコンテキストのハンドル HDC hCompatiDC; // メモリデバイスコンテキスト PAINTSTRUCT ps; // クライアント領域の描画に使う情報を保持 if(!m_BmpInfo) return; hDC = ::GetDC(m_hWnd);//これでもOK ::BeginPaint(m_hWnd,&ps); hCompatiDC = ::CreateCompatibleDC(hDC);//hDC); myDIB = ::CreateDIBitmap(hDC,&m_BmpInfo->bmiHeader, CBM_INIT,m_BmpImage,m_BmpInfo,DIB_RGB_COLORS); oldDIB=(HBITMAP)::SelectObject(hCompatiDC,myDIB); BitBlt(hDC,5,25,m_BmpInfo->bmiHeader.biWidth, m_BmpInfo->bmiHeader.biHeight,hCompatiDC,0,0,SRCCOPY); 略 } 環境 WIN98 VC++6.0 MFC にて

  • マウスカーソルのデスクトップ描画について

    vb2008で現在のマウスカーソルのハンドルを取得し、デスクトップに描画するというプログラムを組んでいます。しかし、以下の部分を実行してもマウスカーソルは描画されません。どこがおかしいのでしょうか? Dim hcur As Long Dim hdc As Long 'マウスカーソルのハンドル取得 hcur = GetCursor() 'デスクトップのデバイスコンテキスト取得 hdc = GetDC(GetDesktopWindow()) 'カーソル描画 DrawIcon(hdc,0,0,hcur) ちなみに同名のAPIの宣言はしてあります。 後,このソースの用途ですが,複数マウスに対応した複数カーソルの表示です。もしそれにあたって別の方法でカーソルを表示すべきなどのご指摘がありましたら,それもよろしくお願いします。

  • GDIからDirectXへの移行

    描画速度を向上させるため、DirectXを使いたいと思っているのですが、裏画面を作成して、線を引いて、文字を書いて、画面に転送するだけの簡単なCでのサンプルはどこかにないでしょうか? サイトや本を探しても、3Dや複雑なサンプルばっかりで、Hello Worldのような超簡単なサンプルを探しています。 今は、CreateCompatibleBitmapで裏画面を作成して、GDIで描画して、BitBltで画面に転送しています。

  • VC++6.0でGDI+利用してメモリリーク?

    Microsoft VC++6.0 で、画像を表示するアプリケーションを作っていて、GDI+ で様々な画像を呼び出せるようにしています。 Gdiplus::Bitmap* pGdiBitmap = Gdiplus::Bitmap::FromFile( ファイル名 ) ; で呼び出し、 HBITMAP hBitmap ; pGdiBitmap->GetHBITMAP(color , hBitmap) によりHBITMAPを取得し、 CBitmap* pBitmap をクラス内に用意し、BitBlt() 関数で画像データを pBitmap にコピーし、その後 delete pGdiBitmap で削除しています。CBitmap* pBitmap にデータを保持していればいいので。 しかし、ファイルを「開く→閉じる」を繰り返し20回や30回行うと、画像を読み込めなくなりました。 最初に調べたのが、 「pGdiBitmap を読み込んだ後に pGdiBitmap->GetHBITMAP() を実行すると戻り値が、 OutOfMemory = 3」 でした。 そこで、タスクマネージャでメモリを見ながら画像を何度も開くと、開いた画像を閉じてもメモリはそんぽままで、画像を開く度にメモリが増え、150Mとかになって、メモリ不足になることがわかりました。  これは、delete pGdiBitmap ではダメと言うことですか?それとも、プログラムがおかしいでしょうか。 Windows7 , Microsoft VC++6.0 Professional Edition , (Microsoft Platform SDK) class CMyPicture { public (コンストラクタなど) void LoadPicture(LPCTSTR lpszFilename); protected: CBitmap* m_pBitmap ; } void CMyPicture::LoadPicture(LPCTSTR lpszFilename) { HBITMAP hBitmap ; WCHAR wPath[MAX_PATH] ; ※ファイル名 lpszFilename をMultiByteToWideChar()で変換済み Gdiplus::Bitmap* pGdiBitmap = Bitmap::FromFile(wPath , TRUE) ; Status r = pGdiBitmap->GetHBITMAP( Color(0,0,0,0) , &hBitmap) ; ※ CDC dcMemory などを用意してBitBlt()で hBitmap から(CBitmap*)m_pBitmap に転送 delete pGdiBitmap ; } こんな感じです。 画像を開いて表示すること自体は成功していますが、画像を閉じてもメモリをどんどん使ってしまいます。 根本的に何か間違っていますか?GDI+をVC++6.0で使っていては限界なのでしょうか。 どなたか、教えていただけると助かります。

  • 些細な質問ですが、よろしくお願いします。

    現在C++のSDKを勉強中の身です。 「猫でも分かるプログラミング」の98章を勉強中に疑問が出てきました。疑問というよりも中身が知りたくて質問させていただきました。 98章 http://www.kumei.ne.jp/c_lang/sdk/sdk_98.htm いままで何気にやってきたことですが、「デバイスコンテキスト」とはどんなものなんでしょうか? 自分ではクライアント領域を描画するためのメモリ空間だと考えていたんですが、次にこんな関数が出てきました。 (HDC)CreateCompatibleDC(hdc) この関数で得られるものは「メモリデバイスコンテキストハンドル」 ・・・? デバイスコンテキストハンドルはメモリ空間じゃなかったの?と疑問を持ってしまいました。 じゃあメモリデバイスコンテキストとはなんぞや?とまたまた新たなる疑問が次々に発生・・・・・ そして例えばビットマップの表示ならば SelectObject関数により、ビットマップハンドルとメモリデバイスコンテキストハンドルを対応図づける?のですが、このSelectObject関数もなにをやっているのかつかみにくいです。「対応づけ」と理解していますが、それがあっているのかどうかも不明です。 よって解決したい問題は (1)「デバイスコンテキストハンドル」および「メモリデバイスコンテキストハンドル」とはなんなのか? (2)SelectObject関数は何をしているのか? すこし図々しい疑問で恐縮ですが、この疑問に答えられる方は返信よろしくお願いします。

  • MFC デバイスコンテキストについて

    MFCのデバイスコンテキストを取得して、DirectXなどで描画を行っています。 環境は、 VS2008 DirextX 9.0 MDIなんですがOnInitDialogでDirectXのデバイスを取得しています。 次にOnDrawで描画を行っています。 GetDcでコンテキストを取得し、円の描画を行っています。 MDIですので、5以上のファイルを作成すると、描画が行われなくなります。 共通デバイスコンテキストは、5以上持てないということは検索して分かったのですが、5以上のファイルに描画を成功させるためには、どうすればいいのでしょうか? ・単純に新規ファイルを作ったときに、以前に作ったファイルのデバイスコンテキストを開放また、Directxのデバイスを開放すればいい? ・DirectXのデバイスをファイルごとに作成するのではなく、共通してもてば解決できる?? ・そもそも解放したりしても無理?? と考えているのですが、どうでしょうか? 助言をお願いします。

専門家に質問してみよう