ビットマップのウィンドウ表示

ビットマップを読込みウィンドウに表示する例です。ウィンドウをビットマップのサイズに合わせ作成した後、ボタンを押すと、色が反転します。2回押すと元の色に戻ります。ファイルのドラッグ・実行ファイルへ画像を送る、等で画像が表示されます。なお、表示の際には自動的にウィンドウのサイズを変更するようになっています。

表示例
 

実行ファイルのダウンロード: winbmp.exe

コンパイルオプション:
 Gami[84]% gcc -o winbmp winbmp.cpp -lgdi32 -mwindows -e_mainCRTStartup

ビットマップのウィンドウ表示(winbmp.cpp)
//-----------------------------------------------------------------
// winbmp.cpp:
//     ビットマップの読込み/表示[色の反転]
//                 Last Update: <2005/01/11 15:38:36 A.Murakami>
//-----------------------------------------------------------------
#include <windows.h>
//-----------------------------------------------------------------
HINSTANCE hAppInst; HWND hAppWnd;
TCHAR iFile[MAX_PATH];
UINT iWidth,iHeight,iLength,biSize,iBCnt,bmpLoad;
LPBYTE lpBMP = NULL;
LPBITMAPINFOHEADER lpBInfo = NULL;
//-----------------------------------------------------------------
BOOL InitApp(HINSTANCE hInst, LPCSTR szClassName);
BOOL InitInstance(HINSTANCE hInst,LPCSTR szClassName,int nCmdShow);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void GetWinPos(HWND hWnd,UINT *x,UINT *y);
void rePaint();
UINT LoadBMP(LPCTSTR szFn,LPBYTE& lpBuf);
void LoadPalette(LPCTSTR szFn);
void revColor(void);
//-----------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hCurInst,HINSTANCE hPrevInst,
                   LPSTR lpsCmdLine,int nCmdShow)
{
    LPCTSTR szClassName = "winbmp"; // 初期化
    bmpLoad = FALSE; iWidth = 300; iHeight = 200;
    // 引数参照
    if(strlen(lpsCmdLine)){
        wsprintf(iFile,lpsCmdLine);
        LoadBMP(iFile,lpBMP);
    }
    // ウィンドウ・クラスの登録
    if(!hPrevInst){
        if(!InitApp(hCurInst,szClassName)) return 0;
        hAppInst = hCurInst;
    }
    // ウィンドウ作成
    if(!InitInstance(hCurInst,szClassName,nCmdShow)){
        return 0;
    }
    // メッセージループ
    MSG msg;
    while(GetMessage(&msg,NULL,0,0)){
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
//-----------------------------------------------------------------
// ウィンドウ・クラスの登録
//-----------------------------------------------------------------
BOOL InitApp(HINSTANCE hInst,LPCSTR szClassName)
{
    WNDCLASSEX wc;
    wc.cbSize        = sizeof(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.hIconSm       = LoadIcon(NULL,IDI_APPLICATION);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = NULL;   // メニュー名 
    wc.lpszClassName = (LPCSTR)szClassName;
    return (RegisterClassEx(&wc));
}
//-----------------------------------------------------------------
// ウィンドウの生成
//-----------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInst,LPCSTR szClassName,int nCmdShow)
{
    TCHAR lpStr[256];
    if(bmpLoad) wsprintf(lpStr,"%s %d*%d Pixel %dBit",
                         iFile,iWidth,iHeight,iBCnt);
    else wsprintf(lpStr,"BMP Viewer");
    hAppWnd = CreateWindow(szClassName,lpStr,   // タイトルバー
                           WS_OVERLAPPEDWINDOW, // ウィンドウ
                           CW_USEDEFAULT,       // X座標
                           CW_USEDEFAULT,       // Y座標
                           15+iWidth,           // 幅
                           65+iHeight,          // 高さ
                           NULL,                // 親ウィンドウのハンドル
                           NULL,                // メニューハンドル 
                           hInst,               // インスタンスハンドル
                           NULL);
    if(!hAppWnd) return FALSE;
    // ドラッグ&ドロップ受入 
    DragAcceptFiles(hAppWnd,TRUE);
    // ウィンドウの表示 
    ShowWindow(hAppWnd,nCmdShow);
    UpdateWindow(hAppWnd);
    return TRUE;
}
//-----------------------------------------------------------------
// メッセージ情報
//-----------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
    switch(iMsg){
    case WM_CHAR:
        if(wParam=='q') SendMessage(hwnd,WM_CLOSE,NULL,NULL);
        break;
    case WM_CREATE:
        // ボタン作成
        CreateWindow("Button","色反転",
                     WS_CHILD | WS_VISIBLE,5,5,80,25,hwnd,
                     (HMENU)0,hAppInst,NULL);
        break;
    case WM_COMMAND:
        revColor();
        rePaint();
        break;
    case WM_DROPFILES: // ファイルがドロップされた時の処理
        UINT wx,wy;
        HDROP hDrop;
        TCHAR szFn[256],lpStr[256];
        hDrop = (HDROP)wParam;
        DragQueryFile(hDrop,0,szFn,256);
        DragFinish(hDrop);
        if(!LoadBMP(szFn,lpBMP)){
            // ウィンドウ幅の変更
            GetWinPos(hwnd,&wx,&wy);
            MoveWindow(hwnd,wx,wy,15+iWidth,iHeight+65,TRUE);
            // タイトル
            wsprintf(lpStr,"%s %d*%d Pixel %dBit",szFn,iWidth,iHeight,iBCnt);
            SetWindowText(hwnd,lpStr);
            rePaint();
        }
        break;
    case WM_PAINT:
        if(bmpLoad){
            HDC hdc; PAINTSTRUCT ps;
            hdc = BeginPaint(hwnd,&ps);
            StretchDIBits(hdc,4,35,iWidth,iHeight,
                          0,0,iWidth,iHeight,lpBMP,(LPBITMAPINFO)lpBInfo,
                          DIB_RGB_COLORS,SRCCOPY);
            EndPaint(hwnd,&ps);
        }
        break;
    case WM_DESTROY:
        // メモリの解放
        if(lpBMP)   GlobalFree(lpBMP);
        if(lpBInfo) GlobalFree(lpBInfo);
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd,iMsg,wParam,lParam);
}

//-----------------------------------------------------------------
// ウィンドウ位置の取得
//-----------------------------------------------------------------
void GetWinPos(HWND hWnd,UINT *x,UINT *y)
{
    WINDOWPLACEMENT wndpl;
    GetWindowPlacement(hWnd,&wndpl);
    *x = wndpl.rcNormalPosition.left;
    *y = wndpl.rcNormalPosition.top;
    return;
}
//-----------------------------------------------------------------
// 描画部の再描画
//-----------------------------------------------------------------
void rePaint()
{
    RECT r;
    r.left = 4;  r.right  = 4+iWidth;
    r.top  = 35; r.bottom = 35+iHeight;
    InvalidateRect(hAppWnd,&r,FALSE);
}
//-----------------------------------------------------------------
// ビットマップの読込み
//-----------------------------------------------------------------
UINT LoadBMP(LPCTSTR szFn,LPBYTE& lpBuf)
{
    BITMAP bmp; HBITMAP hbmp = NULL;
    if(lpBMP)   GlobalFree(lpBMP);
    if(lpBInfo) GlobalFree(lpBInfo);
    // BMP画像の読込み
    hbmp = (HBITMAP)LoadImage(NULL,szFn,IMAGE_BITMAP,0,0,
                              LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    if(hbmp == NULL){
        MessageBox(NULL,"読込みに失敗しました",NULL,MB_OK);
        return 1;
    }
    GetObject(hbmp,sizeof(BITMAP),&bmp);
    // 画像サイズ
    iWidth  = bmp.bmWidth;
    iHeight = bmp.bmHeight;
    iBCnt   = bmp.bmBitsPixel;
    iLength = ((iWidth*iBCnt+31)&~0x1f)*bmp.bmPlanes/8;
    biSize  = iLength*iHeight;
    // BMPヘッダ
    if(iBCnt>=24){
        lpBInfo = (LPBITMAPINFOHEADER)GlobalAlloc(
            GPTR,sizeof(BITMAPINFOHEADER));
    } else {
        lpBInfo = (LPBITMAPINFOHEADER)GlobalAlloc(
            GPTR,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*(1<<iBCnt));
    }
    lpBInfo->biSize          = sizeof(BITMAPINFOHEADER);
    lpBInfo->biPlanes        = bmp.bmPlanes;
    lpBInfo->biCompression   = 0;
    lpBInfo->biXPelsPerMeter = 0;
    lpBInfo->biYPelsPerMeter = 0;
    lpBInfo->biClrUsed       = 0;
    lpBInfo->biClrImportant  = 0;
    lpBInfo->biBitCount      = iBCnt;
    lpBInfo->biWidth         = iWidth;
    lpBInfo->biHeight        = iHeight;
    lpBInfo->biSizeImage     = biSize;
    // BMPカラー
    lpBMP   = (LPBYTE)GlobalAlloc(GPTR,biSize);
    CopyMemory(lpBMP,bmp.bmBits,biSize);
    // カラーパレットの読込み
    if(iBCnt<24) LoadPalette(szFn);
    // 後片付け
    DeleteObject(hbmp);

    bmpLoad = TRUE;
    return 0;
}
//-----------------------------------------------------------------
// カラーパレットの読込み
//-----------------------------------------------------------------
void LoadPalette(LPCTSTR szFn)
{
    HANDLE hFile;
    LPBITMAPINFO     lpbi;
    BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih;
    LOGPALETTE* lpPalette;
    DWORD i,dwRead;
    RGBQUAD rgb;
    // ファイルのオープン
    hFile = CreateFile(szFn,GENERIC_READ,0,NULL,OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile==NULL) return;
    // ビットマップ情報の読込み
    ReadFile(hFile,&bmfh,sizeof(BITMAPFILEHEADER),&dwRead,NULL);
    ReadFile(hFile,&bmih,sizeof(BITMAPINFOHEADER),&dwRead,NULL);
    lpBInfo->biClrUsed = bmih.biClrUsed;
    lpbi = (LPBITMAPINFO)lpBInfo;
    if(bmih.biClrUsed){
        for(i=0;i<bmih.biClrUsed;i++){
            ReadFile(hFile,&rgb,sizeof(RGBQUAD),&dwRead,NULL);
            CopyMemory(&lpbi->bmiColors[i],&rgb,sizeof(RGBQUAD));
        }
    } else {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(NULL,&ps);
        // パレットの確保
        lpPalette=(LOGPALETTE*)GlobalAlloc(
            GPTR,sizeof(LOGPALETTE)+(1<<iBCnt)*sizeof(PALETTEENTRY));
        // システムパレットの参照
        GetSystemPaletteEntries(hdc,0,(1<<iBCnt),lpPalette->palPalEntry);
        for(i=0;i<(1<<iBCnt);i++){
            lpbi->bmiColors[i].rgbRed   = lpPalette->palPalEntry[i].peRed;
            lpbi->bmiColors[i].rgbGreen = lpPalette->palPalEntry[i].peGreen;
            lpbi->bmiColors[i].rgbBlue  = lpPalette->palPalEntry[i].peBlue;
        }
        EndPaint(NULL,&ps);
    }
    // 後片付け
    GlobalFree(lpPalette);
    CloseHandle(hFile);
}

//-----------------------------------------------------------------
// ビットマップの色を反転
//-----------------------------------------------------------------
void revColor(void)
{
    int x,y,ci,cn = 3;
    if(!bmpLoad) return;
    if(iBCnt == 32) cn = 4;
    // 反転処理
    for(y=0;y<iHeight;y++) for(x=0;x<iWidth;x++){
        if(iBCnt < 24){
            lpBMP[x+y*iLength] = 255-lpBMP[x+y*iLength];
        } else {
            for(ci=0;ci<cn;ci++)
                lpBMP[x*cn+y*iLength+ci] = (255-lpBMP[x*cn+y*iLength+ci]);
        }
    }
}
inserted by FC2 system