« 2006年11月 | メイン | 2007年01月 »

前の10件 1  2  3  4  5  6  7  8  9  10

2006年12月 記事一覧

Windows Vistaのシェルアイコンを取得する

test82.gif
Windows Vistaではシェルで利用できるアイコンの数や種類が増えた。それらの新しいアイコンを取得するAPIとしてSHGetStockIconInfoが用意されている。

SHGetStockIconInfoはWindows Vista以降でしか利用できないため、ソースコード中でそのまま利用するとWindows XPなど従来のOSではプログラムが起動しなくなる。そのためここではLoadLibrary、GetProcAddressを利用して動的に呼び出すようにしている。

シェルアイコンを従来のアイコンとしてすべて取得、それらをデスクトップにDrawIconExで描画した。

#include "shellapi.h"


//
//	SHGetStockIconInfo API
//
//シェルアイコン取得用のAPI「SHGetStockIconInfo」をGetProcAddressしただけのもの。
//Windows Vista以前のOSの場合はE_FAILもしくはE_NOTIMPLが返る。
//Windows Vista以降の場合はAPIが実行された結果が返る。
//
//対応OS:Windows Vista以降
//
//
HRESULT		SafeSHGetStockIconInfo(SHSTOCKICONID siid,UINT uFlags,SHSTOCKICONINFO *psii)
{
	HMODULE	hDLL;
	HRESULT	hr;

	HRESULT	(CALLBACK* pfnSHGetStockIconInfo)(SHSTOCKICONID siid,UINT uFlags,SHSTOCKICONINFO *psii);

	hDLL = ::LoadLibrary(_T("shell32.dll"));
	if(hDLL == NULL)
		return	E_FAIL;

	(*(FARPROC*)&pfnSHGetStockIconInfo) = ::GetProcAddress(hDLL,"SHGetStockIconInfo");
	if(pfnSHGetStockIconInfo)
		hr = pfnSHGetStockIconInfo(siid,uFlags,psii);
	else
		hr = E_NOTIMPL;

	::FreeLibrary(hDLL);

	return	hr;
}





bool	Test(void)
{
	int		i;
	HRESULT	hr;
	HDC		hDC;

	hDC = ::GetDC(NULL);
	if(hDC == NULL)
		return	false;

	//MSDNライブラリではSIID_MAXだが、実際の定義はSIID_MAX_ICONS
	for(i = 0; i < (int)SIID_MAX_ICONS ; i++)
	{

		SHSTOCKICONINFO	sInfo;

		::ZeroMemory(&sInfo,sizeof(SHSTOCKICONINFO));
		sInfo.cbSize = sizeof(SHSTOCKICONINFO);
		hr = SafeSHGetStockIconInfo((SHSTOCKICONID)i,SHGSI_ICON,&sInfo);
		if(FAILED(hr))
			continue;

		::DrawIconEx(hDC,200 + (i%16)*35,100 + (i/16)*35, sInfo.hIcon, 0, 0, 0, NULL, DI_IMAGE | DI_COMPAT | DI_DEFAULTSIZE);
	}

	::ReleaseDC(NULL,hDC);

	return	true;
}

プロジェクトファイルをダウンロード

Virtual PC 2004はWindows Vistaに対応していない?

vista.gif
結論を先に書くと、Virtual PC 2004(SP1含む)をWindows Vistaにインストールすることも、仮想マシンとしてWindows Vistaをインストールすることもできないことはない。つまりホスト・ゲストともにWindows Vistaが(で)動く。そのためWindows Vista上でWindows Vistaを利用すること(ホスト・ゲストともにWindows Vista)もできる(図はWindows Vista Ultimate上のVirtual PC 2004 SP1にWindows Vista Home Premiumをインストールしているところ)。

しかし(少なくとも私の環境では)動作がおかしい。

まず、Windows Vistaで動作するPC上でVirtual PC 2004を利用する場合(ホストがWindows Vista)の場合は、Virtual PC 2004を起動すると強制的にAeroがオフ?になる。その状態でも利用できないことはない。しかし仮想マシンが起動しないこともある。そのようなときは一度Virtual PC 2004(仮想マシンではなくソフト側)を再起動する必要がある。

また、Virtual PC 2004にWindows Vistaをインストールする場合(ゲストがWindows Vistaの場合)は、「バーチャルマシン追加機能」がきちんと動作しない。そのため新しいバージョンのVirtual PCやVirtual Serverに添付されているバーチャルマシン追加機能を利用することになる。
Windows Vista Beta 2までに対応している「Virtual Server 2005 R2 SP1 Beta」用の追加機能はMicrosoft Connectから無料でダウンロードできる。ファイル名は「VistaBeta2Additions.msi」。

