Windows应用开发-解析MP4视频文件(第2部分)

//Dlg5.h
#pragma once
#include "afxwin.h"
#include "afxcmn.h"
#include "MyButton.h"

struct Sample
{
	UINT Size;
	ULONGLONG Offset;
	BOOL KeyFrame = FALSE;
};

class CDlg5 : public CDialogEx
{
	DECLARE_DYNAMIC(CDlg5)

public:
	CDlg5(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CDlg5();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG5 };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedOk();
	virtual BOOL OnInitDialog();
	CFont font1, font2;
	CBrush brush1, brush2;
	HANDLE hFile = NULL;
	UINT ListCount = 0;
	DWORD* pSampleList = NULL;
	void GetFrames();
	void Get();
	CProgressCtrl pro;
	CEdit edit;
	afx_msg void OnBnClickedButton1();
	CEdit edit2;
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
	void SetPos();
	CMyButton btn;
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnDestroy();
	virtual BOOL PreTranslateMessage(MSG* pMsg);
};

BYTE ReadOne(HANDLE hFile);//读1个字节
WORD ReadTwo(HANDLE hFile);//读2个字节
UINT ReadThree(HANDLE hFile);//读3个字节
UINT ReadFour(HANDLE hFile);//读4个字节
UINT Read4Return(HANDLE hFile, LONGLONG& pos);//在指定位置读4个字节,并返回到文件原来位置。参数2加4字节
ULONGLONG Read8Return(HANDLE hFile, LONGLONG& pos);//在指定位置读8个字节,并返回到文件原来位置。参数2加8字节
HRESULT MoveFilePointer(HANDLE hFile, LONGLONG size, int flag);//移动文件指针
UINT FindBox(HANDLE hFile, char* pBoxName);//读取BOX大小和名称
BOOL IsEnd(HANDLE hFile);//如果到文件末尾,返回TRUE
LONGLONG GetFilePos(HANDLE hFile);//获取文件当前位置
void GetHdlrType(HANDLE hFile, char* pch);//获取类型,vide或soun
LONGLONG FindTrak(HANDLE hFile, char* pCh);//移动文件指针到符合要求的trak开始位置,返回trak开始位置值。参数2,指定trak类型,视频或音频
LONGLONG FindMdia(HANDLE hFile);//文件指针移动到mdia开始位置,返回mdia开始位置值。查找的起始位置为trak的开始位置
LONGLONG FindMdhd(HANDLE hFile);//文件指针移动到mdhd开始位置,返回mdhd开始位置值。查找的起始位置为mdia的开始位置
LONGLONG FindHdlr(HANDLE hFile);//文件指针移动到hdlr开始位置,返回hdlr开始位置值。查找的起始位置为mdia的开始位置
LONGLONG FindMinf(HANDLE hFile);//文件指针移动到minf开始位置,返回minf开始位置值。查找的起始位置为mdia的开始位置
LONGLONG FindStbl(HANDLE hFile);//文件指针移动到stbl开始位置,返回stbl开始位置值。查找的起始位置为minf的开始位置
LONGLONG FindStblSub(HANDLE hFile, char* pch);//查找stbl的子box。文件指针移动到子box开始位置,返回子box开始位置值。查找的起始位置为stbl的开始位置
// Dlg5.cpp : 实现文件
//

#include "stdafx.h"
#include "解析MP4.h"
#include "Dlg5.h"
#include "afxdialogex.h"
#include "解析MP4Dlg.h"

// CDlg5 对话框

IMPLEMENT_DYNAMIC(CDlg5, CDialogEx)

CDlg5::CDlg5(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_DIALOG5, pParent)
{
	font1.CreatePointFont(100, L"微软雅黑");
	font2.CreatePointFont(100, L"仿宋");
	brush1.CreateSolidBrush(RGB(13, 221, 242));
	brush2.CreateSolidBrush(RGB(20, 20, 20));
	ListCount = 0;
}

CDlg5::~CDlg5()
{
}

void CDlg5::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_PROGRESS1, pro);
	DDX_Control(pDX, IDC_EDIT1, edit);
	DDX_Control(pDX, IDC_EDIT2, edit2);
	DDX_Control(pDX, IDC_BUTTON1, btn);
}


