山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他メモリ上に読み込まれたjpgファイルのイメージをGDI+でウィンドウに表示する標準的なソース(32/64bit)
概要
EXEファイルと同一フォルダーにあるimage.jpgファイルをfreadでメモリ上に読み込んだJpegファイルのイメージをメモリストリームに変換しGDI+で描画するプログラムです。
使用例としては、WMAファイルなどJpegファイルのイメージがそのままファイルに取り込まれている場合、そのイメージをメモリに取り込めば表示が可能となります。
テスト環境
コンパイラ
Visual C++ 2008/2013 Express 32/64bit マルチバイト/UNICODE実行環境
Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)Windows 7 Enterprise Service Pack 1 64bit
動作例
プログラムソースの概要
jpgviewmem.cpp
_tWinMain
GdiplusStartupによりGDI+の初期化をします。その後Windowを作成します。
Windowが閉じられたら、GdiplusShutdownにより終了処理を実行します。
WndProc
ウィンドウの初期化時にWndProc関数にWM_CREATEメッセージが発生するので、image.jpgをfopenで開き、ファイルサイズを調べサイズをszに保存します。ファイルサイズ分のメモリをGlobalAlloc APIで確保しハンドルを取得します。その後メモリをロックし先頭のアドレスを取得します。そのアドレスにfread関数でファイルを読み込みます。メモリをストリームとして扱うため、CreateStreamOnHGlobal を実行しメモリストリームのハンドルを得ます。画面の更新が必要な時にWM_PAINTメッセージが発生します。メッセージ発生時にストリームよりImageオブジェクトを作成し、それをDrawImageにより描画します。
ソースコード
jpgviewmem.cpp
// メモリ上に読み込まれたjpgファイルのイメージををGDI+でウィンドウに表示する標準的なソース
// Visual C++ 2008/2013 Express
#include <windows.h>
#include <gdiplus.h>
#include <tchar.h>
#include <iostream>
#pragma comment(lib,"gdiplus.lib")
// 表示するファイル名指定
//TCHAR* szFile=TEXT("D:\\docu\\documents\\data\\program\\vc2013\\jpgviewmem\\Debug\\image.JPG");
TCHAR* szFile=TEXT("image.jpg");
using namespace Gdiplus;
GdiplusStartupInput gdiSI;
ULONG_PTR gdiToken;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL InitApp(HINSTANCE, WNDPROC, TCHAR*);
BOOL InitInstance(HINSTANCE, TCHAR*, int);
HWND hWnd;
// 最初に呼び出される関数
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,TCHAR* lpsCmdLine, int nCmdShow){
MSG msg;
BOOL b;
TCHAR szClassName[] = TEXT("jpg_view");
GdiplusStartup(&gdiToken, &gdiSI, NULL);
if(!hPrevInst){
if(!InitApp(hCurInst,WndProc, szClassName)) // ウィンドウクラスの登録
return FALSE;
}
if (!InitInstance(hCurInst, szClassName, nCmdShow)) { // ウィンドウの作成
return FALSE;
}
// 見慣れないメッセージループだがエラーの場合-1が返る場合があるのでこのように記述
// MSDNを見てください。
while ((b=GetMessage(&msg, NULL, NULL, NULL))!=0 && b!=-1) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiToken);
return (int)msg.wParam;
}
// ウィンドウを作成/閉じる/移動等のメッセージにより起動される関数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
HDC hdc;
PAINTSTRUCT ps;
static BYTE* jpg_mem=0;
FILE* fp;
static unsigned long sz;
static HGLOBAL hBuf;
static IStream* pIStream;
switch (msg) {
case WM_CREATE:
if(_tfopen_s(&fp,szFile,_TEXT("rb"))){
MessageBox(0,_TEXT("ファイルが開けません"),_TEXT("エラー"),MB_OK);
PostQuitMessage(0);
}
fseek(fp,0,SEEK_END);
sz=ftell(fp);
fseek(fp,0,SEEK_SET);
hBuf=GlobalAlloc(GMEM_MOVEABLE,sz);
if(hBuf==0){
MessageBox(0,_TEXT("GlobalAlloc APIでのメモリの確保に失敗しました"),_TEXT("エラー"),MB_OK);
fclose(fp);
PostQuitMessage(0);
}
jpg_mem=(BYTE*)GlobalLock(hBuf);
if(jpg_mem==0){
MessageBox(0,_TEXT("GlobalLock APIでのメモリのロックに失敗しました"),_TEXT("エラー"),MB_OK);
fclose(fp);
PostQuitMessage(0);
}
fread(jpg_mem,sizeof(BYTE),sz,fp);
fclose(fp);
pIStream=0;
if(CreateStreamOnHGlobal(hBuf,FALSE,&pIStream)!=S_OK){
MessageBox(0,_TEXT("CreateStreamOnHGlobal APIでのメモリストリームの作成に失敗しました"),_TEXT("エラー"),MB_OK);
GlobalFree(hBuf);
PostQuitMessage(0);
}
break;
case WM_PAINT: { // ウィンドウの描画が必要な場合に呼び出される。
hdc = BeginPaint(hWnd, &ps);
Graphics MyGraphics(hdc);
Image myImage(pIStream);
MyGraphics.DrawImage(&myImage, 0, 0);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY: // ウィンドウを閉じる場合に呼び出される。
GlobalFree(hBuf);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0L;
}
// ウィンドウクラスの登録 1回しか呼ばれないのに関数化しているのは、ウィンドウを2回呼び出す場合に
// この関数を再利用できるからです。
BOOL InitApp(HINSTANCE hInst,WNDPROC WndProc,TCHAR* szClassName){
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = (TCHAR*)szClassName;
return (RegisterClass(&wc));
}
// ウィンドウの作成 1回しか呼ばれないのに関数化しているのは、ウィンドウを2回呼び出す場合に
// この関数を再利用できるからです。
BOOL InitInstance(HINSTANCE hInst, TCHAR* szClassName, int nCmdShow){
hWnd = CreateWindow(szClassName,
TEXT("GDI+ Sample"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
Copyright (C) 2012 山本ワールド All Rights Reserved.