正式?にWindows Vistaに対応している「Virtual PC 2007 Beta」用のバーチャルマシン追加機能もMicrosoft Connectから無料でダウンロードできる。しかしVirtual PC 2007 Betaをインストールしないとバーチャルマシン追加機能は基本的に取得できない。


結局のところ、現状でホストがWindows Vistaの場合は再起動の必要が多く使い勝手が悪く、ゲストがWindows Vistaの場合はMicrosoft Connectから追加機能をダウンロードする必要がある。

そのためWindows VistaをVirtual PCで使うのなら、Virtual PC 2004は避けてVirtual PC 2007(Beta)を利用したほうがいい。ちなみに2007年1月にVirtual PC 2007正式版の無料ダウンロードが開始される予定だ。

2006年12月20日

第1回 プロジェクトを作成する

■はじめに
ここでは画像を表示するためのプログラムの開発を通じてVisual Studio 2005の使い方を紹介する。
本来であればプログラムの完成形を明確に決めてから作業すべきだ。しかしここでは行き当たりばったり私が思いついた機能や処理を実装ながら作業を進める。

作業環境としては
・Visual Studio 2005 Professional以上
・Visual Studio 2005 Service Pack 1
・Windows SDK
・WTL 8.0(日本語版)
を前提としている。


ImageViewer01_01.gif
最初にプロジェクトを作成する。Visual Studio 2005を起動する。そして「ファイル」メニューの「新規作成」から「プロジェクト」を選択する。


ImageViewer01_02.gif
すると「新しいプロジェクト」ウインドウが開く。ここで左側のプロジェクトの種類から「WTL」を選択し、テンプレートとして「ATL/WTLアプリケーションウイザード」を選択する。そしてプロジェクト名を指定する。ここでは「ImageViewer」とした。

もしも「WTL」や「ATL/WTLアプリケーションウイザード」が見当たらない場合は、WTL8.0日本語版アプリケーションウイザードをインストールする。


ImageViewer01_03.gif
ATL/WTLアプリケーションウイザードが開いた。ここでさまざまなオプションを指定可能だ。今回はデフォルトのまま利用するため、そのまま「完了」ボタンを押す。


ImageViewer01_04.gif
これでプロジェクトが作成され、基本的なソースコードが自動生成された。
自動的に生成されるのはhファイルが5ファイル、cppファイルが2ファイル、アイコンとツールバー用画像とリソースファイルになる。


ImageViewer01_05.gif
まだ何もソースコードに変更を加えていないが、まずは実行してみよう。プログラムを実行する前にはビルドする必要がある。「ビルド」メニューから「ImageViewerのビルド」を選択する。


ImageViewer01_06.gif
するとコンパイル、リンクと自動的に処理され、ソースコードから実行ファイルが生成される。
ビルドが正常に終わると画面下部の「出力」ウインドウに「ビルド: 1 正常終了、 0 失敗、 0 更新、 0 スキップ」のように表示される。


ImageViewer01_07.gif
ビルドが正常に終わったことを確認したら実行する。実行するには「デバッグ」メニューから「デバッグ開始」を選択する。


ImageViewer01_08.gif
これで自動生成したプログラムを実行できた。メニューバーとツールバー、ステータスバーを備えたウインドウになる。
今回は画像表示に関する処理を何もしていない。次回はこのウインドウの白背景部分に画像を表示できるようにしよう。

プロジェクトファイルをダウンロード

第2回 画像を表示する

ImageViewer02_01.gif
今回はいきなり画像(jpegファイル)をウインドウに表示する処理を作る。
Visual Studio 2005の左側にある「ソリューションエクスプローラ」にある「ImageViewerView.h」をダブルクリックして開く。cppファイルではなく、ヘッダーファイルであることに注意。


ImageViewer02_02.gif
もしもソリューションエクスプローラが見当たらない場合は、「表示」メニューから「ソリューションエクスプローラ」を選択すればいい。


ImageViewer02_03.gif
ImageViewerView.hが開いた。今まで変更を加えていないので、ATL/WTLアプリケーションウイザードが自動生成したままになっている。