BEGIN_MESSAGE_MAP(CDlg5, CDialogEx)
	ON_BN_CLICKED(IDOK, &CDlg5::OnBnClickedOk)
	ON_BN_CLICKED(IDC_BUTTON1, &CDlg5::OnBnClickedButton1)
	ON_WM_CTLCOLOR()
	ON_WM_ERASEBKGND()
	ON_WM_DESTROY()
END_MESSAGE_MAP()

void CDlg5::OnBnClickedOk()
{
}

void CDlg5::Get()
{
	C解析MP4Dlg* pDlg = (C解析MP4Dlg*)theApp.m_pMainWnd;
	if (pDlg->Path.IsEmpty())return;
	hFile = CreateFile(pDlg->Path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//打开MP4文件
	if (hFile == INVALID_HANDLE_VALUE)
	{
		MessageBox(L"打开文件失败"); return;
	}
	EnableWindow(FALSE);
	for (UINT i = 0; i < ListCount; i++)//删除列表中所有对象。为过滤器指定读取文件可能多次,须删除原来的列表中的元素
	{
		Sample* pS = (Sample*)pSampleList[i]; delete pS;
	}
	if (pSampleList)delete[] pSampleList;
	FindTrak(hFile, "vide");//查找视频trak
	LONGLONG MdiaStar = FindMdia(hFile);//查找视频mdia,记录mdia开始位置
	FindMdhd(hFile);//查找视频mdhd
	MoveFilePointer(hFile, MdiaStar, FILE_BEGIN);//回到mdia开始位置
	FindMinf(hFile);//查找视频minf
	LONGLONG StblStar = FindStbl(hFile);//查找视频stbl,记录stbl开始位置
	LONGLONG SttsStar = FindStblSub(hFile, "stts");//stts起始位置
	MoveFilePointer(hFile, SttsStar + 12, FILE_BEGIN);//移动到stts条目数位置
	UINT SttsEnter = ReadFour(hFile);//获取条目数量
	UINT uL;//单个样本的时长,单位100纳秒
	ListCount = 0;//视频样本数量(视频帧数量)
	for (UINT i = 0; i < SttsEnter; i++)//读取每个条目
	{
		UINT uS = ReadFour(hFile); uL = ReadFour(hFile); ListCount += uS;
	}
	MoveFilePointer(hFile, StblStar, FILE_BEGIN);//回到stbl开始位置
	LONGLONG StssStar = FindStblSub(hFile, "stss");//stss起始位置
	MoveFilePointer(hFile, StblStar, FILE_BEGIN);//回到stbl开始位置
	LONGLONG StscStar = FindStblSub(hFile, "stsc");//stsc起始位置
	MoveFilePointer(hFile, StblStar, FILE_BEGIN);//回到stbl开始位置
	LONGLONG StszStar = FindStblSub(hFile, "stsz");//stsz起始位置
	MoveFilePointer(hFile, StblStar, FILE_BEGIN);//回到stbl开始位置
	LONGLONG StcoStar = FindStblSub(hFile, "stco");//stco起始位置
	MoveFilePointer(hFile, StblStar, FILE_BEGIN);//回到stbl开始位置
	LONGLONG Co64Star = FindStblSub(hFile, "co64");//co64起始位置

	pSampleList = new DWORD[ListCount];

	pro.SetRange32(0, ListCount);
	UINT index = 0;//样本索引
	LONGLONG stss_enter_star = StssStar + 16;//stss条目位置
	LONGLONG stco_enter_star = StcoStar + 16;//stco条目位置
	LONGLONG co64_enter_star = Co64Star + 16;//co64条目位置
	LONGLONG stsz_enter_star = StszStar + 20;//stsz条目位置

	UINT KeyFrame = Read4Return(hFile, stss_enter_star);//从stss条目中读取第一个关键帧序号,并将文件指针返回到原来的位置
	MoveFilePointer(hFile, StscStar + 12, FILE_BEGIN);//移动文件指针到,stsc条目数位置
	UINT StscNu = ReadFour(hFile);//获取stsc条目数
	UINT First = ReadFour(hFile);//起始块序号
	UINT NextFirst;//下一个条目起始块序号
	UINT Nu;
	for (UINT i = 0; i < StscNu; i++)//读取stsc每个条目
	{
		UINT nSample = ReadFour(hFile); //块中样本数量
		UINT id = ReadFour(hFile); //stsd序号
		if (i != StscNu - 1)//如果不是stsc最后一个条目
		{
			NextFirst = ReadFour(hFile);//读取下一个条目的起始块序号
			Nu = NextFirst - First;
			First = NextFirst;
		}
		else//如果是stsc最后一个条目
		{
			Nu = 1;
		}
		if (StscNu == 1)nSample = ListCount;//如果stsc只有1个条目,样本数量为全部样本数量
		for (UINT j = 0; j < Nu; j++)//读取stco每个条目
		{
			ULONGLONG Offset;
			if (StcoStar)//有stco
			{
				Offset = Read4Return(hFile, stco_enter_star);//从stco条目中读取块偏移量,并将文件指针返回到原来的位置
			}
			else//有co64
			{
				Offset = Read8Return(hFile, co64_enter_star);//从co64条目中读取块偏移量,并将文件指针返回到原来的位置
			}
			ULONGLONG NextOffset;//下一个偏移量
			for (UINT k = 0; k < nSample; k++)//读取stsz每个条目
			{
				UINT size = Read4Return(hFile, stsz_enter_star);//从stsz条目中读取样本大小,并将文件指针返回到原来的位置
				ULONGLONG offset;
				if (k == 0)offset = Offset;
				else offset = NextOffset;
				NextOffset = offset + size;
				BOOL KEY = FALSE;
				if (KeyFrame == index + 1)//如果是关键帧
				{
					KEY = TRUE;
					KeyFrame = Read4Return(hFile, stss_enter_star);//获取下一个关键帧序号
				}
				Sample* pSample = new Sample();
				pSample->Size = size;
				pSample->Offset = offset;
				if (KEY)pSample->KeyFrame = TRUE;
				pSampleList[index] = (DWORD)pSample;
				index++;
				pro.SetPos(index);
			}
		}
	}
	CString str; str.Format(L"%u", index);
	edit.SetWindowText(str);
	CloseHandle(hFile);
	EnableWindow(TRUE);
}

UINT Thread5(LPVOID pParam)
{
	CDlg5* pdlg5 = (CDlg5*)pParam;
	pdlg5->Get();
	return 1;
}

BOOL CDlg5::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	edit.SetFont(&font1); edit2.SetFont(&font2);
	edit2.LimitText(UINT_MAX); 
	CRect rect(0, 0, 600, 600);//设置客户区大小
	DWORD style = GetExStyle();//获取对话框扩展样式
	if (style & WS_EX_CLIENTEDGE)
	{
		CalcWindowRect(rect, CWnd::adjustOutside);
	}
	else
	{
		CalcWindowRect(rect, CWnd::adjustBorder);
	}
	MoveWindow(&rect);//设置对话框的大小
	CenterWindow();//居中对话框
	SetPos();
	SetWindowTheme(pro.GetSafeHwnd(), _T(""), _T(""));//设置进度条颜色和背景颜色需关闭视觉样式
	pro.SetBarColor(RGB(250, 60, 10));//设置进度条颜色
	pro.SetBkColor(RGB(50, 60, 100));//设置进度条背景色
	return TRUE;  
}

