// API.cpp : Определяет точку входа приложения
//

#include "stdafx.h"
#include "API.h"
#define MAX_LOADSTRING 100

//======== Глобальные переменные:
HINSTANCE hInst;						// Текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING];		// Текст заголовка окна
TCHAR szWindowClass[MAX_LOADSTRING];	// Текст регистрации

//======== Прототипы функций, входящих в данный модуль
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
							HINSTANCE hPrevInstance,
							LPSTR lpCmdLine,
							int nCmdShow)
{
	//======= TODO: Помещайте код здесь
	MSG msg;
	HACCEL hAccelTable;

	//======= Инициализация глобальных строк текста
	LoadString(hInstance, IDS_APP_TITLE, szTitle,
											MAX_LOADSTRING);
	LoadString(hInstance, IDC_API, szWindowClass,
											MAX_LOADSTRING);

	//======= Вызов функции регистрации приложения
	MyRegisterClass(hInstance);

	//======= Инициализация приложения:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	//======= Загрузка клавиатурных ускорителей
	hAccelTable = LoadAccelerators(hInstance,
										(LPCTSTR)IDC_API);

	//======= Цикл ожидания и обработки сообщений:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable,
										&msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: Регистрирует оконный класс
//
//  COMMENTS:
//
// Эта функция нужна только если вы хотите, чтобы код был
// совместим с Win32 системами, которые были до создания
// функции 'RegisterClassEx', введенной в Windows 95.
// Вызов 'RegisterClassEx' необходим для правильного
// создания маленькой (small) иконки, ассоциированной
// с приложением.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc		= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance,
								(LPCTSTR)IDI_API);
	wcex.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_API;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm	= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
										 
	return RegisterClassEx(&wcex);
}

//
//		FUNCTION: InitInstance(HANDLE, int)
//
// НАЗНАЧЕНИЕ: Запоминание описателя экземпляра приложения
// и создание главного окна приложения
//
//   COMMENTS:
//
// В этой функции мы запоминаем описатель экземпляра
// приложения в глобальной переменной и создаем главное
// окно приложения.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;

	//======= Запоминаем экземпляра приложения
	hInst = hInstance;
	//======= Создаем главное окно
	hWnd = CreateWindow(szWindowClass, szTitle,
			WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,
			0, NULL, NULL, hInstance, NULL);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  НАЗНАЧЕНИЕ: Обработка сообщений главного окна.
//
//  WM_COMMAND	- обработка команд меню
//  WM_PAINT	- перерисрвка окна
//  WM_DESTROY	- посылка сообщения о завершении и выход
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
								WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		//====== Расшифровка выбора в меню:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst,(LPCTSTR)IDD_ABOUTBOX,hWnd,
						(DLGPROC)About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam,
									lParam);
		}
		break;
	//======= Ветвь перерисовки содержимого окна
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		//======= TODO: Вставьте сюда рисующий код
		EndPaint(hWnd, &ps);
		break;
	//======= Ветвь закрытия окна
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

//======= Обработчик команды вызова диалога About
LRESULT CALLBACK About(HWND hDlg, UINT message,
								WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	//======= Ветвь инициализации окна диалога
	case WM_INITDIALOG:
		return TRUE;

	//======= Ветвь обработки команд, исходящих
	//======= от элементов управления диалога
	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || 
			LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return TRUE;
		}
		break;
	}
	return FALSE;
}


	//===== Структура для работы со стандартным диалогом
	CHOOSECOLOR cc;
	//===== Переменная для хранения текущего цвета
	static COLORREF color = RGB(255,0,0);
	//===== Массив цветов, выбираемых пользователем
	static COLORREF CustColors[16];


	#include <string>
	using namespace std;


	// Если была выбрана команда с идентификатором IDM_COLOR
	case ID_EDIT_COLOR:
		// Подготовка структуры для обмена данными с диалогом
		ZeroMemory(&cc, sizeof(CHOOSECOLOR));

		//====== Ее размер
		cc.lStructSize = sizeof(CHOOSECOLOR);
		//====== Адрес массива с любимыми цветами
		cc.lpCustColors = (LPDWORD)CustColors;
	
		if (ChooseColor(&cc))	// Вызов диалога
		{							// Если была нажата кнопка OK,
			// то запоминаем выбранный цвет
			color = cc.rgbResult;
			// Объявляем недействительной 
			// клиентскую область окна
			InvalidateRect(hWnd,NULL,TRUE);
		}
		break;


	//====== x-координаты:
	static int iXCenter;	// центра окна,
	static int iXPos;		// текущей позиции
 static int iXMax;		// допустимой позиции

	int iYPos = 0;			// Текущая y-координата вывода
	int nLines;				// Количество линий
	SIZE szText;		// Экранные размеры строки текста

	//====== Стили пера Windows
	static DWORD dwPenStyle[] = 
	{
		PS_NULL, PS_SOLID, PS_DOT, PS_DASH,
		PS_DASHDOT, PS_DASHDOTDOT
	};