ImageViewer02_04.gif
ここで、まずはファイルの先頭部分に3行追加する。ここでは画像の表示に「GDI+」と呼ばれるコンポーネントを利用する。これはそのコンポーネントを使うための定義になる。
GDI+を利用するにはgdiplus.hとgdiplus.libが必要なため、そのインクルードおよびリンク設定。「using namespace Gdiplus;」は名前空間の設定用だ。

今回は「とりあえず画像を表示する」ということに主眼を置いている。そのためこの定義は次回以降ほかの場所に移動することになる。
#include	"gdiplus.h"
#pragma	comment(lib,"Gdiplus.lib")
using namespace Gdiplus;


ImageViewer02_05.gif
次に赤枠で囲んだOnPaint関数の中に画像の読み込みおよび表示処理を追加する。ここでは「test.jpg」という画像ファイルを読み込み、ウインドウ内に元のサイズで表示している。

具体的な処理内容については次回以降に行うが、この部分の処理は本来やってはいけない使い方をしている。まずGDI+の解放処理はコメントアウトされているため実行されない。さらにOnPaint()は描画毎に呼ばれる関数のため、描画毎にGDI+の初期化や画像ファイルの読み込みを行っていて効率が悪い。そのためこの処理も今後大幅に変更することになる。
	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		CPaintDC dc(m_hWnd);

		//GDI+初期化
		ULONG_PTR	_nToken;
		GdiplusStartupInput _sGdiplusStartupInput;
		GdiplusStartup(&_nToken,&_sGdiplusStartupInput,NULL);

		//画像読み込み
		Bitmap*		pImage;
		Graphics	cGraphics(dc.m_hDC);

		pImage = Bitmap::FromFile(L"test.jpg",TRUE);

		//画像表示
		cGraphics.DrawImage(pImage,(REAL)0,(REAL)0,(REAL)pImage->GetWidth(),(REAL)pImage->GetHeight());

		//画像開放
		delete	pImage;

		//GDI+開放処理
//		GdiplusShutdown(_nToken);
		return 0;
	}


ImageViewer02_06.gif
ソースコードに必要な変更を施したら実行してみる。まずは「ビルド」メニューの「ImageViewerのビルド」からビルドする。


ImageViewer02_07.gif
画面下部の「出力」ウインドウをチェックしてビルドが正常に終了したことを確認する。もしも失敗した場合はソースコードの変更部分を確認しなおす。


ImageViewer02_08.gif
ビルドが正常に終了したら実行する。「デバッグ」メニューにある「デバッグ開始」を選択する。


ImageViewer02_09.gif
これでプログラムが実行され、画像が表示されたウインドウが開いた。ここで読み込まれる画像ファイルはプロジェクトフォルダに保存された「test.jpg」になる。

次回はウインドウサイズに応じて画像を拡大・縮小表示する処理を追加しよう。


プロジェクトファイルをダウンロード

2006年12月21日

第3回 ウインドウいっぱいに画像を表示する

ImageViewer03_01.gif
保存したプロジェクトを開くには、slnファイルをダブルクリックする。プロジェクト名(ソリューション名)がImageViewerの場合は「ImageViewer.sln」となる。

Visual Studio 2005では複数のプロジェクトからなるアプリケーションの作成にも対応する。
例えば"画像表示プログラム"と"インストーラー"からなる場合は、画像表示プログラム用のプロジェクトとインストーラー用のプロジェクトの2つのプロジェクトからなるソリューションということになる。
というものの簡単な開発であれば1つのプロジェクトしか扱わないことも多い。そのためソリューション=プロジェクトと考えていても差支えはない。


ImageViewer03_02.gif
slnファイルをダブルクリックするとプロジェクトが開いた。


ImageViewer03_03.gif
ソースコードを開くため、「表示」メニューの「ソリューションエクスプローラ」を選択する。


ImageViewer03_04.gif
そして左側のソリューションエクスプローラから「ImageViewerView.h」を探してダブルクリックする。すると前回までに作成したソースコードが開く。ここで右の赤枠で囲まれた画像表示用の処理を変更する。

ImageViewer03_05.gif このように変更する。 ここでRECT型は四角い領域を示す型で、GetClientRectによってクライアント領域の位置と大きさを取得している。クライアント領域というのはこのプログラムで言うと画像が表示されている部分に当たる。 そして取得したクライアント領域の横幅(右位置から左位置の差)と縦幅(下位置から上位置の差)の大きさで画像を表示している。
		//画像表示
		RECT	rect;
		GetClientRect(&rect);
		cGraphics.DrawImage(pImage,(REAL)0,(REAL)0,(REAL)(rect.right - rect.left),(REAL)(rect.bottom - rect.top));


