// инициализация данных FormEx

#include "stdafx.h"
#include "Service.h"
#include "FormEx.h"
#include "AttribEx.h"
#include "PaintHook.h"
#include "MDIClientWnd.h"
#include "WrapAboutDlg.h"
#include "v7Windows.h"

#include "InitFormEx.h"

// FORMEX:BEGIN
extern CMapStringToPtr cModuleMap;
extern HINSTANCE hDllInstance;
class CMDIFrameWnd * pMainWindow = NULL;
class CWinApp* pApp = NULL; //CApp7

HHOOK MouseHookHandle = 0;
HHOOK HookHandle = 0;
HHOOK WndHookHandle = 0;
HHOOK WndPreHookHandle = 0;

BOOL m_bEnabledColor = FALSE;
BOOL m_bLocalColor = FALSE;
BOOL m_bShowKL = FALSE;
UINT StatusTimer = 0;

DWORD myPlatformId;

CMDIClientWnd * wndMDIClient = NULL;
LONG hMainWndProc = 0;
CDWordArray glColContArray;
CString strTimerName = "";
UINT uTimer = 0;

UINT uMainWindowStyle = 0;
UINT uChildWindowStyle = 0;
UINT uChildModalWindowStyle = 0;
BOOL bModalState = FALSE;
CDWordArray srcMenus;
CDWordArray tempMenus;
CStringArray unvisibleMenus;
CStringArray unenableMenus;

CDWordArray glCursorArray;
CDWordArray glCursorWindowsArray;

bool bMinimizeToTray = false;
NOTIFYICONDATA	nidIconData;

//IDispatch *pGlobalConnection = NULL;

//-------------------------------------------------------------------------------------
LRESULT FormEx_OnSetCursor(WORD nHittest)
{
	CWnd* pWnd = NULL;
	POINT curPoint;
	if(::GetCursorPos(&curPoint))
	{
		CMDIFrameWnd * pMain1CFrame = GetMainFrame();
		if(pMain1CFrame)
		{
			int szArr = glCursorWindowsArray.GetSize();
			if(szArr > 0)
			{
				CWnd* pWndT = pMain1CFrame;
				CGetDoc7* pDoc7 = CGetDlg::GetTopmostDocunent();
				if(pDoc7)
				{
					CGetDlg* pGetDlg = (CGetDlg*)pDoc7->GetFrame();
					if(pGetDlg)
					{
						pGetDlg->ScreenToClient(&curPoint);
						pWnd = pGetDlg->ChildWindowFromPoint(curPoint,CWP_SKIPINVISIBLE);//CWP_ALL);
						if(pWnd)
						{
							if((CString("CButton") == pWnd->GetRuntimeClass()->m_lpszClassName) && ((pWnd->GetStyle() & BS_GROUPBOX) == BS_GROUPBOX))
							{
								if(::SetWindowPos(pWnd->GetSafeHwnd(),HWND_BOTTOM,0,0,0,0,
													SWP_NOMOVE|
													SWP_NOACTIVATE|
													SWP_NOREDRAW|
													SWP_NOOWNERZORDER|
													SWP_NOSIZE|
													SWP_NOSENDCHANGING))
								{
									pWnd = pGetDlg->ChildWindowFromPoint(curPoint,CWP_ALL);
								}
							}
							else
							if((CString("CTabCtrl") == pWnd->GetRuntimeClass()->m_lpszClassName))
							{
								if(::SetWindowPos(pWnd->GetSafeHwnd(),HWND_BOTTOM,0,0,0,0,
													SWP_NOMOVE|
													SWP_NOACTIVATE|
													SWP_NOREDRAW|
													SWP_NOOWNERZORDER|
													SWP_NOSIZE|
													SWP_NOSENDCHANGING))
								{
									pWnd = pGetDlg->ChildWindowFromPoint(curPoint,CWP_ALL);
								}
							}
						}
					}
				}
				else
				{
					pMain1CFrame->ScreenToClient(&curPoint);
					pWnd = pMain1CFrame->ChildWindowFromPoint(curPoint,CWP_ALL);
				}
				if(pWnd == NULL) pWnd = pWndT;
				while(pWnd != pWndT)
				{
					pWndT->ClientToScreen(&curPoint);
					pWndT = pWnd;
					pWnd->ScreenToClient(&curPoint);
					pWnd = pWnd->ChildWindowFromPoint(curPoint,CWP_ALL);
					if(pWnd == NULL) pWnd = pWndT;
					else
					{
						if((CString("CButton") == pWnd->GetRuntimeClass()->m_lpszClassName) && ((pWnd->GetStyle() & BS_GROUPBOX) == BS_GROUPBOX))
						{
							if(::SetWindowPos(pWnd->GetSafeHwnd(),HWND_BOTTOM,0,0,0,0,
												SWP_NOMOVE|
												SWP_NOACTIVATE|
												SWP_NOREDRAW|
												SWP_NOOWNERZORDER|
												SWP_NOSIZE|
												SWP_NOSENDCHANGING))
							{
								pWnd = pWndT->ChildWindowFromPoint(curPoint,CWP_ALL);
								if(pWnd == NULL) pWnd = pWndT;
							}
						}
						else
						if((CString("CTabCtrl") == pWnd->GetRuntimeClass()->m_lpszClassName))
						{
							if(::SetWindowPos(pWnd->GetSafeHwnd(),HWND_BOTTOM,0,0,0,0,
												SWP_NOMOVE|
												SWP_NOACTIVATE|
												SWP_NOREDRAW|
												SWP_NOOWNERZORDER|
												SWP_NOSIZE|
												SWP_NOSENDCHANGING))
							{
								pWnd = pWndT->ChildWindowFromPoint(curPoint,CWP_ALL);
								if(pWnd == NULL) pWnd = pWndT;
							}
						}
					}
				}
				pWnd = pWndT;
				while(pWnd)
				{
					DWORD dwHWnd = (DWORD)pWnd->GetSafeHwnd();
					int iContAr = -1;
					for(iContAr = 0; iContAr < szArr; iContAr++)
						if(glCursorWindowsArray.GetAt(iContAr) == dwHWnd)
							break;

					if((iContAr >= 0) && (iContAr < szArr))
					{
						HCURSOR hCur = (HCURSOR)glCursorArray.GetAt(iContAr);
						::SetCursor(hCur);
						return 1;
					}
					else if(pWnd == pMain1CFrame)
						pWnd = NULL;
					else
						pWnd = pWnd->GetParent();
				}
			}
		}
	}
	return 0;
}

