#include "stdafx.h"
#include "apl_gui.h"

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


#include <windows.h>		//Файл определений функций windows
#include <commctrl.h>		//Функции работы со стандартными окнами windows

//******************************************************************************************

HICON aplResizeIcon(HICON hInIcon, int cx, int cy)
{
	if(0==hInIcon) return 0;
	if(cx<4 || cx>256) return 0;
	if(cy<4 || cy>256) return 0;
	
	// Вычисляем пропорциональные размеры для исходной иконки
	ICONINFO in_icon_info = { 0 };
	if(!GetIconInfo(hInIcon, &in_icon_info)) return 0;
	BITMAP in_bm = {0};
	GetObject(in_icon_info.hbmColor, sizeof(in_bm), &in_bm);

	int cx0=in_bm.bmWidth;
	int cy0=in_bm.bmHeight;

	if(0==cx0 || 0== cy0) return 0;

	double kx=((double)cx)/cx0;
	double ky=((double)cy)/cy0;

	if(ky<kx) kx=ky;

	cx0=(int)(kx*cx0);
	cy0=(int)(kx*cy0);

	int dx=(cx-cx0)/2;
	int dy=(cy-cy0)/2;
	
	// делаем иконку

	CDC *desktopDC = CWnd::GetDesktopWindow()->GetDC();
	if(0==desktopDC) return 0;

	COLORREF backColor=RGB(91,74,20);

	CDC bmpDC;
	bmpDC.CreateCompatibleDC(desktopDC);
	
	CBitmap bmp; 
	bmp.CreateCompatibleBitmap(desktopDC,cx,cy);
	CWnd::GetDesktopWindow()->ReleaseDC(desktopDC); desktopDC=0;

	CBitmap *oldBmp=bmpDC.SelectObject(&bmp);

	bmpDC.FillSolidRect(0,0,cx,cy,backColor);

	::DrawIconEx(HDC(bmpDC),dx,dy,hInIcon,cx0,cy0,0,NULL,DI_NORMAL);

	bmpDC.SelectObject(oldBmp);

	CImageList il;
	il.Create(cx, cy, ILC_COLOR24 | ILC_MASK, 0, 1);
	il.Add(&bmp, backColor);

	HICON iconOut = il.ExtractIcon(0);

	// Делаем копию, т.к. il пропадет при выходе
	ICONINFO out_icon_info = { 0 };
	if(!GetIconInfo(iconOut, &out_icon_info)) return 0;

	HICON  iconOut2=CreateIconIndirect(&out_icon_info);

	return iconOut2;
}

//******************************************************************************************

