// LoadMemoryDlg.cpp : implementation file
//

#include "stdafx.h"
#include "afxdialogex.h"
#include "resource.h"
#include "LoadMemoryDlg.h"
#include "MSFManager.h"
#include <vfw.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CLoadMemoryDlg

IMPLEMENT_DYNAMIC(CLoadMemoryDlg, CFileDialog)

CLoadMemoryDlg::CLoadMemoryDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
                               DWORD dwFlags, LPCTSTR lpszFilter, CWnd *pParentWnd, DWORD dwSize, BOOL bVistaStyle) :
	CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd, dwSize, bVistaStyle)
{
	m_ofn.hwndOwner = pParentWnd->GetSafeHwnd();
	m_ofn.Flags |= OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE; //|OFN_ENABLESIZING;
	m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_LOAD_MEMORY);
	m_ofn.lpfnHook = OFNHookProc;
	m_ofn.lCustData = reinterpret_cast<LPARAM>(this);
}


BEGIN_MESSAGE_MAP(CLoadMemoryDlg, CFileDialog)
END_MESSAGE_MAP()


UINT_PTR CALLBACK CLoadMemoryDlg::OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
	static CRect rectHD;
	auto obj = reinterpret_cast<CLoadMemoryDlg *>(lParam);

	switch (uiMsg)
	{
		case WM_INITDIALOG:
		{
			::GetWindowRect(hdlg, &rectHD);
			break;
		}

		case WM_CHILDACTIVATE:
		{
			HWND hParent = ::GetParent(hdlg);
			CRect rectFD;
			BOOL bres = ::GetWindowRect(hParent, &rectFD);
			CRect rectHD1;
			bres = ::GetWindowRect(hdlg, &rectHD1);
			//увеличим окно в ширину
			bres = ::MoveWindow(hParent, rectFD.left, rectFD.top, rectFD.Width() + rectHD.Width(), rectFD.Height() - rectHD.Height(), FALSE);
			//переместим превьюшку на своё новое место
			bres = ::MoveWindow(hdlg, rectFD.Width() - 20, -355, rectHD.Width(), rectHD1.Height(), FALSE);
			break;
		}

		case WM_NOTIFY:
		{
			auto pNm = reinterpret_cast<LPNMHDR >(lParam);
			auto pOFN = reinterpret_cast<LPOFNOTIFY >(wParam);

			if (pNm->code == CDN_SELCHANGE)
			{
				CString strPath;
				HWND hParent = ::GetParent(hdlg);
				::SendMessage(hParent, CDM_GETFILEPATH, 1024, reinterpret_cast<LPARAM>(strPath.GetBufferSetLength(1024)));
				strPath.ReleaseBuffer();
				CLoadMemoryDlg::DrawPreview(hdlg, strPath);
				return 0;
			}
		}
		break;
	}

	return 0;
}


void CLoadMemoryDlg::DrawPreview(HWND hdlg, const CString &strPath)
{
	CFile file;

	if (file.Open(strPath, CFile::modeRead))
	{
		ULONGLONG curPos = 0;
		ULONGLONG fileLength = file.GetLength();
		MSF_FILE_HEADER sfh;
		file.Read(&sfh, sizeof(MSF_FILE_HEADER));
		curPos += sizeof(MSF_FILE_HEADER);

		if (sfh.type == MSF_STATE_ID && sfh.version >= 10)
		{
			MSF_BLOCK_HEADER bh;
			bh.type = MSF_BLOCKTYPE_UNKNOWN;
			bh.length = sizeof(bh);

			while (bh.type != MSF_BLOCKTYPE_PREVIEW)
			{
				file.Seek(bh.length - sizeof(bh), SEEK_CUR);
				file.Read(&bh, sizeof(bh));
				curPos += bh.length;

				if (curPos >= fileLength)
				{
					return;
				}
			}

			BITMAPINFO bminfo;
			ZeroMemory(&bminfo, sizeof(BITMAPINFO));
			file.Read(&bminfo.bmiHeader, sizeof(BITMAPINFOHEADER));
			int bpr = (bminfo.bmiHeader.biWidth * (bminfo.bmiHeader.biBitCount / 8) + 3) / 4 * 4;
			int length = bpr * bminfo.bmiHeader.biHeight;
			void *pBits;
			HBITMAP hBm = CreateDIBSection(nullptr, &bminfo, DIB_RGB_COLORS, (void **) &pBits, nullptr, 0);

			if (hBm)
			{
				file.Read(pBits, length);
				CWnd *pDlg = CWnd::FromHandle(hdlg);
				CRect rcPreview;
				pDlg->GetDlgItem(IDC_PREVIEW_BORDER)->GetWindowRect(&rcPreview);
				pDlg->ScreenToClient(rcPreview);
				rcPreview.DeflateRect(1, 1);
				HDRAWDIB hdd = DrawDibOpen();
				HDC hdc = ::GetDC(hdlg);
				DrawDibDraw(hdd, hdc,
				            rcPreview.left, rcPreview.top, rcPreview.Width(), rcPreview.Height(),
				            &bminfo.bmiHeader, pBits,
				            0, 0, bminfo.bmiHeader.biWidth, bminfo.bmiHeader.biHeight,
				            0);
				::ReleaseDC(hdlg, hdc);
				DrawDibClose(hdd);
				DeleteObject(hBm);
			}
		}

		file.Close();
	}
}