ImageViewer03_06.gif
ソースコードの変更が済んだらビルドする。「ビルド」メニューの「ImageViewerのビルド」を選択する。


ImageViewer03_07.gif
ビルドが正常に終わったのを確認したら実行する。「デバッグ」メニューの「デバッグ開始」を選択する。


ImageViewer03_08.gif
すると画像がウインドウいっぱいに表示された。


ImageViewer03_09.gif
ウインドウのサイズを変更するとそれに従って画像の表示も変わる。しかし縦横比に関係なく画像を表示しているため、横長や縦長な表示になってしまうこともある。また、描画毎に画像ファイルを読み込んでいるためウインドウサイズを変更すると画像表示がちらつく。
次回は画像表示処理内容を見ながら表示毎に画像を読み込まないようにする。


プロジェクトファイルをダウンロード

第4回 GDI+をきちんと使う

これまでの作業ではATL/WTLアプリケーションウイザードの標準設定で「ImageViewer」というプロジェクトを作成、自動生成されたソースコードのうち「ImageViewerView.h」を書き換えて以下のようにした。

// ImageViewerView.h : CImageViewerView クラスのインターフェイス
//
/////////////////////////////////////////////////////////////////////////////

#pragma once

#include	"gdiplus.h"
#pragma	comment(lib,"Gdiplus.lib")
using namespace Gdiplus;

class CImageViewerView : public CWindowImpl<CImageViewerView>
{
public:
	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		pMsg;
		return FALSE;
	}

	BEGIN_MSG_MAP(CImageViewerView)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
	END_MSG_MAP()

// ハンドラーのプロトタイプ (引数が必要な場合はコメントを外してください):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		CPaintDC dc(m_hWnd);

		//GDI+初期化
		ULONG_PTR	_nToken;
		GdiplusStartupInput _sGdiplusStartupInput;
		GdiplusStartup(&_nToken,&_sGdiplusStartupInput,NULL);

		//画像読み込み
		Bitmap*		pImage;
		Graphics	cGraphics(dc.m_hDC);

		pImage = Bitmap::FromFile(L"test.jpg",TRUE);

		//画像表示
		RECT	rect;
		GetClientRect(&rect);
		cGraphics.DrawImage(pImage,(REAL)0,(REAL)0,(REAL)(rect.right - rect.left),(REAL)(rect.bottom - rect.top));

		//画像開放
		delete	pImage;

		//GDI+開放処理
//		GdiplusShutdown(_nToken);
		return 0;
	}
};


たったこれだけのソースコードで画像ファイルを読み込んで画面いっぱいに表示できた。しかし前にも述べたように、このソースコードは誤った使い方をしている部分が少なからずある。また描画するごとに画像ファイルを読み込んでいるため効率も悪い。ここではこれらの点を修正する。

まず先頭にある以下の3行。
#include	&quot;gdiplus.h&quot;
#pragma	comment(lib,&quot;Gdiplus.lib&quot;)
using namespace Gdiplus;

これは画像描画に用いるGDI+を利用するための宣言だ。これらはソースコード中のどこからも参照できるようにする。

ImageViewer04_01.gif
画面左側のソリューションエクスプローラにある「stdafx.h」をダブルクリックして開く。このヘッダーファイルはプロジェクト内で共通の宣言を置く場所だ。


ImageViewer04_02.gif
ここに先ほどの3行を移動する。

少し飛んでOnPaint内の以下の2箇所の部分。
		//GDI+初期化
		ULONG_PTR	_nToken;
		GdiplusStartupInput _sGdiplusStartupInput;
		GdiplusStartup(&_nToken,&_sGdiplusStartupInput,NULL);
		//GDI+開放処理
//		GdiplusShutdown(_nToken);

これらはそれぞれGDI+を利用するための初期化と終了処理だ。このソースコードでは描画毎に初期化を行い、終了処理は行っていない。 本来描画ごとに行うべきではない。GDI+の初期化と終了処理はアプリケーションの起動時と終了時に1回ずつ行えばいい。そのためこれらの処理も移動する。

ImageViewer04_03.gif
画面左側のソリューションエクスプローラにある「ImageViewer.cpp」をダブルクリックして開く。このcppファイルはアプリケーションの起動処理が書かれている場所だ。

