지금까지 설명한 핵심 코드에 주석과 예외 사항 체크를 추가한 완전한 OnLButtonDown 함수를 소스 3-1에 나타내었다.

    소스 3-1 OnLButtonDown 함수 전체 소스 내용(BmpShowView.cpp)
    #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
    
    void CBmpShowView::OnLButtonDown(UINT nFlags, CPoint point)
    {
        FILE* fp = NULL;
        fopen_s(&fp, "lenna.bmp", "rb");
        if (!fp)
            return;
    
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
    
        // BITMAPFILEHEADER 읽기
        if (fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, fp) != 1) {
            fclose(fp);
            return;
        }
    
        // BMP 파일임을 나타내는 'BM' 마커가 있는지 확인
        if (bmfh.bfType != DIB_HEADER_MARKER) {
            fclose(fp);
            return;
        }
    
        // BITMAPINFOHEADER 읽기
        if (fread(&bmih, sizeof(BITMAPINFOHEADER), 1, fp) != 1) {
            fclose(fp);
            return;
        }
    
        LONG nWidth = bmih.biWidth;
        LONG nHeight = bmih.biHeight;
        WORD nBitCount = bmih.biBitCount;
    
        DWORD dwWidthStep = (DWORD)((nWidth * nBitCount / 8 + 3) & ~3);
        DWORD dwSizeImage = nHeight * dwWidthStep;
    
        // DIB 구조 전체 크기 계산 (BITMAPINFOHEADER + 색상 테이블 + 픽셀 데이터)
        DWORD dwDibSize;
        if (nBitCount = = 24)
            dwDibSize = sizeof(BITMAPINFOHEADER) + dwSizeImage;
        else
            dwDibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << nBitCount) + dwSizeImage;
    
        // 파일로부터 DIB 구조를 읽어서 저장할 메모리 공간 할당
        BYTE* pDib = new BYTE[dwDibSize];
    
        if (pDib = = NULL)
        {
            fclose(fp);
            return;
        }
    
        // 파일로부터 Packed-DIB 크기만큼을 읽기
        fseek(fp, sizeof(BITMAPFILEHEADER), SEEK_SET);
        if (fread(pDib, sizeof(BYTE), dwDibSize, fp) != dwDibSize)
        {
            delete[] pDib;
            pDib = NULL;
            fclose(fp);
            return;
        }
    
        // 픽셀 데이터 시작 위치 계산
        LPVOID lpvBits;
        if (nBitCount = = 24)
            lpvBits = pDib + sizeof(BITMAPINFOHEADER);
        else
            lpvBits = pDib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << nBitCount);
    
        // DIB 화면 출력
        CClientDC dc(this);
        ::SetDIBitsToDevice(dc.m_hDC, point.x, point.y, nWidth, nHeight, 0, 0, 0,
            nHeight, lpvBits, (BITMAPINFO*)pDib, DIB_RGB_COLORS);
    
        // 메모리 해제 및 파일 닫기
        delete[] pDib;
        fclose(fp);
    
        CView::OnLButtonDown(nFlags, point);
    }
    
    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.