void CDlg5::GetFrames()
{
	AfxBeginThread(Thread5, this, 0, 0, 0);
}

void CDlg5::OnBnClickedButton1()//获取指定帧数据
{
	C解析MP4Dlg* pDlg = (C解析MP4Dlg*)theApp.m_pMainWnd;
	UINT index = GetDlgItemInt(IDC_EDIT1);
	if (index < 1)index = 1;
	if (index > ListCount)index = ListCount;
	SetDlgItemInt(IDC_EDIT1, index);
	Sample* pSample = (Sample*)pSampleList[index - 1];
	BYTE* pB = new BYTE[pSample->Size];
	CFile F;
	F.Open(pDlg->Path, CFile::modeRead);
	F.Seek(pSample->Offset, CFile::begin);
	F.Read(pB, pSample->Size);
	F.Close();
	CString item;
	for (UINT i = 0; i < pSample->Size; i++)
	{
		CString s; s.Format(L"%0*X ", 2, pB[i]); item += s;
	}
	delete[] pB;
	edit2.SetWindowText(item);
}

void CDlg5::SetPos()
{
	edit.MoveWindow(6, 7, 152, 18); btn.MoveWindow(164, 5, 106, 22); pro.MoveWindow(275, 10, 320, 12);
	edit2.MoveWindow(5, 34, 590, 561);
}