ImageViewer04_04.gif
ImageViewer.cpp内の_tWinMain()を見ると、「int nRet = Run(lpstrCmdLine, nCmdShow);」という部分がある。このRun()の中でアプリケーションのウインドウが生成・表示されている。そのためこの部分を挟んで初期化と終了処理を行う。

ImageViewer04_05.gif
このとき今まで実行しないようにコメントアウトしていた終了処理のコメントを外しておく。
具体的には以下のようにする。

	//GDI+初期化
	ULONG_PTR	_nToken;
	GdiplusStartupInput _sGdiplusStartupInput;
	GdiplusStartup(&_nToken,&_sGdiplusStartupInput,NULL);

	int nRet = Run(lpstrCmdLine, nCmdShow);

	//GDI+開放処理
	GdiplusShutdown(_nToken);

場所を戻って「ImageViewerView.h」内の以下の項目。
	BEGIN_MSG_MAP(CImageViewerView)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
	END_MSG_MAP()

// ハンドラーのプロトタイプ (引数が必要な場合はコメントを外してください):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)


ImageViewer04_06.gif
この部分はメッセージマップと呼ばれる。ここではWM_PAINTというメッセージの処理が定義されている。
WM_PAINTは描画(ペイント)用のメッセージで、ウインドウの表示内容を描画しなおさなければならないときに送られるメッセージだ。そのWM_PAINTメッセージをOnPaint()という関数で処理することが定義されている。

ImageViewer04_07.gif
このメッセージマップの部分にウインドウが生成されるときと破壊されるときのメッセージ処理を定義する。
ウインドウが生成するときに送られるメッセージはWM_CREATE、破壊するときはWM_DESTROYになる。それぞれOnCreate()とOnDestroy()で処理する。

	BEGIN_MSG_MAP(CImageViewerView)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()

// ハンドラーのプロトタイプ (引数が必要な場合はコメントを外してください):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	//ウインドウ生成時処理
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return	0;
	}

	//ウインドウ破壊時処理
	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return	0;
	}


ImageViewer04_08.gif
ウインドウ生成時と破壊時処理用の関数を用意しただけでは意味がない。次にウインドウの生成時に画像を読み込み、破壊時に画像を開放する処理を入れる。これによりOnPaint()内もだいぶスマートになった。

	Bitmap*		pImage;

	//ウインドウ生成時処理
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		//画像読み込み
		pImage = Bitmap::FromFile(L"test.jpg",TRUE);

		return	0;
	}

	//ウインドウ破壊時処理
	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		//画像開放
		delete	pImage;

		return	0;
	}

	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		CPaintDC dc(m_hWnd);

		Graphics	cGraphics(dc.m_hDC);

		//画像表示
		RECT	rect;
		GetClientRect(&rect);
		cGraphics.DrawImage(pImage,(REAL)0,(REAL)0,(REAL)(rect.right - rect.left),(REAL)(rect.bottom - rect.top));

		return 0;
	}


ImageViewer04_09.gif
これでソースコードの修正が済んだ。ビルドを行い、デバッグする。


ImageViewer04_10.gif
ソースコードではGDI+を起動時、画像読み込みをウインドウ生成時、GDI+終了処理を最後に行うようにし、処理効率が上がった。しかしウインドウサイズを変更すると...まだちらついてしまう。
次回はこの"ちらつき"を解消する。

プロジェクトファイルをダウンロード

2006年12月22日

第5回 ウインドウの"ちらつき"をなくす


ImageViewer05_01.gif
前回までに作成したソースコードでは画像は表示される。しかしウインドウサイズを変えると画像がちらついてしまった。

ImageViewer05_02.gif "ちらつき"はWM_PAINTが送られてくる前、つまり画像を描画する前にウインドウの背景が白く塗られていることによる。そのためウインドウの背景を塗るときに送られてくるメッセージを無効化してしまえばいい。 ウインドウの背景を塗るときのメッセージはWM_ERASEBKGNDだ。これをメッセージマップに追加して何もしない処理をする。
	BEGIN_MSG_MAP(CImageViewerView)
		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()
	//背景描画(何もしない)
	LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return	0;
	}

ImageViewer05_03.gif
これで実行するとウインドウサイズを変えてもちらつきなくスムースに表示できるようになった。

今回のWM_ERASEBKGNDが使われないようにする、という方法は画像表示ソフトに限らず様々な場面で利用されている。


ImageViewer05_04.gif
ちなみに画像を描画するためのOnPaint()が動かないようにすると...背景が描画されないため、ウインドウサイズを変えると枠の部分が残って変な描画内容になる。