//====== Строки текста для вывода в окно
	static string style[] = 
	{
		"PS_NULL","PS_SOLID","PS_DOT","PS_DASH",
		"PS_DASHDOT","PS_DASHDOTDOT"
	};

	string sText;		// Дежурная строка текста

	//===== Логическая кисть - как основа для создания пера
	LOGBRUSH lb = { BS_SOLID, color, 0 };


	case WM_SIZE:
		//==== В lParam упрятаны размеры окна.
		//==== Нас интересует только ширина окна
		iXMax = LOWORD(lParam) - 50;
		iXCenter = LOWORD(lParam)/2;
		break;

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		//===== Режим выравнивания текста (см. MSDN)
		SetTextAlign(hdc, TA_NOUPDATECP |
						TA_LEFT | TA_BASELINE);
		sText = "Стили линий в Win32  (Cosmetic pen)";

		//== Выясняем размеры строки с текстом заголовка
		GetTextExtentPoint(hdc,sText.c_str(),
							sText.size(),&szText);

		//===== Сдвигаемся вниз на одну строку
		iYPos += szText.cy;
		iXPos = iXCenter - szText.cx/2;
		//==== Выводим заголовок
		TextOut(hdc,iXPos, iYPos, sText.c_str(),
				sText.size());

		//==== Перебираем массив стилей пера
		nLines = sizeof(style)/sizeof(style[0]);
		for (int i = 0; i < nLines; i++)
		{
			//===== Устанавливаем биты стиля пера
			DWORD dw = PS_COSMETIC | dwPenStyle[i];
			//===== Создаем перо с учетом стиля
			//===== и толщиной в 1 пиксел
			HPEN hp = ExtCreatePen(dw, 1, &lb, 0,NULL);
			//===== Помещаем перо в контекст устройства
			HPEN hOld = (HPEN)SelectObject(hdc,hp);
			iYPos += szText.cy;			// Сдвиг позиции
			//===== Помещаем перо в точку (10, iYPos)
			MoveToEx(hdc, 10, iYPos, NULL);
			//==== Проводим линию до точки (iXMax, iYPos)
			LineTo(hdc, iXMax, iYPos);
			//=== Возвращаем старое перо в контекст устройства
			SelectObject(hdc, hOld);
			//=== Освобождаем ресурс пера
			DeleteObject(hp);
			//=== Выводим поясняющий текст
			TextOut(hdc, 10, iYPos, style[i].c_str(),
						style[i].size());
		}

		EndPaint(hWnd, &ps);
		break;


//======= Косметическое перо (alternate - solid)
		lb.lbStyle = BS_SOLID;
		sText = "Косметическое перо alternate или solid";
		GetTextExtentPoint(hdc,sText.c_str(),
								sText.size(),&szText);

		iYPos += 2 * szText.cy;
		iXPos = iXCenter - szText.cx/2;
		TextOut(hdc, iXPos, iYPos,
						sText.c_str(), sText.size());

		for (i = 0; i < 2; i++) 
		{
			DWORD dw = i ? PS_COSMETIC
							: PS_COSMETIC | PS_ALTERNATE;
			HPEN hp = ExtCreatePen(dw, 1, &lb, 0, NULL);
			HPEN hOld = (HPEN)SelectObject(hdc, hp);
			iYPos += szText.cy;
			MoveToEx(hdc, 10, iYPos, NULL);
			LineTo(hdc, iXMax,iYPos);
			SelectObject(hdc, hOld);
			DeleteObject(hp);
			TextOut(hdc, 10, iYPos, alt[i].c_str(),
								alt[i].size());
		}


	//====== Узоры штрихов (hatch) кисти, на основе
	//====== которых будет основано перо
	static UINT uHatch[] =
	{
		HS_BDIAGONAL, HS_CROSS, HS_DIAGCROSS,
		HS_FDIAGONAL, HS_HORIZONTAL, HS_VERTICAL
	};
	//===== Строки текста для пояснений
	static string brush[] =
	{
		"HS_BDIAGONAL", "HS_CROSS", "HS_DIAGCROSS",
		"HS_FDIAGONAL", "HS_HORIZONTAL", "HS_VERTICAL"
	};