HBRUSH CDlg5::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
	{
		pDC->SetTextColor(RGB(0, 0, 0)); pDC->SetBkColor(RGB(13, 221, 242));
		return brush1;
	}
	if (pWnd->GetDlgCtrlID() == IDC_EDIT2)
	{
		pDC->SetTextColor(RGB(0, 255, 255)); pDC->SetBkColor(RGB(20, 20, 20));
		return brush2;
	}
	return hbr;
}

BOOL CDlg5::OnEraseBkgnd(CDC* pDC)
{
	CRect rect; GetClientRect(rect);
	pDC->FillSolidRect(rect, RGB(9, 26, 10));
	CRect RT; RT.CopyRect(rect); RT.bottom = 30;
	pDC->FillSolidRect(RT, RGB(30, 80, 80));
	CRect r1, r2;
	edit.GetWindowRect(r1); ScreenToClient(r1); r1.InflateRect(1, 1);
	pDC->FrameRect(r1, &CBrush(RGB(0, 0, 0)));
	pro.GetWindowRect(r2); ScreenToClient(r2); r2.InflateRect(1, 1);
	pDC->FrameRect(r2, &CBrush(RGB(0, 0, 0)));
	return TRUE;
//	return CDialogEx::OnEraseBkgnd(pDC);
}

BOOL CDlg5::PreTranslateMessage(MSG* pMsg)
{
	if (GetFocus() == GetDlgItem(IDC_EDIT1) && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
	{
		OnBnClickedButton1();
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

void CDlg5::OnDestroy()
{
	CDialogEx::OnDestroy();
	for (UINT i = 0; i < ListCount; i++)//删除列表中所有对象。为过滤器指定读取文件可能多次,须删除原来的列表中的元素
	{
		Sample* pS = (Sample*)pSampleList[i]; delete pS;
	}
	if (pSampleList)delete[] pSampleList;
}

ULONGLONG FindExBox(HANDLE hFile, char* pBoxName)
{
	UINT box_size = ReadFour(hFile);
	ReadFile(hFile, pBoxName, 4, NULL, NULL); pBoxName[4] = 0;
	ULONGLONG Hi = ReadFour(hFile); UINT Lo = ReadFour(hFile);
	ULONGLONG Exbox_size = (Hi << 32) + Lo;
	MoveFilePointer(hFile, -16, FILE_CURRENT);//移动文件指针
	return Exbox_size;
}

LONGLONG FindTrak(HANDLE hFile, char* pCh)//移动文件指针到符合要求的trak开始位置,返回trak开始位置值。参数2,指定trak类型,视频或音频
{
	SetFilePointer(hFile, 0, NULL, FILE_BEGIN);//移动文件指针到文件开头
	char ch[5];
Agan:
	ULONGLONG box_size = FindBox(hFile, ch);
	if (box_size == 1)box_size = FindExBox(hFile, ch);
	if (strcmp(ch, "moov") == 0)
	{
		ULONGLONG moov_size = box_size - 8;
		MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
	moov_Agan:
		box_size = FindBox(hFile, ch);
		if (strcmp(ch, "trak") == 0)
		{
			LONGLONG TrakPos = GetFilePos(hFile);
			FindMdia(hFile); FindHdlr(hFile);
			GetHdlrType(hFile, ch);
			MoveFilePointer(hFile, TrakPos, FILE_BEGIN);//移动文件指针到trak开始位置
			if (strcmp(ch, pCh) == 0)return TrakPos;
			else
			{
				MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
				moov_size -= box_size;
				if (moov_size>0)goto moov_Agan;
			}
		}
		else
		{
			MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
			moov_size -= box_size;
			if (moov_size>0)goto moov_Agan;
		}
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		if (IsEnd(hFile))return 0;//如果到文件末尾,跳出循环
		goto Agan;
	}
	AfxMessageBox(L"查找trak失败");
	return 0;
}

LONGLONG FindMdia(HANDLE hFile)//文件指针移动到mdia开始位置,返回mdia开始位置值。查找的起始位置为trak的开始位置
{
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT trak_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
trak_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, "mdia") == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		trak_size -= box_size;
		if (trak_size > 0)goto trak_Agan;
	}
	AfxMessageBox(L"查找mdia失败");
	return 0;
}

LONGLONG FindMdhd(HANDLE hFile)//文件指针移动到mdhd开始位置,返回mdhd开始位置值。查找的起始位置为mdia的开始位置
{
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT mdia_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
mdia_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, "mdhd") == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		mdia_size -= box_size;
		if (mdia_size > 0)goto mdia_Agan;
	}
	AfxMessageBox(L"查找mdhd失败");
	return 0;
}