HICON aplIconCopyAsSpecificBlend(HICON hIcon,int blend,bool MakeGrayed,COLORREF BaseColor)
{
	if(blend<0) return 0;
	if(blend>100) return 0;
	
	ICONINFO iconinfo = { 0 };
	HICON hicon = NULL;

	int baseR = GetRValue(BaseColor);
	int baseG = GetGValue(BaseColor);
	int baseB = GetBValue(BaseColor);

// Для обработки иконки запрашиваются составляющие иконки -
// цветная картинка и маска.
// Функция возвращает копию (!) картинок и мы в праве ими
// воспользоваться
	if(GetIconInfo(hIcon, &iconinfo))
	{
	// чернобелые иконки не обрабатываем, т.к. они содержат
	// только маску
		if(iconinfo.hbmColor)
		{
		// Определяем размеры иконки
			BITMAP bm = {0};
			GetObject(iconinfo.hbmColor, sizeof(bm), &bm);

		// И для обработки запрашиваем два контекста экрана
			HDC hDC = GetDC(GetDesktopWindow());

		// ... для цветной картинки
			HDC dcColor = CreateCompatibleDC(hDC);
			HGDIOBJ oBmpColor = SelectObject(dcColor, iconinfo.hbmColor);

		// ... и маски (чтобы не испортить фон)
			HDC dcMask = CreateCompatibleDC(hDC);
			HGDIOBJ oBmpMask = SelectObject(dcMask, iconinfo.hbmMask);

		// Перебираем все пиксели картинки
			for(int y=0;y<bm.bmHeight;y++)
			for(int x=0;x<bm.bmWidth;x++)
			{
			// Пиксел должен быть не отброшен маской
				if(!GetPixel(dcMask, x, y))
				{
				// Получаем пиксел
					COLORREF cl = GetPixel(dcColor, x, y);

				// Находим составляющие цвета
					int cR = GetRValue(cl);
					int cG = GetGValue(cl);
					int cB = GetBValue(cl);
					
					if(MakeGrayed)
					{
						int c = ( GetRValue(cl) + GetGValue(cl) + GetBValue(cl) ) / 3;
						cR=cG=cB=c;
					}

					if(blend!=100)
					{
						cR = baseR+((cR-baseR)*blend/100); 
						cG = baseG+((cG-baseG)*blend/100);
						cB = baseB+((cB-baseB)*blend/100);
					}
					// И записываем пиксел обратно
					SetPixel(dcColor, x, y, RGB(cR, cG, cB));
				}
			}

		// Высвобождаем ресурсы...
		// ... маску и ее контекст
			SelectObject(dcMask, oBmpMask);
			DeleteDC(dcMask);

		// ... цветную картинку и контекст
			SelectObject(dcColor, oBmpColor);
			DeleteDC(dcColor);

		// Отпускаем контекст экрана
			ReleaseDC(GetDesktopWindow(), hDC);
		}

	// Теперь создаем иконку на основе обработаных картинок
		hicon = CreateIconIndirect(&iconinfo);

	// т.к. ф-ции GetIconInfo() и CreateIconIndirect() делают
	// копии картинок, их нужно так-же высвободить
		if(iconinfo.hbmColor) DeleteObject(iconinfo.hbmColor);
		if(iconinfo.hbmMask) DeleteObject(iconinfo.hbmMask);
	}

// Теперь возвращаем либо новую иконку, либо NULL в случае ошибки
	return hicon;
}

//******************************************************************************************

HIMAGELIST aplImageListCopyAsSpecificBlend(HIMAGELIST hImageList,int blend,bool MakeGrayed,COLORREF BaseColor)
{
	HICON hIcon, hIcon0;
	int cx, cy;
	unsigned i;

// Опрежедяем кол-во иконок
	unsigned cnt = ImageList_GetImageCount(hImageList);

// Их размер
	if(!ImageList_GetIconSize(hImageList, &cx, &cy)) return NULL;

// Создаём пустой имайджлист указанных размеров и на кол-во иконок
	HIMAGELIST himlDestination = ImageList_Create(cx, cy, ILC_COLOR16|ILC_MASK, cnt, 0);

// Если имайджлист не создаётся, то вываливаемся
	if(!himlDestination) return NULL;

// Перебираем все индекса иконок
	for(i=0;i<cnt;i++)
	{
	// Запрашиваем (копию) нормальную иконку - с картинкой и маской
		hIcon = (HICON)ImageList_GetIcon(hImageList, (int)i, ILD_TRANSPARENT);

	// Создаём иконку в оттенках серого
		hIcon0 = aplIconCopyAsSpecificBlend(hIcon, blend, MakeGrayed, BaseColor);

	// Закидываем в имайджлист новую иконку
		ImageList_AddIcon(himlDestination, hIcon0);

	// Обязательно высвобождаем все ресурсы, т.к.
	// функции ImageList_GetIcon() и Icon_CopyAsGreyScale()
	// создают копии, а ImageList_AddIcon() не удаляет
	// передаваемую иконку (делает копию)
		DestroyIcon(hIcon0);
		DestroyIcon(hIcon);
	}

	// Возвращаем новый имайджлист
	return himlDestination;
}

//******************************************************************************************