LRESULT CALLBACK newMainWndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
	if(nMessage == WM_SETCURSOR)
	{
		if(FormEx_OnSetCursor(LOWORD(lParam))) return 1;
	}
	return ((WNDPROC)hMainWndProc)(hWnd, nMessage, wParam, lParam);
}

LRESULT WINAPI DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch( uMsg ) {
	case WM_INITDIALOG:
		return TRUE;
	case WM_COMMAND:
		switch( wParam ) {
		case IDOK:
			EndDialog( hDlg, TRUE );
			return TRUE;
		}
		break;
	}
	
	return FALSE;
}
// FORMEX:END

// вызывается в CAddIn::Init()
bool CInitFormEx::Init(void)
{
	// определяем версию ОС
	OSVERSIONINFO osvi;
	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx((OSVERSIONINFO*)&osvi);
	myPlatformId = osvi.dwPlatformId;
	
	pMainWindow = GetMainFrame();
	//if(!pMainWindow) return E_FAIL;
	if(!pMainWindow) return false;

	CWrapModule WrapModule;
	CGetDlgWrapped::SetWrap();

	/*CSetOfHierarchy *pHierarchy = CSetOfHierarchy::GetHierarchy();
	
	pHierarchy->Init();
	pHierarchy->ProcessDefines();
	
	pHierarchy->RegistersContextClasses();
	
	pMainAddIn = this;
	
	CComponentClass::ExceptionValue = new CValue;*/
	
	if(pApp)
	{
		MouseHookHandle = SetWindowsHookEx(WH_MOUSE, Mouse_Hook, pApp->m_hInstance, pApp->m_nThreadID);
		HookHandle = SetWindowsHookEx(WH_KEYBOARD, Key_Hook, pApp->m_hInstance, pApp->m_nThreadID);
		WndHookHandle = SetWindowsHookEx(WH_CALLWNDPROCRET, Wnd_Hook, pApp->m_hInstance, pApp->m_nThreadID);
		WndPreHookHandle = SetWindowsHookEx(WH_CALLWNDPROC, WndPre_Hook, pApp->m_hInstance, pApp->m_nThreadID);

		if(m_bEnabledColor)
		{
			CBrowseWrapper::SetWrap();
		}
		if(m_bShowKL)
		{
			SECStatusBar* pStatus = (SECStatusBar*)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
			if(pStatus)
			{
				int count = pStatus->GetCount();
				UINT* nIDs;
				nIDs = (UINT*)malloc(count*sizeof(UINT));
				for(int i = 0; i<count; i++)
					nIDs[i] = pStatus->GetItemID(i);
				pStatus->SetIndicators(nIDs, count);
				StatusTimer = pStatus->SetTimer(500,100,(TIMERPROC)TimerProc);
				free(nIDs);
			}
		}
	}

	hMainWndProc = ::GetWindowLong(pMainWindow->GetSafeHwnd(),GWL_WNDPROC);
	::SetWindowLong(pMainWindow->GetSafeHwnd(),GWL_WNDPROC,(LONG)newMainWndProc);
	wndMDIClient = new CMDIClientWnd;
	if(!wndMDIClient->SubclassWindow(pMainWindow->m_hWndMDIClient))
	{
		pBkEndUI->DoMessageLine("Failed to subclass MDI client window", mmRedErr);
		delete wndMDIClient;
		wndMDIClient = NULL;
	}
	else
	{
		CGalleryHolder * pGalleryHolder = CGalleryHolder::GetGallery();
		if(pGalleryHolder)
		{
			ULONG picID = pGalleryHolder->FindByAlias("Wallpaper");
			if(picID)
			{
				CPictureHolder7 * pic;
				pic = new CPictureHolder7(pGalleryHolder->GetPicture(picID));

				CDC dcMem;
				CDC* pDC = CWnd::GetDesktopWindow()->GetDC();

				if (dcMem.CreateCompatibleDC(pDC))
				{
					CSize hmSize = pic->GetSize();

					CBitmap bmMem;

					if (bmMem.CreateCompatibleBitmap(pDC, hmSize.cx, hmSize.cy))
					{
						CBitmap* pOldBM = dcMem.SelectObject(&bmMem);

						dcMem.FillSolidRect(0, 0, hmSize.cx, hmSize.cy, RGB(0x100,0x100,0x100));
						RECT rect1;
						RECT rect2;
						rect1.top = 0;
						rect1.left = 0;
						rect1.right = hmSize.cx;
						rect1.bottom = hmSize.cy;
						
						pic->Render(dcMem, rect1, 0, &rect2);

						wndMDIClient->m_Bitmap.Attach(bmMem.Detach());
						wndMDIClient->m_nType = 1;
						wndMDIClient->CreateGrayBitmap();

						dcMem.SelectObject(pOldBM);
					}
				}
				CWnd::GetDesktopWindow()->ReleaseDC(pDC);
				delete pic;
			}
		}

		wndMDIClient->m_nBkColor = -1;
		wndMDIClient->m_bGray = false;
		wndMDIClient->RedrawWindow();
	}

	nidIconData.cbSize				= sizeof(NOTIFYICONDATA);
	
	nidIconData.hWnd				= pMainWindow->GetSafeHwnd();
	nidIconData.uID					= 1;

	nidIconData.uCallbackMessage	= WM_TRAY_ICON_NOTIFY_MESSAGE;

	nidIconData.hIcon				= ::LoadIcon(hDllInstance,MAKEINTRESOURCE(IDI_ICONMAIN));//pMainFrame->GetIcon(TRUE);
	nidIconData.szTip[0]			= 0;
	nidIconData.uFlags				= NIF_MESSAGE | NIF_ICON | NIF_TIP;

	CString lpszToolTip = "";
	pMainWindow->GetWindowText(lpszToolTip);
	strcpy(nidIconData.szTip, lpszToolTip.Left(63));

	CAboutDlg AboutDlg(0);
	CWrapAboutDlg::Wrap(&AboutDlg);

	return true;
}