LineTo(hdc, iXMax, iYPos + 3);


//======== Геометричесое перо
		lb.lbStyle = BS_HATCHED;		// Узорная кисть
		sText = "Стили на основе кисти (Geometric pen)";
		GetTextExtentPoint(hdc,sText.c_str(),
								sText.size(),&szText);
		iYPos += 2 * szText.cy;		// Сдвиг позиции вывода
		iXPos = iXCenter - szText.cx/2;
		TextOut(hdc, iXPos, iYPos,
								sText.c_str(), sText.size());
		nLines = sizeof(brush)/sizeof(brush[0]);

		for (i = 0; i < nLines; i++)
		{
			//======= Выбираем узор штриха кисти
			lb.lbHatch = uHatch[i];
			//== Создаем на его основе перо тощиной 5 пиксел
			HPEN hp = ExtCreatePen(PS_GEOMETRIC, 5, &lb,0,0);
			HPEN hOld = (HPEN)SelectObject(hdc, hp);
			iYPos += szText.cy;
			MoveToEx(hdc, 10, iYPos, NULL);
			LineTo(hdc, iXMax,iYPos);
			SelectObject(hdc, hOld);
			DeleteObject(hp);
			TextOut(hdc, 10, iYPos, brush[i].c_str(),
						brush[i].size());
		}


	//======= Три узора геометрического пера
	static DWORD dwUser[3][4] =
	{
		{8,3,3,3},
		{3,3,3,3},
		{15, 4, 3, 4}
	};



//======= Геометричесое перо (user-defined)
		lb.lbStyle = BS_SOLID;

		sText = "Стили на основе узора (Geometric pen)";
		GetTextExtentPoint(hdc,sText.c_str(),
								sText.size(),&szText);
		iYPos += 2 * szText.cy;
		iXPos = iXCenter - szText.cx/2;
		TextOut(hdc, iXPos, iYPos,
							sText.c_str(), sText.size());
		nLines = sizeof(dwUser)/sizeof(dwUser[0]);
		//====== Перебираем узоры пользователя
		//====== (строки массива dwUser)
		for (i = 0; i < nLines; i++)
		{
			DWORD dw = PS_GEOMETRIC | PS_USERSTYLE
						| PS_ENDCAP_FLAT;
			HPEN hp = ExtCreatePen(dw, i+2, &lb, 4, dwUser[i]);
			HPEN hOld = (HPEN)SelectObject(hdc, hp);
			iYPos += szText.cy;
			MoveToEx(hdc, 10, iYPos, NULL);
			LineTo(hdc, iXMax,iYPos);
			SelectObject(hdc, hOld);
			DeleteObject(hp);
			TextOut(hdc, 10, iYPos,
							user[i].c_str(), user[i].size());
		}


	//======= Массив идентификаторов bitmap
	static UINT nPatterns[] =
	{
		IDB_PAT1, IDB_PAT2, IDB_PAT3
	};
	static string bitmap[] =
	{
		"BS_PATTERN, 1", "BS_PATTERN, 2", "BS_PATTERN, 3"
	};


	//======= Геометричесое перо (bitmap)
	lb.lbStyle = BS_PATTERN;
	sText = "Стили на основе bitmap-узора (Geometric pen)";
	GetTextExtentPoint(hdc,sText.c_str(),
							sText.size(),&szText);
	iYPos += 2 * szText.cy;
	iXPos = iXCenter - szText.cx/2;
	TextOut(hdc, iXPos, iYPos, sText.c_str(), sText.size());
	nLines = sizeof(nPatterns)/sizeof(nPatterns[0]);

	for (i = 0; i < nLines; i++) 
	{
		HBITMAP hBmp;
		hBmp = LoadBitmap(GetModuleHandle(NULL),
									(char*)nPatterns[i]);
		lb.lbHatch = long(hBmp);
		HPEN hp = ExtCreatePen(PS_GEOMETRIC, 5, &lb, 0, 0);
		HPEN hOld = (HPEN)SelectObject(hdc, hp);
		iYPos += szText.cy;
		MoveToEx(hdc, 10, iYPos, NULL);
		LineTo(hdc, iXMax,iYPos);
		SelectObject(hdc, hOld);
		DeleteObject(hp);
		TextOut(hdc, 10, iYPos, bitmap[i].c_str(),
					bitmap[i].size());
	}