LONGLONG FindHdlr(HANDLE hFile)//文件指针移动到hdlr开始位置,返回hdlr开始位置值。查找的起始位置为mdia的开始位置
{
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT mdia_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
mdia_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, "hdlr") == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		mdia_size -= box_size;
		if (mdia_size > 0)goto mdia_Agan;
	}
	AfxMessageBox(L"查找hdlr失败");
	return 0;
}

LONGLONG FindMinf(HANDLE hFile)//文件指针移动到minf开始位置,返回minf开始位置值。查找的起始位置为mdia的开始位置
{
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT mdia_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
mdia_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, "minf") == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		mdia_size -= box_size;
		if (mdia_size > 0)goto mdia_Agan;
	}
	AfxMessageBox(L"查找minf失败");
	return 0;
}

LONGLONG FindStbl(HANDLE hFile)//文件指针移动到stbl开始位置,返回stbl开始位置值。查找的起始位置为minf的开始位置
{
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT minf_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
minf_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, "stbl") == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		minf_size -= box_size;
		if (minf_size > 0)goto minf_Agan;
	}
	AfxMessageBox(L"查找stbl失败");
	return 0;
}

LONGLONG FindStblSub(HANDLE hFile, char* pch)//查找stbl的子box。文件指针移动到子box开始位置,返回子box开始位置值。查找的起始位置为stbl的开始位置
{
	LONGLONG Star = GetFilePos(hFile);//记录stbl开始位置
	char ch[5];
	UINT box_size = FindBox(hFile, ch);
	UINT stbl_size = box_size - 8;
	MoveFilePointer(hFile, 8, FILE_CURRENT);//移动文件指针8字节
stbl_Agan:
	box_size = FindBox(hFile, ch);
	if (strcmp(ch, pch) == 0)
	{
		return GetFilePos(hFile);
	}
	else
	{
		MoveFilePointer(hFile, box_size, FILE_CURRENT);//移动文件指针box_size大小
		stbl_size -= box_size;
		if (stbl_size > 0)goto stbl_Agan;
	}
	MoveFilePointer(hFile, Star, FILE_BEGIN);//查找失败,回到stbl开始位置
	return 0;
}

void GetHdlrType(HANDLE hFile, char* pch)
{
	MoveFilePointer(hFile, 16, FILE_CURRENT);//移动文件指针16字节
	ReadFile(hFile, pch, 4, NULL, NULL); pch[4] = 0;
}

BYTE ReadOne(HANDLE hFile)
{
	BYTE mby1;
	ReadFile(hFile, &mby1, 1, NULL, NULL);
	return mby1;
}

WORD ReadTwo(HANDLE hFile)
{
	BYTE mby1, mby2;
	ReadFile(hFile, &mby1, 1, NULL, NULL); ReadFile(hFile, &mby2, 1, NULL, NULL);
	WORD size = mby1 * 256 + mby2;
	return size;
}

UINT ReadThree(HANDLE hFile)
{
	BYTE mby1, mby2, mby3;
	ReadFile(hFile, &mby1, 1, NULL, NULL); ReadFile(hFile, &mby2, 1, NULL, NULL); ReadFile(hFile, &mby3, 1, NULL, NULL);
	UINT size = mby1 * 256 * 256 + mby2 * 256 + mby3;
	return size;
}

