/*
 Copyright (C) 2010 Kuri-Applications

 AppClass.cpp - implementations of CMyApplication and WinMain
 */

#include "StdAfx.h"
#include "AppClass.h"

#include "MyWindow.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static CMyApplication* s_pMainApp = NULL;

extern "C" void WINAPI EndWindowData();

EXTERN_C int APIENTRY MyWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)
{
	if (!s_pMainApp)
		return -1;
	s_pMainApp->m_hInstance = hInstance;
	s_pMainApp->m_lpCmdLine = lpCmdLine;
	s_pMainApp->m_nCmdShow = nCmdShow;
	if (!s_pMainApp->InitInstance())
		return s_pMainApp->ExitInstance();
	int ret = s_pMainApp->Run();
	::EndWindowData();
	return ret;
}

EXTERN_C BOOL APIENTRY MyDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	switch (dwReason)
	{
		case DLL_PROCESS_ATTACH:
		{
			if (!s_pMainApp)
				return FALSE;
			s_pMainApp->m_hInstance = hInstance;
			s_pMainApp->m_lpCmdLine = NULL;
			s_pMainApp->m_nCmdShow = SW_SHOWNORMAL;
			if (!s_pMainApp->InitInstance())
			{
				s_pMainApp->ExitInstance();
				return FALSE;
			}
		}
		break;
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
		case DLL_PROCESS_DETACH:
			s_pMainApp->ExitInstance();
			::EndWindowData();
			break;
	}
	return TRUE;
}

CMyApplication* WINAPI GetCurApp()
{
	return s_pMainApp;
}

////////////////////////////////////////////////////////////////////////////////

CMyApplication::CMyApplication()
{
	memset(&m_msg, 0, sizeof(m_msg));
	m_msg.message = WM_QUIT;
	m_msg.wParam = (WPARAM) -1;
	m_msg.lParam = 0;

	if (!s_pMainApp)
		s_pMainApp = this;
}

CMyApplication::~CMyApplication()
{
}

int CMyApplication::ExitInstance()
{
	return (int) m_msg.wParam;
}

int CMyApplication::Run()
{
	if (!m_pMainWnd)
		return ExitInstance();
	// メイン メッセージ ループ:
	long c;
	bool bExit = false;
	while (!bExit)
	{
		c = 0;
		// キューにメッセージが無い間 OnIdle を呼び続ける
		while (!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (!OnIdle(c++))
				break;
		}
		// キューにメッセージがある限り、それらを処理する
		// (OnIdle が false を返して戻った場合、GetMessage で待機する)
		while (true)
		{
			if (!PumpMessage())
			{
				bExit = true;
				break;
			}
			if (!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
				break;
		}
	}
	return ExitInstance();
}

bool CMyApplication::PumpMessage()
{
	//if (!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
	//	return true;
	if (!::GetMessage(&m_msg, NULL, 0, 0))
		return false;
	CMyWindow* pWnd = CMyWindow::FromHandle(m_msg.hwnd);
	if (pWnd && pWnd != m_pMainWnd && pWnd->PreTranslateMessage(&m_msg))
		return true;
	if (!m_pMainWnd || !m_pMainWnd->PreTranslateMessage(&m_msg))
	{
		::TranslateMessage(&m_msg);
		::DispatchMessage(&m_msg);
	}
	return true;
}

bool CMyApplication::OnIdle(long lCount)
{
	return false;
}
