デバイスコンテキスト上で描画した画像を.icoファイルに出力

C++

1typedef struct _ICONDIR2 {3 WORD wReserved; // 予約 常に04 WORD wResourceType; // リソースタイプ 1:アイコン 2:カーソル5 WORD wResourceCount; // アイコンの数6 } ICONDIR;7 8 typedef struct _ICONDIRENTRY9 {10 BYTE bWidth; // アイコンの幅11 BYTE bHeight; // アイコンの高さ12 BYTE bColorCount; // カラー数13 BYTE bReserved; // 予約14 WORD wColorPlanes; // カラープレーン数(カーソル時、Xホットスポット)15 WORD wPixcelBit; // ピクセルのビット深度(カーソル時、Yホットスポット)16 DWORD dwIconFileSize; // アイコンファイルのサイズ17 DWORD dwIconOffset; // ファイルの先頭からピクセルデータまでのオフセット18 } ICONDIRENTRY;19 20void CTalkListDlg::ChangeIconUnreadState()21{22 int nUnreadCount = CountUnreadMessage(); // 未読コメント数を取得23 24 if ( 0 < nUnreadCount ) { // 未読コメントがある場合25 // 未読件数付きのアイコンを作成26 MakeUnreadCountIcon( nUnreadCount );27 28 // タスクバーアイコン変更29 theApp.m_hTaskBarIcon = (HICON)LoadImage( AfxGetApp()->m_hInstance, _T( "アイコンファイルのパス" ), IMAGE_ICON, 0, 0, LR_LOADFROMFILE );30 HICON hIcon = (HICON)LoadImage( AfxGetApp()->m_hInstance, MAKEINTRESOURCE( アイコンファイルのリソースID ), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );31 SetIcon( hIcon, FALSE );32 SetIcon( theApp.m_hTaskBarIcon, TRUE );33 }34}35 36//// 未読件数を表示した画像を作成37void CTalkListDlg::MakeUnreadCountIcon( int nUnreadCount )38{39 HICON hIcon = (HICON)LoadImage( AfxGetApp( )->m_hInstance, MAKEINTRESOURCE( アイコンファイルのリーソースID ), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR );40 41 CImage ciLoadImage;42 CImage ciBackImage;43 CDC *pDC = GetDC();44   CString strIconPath;45 strIconPath.Format( _T( "下地となるアイコンファイルのパス" ) );46 ciLoadImage.Load( strIconPath );47 ciBackImage.Create( 32, 32, 24, 0 );48 HDC hDC = ciBackImage.GetDC( );49 DrawIconEx( hDC, 0, 0, hIcon, 32, 32, 0, NULL, DI_NORMAL );50 ciLoadImage.Draw( hDC, 0, 0, 32, 32 );51 ciLoadImage.Destroy();52 53 //HDC hDC = ::GetDC( m_hWnd );54 //HDC hMemDC = CreateCompatibleDC( hDC ); // メモリデバイスコンテキスト作成55 //HBITMAP hBmp = CreateCompatibleBitmap( hMemDC, 32, 32 ); // サイズ指定してビットマップ作成56 //::ReleaseDC( m_hWnd, hDC );57 //SelectObject( hMemDC, hBmp );58 //DrawIconEx( hMemDC, 0, 0, hIcon, 32, 32, 0, NULL, DI_NORMAL | DI_DEFAULTSIZE );59 60 // 赤い円を描画61 int nCircleLeft = 13;62 int nCircleTop = 13;63 int nCircleRight = 32;64 int nCircleBottom = 32;65 HPEN hOldPen = (HPEN)SelectObject( hDC, GetStockObject( NULL_PEN ) );66 HBRUSH hNewBrush = (HBRUSH)CreateSolidBrush( RGB( 255, 0, 0 ) );67 HBRUSH hOldBrush = (HBRUSH)SelectObject( hDC, hNewBrush );68 Ellipse( hDC, nCircleLeft, nCircleTop, nCircleRight, nCircleBottom );69 SelectObject( hDC, hOldPen );70 SelectObject( hDC, hOldBrush );71 DeleteObject( hNewBrush );72 //73 74 // 未読件数を描画75 CString strUnreadCount;76 HFONT hNewFont;77 if ( 99 < nUnreadCount ) {78 strUnreadCount = _T( "99+" );79 hNewFont = CreateFont( 16, 7, 0, 0, FW_MEDIUM, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T( "メイリオ" ) );80 }81 else if ( 9 < nUnreadCount ) {82 strUnreadCount.Format( _T( "%d" ), nUnreadCount );83 hNewFont = CreateFont( 16, 9, 0, 0, FW_MEDIUM, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T( "メイリオ" ) );84 }85 else {86 strUnreadCount.Format( _T( "%d" ), nUnreadCount );87 hNewFont = CreateFont( 18, 11, 0, 0, FW_MEDIUM, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T( "メイリオ" ) );88 }89 HGDIOBJ hObj = SelectObject( hDC, hNewFont );90 91 int nDifference = 4;92 CRect rcText;93 rcText.left = nCircleLeft + nDifference;94 rcText.top = nCircleTop + nDifference;95 rcText.right = nCircleRight - nDifference;96 rcText.bottom = nCircleBottom - nDifference;97 SetTextColor( hDC, RGB( 255, 255, 255 ) );98 SetBkColor( hDC, RGB( 255, 0, 0 ) );99 DrawText( hDC, strUnreadCount, strUnreadCount.GetLength( ), rcText, DT_SINGLELINE | DT_CENTER | DT_VCENTER );100 DeleteObject( hNewFont );101 //102 103 CString strOutputFile = _T( "出力するアイコンファイルの保存先パス" );104 HBITMAP hBitmap = (HBITMAP)GetCurrentObject( hDC, OBJ_BITMAP );105 SaveIconFile( hBitmap, strOutputFile );106 107 //ciBackImage.Draw( *pDC, 0, 0, 32, 32 ); // 描画する画像の確認用108 ciBackImage.ReleaseDC();109 ciBackImage.Destroy();110 111 DeleteObject( hIcon );112 ::ReleaseDC( m_hWnd, hDC );113}114 115int sizebits( BITMAPINFO *lpbi )116{117 if ( 1 != lpbi->bmiHeader.biPlanes ) {118 return -1;119 }120 121 switch ( lpbi->bmiHeader.biBitCount ) {122 default:123 return -1;124 case 1:125 case 4:126 case 8:127 case 16:128 case 24:129 case 32:130 break;131 }132 int szbits = ( ( ( ( lpbi->bmiHeader.biWidth * lpbi->bmiHeader.biBitCount + 7 ) / 8 + 3 ) / 4 ) * 4 ) * ( lpbi->bmiHeader.biHeight );133 return szbits;134}135 136// Bitmapヘッダー作成、Bitmapファイル出力137void CTalkListDlg::SaveIconFile( HBITMAP hBmp, CString strFileName )138{139 ICONDIR icDirHeader = { 0 }; // アイコンファイルヘッダー    6byte140 ICONDIRENTRY icDirEntry = { 0 }; // アイコン情報 16byte141 BITMAPINFO *pBmpInfo; // ビットマップ情報 40byte142 143 BITMAP bmp = { 0 }; // ビットマップ構造体144 LONG imageSize;   // 画像のサイズ145 LONG pixcels; // 画素数146 LPBYTE bits; // 画像ビット147 HDC hDC, hMemDC;148 149 // BITMAP情報を取得する150 GetObject( hBmp, sizeof( bmp ), &bmp );151 hDC = ::GetDC( 0 );152 hMemDC = CreateCompatibleDC( hDC );153 ::ReleaseDC( 0, hDC );154 HBITMAP hBmpOld = (HBITMAP)SelectObject( hMemDC, hBmp );155 156 // ファイルサイズ計算157 imageSize = bmp.bmWidthBytes * bmp.bmHeight + sizeof( ICONDIR ) + sizeof( ICONDIRENTRY ) + sizeof( BITMAPINFOHEADER );158 switch ( bmp.bmBitsPixel ) {159 case 2:160 pixcels = 2;161 break;162 case 4:163 pixcels = 16;164 break;165 case 8:166 pixcels = 256;167 break;168 default:169 pixcels = 0;170 }171 imageSize += ( sizeof( RGBQUAD ) * pixcels );172 173 // ICONDIR出力174 ZeroMemory( &icDirHeader, sizeof( icDirHeader ) );175 icDirHeader.wReserved = 0;176 icDirHeader.wResourceType = 1;177 icDirHeader.wResourceCount = 1;178 179 // BITMAPINFOHEADER 出力180 pBmpInfo = new BITMAPINFO[sizeof( BITMAPINFOHEADER ) + sizeof( RGBQUAD ) * pixcels];181 ZeroMemory( pBmpInfo, sizeof( BITMAPINFOHEADER ) );182 pBmpInfo->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );183 pBmpInfo->bmiHeader.biWidth = bmp.bmWidth;184 pBmpInfo->bmiHeader.biHeight = bmp.bmHeight;185 pBmpInfo->bmiHeader.biPlanes = 1; // 1186 pBmpInfo->bmiHeader.biBitCount = bmp.bmBitsPixel;187 pBmpInfo->bmiHeader.biCompression = BI_RGB; // 非圧縮188 if ( 0 != pixcels ) {189 GetDIBColorTable( hMemDC, 0, pixcels, pBmpInfo->bmiColors ); // カラーDIB情報取得190 }191 192 // 画像データ取得193 bits = new BYTE[bmp.bmWidthBytes * bmp.bmHeight];194 GetDIBits( hMemDC, hBmp, 0, bmp.bmHeight, bits, pBmpInfo, DIB_RGB_COLORS );195 196 // ICONDIRENTRY出力197 char chWidth = bmp.bmWidth;198 char chHeight = bmp.bmHeight;199 200 icDirEntry.bWidth = chWidth;201 icDirEntry.bHeight = chHeight;202 icDirEntry.bColorCount = 1 << pBmpInfo->bmiHeader.biBitCount;203 icDirEntry.bReserved = 0;204 icDirEntry.wColorPlanes = pBmpInfo->bmiHeader.biPlanes;205 icDirEntry.wPixcelBit = pBmpInfo->bmiHeader.biBitCount;206 207 int palettesize = pBmpInfo->bmiHeader.biBitCount <= 8 ? ( 1 << pBmpInfo->bmiHeader.biBitCount ) : 0;208 icDirEntry.dwIconFileSize = palettesize + sizebits( pBmpInfo ) + sizebits( pBmpInfo ); // 対応するビットマップデータのバイト数209 icDirEntry.dwIconOffset = sizeof( ICONDIR ) + sizeof( ICONDIRENTRY ); // 22210 211 // バイナリファイル書き込み212 CString strErrorMsg;213 WriteIconBinary( strFileName, icDirHeader, icDirEntry, *pBmpInfo, bits, strErrorMsg );214 215 delete[] bits;216 delete[] pBmpInfo;217 SelectObject( hMemDC, hBmpOld );218 DeleteDC( hMemDC );219}

コメントを投稿

0 コメント