第1回 アイコン
BTMemoでは、ファイルのリンクにアイコンを表示しています。
ここでは、アイコンの取得・描画・印刷の仕方をお伝えします。
(1)アイコンの取得
BTMemoでは、SHGetFileInfoというAPIを使用してアイコンを取得しています。
このAPIは、拡張子に関連付けされているアイコンを取得してくれます。
ファイル名を指定すると、その拡張子に関連付けられている情報(アイコン等)を取り出してくれる便利なAPIです。
コード例を以下に示します。
// ファイル(拡張子)に関連付けられている「小さいアイコン」を取得します HICON GetFileIcon(char *pszPathName) { SHFILEINFO
shfi; ::SHGetFileInfo(
pszPathName, 0, &shfi, sizeof(SHFILEINFO),SHGFI_ICON | SHGFI_SMALLICON ); return
shfi.hIcon; } |
(2)アイコンの描画
アイコンの描画を行うためには、通常は DrawIcon や DrawIconEx といったAPIを使用します。
こんな感じです。
… HDC
hDC; //
デバイスコンテキストハンドラ int
x, y; //
アイコンを描画する位置 int
cx, cy; //
アイコンの大きさ char
szPathName[_MAX_PATH]; //
対象となるファイルのパス名 … HICON
hIcon = GetFileIcon(szPathName); //
アイコンを取得。(1)を参照 if
(hIcon != NULL) { ::DrawIconEx(hDC,
x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL); //
アイコンを描画 ::DestroyIcon(hIcon); //
使い終わったアイコンは忘れずに削除しましょう! } … |
でも、BTMemoでは、上記の方法は使用していません。理由は(3)を参照
(3)アイコンの印刷
Windowsでは、画面に描画するのもプリンタに印刷するのも基本的には同じです。画面のデバイスコンテキストに対して描画APIを実行すれば画面表示できますし、プリンタのデバイスコンテキストに対して描画APIを実行すれば印刷できます。(出力先デバイスの解像度が違ったり、印刷の場合は前後に特殊な処理が必要とはなりますが、ここでは無視します)
したがってアイコンを印刷するのにも、(2)のAPIが使用できると思っていたのですが、残念ながらうまくいきませんでした。(何種類かのプリンタで試してみましたが全てだめだったので、プリンタドライバなどの問題ではなく、APIのバグではないかと考えています。)
あれこれ試してみた結果、以下のような関数を作成し、(2)のDrawIconEx の代わりに使用しています。
// アイコンを描画する void MyDrawIcon(HDC hdc, int xLeft, int yTop, HICON hIcon,
int cxWidth, int cyWidth, COLORREF colBg) { //
アイコンからカラービットマップとマスクビットマップを取得 ICONINFO
ii; GetIconInfo(hIcon,
&ii); //
作業用のデバイスコンテキストを2つ作成 HDC
dcImage = ::CreateCompatibleDC(NULL); HDC
dcTrans = ::CreateCompatibleDC(NULL); //
アイコンと同じサイズのビットマップを作成し、指定背景色で塗りつぶす BITMAP
bmap; int
nBit = GetObject(ii.hbmColor, sizeof(bmap), &bmap); HBITMAP
hBmp = CreateCompatibleBitmap(hdc, bmap.bmWidth, bmap.bmHeight); HBITMAP
hOldBitmapTrans = (HBITMAP)::SelectObject(dcTrans, hBmp); HBRUSH
br = CreateSolidBrush(colBg); RECT
rc; rc.left
= 0; rc.top = 0; rc.right = bmap.bmWidth; rc.bottom = bmap.bmHeight; FillRect(dcTrans,
&rc, br); DeleteObject(br); //
マスクビットマップを登録し、作成先へ AND で描画 HBITMAP
hOldBitmapImage = (HBITMAP)::SelectObject(dcImage, ii.hbmMask); BitBlt(dcTrans,
0, 0, bmap.bmWidth, bmap.bmHeight, dcImage, 0, 0, SRCAND); //
カラービットマップを登録し、作成先へ OR で描画 ::SelectObject(dcImage,
ii.hbmColor); BitBlt(dcTrans,
0, 0, bmap.bmWidth, bmap.bmHeight, dcImage, 0, 0, SRCPAINT); //
出来上がったビットマップを目的のDCへ描画 StretchBlt(hdc,
xLeft, yTop, cxWidth, cyWidth, dcTrans, 0, 0, bmap.bmWidth, bmap.bmHeight,
SRCCOPY); //
元のビットマップをDCへ戻す SelectObject(dcImage,
hOldBitmapImage); SelectObject(dcTrans,
hOldBitmapTrans); //
作成したGDIオブジェクトの廃棄 DeleteObject(ii.hbmColor); DeleteObject(ii.hbmMask); DeleteObject(hBmp); DeleteDC(dcImage); DeleteDC(dcTrans); } |