// вызывается в CAddIn::Done()
void CInitFormEx::Destroy(void)
{
	int n = tempMenus.GetSize();
	for(int i = 0; i < n; i++)
	{
		CMenu *pMenuT = CMenu::FromHandle((HMENU)tempMenus.GetAt(i));
		if(pMenuT) pMenuT->DestroyMenu();
	}
	srcMenus.RemoveAll();
	tempMenus.RemoveAll();
	unvisibleMenus.RemoveAll();
	unenableMenus.RemoveAll();

	if(MouseHookHandle != 0) UnhookWindowsHookEx(MouseHookHandle);
	if(HookHandle != 0) UnhookWindowsHookEx(HookHandle);
	if(WndHookHandle != 0) UnhookWindowsHookEx(WndHookHandle);
	if(WndPreHookHandle != 0) UnhookWindowsHookEx(WndPreHookHandle);
	
	if(wndMDIClient != NULL)
	{
		CMDIFrameWnd * pMainFrame = GetMainFrame();
		if(pMainFrame)
		{
			wndMDIClient->RedrawWindow();
			if(!wndMDIClient->UnsubclassWindow())
				pBkEndUI->DoMessageLine("Failed to unsubclass MDI client window", mmRedErr);
			delete wndMDIClient;
		}
	}
	
	if(uTimer)
	{
		CWnd* pMainWnd = GetMainFrame();
		if(pMainWnd) pMainWnd->KillTimer(uTimer);
	}

	glColContArray.RemoveAll();
	glCursorArray.RemoveAll();
	glCursorWindowsArray.RemoveAll();
	
	if(bModalState)
	{
		bModalState = FALSE;
		HWND hwnd;

		if(hwnd=::FindWindowEx(GetDesktopWindow(),NULL,"Progman",NULL))
			if(hwnd=::FindWindowEx(hwnd,NULL,"SHELLDLL_DefView",NULL))
				::EnableWindow(hwnd, TRUE);
		if(hwnd=::FindWindowEx(::GetDesktopWindow(),NULL,"Shell_TrayWnd",NULL))
			::EnableWindow(hwnd, TRUE);

		::SetWindowPos(pMainWindow->GetSafeHwnd(),HWND_NOTOPMOST,0,0,0,0, SWP_DRAWFRAME | SWP_NOSIZE);
	}

	Shell_NotifyIcon(NIM_DELETE,&nidIconData);

	n = cModuleMap.GetCount();
	POSITION pos = cModuleMap.GetStartPosition();
	while(pos)
	{
		CString s;
		CModuleInfoFormEx* p = NULL;
		cModuleMap.GetNextAssoc(pos, s, (void *&)p);
		
		POSITION pos0 = p->cProcMap.GetStartPosition();
		while(pos0)
		{
			void* p0 = NULL;
			p->cProcMap.GetNextAssoc(pos0, s, (void *&)p0);
			delete p0;
		}
		p->cProcMap.RemoveAll();
		delete p;
	}
	cModuleMap.RemoveAll();

}