プロジェクトファイルをダウンロード

MicrosoftのWindows Vista用開発環境が出そろいました

今日、ようやく「Visual Studio 2005 Service Pack 1 Update for Windows Vista(日本語版)」が公開されました(BETAですが)。

これによりようやくWindows Vista用の開発環境が出そろったことになります。インストール順序とダウンロード先は以下です。

1.Windows Vista

2.Visual Studio 2005 Professional

3.MSDNライブラリ(2006年8月版)

4.Windows SDK for Windows Vista

5.Visual Studio 2005 Service Pack 1

6.Vista Support Update(日本語BETA)

7.Visual Studio 2005 Extensions for WCF, WPF(2006年11月CTP版)

8.Visual Studio 2005 Extensions for WF

2006年12月23日

第6回 画像の縦横比を保ったまま拡大縮小する

ImageViewer06_01.gif
前回までにウインドウにJPEG画像を表示する処理を作成した。しかし表示される画像は縦横比に関係なく拡大縮小されてしまっている。そのため今回は縦横比を保ったまま拡大縮小させる。

ImageViewerView.hを開く。ここで赤枠内を修正する。この部分は画像表示をするクライアント領域の取得と画像の描画をしている。
DraiImage()は第一引数にImage、それ以降の4引数はそれぞれ描画開始XY位置と描画サイズを示している。

ImageViewer06_02.gif 赤枠のように変更した。かなり長いソースコードになってしまった。しかし処理内容自体は非常に簡単だ。画像とウインドウの縦横比を比較して、画像の方が横長なら画像の縦方向に余白を作る、などのようにしている。
		//画像表示サイズ計算
		RECT	rect;
		UINT	nImageWidth;
		UINT	nImageHeight;
		UINT	nWindowWidth;
		UINT	nWindowHeight;
		UINT	nWidth;
		UINT	nHeight;

		//画像サイズ
		nImageWidth = pImage->GetWidth();
		nImageHeight = pImage->GetHeight();

		//クライアント領域サイズ
		GetClientRect(&rect);
		nWindowWidth = rect.right - rect.left;
		nWindowHeight = rect.bottom - rect.top;

		if((double)nImageWidth / nImageHeight < (double)nWindowWidth / nWindowHeight)
		{
			//クライアント領域の方が横長なら、縦方向はいっぱいに表示
			nHeight = nWindowHeight;
			nWidth = nWindowHeight * nImageWidth / nImageHeight;
		}
		else
		{
			//画像の方が横長なら、横方向はいっぱいに表示
			nWidth = nWindowWidth;
			nHeight = nWindowWidth * nImageHeight / nImageWidth;
		}

		//画像表示
		cGraphics.DrawImage(pImage,(REAL)0,(REAL)0,(REAL)nWidth,(REAL)nHeight);

ImageViewer06_03.gif
実際に実行してみると縦横比が崩れずに拡大縮小できるようになった。

プロジェクトファイルをダウンロード

第7回 画像をウインドウの中央に配置する

ImageViewer07_01.gif
前回は縦横比を保ったまま拡大縮小できるようにした。画像表示ソフトの多くはウインドウの中央に画像を表示して左右や上下に均等に余白が作られる。しかし画像の右側や下側に余白が作られる形式での表示になっている。
今回は一般的な画像表示ソフトと同様にウインドウの中央に画像を表示させる。

ImageViewer07_02.gif ImageViewerView.hに追加および変更を施した。 DrawImageに渡す第二、第三引数を利用してウインドウの中央に画像が表示されるようにしている。
		UINT	nX;
		UINT	nY;
			//描画位置計算
			nX = (nWindowWidth - nWidth) / 2;
			nY = 0;
			//描画位置計算
			nX = 0;
			nY = (nWindowHeight- nHeight) / 2;
		//画像表示
		cGraphics.DrawImage(pImage,(REAL)nX,(REAL)nY,(REAL)nWidth,(REAL)nHeight);

ImageViewer07_03.gif
実行するときちんと画像がウインドウの中央に表示され、左右均等に余白が割り当てられた。

プロジェクトファイルをダウンロード

前の10件 1  2  3  4  5  6  7  8  9  10





usefullcode@gmail.com

About 2006年12月

2006年12月にブログ「UsefullCode.net」に投稿されたすべてのエントリーです。

前の記事は2006年11月です。

次の記事は2007年01月です。

他にも多くのエントリーがあります。メインページ記事一覧も見てください。