直接、デバイスコンテキストに描画することもできるが、一手間かけて、メモリビットマップに描画した後、デバイスコンテキストに描画したほうが高速に描画できる
|
#include <windows.h> #include <GdiPlus.h> #pragma comment(lib,"GdiPlus.lib") using namespace Gdiplus; GdiplusStartupInput gdiSI; ULONG_PTR gdiToken; Bitmap *Bmp_R = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Draw_Image(HDC hDC, int width, int height); void Read_Image(char *fname); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int width,height; switch (uMsg) { case WM_CREATE: GdiplusStartup(&gdiToken,&gdiSI,NULL); Read_Image("sample.jpg"); return 0; case WM_SIZE: width = LOWORD(lParam); height = HIWORD(lParam); return 0; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; // 描画準備 hDC = BeginPaint(hWnd,&ps); Draw_Image(hDC, width, height); // 描画終了 EndPaint(hWnd,&ps); return 0; case WM_CLOSE: delete Bmp_R; DestroyWindow(hWnd); GdiplusShutdown(gdiToken); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }// WndProc // 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // 画像を作業用ビットマップへ描画 if(Bmp_R){ gBmp.DrawImage(Bmp_R, 0, 0, Bmp_R->GetWidth(), Bmp_R->GetHeight()); } // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image // ファイルから画像を読み込む void Read_Image(char *fname) { WCHAR wfname[MAX_PATH]; MultiByteToWideChar(CP_ACP,0,fname,-1,wfname,sizeof(wfname)); delete Bmp_R; Bmp_R = Bitmap::FromFile(wfname,FALSE); }// Read_Image |
|
|
#define FREE(p) {free(p);p=NULL;} Bitmap *Bmp_R1 = NULL,*Bmp_R2 = NULL,*Bmp_S = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Draw_Image(HDC hDC); void Read_Image(Bitmap **Bmp, char *fname); void Save_Jpeg(char *sfname); int GetEncoderClsid(const WCHAR* format, CLSID* pClsid); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: GdiplusStartup(&gdiToken,&gdiSI,NULL); Read_Image(&Bmp_R1, "sample.jpg"); Read_Image(&Bmp_R2, "sample2.png"); Bmp_S = new Bitmap(240, 320, PixelFormat32bppARGB); return 0; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; // 描画準備 hDC = BeginPaint(hWnd,&ps); Draw_Image(hDC); // 描画終了 EndPaint(hWnd,&ps); return 0; case WM_CLOSE: Save_Jpeg("save.jpg"); delete Bmp_R1; delete Bmp_R2; delete Bmp_S; DestroyWindow(hWnd); GdiplusShutdown(gdiToken); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }// WndProc // 画像の描画 void Draw_Image(HDC hDC) { // 保存用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(Bmp_S); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, Bmp_S->GetWidth(), Bmp_S->GetHeight()); gBmp.SetClip(rcBmp); // 画像を作業用ビットマップへ描画 if(Bmp_R1){ gBmp.DrawImage(Bmp_R1, 0, 0, Bmp_R1->GetWidth(), Bmp_R1->GetHeight()); } if(Bmp_R2){ gBmp.DrawImage(Bmp_R2, 50, 50, Bmp_R2->GetWidth(), Bmp_R2->GetHeight()); } // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(Bmp_S, 0, 0, Bmp_S->GetWidth(), Bmp_S->GetHeight()); }// Draw_Image // ファイルから画像を読み込む void Read_Image(Bitmap **Bmp, char *fname) { WCHAR wfname[MAX_PATH]; MultiByteToWideChar(CP_ACP,0,fname,-1,wfname,sizeof(wfname)); delete *Bmp; *Bmp = Bitmap::FromFile(wfname,FALSE); }// Read_Image // 画像をJPEGファイルに保存する void Save_Jpeg(char *sfname) { Status st; CLSID clsid; EncoderParameters ecps; ULONG quality; WCHAR wsfname[MAX_PATH]; // JPEGのCLSIDを取得 GetEncoderClsid(L"image/jpeg", &clsid); // ファイル名をユニコードに変換 MultiByteToWideChar(CP_ACP,0,sfname,-1,wsfname,sizeof(wsfname)); // JPEG品質設定 ecps.Count = 1; quality = 80; // 画像の品質(0 - 100) ecps.Parameter[0].Guid = EncoderQuality; ecps.Parameter[0].Type = EncoderParameterValueTypeLong; ecps.Parameter[0].NumberOfValues = 1; ecps.Parameter[0].Value = &quality; // 画像をファイルに保存 st = Bmp_S->Save(wsfname, &clsid, &ecps); if(st == Ok){ MessageBox(GetFocus(), "画像を保存しました",MYWNDTITLE ,MB_OK); } }// Save_Jpeg // MIMEからCLSIDを取得する int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; // Failure GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; FREE(pImageCodecInfo); return j; // Success } } FREE(pImageCodecInfo); return -1; // Failure }// GetEncoderClsid |
BMP, PNG, TIFF で保存するときは、色深度を設定できるが、画像の色深度が保存するそれと異なっている場合は期待した結果にはならない。GIF の色深度は8ビットのみだ。以下は、24ビットで保存した場合。
|
ここでのプロパティは、EXIF情報の事で、画像情報の事ではない。
両者に相関関係はない。 例えば、画像サイズや解像度などは、両方で設定する必要がある。 以下のサンプルコードは、PropertyTagTypeASCII と PropertyTagTypeRational だけであり、その他はやってないが、他も似たような感じである。 マイクロソフトは、プロパティ表示のサンプルをほとんど公表していない。 それを公表すると、この会社は、GDI+を使用できなくしてしまうから、書けない。 つまり、次のOSのバージョンでGDI+がサポートされなくなる。 だからと言って、代わりのGDI機能をリリースする事もない。 ウィンドウズはOSとして既に潮時であり、他のOSへの乗り換えを検討すべきだと、マイクロソフト自身も考えている証拠だが、使い勝手のいいOSは出ないかな。 クロームOSは、シンクライアント専用だから駄目だ。 現在でもPC−9801やオフコンが現役で動いている企業は多いらしいが、ウィンドウズもそうなりそうだ。 98は、工作機械を動かすのに使っている。 ソフトもPCもサポートが切れているから、修理できないのが町工場の悩みの種だ。 察するに彼らの望みは、工作機械はそのままにPCとソフトだけをウィンドウズに切り替える事だ。 彼らは「東京の企業はサポートに来ない」とぼやいている。 それだけの技術力を持った企業に地方に拠点を持ってもらうのが彼らのベストだろう。 ウィンドウズがなくなると開発に携わる人の数も減るから、スマホやタブレットPCも消滅する運命が待っているわけで、今後、オタクのリナックスが主流となる可能性がある。 最先端はリナックス、現場は化石のウィンドウズという形だ。 |
#define _CRT_SECURE_NO_WARNINGS #include <windows.h> #include <stdio.h> #include <GdiPlus.h> #pragma comment(lib,"GdiPlus.lib") using namespace Gdiplus; GdiplusStartupInput gdiSI; ULONG_PTR gdiToken; Bitmap *Bmp_R = NULL; // ビットマップオブジェクト PropertyItem *gpPropBuffer = NULL; // ビットマップ情報 UINT gnumProperties = 0; // ビットマップ情報の項目数 // 関数のプロトタイプ宣言 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); Status Get_Property(); void Read_Image(char *fname); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int width,height; switch (uMsg) { case WM_CREATE: // 初期化 GdiplusStartup(&gdiToken, &gdiSI, NULL); Read_Image("sample.jpg"); return 0; case WM_PAINT: // 描画 HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hWnd, &ps); if(gpPropBuffer){ UINT i; char strValue[256],strBuf[512]; // プロパティ数の表示 _itoa(gnumProperties ,strValue, 10); _snprintf(strBuf, sizeof(strBuf)-1, "項目数 %s", strValue); TextOut(hDC, 0, 0, strBuf, strlen(strBuf)); _snprintf(strBuf, sizeof(strBuf)-1, "ID TYPE 長さ 値", strValue); TextOut(hDC, 0, 18, strBuf, strlen(strBuf)); // プロパティ値の表示 for(i=0; i<gnumProperties; i++){ switch (gpPropBuffer[i].type) { case PropertyTagTypeASCII: strncpy(strValue, (char*) gpPropBuffer[i].value, sizeof(strValue)-1); break; case PropertyTagTypeRational: { DWORD* value = (DWORD*)(gpPropBuffer[i].value); if(gpPropBuffer[i].length == 24){ _snprintf(strValue, sizeof(strValue)-1, "%d/%d/%d/%d", value[0], value[1], value[2], value[3]); } else{ _snprintf(strValue, sizeof(strValue)-1, "%d/%d", value[0], value[1]); } } break; default: { BYTE* value = (BYTE*) gpPropBuffer[i].value; _snprintf(strValue, sizeof(strValue)-1, "%d", value[0]); } break; } _snprintf(strBuf, sizeof(strBuf)-1, "0x%04x %d % 6u %s", gpPropBuffer[i].id, gpPropBuffer[i].type, gpPropBuffer[i].length, strValue); TextOut(hDC, 0, (i+2)*18, strBuf, strlen(strBuf)); } } // 描画終了 EndPaint(hWnd, &ps); return 0; case WM_CLOSE: // 終了処理 free(gpPropBuffer); delete Bmp_R; DestroyWindow(hWnd); GdiplusShutdown(gdiToken); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }// WndProc // 画像のプロパティを取得する Status Get_Property() { Status st = GenericError; UINT totalBufferSize; if(!Bmp_R){ return st; } st = Bmp_R->GetPropertySize(&totalBufferSize, &gnumProperties); if(st == Ok){ gpPropBuffer = (PropertyItem*) malloc(totalBufferSize); st = Bmp_R->GetAllPropertyItems(totalBufferSize, gnumProperties, gpPropBuffer); } return st; }// Get_Property // ファイルから画像を読み込む void Read_Image(char *fname) { WCHAR wfname[MAX_PATH]; MultiByteToWideChar(CP_ACP,0,fname,-1,wfname,sizeof(wfname)); delete Bmp_R; Bmp_R = Bitmap::FromFile(wfname,FALSE); Get_Property(); }// Read_Image |
|
// 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // 作業用ビットマップへ直線を描画 Pen pen1(Color::Blue, 8); gBmp.DrawLine(&pen1, 20, 30, 200, 30); // ラインキャップをつけた場合 pen1.SetStartCap((LineCap)(LineCapNoAnchor + 2)); pen1.SetEndCap((LineCap)(LineCapNoAnchor + 1)); gBmp.DrawLine(&pen1, 20, 60, 200, 60); // 矢印をつけた場合 AdjustableArrowCap acap(4.0f, 3.0f); acap.SetMiddleInset(1.0f); pen1.SetCustomEndCap(&acap); gBmp.DrawLine(&pen1, 20, 90, 200, 90); // 線種の設定 pen1.SetDashStyle((DashStyle)(DashStyleSolid + 1)); gBmp.DrawLine(&pen1, 20, 120, 200, 120); // 線種のラインキャップをつけた場合 pen1.SetDashCap((DashCap)(DashCapFlat + 2)); gBmp.DrawLine(&pen1, 20, 150, 200, 150); // スムージング gBmp.SetSmoothingMode(SmoothingModeAntiAlias); gBmp.DrawLine(&pen1, 20, 180, 200, 180); // 折れ線の場合 Point pt1[] = {Point(20, 210), Point(200, 210), Point(200, 300)}; Pen pen2(Color::Coral, 12); gBmp.DrawLines(&pen2, pt1, 3); // 線の曲がり角の設定 Point pt2[] = {Point(20, 240), Point(150, 240), Point(150, 300)}; pen2.SetLineJoin((LineJoin)(LineJoinMiter + 2)); gBmp.DrawLines(&pen2, pt2, 3); // 曲線の場合 Point pt3[] = {Point(20, 270), Point(100, 270), Point(100, 300)}; gBmp.DrawCurve(&pen2, pt3, 3); // ハッチブラシの場合 HatchBrush brush1((HatchStyle) 35, Color::Green, Color::LightSkyBlue); pen2.SetWidth(20); pen2.SetBrush(&brush1); gBmp.DrawLine(&pen2, 20, 330, 200, 330); // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image |
パスは不可視の図形で、描画する事で可視化できる。 図形の回転や拡大・縮小もできる。 ドラッグ&ドロップなどで図形の移動にも使える。 パスでマスクを作ることでコピー領域の設定にも使える。 |
using namespace Gdiplus; GdiplusStartupInput gdiSI; ULONG_PTR gdiToken; GraphicsPath *Path1 = NULL; GraphicsPath *Path2 = NULL; // 関数のプロトタイプ宣言 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Draw_Image(HDC hDC, int width, int height); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int width,height; switch (uMsg) { case WM_CREATE: GdiplusStartup(&gdiToken,&gdiSI,NULL); // パスオブジェクトの作成 Path1 = new GraphicsPath(); Path2 = new GraphicsPath(); return 0; case WM_SIZE: width = LOWORD(lParam); height = HIWORD(lParam); return 0; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; // 描画準備 hDC = BeginPaint(hWnd,&ps); // 画像の描画 Draw_Image(hDC, width, height); // 描画終了 EndPaint(hWnd,&ps); return 0; case WM_CLOSE: delete Path1; delete Path2; DestroyWindow(hWnd); GdiplusShutdown(gdiToken); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }// WndProc // 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // パス1の作成と描画 if(Path1){ // パス1の作成を開始 Path1->StartFigure(); // パス1にポイントを追加 Point pt1[] = {Point(20, 10), Point(200, 10), Point(200, 150)}; Path1->AddPolygon(pt1, 3); // パス1に楕円を追加 Path1->AddEllipse(30, 60, 150, 100); // パス1を閉じる Path1->CloseFigure(); // 塗りつぶしモードの設定 Path1->SetFillMode((FillMode) 1); // 0 or 1 // パス1を黄色で塗りつぶす SolidBrush brush1(Color(255,255,255,0)); gBmp.FillPath(&brush1, Path1); // パス1の輪郭を青色で描画 Pen pen1(Color::Blue, 1); gBmp.DrawPath(&pen1, Path1); // パス1のバウンディングボックスを取得 Rect bounds; Path1->GetBounds(&bounds); // バウンディングボックスを赤色で描画 Pen pen2(Color::Red, 1); gBmp.DrawRectangle(&pen2, bounds); } // パス2の作成と変更と描画 if(Path2){ // パス2の作成を開始 Path2->StartFigure(); // パス2にポイントを追加 Point pt1[] = {Point(220, 10), Point(400, 10), Point(400, 150)}; Path2->AddPolygon(pt1, 3); // パス2を閉じる Path2->CloseFigure(); // パスデータの取得 PathData path_data; Path2->GetPathData(&path_data); // パスの最初のポイントを変更 path_data.Points[0] = PointF(220, 150); // パス2を新しいパスデータで作り直す delete Path2; Path2 = new GraphicsPath(path_data.Points, path_data.Types, path_data.Count); // パス2を水色で塗りつぶす SolidBrush brush1(Color(255,0,255,255)); gBmp.FillPath(&brush1, Path2); // パス2の輪郭を青色で描画 Pen pen1(Color::Blue, 1); gBmp.DrawPath(&pen1, Path2); } // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image |
パスの移動、回転、拡大・縮小のサンプル。 各行列を追加する順番によっては結果が変わる事がある。 |
// 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // パス1の作成と描画 if(Path1){ // パス1の作成を開始 Path1->StartFigure(); // パス1に長方形を追加 Rect rc1 = Rect(50, 50, 150, 50); Path1->AddRectangle(rc1); // パス1を閉じる Path1->CloseFigure(); // パス1を緑色で塗りつぶす SolidBrush brush1(Color(255,0,255,0)); gBmp.FillPath(&brush1, Path1); // 行列オブジェクトの作成 Matrix mtrx; // 行列に(200, 0)移動を追加 mtrx.Translate(200, 0); // 行列に(125, 75)を中心に45度回転を追加 mtrx.RotateAt(45, PointF(25, 75)); // 行列に縦横0.5倍を追加 mtrx.Scale(0.5f, 0.5f); // パス1の行列変換 Path1->Transform(&mtrx); // パス1を桃色で塗りつぶす SolidBrush brush2(Color(255,255,0,255)); gBmp.FillPath(&brush2, Path1); } // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image |
|
using namespace Gdiplus; GdiplusStartupInput gdiSI; ULONG_PTR gdiToken; GraphicsPath *Path1 = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Draw_Image(HDC hDC, int width, int height); void Drag_Image(HWND hWnd, LPARAM lParam, bool bDown, Point &posStart); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int width, height; static bool bDown = false; static Point posStart = Point(0, 0); switch (uMsg) { case WM_CREATE: GdiplusStartup(&gdiToken,&gdiSI,NULL); // パスオブジェクトの作成 Path1 = new GraphicsPath(); // パス1の作成 if(Path1){ // パス1の作成を開始 Path1->StartFigure(); // パス1に長方形を追加 Rect rc1 = Rect(50, 50, 150, 50); Path1->AddRectangle(rc1); // パス1を閉じる Path1->CloseFigure(); } return 0; case WM_SIZE: width = LOWORD(lParam); height = HIWORD(lParam); return 0; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; // 描画準備 hDC = BeginPaint(hWnd, &ps); // 画像の描画 Draw_Image(hDC, width, height); // 描画終了 EndPaint(hWnd, &ps); return 0; case WM_LBUTTONDOWN: // 左ボタン押す // マウス座標がパス内にあるか? if(Path1->IsVisible(LOWORD(lParam), HIWORD(lParam))){ bDown = true; posStart.X = LOWORD(lParam); posStart.Y = HIWORD(lParam); } return 0; case WM_LBUTTONUP: // 左ボタン離す bDown = false; return 0; case WM_MOUSEMOVE: // マウスカーソル動く Drag_Image(hWnd, lParam, bDown, posStart); return 0; case WM_CLOSE: delete Path1; DestroyWindow(hWnd); GdiplusShutdown(gdiToken); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }// WndProc // 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // 背景を白色でクリア gBmp.Clear(Color(255,255,255,255)); // パス1の描画 if(Path1){ // パス1を緑色で塗りつぶす SolidBrush brush1(Color(255,0,255,0)); gBmp.FillPath(&brush1, Path1); } // 文字列表示 Font fnt(L"Times New Roman", 12); SolidBrush brushMes(Color(255,0,0,0)); WCHAR strMes[] = L"図形はドラッグ移動可能"; gBmp.DrawString(strMes, wcslen(strMes), &fnt, PointF(0, 0), &brushMes); // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image // 画像をドラッグ void Drag_Image(HWND hWnd, LPARAM lParam, bool bDown, Point &posStart) { Point pt = Point(LOWORD(lParam), HIWORD(lParam)); if(bDown){ static Point pt_pre = Point(pt.X, pt.Y); Point pt_mv = Point(pt.X - posStart.X, pt.Y - posStart.Y); // 行列オブジェクトの作成 Matrix mtrx; // 行列に移動を追加 mtrx.Translate((REAL) pt_mv.X, (REAL) pt_mv.Y); // パス1の行列変換 Path1->Transform(&mtrx); // 再描画 InvalidateRect(hWnd, NULL, FALSE); // 変数の初期化 pt_pre = Point(pt_mv.X, pt_mv.Y); posStart.X = pt.X; posStart.Y = pt.Y; } }// Drag_Image |
画像を拡大表示するときのスムージングモード設定は、SetInterpolationMode で行う。 InterpolationModeNearestNeighbor に設定した場合は、PixelOffsetModeHalf に設定すると上手く表示される。 g.SetInterpolationMode(InterpolationModeNearestNeighbor); g.SetPixelOffsetMode(PixelOffsetModeHalf); 以下は画像を縦横5倍表示にしたサンプル。 |
// 画像の描画 void Draw_Image(HDC hDC, int width, int height) { // クライアント領域サイズの作業用ビットマップを作成 Bitmap bmpCp(width, height, PixelFormat32bppARGB); // 作業用ビットマップのグラフィックオブジェクトを作成 Graphics gBmp(&bmpCp); // 作業用ビットマップのクリッピング Rect rcBmp(0, 0, width, height); gBmp.SetClip(rcBmp); // 背景を白色でクリア gBmp.Clear(Color(255,255,255,255)); // 描画モード設定 gBmp.SetPixelOffsetMode(PixelOffsetModeHalf); gBmp.SetInterpolationMode(InterpolationModeNearestNeighbor); // 文字描画用ビットマップを作成 Bitmap bmpText(300, 300, PixelFormat32bppARGB); // 文字描画用ビットマップのグラフィックオブジェクトを作成 Graphics gBmpText(&bmpText); // 文字列表示 Font fnt(L"Times New Roman", 12); SolidBrush brushMes(Color(255,0,0,0)); WCHAR strMes[] = L"▲◎"; gBmpText.DrawString(strMes, wcslen(strMes), &fnt, PointF(0, 0), &brushMes); // 文字描画用ビットマップを作業用ビットマップへ描画(拡大率:縦横5倍) gBmp.DrawImage(&bmpText, 0, 0, bmpText.GetWidth() * 5, bmpText.GetHeight() * 5); // クリッピング解除 gBmp.ResetClip(); // デバイスコンテキストのグラフィックオブジェクトを作成 Graphics g(hDC); // 作業用ビットマップをデバイスコンテキストへ描画 g.DrawImage(&bmpCp, 0, 0, bmpCp.GetWidth(), bmpCp.GetHeight()); }// Draw_Image |
|
|