static BOOL boolShowLast;

// вызывается в начале CAddIn::Apply()
void CInitFormEx::BeforeApply(void)
{
	// след. проверка для того, чтобы элементы панели добавились всего один раз
	boolShowLast = m_bShowKL;
}

// вызывается в конце CAddIn::Apply()
void CInitFormEx::Apply(void)
{
	//BOOL boolShowLast = m_bShowKL;

	if(m_bEnabledColor)
	{
		CBrowseWrapper::SetWrap();
	}
	else
	{
		m_bLocalColor = FALSE;
		CBrowseWrapper::OffWrap();
	};
	SECStatusBar* pStatus = (SECStatusBar*)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
	
	if(pStatus)
	{
		int count = pStatus->GetCount();
		UINT* nIDs;
		UINT* nStyles;
		int* cxWidths;
		nIDs = (UINT*)malloc((count+2)*sizeof(UINT));
		nStyles = (UINT*)malloc(count*sizeof(UINT));
		cxWidths = (int*)malloc(count*sizeof(int));
		for(int i = 0; i<count; i++)
			pStatus->GetPaneInfo(i,nIDs[i],nStyles[i],cxWidths[i]);

		// след. проверка для того, чтобы элементы панели добавились всего один раз
		if((m_bShowKL == TRUE) && (boolShowLast == FALSE)) 
		{
			/*
			pStatus->AllocElements(count+2,100);
			pStatus->SetPaneInfo(count+1,NULL,SBPS_NORMAL, 43);
			pStatus->SetPaneInfo(count,NULL,SBPS_NORMAL, 20);
			char KLName[KL_NAMELENGTH]; 
			if(GetLocaleInfo((LCID)((WORD)GetKeyboardLayout(AfxGetApp()->m_nThreadID)),LOCALE_SABBREVLANGNAME,KLName,KL_NAMELENGTH))
				pStatus->SetPaneText(count,KLName,KL_NAMELENGTH);
			nIDs[count++] = 0;
			nIDs[count++] = 0;
			*/
			StatusTimer = pStatus->SetTimer(500,100,(TIMERPROC)TimerProc);
		}
		else if((m_bShowKL == FALSE) & (boolShowLast == TRUE))
		{
			count -= 2;
			pStatus->AllocElements(count,100);
			if(StatusTimer)
			{
				pStatus->KillTimer(StatusTimer);
				StatusTimer = 0;
			}
		}
//		for(i = 0; i<count; i++)
//			pStatus->SetPaneInfo(i,nIDs[i],nStyles[i],cxWidths[i]);

		pStatus->SetIndicators(nIDs, count);
//		pStatus->UpdateAllPanes(1,1);

		free(nIDs);
		free(nStyles);
		free(cxWidths);
	}
}