/*-----------------------------------------------
DIBHEADS.C -- Displays DIB Header Information
(c) Charles Petzold, 1998
-----------------------------------------------*/
#define WINVER 0x0500
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
TCHAR szAppName[] = TEXT ("DibHeads") ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HACCEL hAccel ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("DIB Headers"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
hAccel = LoadAccelerators (hInstance, szAppName) ;
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateAccelerator (hwnd, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
// 可变参数函数
void Printf (HWND hwnd, TCHAR * szFormat, ...)
{
TCHAR szBuffer [1024] ;
// 指针变量,用于存取各个参数
va_list pArgList ;
// 将pArgList参数指针,指向第一个可变参数;
// 最后一个固定参数szFormat指明了位置
va_start (pArgList, szFormat) ;
// 将格式化字符串szFormat,写入到字符串缓冲区szBuffer
wvsprintf (szBuffer, szFormat, pArgList) ;
// 进行取完参数后的清理工作
va_end (pArgList) ;
/* (WPARAM) -1,取消现有的选择;(LPARAM) -1,文字尾
表明将插入符号的位置定在现有文字尾*/
SendMessage (hwnd, EM_SETSEL, (WPARAM) -1, (LPARAM) -1) ;
/* EM_REPLACESEL 使用别的文字来置换目前的选择内容
FALSE 表示不可以进行撤销操作
(LPARAM) szBuffer 置换的文字缓冲区*/
SendMessage (hwnd, EM_REPLACESEL, FALSE, (LPARAM) szBuffer) ;
// 滚动到编辑控件视图中插入符号的位置处。
SendMessage (hwnd, EM_SCROLLCARET, 0, 0) ;
}
void DisplayDibHeaders (HWND hwnd, TCHAR * szFileName)
{
static TCHAR * szInfoName [] = { TEXT ("BITMAPCOREHEADER"),
TEXT ("BITMAPINFOHEADER"),
TEXT ("BITMAPV4HEADER"),
TEXT ("BITMAPV5HEADER") } ;
static TCHAR * szCompression [] = { TEXT ("BI_RGB"), TEXT ("BI_RLE8"),
TEXT ("BI_RLE4"),
TEXT ("BI_BITFIELDS"),
TEXT ("unknown") } ;
BITMAPCOREHEADER * pbmch ;
BITMAPFILEHEADER * pbmfh ;
BITMAPV5HEADER * pbmih ;
BOOL bSuccess ;
DWORD dwFileSize, dwHighSize, dwBytesRead ;
HANDLE hFile ;
int i ;
PBYTE pFile ;
TCHAR * szV ;
// 输出打开的文件路径及文件名和后缀
Printf (hwnd, TEXT ("File: %s/r/n/r/n"), szFileName) ;
/* CreateFile(pstrFileName 要打开的文件名,GENERIC_READ 表示允许对设备进行读访问,
FILE_SHARE_READ 允许对文件进行共享读访问,
NULL 指向一个SECURITY_ATTRIBUTES结构的指针-定义了文件的安全特性,
OPEN_EXISTING 表示文件必须已经存在-向设备提出要求,
FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化
NULL 如果不为零-则指定一个文件句柄-新文件将从这个文件中复制扩展属性) */
// hFile 接受打开的文件句柄
hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
// INVALID_HANDLE_VALUE表示出错
if (hFile == INVALID_HANDLE_VALUE)
{
Printf (hwnd, TEXT ("Cannot open file./r/n/r/n")) ;
return ;
}
// 返回文件长度。&HFFFFFFFF表示出错。
// dwHighSize 用于装载一个64位文件长度的头32位。如这个长度没有超过2^32字节,则该参数设为NULL(变成ByVal)
dwFileSize = GetFileSize (hFile, &dwHighSize) ;
// 如果dwHighSize装载了长度,说明文件大于2^32字节
if (dwHighSize)
{
Printf (hwnd, TEXT ("Cannot deal with >4G files./r/n/r/n")) ;
CloseHandle (hFile) ;
return ;
}
// 为位图文件分配内存
pFile = malloc (dwFileSize) ;
if (!pFile)
{
Printf (hwnd, TEXT ("Cannot allocate memory./r/n/r/n")) ;
CloseHandle (hFile) ;
return ;
}
// 设置鼠标光标为等待图标,并增加鼠标显示计数1次
SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
ShowCursor (TRUE) ;
/*从文件指针指向的位置开始将数据读出到一个文件中
ReadFile(hFile 文件的句柄
pFile 用于保存读入数据的一个缓冲区
dwFileSize 要读入的字符数
&dwBytesRead 指向实际读取字节数的指针
NULL 如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。
该结构定义了一次异步读取操作。否则,应将这个参数设为NULL)
调用成功,返回非0
调用不成功,返回为0*/
bSuccess = ReadFile (hFile, pFile, dwFileSize, &dwBytesRead, NULL) ;
// 鼠标显示计数减1,设置鼠标光标为箭头
ShowCursor (FALSE) ;
SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
// 调用失败或读取大小与实际文件不符时执行
if (!bSuccess || (dwBytesRead != dwFileSize))
{
Printf (hwnd, TEXT ("Could not read file./r/n/r/n")) ;
CloseHandle (hFile) ;
free (pFile) ;
return ;
}
// 关闭打开的文件,这时已经在程序内存中拷贝了文件数据了
CloseHandle (hFile) ;
// 显示文件大小
Printf (hwnd, TEXT ("File size = %u bytes/r/n/r/n"), dwFileSize) ;
// 显示BITMAPFILEHEADER结构信息(文件标头信息)
pbmfh = (BITMAPFILEHEADER *) pFile ;
Printf (hwnd, TEXT ("BITMAPFILEHEADER/r/n")) ;
Printf (hwnd, TEXT ("/t.bfType = 0x%X/r/n"), pbmfh->bfType) ;
Printf (hwnd, TEXT ("/t.bfSize = %u/r/n"), pbmfh->bfSize) ;
Printf (hwnd, TEXT ("/t.bfReserved1 = %u/r/n"), pbmfh->bfReserved1) ;
Printf (hwnd, TEXT ("/t.bfReserved2 = %u/r/n"), pbmfh->bfReserved2) ;
Printf (hwnd, TEXT ("/t.bfOffBits = %u/r/n/r/n"), pbmfh->bfOffBits) ;
// 读取信息标头
pbmih = (BITMAPV5HEADER *) (pFile + sizeof (BITMAPFILEHEADER)) ;
// 读取位图信息标头大小,判断位图版本
switch (pbmih->bV5Size)
{
case sizeof (BITMAPCOREHEADER): i = 0 ; break ;
case sizeof (BITMAPINFOHEADER): i = 1 ; szV = TEXT ("i") ; break ;
case sizeof (BITMAPV4HEADER): i = 2 ; szV = TEXT ("V4") ; break ;
case sizeof (BITMAPV5HEADER): i = 3 ; szV = TEXT ("V5") ; break ;
default:
Printf (hwnd, TEXT ("Unknown header size of %u./r/n/r/n"),
pbmih->bV5Size) ;
free (pFile) ;
return ;
}
// 显示位图版本
Printf (hwnd, TEXT ("%s/r/n"), szInfoName[i]) ;
// 如果是BITMAPCOREHEADER结构,则显示信息
if (pbmih->bV5Size == sizeof (BITMAPCOREHEADER))
{
pbmch = (BITMAPCOREHEADER *) pbmih ;
Printf (hwnd, TEXT ("/t.bcSize = %u/r/n"), pbmch->bcSize) ;
Printf (hwnd, TEXT ("/t.bcWidth = %u/r/n"), pbmch->bcWidth) ;
Printf (hwnd, TEXT ("/t.bcHeight = %u/r/n"), pbmch->bcHeight) ;
Printf (hwnd, TEXT ("/t.bcPlanes = %u/r/n"), pbmch->bcPlanes) ;
Printf (hwnd, TEXT ("/t.bcBitCount = %u/r/n/r/n"), pbmch->bcBitCount);
free (pFile) ;
return ;
}
// 如果不是BITMAPCOREHEADER结构,则显示BITMAPINFOHEADER信息
Printf (hwnd, TEXT ("/t.b%sSize = %u/r/n"), szV, pbmih->bV5Size) ;
Printf (hwnd, TEXT ("/t.b%sWidth = %i/r/n"), szV, pbmih->bV5Width);
Printf (hwnd, TEXT ("/t.b%sHeight = %i/r/n"), szV, pbmih->bV5Height) ;
Printf (hwnd, TEXT ("/t.b%sPlanes = %u/r/n"), szV, pbmih->bV5Planes) ;
Printf (hwnd, TEXT ("/t.b%sBitCount = %u/r/n"), szV, pbmih->bV5BitCount) ;
// BI_RGB、BI_RLE8、BI_RLE4或BI_BITFIELDS。它们定义在WINGDI.H表头文件中,值分别为0到3。
Printf (hwnd, TEXT ("/t.b%sCompression = %s/r/n"), szV,
szCompression [min (4, pbmih->bV5Compression)]) ;
Printf (hwnd, TEXT ("/t.b%sSizeImage = %u/r/n"), szV, pbmih->bV5SizeImage);
Printf (hwnd, TEXT ("/t.b%sXPelsPerMeter = %i/r/n"), szV,
pbmih->bV5XPelsPerMeter) ;
Printf (hwnd, TEXT ("/t.b%sYPelsPerMeter = %i/r/n"), szV,
pbmih->bV5YPelsPerMeter) ;
Printf (hwnd, TEXT ("/t.b%sClrUsed = %i/r/n"), szV, pbmih->bV5ClrUsed) ;
Printf (hwnd, TEXT ("/t.b%sClrImportant = %i/r/n/r/n"), szV,
pbmih->bV5ClrImportant) ;
// 如果使用了BITMAPINFOHEADER结构并用BI_BITFIELDS压缩格式,则显示屏蔽值
if (pbmih->bV5Size == sizeof (BITMAPINFOHEADER))
{
if (pbmih->bV5Compression == BI_BITFIELDS)
{
// 输出十六进制值,宽度为8,用0填充
Printf (hwnd, TEXT ("Red Mask = %08X/r/n"),
pbmih->bV5RedMask) ;
Printf (hwnd, TEXT ("Green Mask = %08X/r/n"),
pbmih->bV5GreenMask) ;
Printf (hwnd, TEXT ("Blue Mask = %08X/r/n/r/n"),
pbmih->bV5BlueMask) ;
}
free (pFile) ;
return ;
}
// 显示BITMAPV4HEADER结构信息
Printf (hwnd, TEXT ("/t.b%sRedMask = %08X/r/n"), szV,
pbmih->bV5RedMask) ;
Printf (hwnd, TEXT ("/t.b%sGreenMask = %08X/r/n"), szV,
pbmih->bV5GreenMask) ;
Printf (hwnd, TEXT ("/t.b%sBlueMask = %08X/r/n"), szV,
pbmih->bV5BlueMask) ;
Printf (hwnd, TEXT ("/t.b%sAlphaMask = %08X/r/n"), szV,
pbmih->bV5AlphaMask) ;
Printf (hwnd, TEXT ("/t.b%sCSType = %u/r/n"), szV,
pbmih->bV5CSType) ;
// 色彩调配技术,显示设备无关标准修正值
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzRed.ciexyzX = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzRed.ciexyzX) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzRed.ciexyzY = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzRed.ciexyzY) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzRed.ciexyzZ = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzRed.ciexyzZ) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzGreen.ciexyzX = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzGreen.ciexyzX) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzGreen.ciexyzY = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzGreen.ciexyzY) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzGreen.ciexyzZ = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzGreen.ciexyzZ) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzBlue.ciexyzX = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzBlue.ciexyzX) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzBlue.ciexyzY = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzBlue.ciexyzY) ;
Printf (hwnd, TEXT ("/t.b%sEndpoints.ciexyzBlue.ciexyzZ = %08X/r/n"), szV,
pbmih->bV5Endpoints.ciexyzBlue.ciexyzZ) ;
// 伽马值
Printf (hwnd, TEXT ("/t.b%sGammaRed = %08X/r/n"), szV,
pbmih->bV5GammaRed) ;
Printf (hwnd, TEXT ("/t.b%sGammaGreen = %08X/r/n"), szV,
pbmih->bV5GammaGreen) ;
Printf (hwnd, TEXT ("/t.b%sGammaBlue = %08X/r/n/r/n"), szV,
pbmih->bV5GammaBlue) ;
if (pbmih->bV5Size == sizeof (BITMAPV4HEADER))
{
free (pFile) ;
return ;
}
// 显示BITMAPV5HEADER结构信息
Printf (hwnd, TEXT ("/t.b%sIntent = %u/r/n"), szV, pbmih->bV5Intent) ;
Printf (hwnd, TEXT ("/t.b%sProfileData = %u/r/n"), szV,
pbmih->bV5ProfileData) ;
Printf (hwnd, TEXT ("/t.b%sProfileSize = %u/r/n"), szV,
pbmih->bV5ProfileSize) ;
Printf (hwnd, TEXT ("/t.b%sReserved = %u/r/n/r/n"), szV,
pbmih->bV5Reserved) ;
free (pFile) ;
return ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndEdit ;
static OPENFILENAME ofn ;
static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH] ;
static TCHAR szFilter[] = TEXT ("Bitmap Files (*.BMP)/0*.bmp/0")
TEXT ("All Files (*.*)/0*.*/0/0") ;
switch (message)
{
case WM_CREATE:
hwndEdit = CreateWindow (TEXT ("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER |
WS_VSCROLL | WS_HSCROLL |
ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
0, 0, 0, 0, hwnd, (HMENU) 1,
((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
ofn.lStructSize = sizeof (OPENFILENAME) ;
ofn.hwndOwner = hwnd ;
ofn.hInstance = NULL ;
ofn.lpstrFilter = szFilter ; // 文件后缀过滤字符串
ofn.lpstrCustomFilter = NULL ;
ofn.nMaxCustFilter = 0 ;
ofn.nFilterIndex = 0 ;
ofn.lpstrFile = szFileName ; // 这个缓冲包含驱动器,路径,文件名,及所选择的文件的扩展名
ofn.nMaxFile = MAX_PATH ;
ofn.lpstrFileTitle = szTitleName ; //指向接收选择的文件的文件名和扩展名的缓冲(不带路径信息)
ofn.nMaxFileTitle = MAX_PATH ;
ofn.lpstrInitialDir = NULL ;
ofn.lpstrTitle = NULL ;
ofn.Flags = 0 ;
ofn.nFileOffset = 0 ;
ofn.nFileExtension = 0 ;
ofn.lpstrDefExt = TEXT ("bmp") ; // 默认文件后缀名
ofn.lCustData = 0 ;
ofn.lpfnHook = NULL ;
ofn.lpTemplateName = NULL ;
return 0 ;
case WM_SIZE:
MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ;
return 0 ;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_FILE_OPEN:
// 激活Open通用对话框,成功返回非零
if (GetOpenFileName (&ofn))
DisplayDibHeaders (hwndEdit, szFileName) ;
return 0 ;
}
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}