UINT ReadFour(HANDLE hFile)
{
	BYTE mby1, mby2, mby3, mby4;
	ReadFile(hFile, &mby1, 1, NULL, NULL); ReadFile(hFile, &mby2, 1, NULL, NULL); ReadFile(hFile, &mby3, 1, NULL, NULL); ReadFile(hFile, &mby4, 1, NULL, NULL);
	UINT size = mby1 * 256 * 256 * 256 + mby2 * 256 * 256 + mby3 * 256 + mby4;
	return size;
}

UINT Read4Return(HANDLE hFile, LONGLONG& pos)//在指定位置读4个字节,并返回到文件原来位置。参数2加4字节
{
	LONGLONG Cur = GetFilePos(hFile);
	MoveFilePointer(hFile, pos, FILE_BEGIN);
	UINT size = ReadFour(hFile); pos += 4;
	MoveFilePointer(hFile, Cur, FILE_BEGIN);
	return size;
}

ULONGLONG Read8Return(HANDLE hFile, LONGLONG& pos)//在指定位置读8个字节,并返回到文件原来位置。参数2加8字节
{
	LONGLONG Cur = GetFilePos(hFile);
	MoveFilePointer(hFile, pos, FILE_BEGIN);
	ULONGLONG size1 = ReadFour(hFile); UINT size2 = ReadFour(hFile);
	ULONGLONG UL = (size1 << 32) + size2;
	pos += 8;
	MoveFilePointer(hFile, Cur, FILE_BEGIN);
	return UL;
}

HRESULT MoveFilePointer(HANDLE hFile, LONGLONG size, int flag)//移动文件指针
{
	LARGE_INTEGER move;
	move.QuadPart = size;
	SetFilePointerEx(hFile, move, NULL, flag);
	return S_OK;
}

UINT FindBox(HANDLE hFile, char* pBoxName)//读取BOX大小和名称
{
	UINT box_size = ReadFour(hFile);
	ReadFile(hFile, pBoxName, 4, NULL, NULL); pBoxName[4] = 0;
	MoveFilePointer(hFile, -8, FILE_CURRENT);//移动文件指针
	return box_size;
}

BOOL IsEnd(HANDLE hFile)//如果到文件末尾,返回TRUE
{
	LARGE_INTEGER SIZE;
	GetFileSizeEx(hFile, &SIZE);
	LONGLONG Pos = GetFilePos(hFile);
	if (Pos == SIZE.QuadPart)return TRUE;
	else return FALSE;
}

LONGLONG GetFilePos(HANDLE hFile)//获取文件当前位置
{
	LARGE_INTEGER move;
	move.QuadPart = 0;
	LARGE_INTEGER CUR;
	SetFilePointerEx(hFile, move, &CUR, FILE_CURRENT);
	return CUR.QuadPart;
}

// MyButton.cpp : 实现文件
//

#include "stdafx.h"
#include "解析MP4.h"
#include "MyButton.h"


// CMyButton

IMPLEMENT_DYNAMIC(CMyButton, CButton)

CMyButton::CMyButton()
{
	font1.CreatePointFont(90, _T("微软雅黑"), NULL);//
}

CMyButton::~CMyButton()
{
}

BEGIN_MESSAGE_MAP(CMyButton, CButton)
END_MESSAGE_MAP()


void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);
	dc.SelectObject(&font1);
	dc.SetBkMode(TRANSPARENT); dc.SetTextColor(RGB(0, 255, 255));
	CString str;
	if (lpDrawItemStruct->CtlID == IDC_BUTTON1)
	{
		CRect rect(lpDrawItemStruct->rcItem);
		dc.FillSolidRect(&rect, RGB(30, 80, 80));
		CRgn rgn; 
		rgn.CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 4, 4);
		CRect r1; r1.CopyRect(rect); r1.DeflateRect(1, 1);
		CRgn rgn1; rgn1.CreateRoundRectRgn(r1.left, r1.top, r1.right, r1.bottom, 2, 2);
		CRgn rgnA; rgnA.CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
		rgnA.CombineRgn(&rgn, &rgn1, RGN_DIFF);
		dc.FillRgn(&rgnA, &CBrush(RGB(0, 255, 255)));
		dc.SelectObject(&font1); dc.SetTextColor(RGB(0, 255, 255));
		GetWindowText(str);
		dc.DrawText(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	}
	dc.Detach();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值