bool aplCreateImageListFromBitmap(UINT bitmapID, COLORREF mask, CImageList &il)
{
	if(HIMAGELIST(il)!=0) il.DeleteImageList();
	CBitmap bm;
	if(!bm.LoadBitmap(bitmapID)) return false;
	BITMAP BitMap;
	if(!bm.GetBitmap(&BitMap)) return false;
	if(!il.Create(BitMap.bmWidth,BitMap.bmHeight, ILC_COLOR24|ILC_MASK, 0, 1)) return false;
	il.Add(&bm, mask);
	bm.DeleteObject();
	return true;
}

//*************************************************************************

void  aplFormatNumericString (CString &sInput)
{
	sInput.Remove(_T(' '));
	int i,j;

	i = sInput.Find(_T("."));

	if(i == -1)	i = sInput.GetLength();
	else
	{
		j = i+4;
		while (j < sInput.GetLength())
		{
			sInput.Insert(j,_T(' '));
			j+=4;
		}
	}
	j=i-3;
	while(j > 0)
	{
		sInput.Insert(j,_T(' '));
		j-=3;
	}
}
//*************************************************************************
int aplCompareNumericStr(LPCTSTR pstr1, LPCTSTR pstr2, bool bNoCase)
{
	if(0==pstr1 || 0==pstr2) return 0;

	int i1=0,i2=0;

	while(true)
	{
		TCHAR c1=pstr1[i1];
		TCHAR c2=pstr2[i2];

		if(c1==_T('\0') && c2==_T('\0')) return 0;
		if(c1==_T('\0')) return -1;
		if(c1==_T('\0')) return 1;

		if(c1>=_T('0') && c1<=_T('9') && c2>=_T('0') && c2<=_T('9'))
		{

			int ic1=_atoi(pstr1+i1);
			int ic2=_atoi(pstr2+i2);

			if(ic1<ic2) return -1;
			if(ic1>ic2) return 1;

			// Цифры совпали, ищем разделитель

			while(true)
			{
				TCHAR c=pstr1[i1];
				if(c<_T('0') || c>_T('9')) break;
				i1++;
			}

			while(true)
			{
				TCHAR c=pstr2[i2];
				if(c<_T('0') || c>_T('9')) break;
				i2++;
			}
			continue;;
		}
		else //Не все цифры
		{
			if(c1!=c2)
			{
				if(bNoCase)
				{
					// Преобразуем к верхнему регистру
					if(c1>=_T('a') && c1<=_T('z')) c1+=(_T('A')-_T('a'));
					else if(c1>=_T('а') && c1<=_T('я')) c1+=(_T('Я')-_T('я'));

					if(c2>=_T('a') && c2<=_T('z')) c2+=(_T('A')-_T('a'));
					else if(c2>=_T('а') && c2<=_T('я')) c2+=(_T('Я')-_T('я'));
				}

				if(c1<c2) return -1;
				if(c1>c2) return 1;
			}

			i1++;
			i2++;
		}
	}
	return 0; // По идее сюда не попадет никогда
}
//*************************************************************************

//////////////////////////////////////////////////////////////////////////
HICON aplConvertCBitmap2HICON(HBITMAP bitmap, COLORREF clrMask)
{
	CImageList il;
	BITMAP	csBitmapSize;
	int nRetValue = ::GetObject(bitmap, sizeof(csBitmapSize), &csBitmapSize);

	il.Create(csBitmapSize.bmWidth, csBitmapSize.bmHeight, ILC_COLOR24 | ILC_MASK, 0, 1);
	il.Add(CBitmap::FromHandle(bitmap), clrMask);

	return il.ExtractIcon(0);
}

HICON aplConvertCBitmap2HICON(UINT nId, COLORREF clrMask, HINSTANCE hModule /*= NULL*/)
{
	CBitmap bm;

	if (hModule)
	{
		HBITMAP hBitmap = ::LoadBitmap(hModule, MAKEINTRESOURCE(nId));

		return aplConvertCBitmap2HICON(hBitmap, clrMask);
	}
	else
	{
		bm.LoadBitmap(nId);
	}

	return aplConvertCBitmap2HICON(bm, clrMask);
}
//////////////////////////////////////////////////////////////////////////