Показано с 1 по 17 из 17

Социальные закладки

  1. #1
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 11 за это сообщение
    1,688 Всего

    По умолчанию [C/C++] Graphical User Interface DirectX v.2017

    В связи с неактуальностью некоторых аспектов в данной теме(имхо),Решил описать более "качественное" решение. Сначала хотел просто поправить код в старой теме, но поразмыслив решил что проще будет написать все с нуля, с опорой на предыдущию вариацию.
    Буду по мере свободного времени описывать код и методы, которые помогут новичкам(надеюсь) разобраться в механике построения графического интерфейса под свои нужды.

    Текст скорее всего будет с орф. ошибками и исправлять их скорее всего не буду(хотя постараюсь писать грамотно), поэтому по этому поводу прошу не поднимать шум и принять это как стиль написания автора)
    Вариации выбора того или иного решения будут складываться из личного опыта и наблюдений, и не претендуют на звание "эталонное решение"))


    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    Последний раз редактировалось qazwar; 24.02.2017 в 16:28.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  2. Сказали спасибо:

    Velasav (26.01.2018) , MOPO3OB (25.11.2017) , Jefferson (26.09.2017) , Freedrikson (19.09.2017) , prapor (18.04.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (20.02.2017) , SKY (20.02.2017) , ropox (20.02.2017)

  3. #2
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 11 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Все примеры будут описаны на "MVS2015 Rus" с применением стандарта С++11.


    Step #1: Создание проекта. Первичная настройка.
    1) Создаем пустой проект Win32(я назвал проект "GUI DX v.2017")
    2) [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]


    Tеперь у нас стоит выбор в способе подключения этого SDK к проекту.Вариантов несколько, но предлагаю рассмотреть два, на мой взгляд, самых "правильно-актуальных", назовем их "удаленное подключение" и "компактное".
    1. В случаи с "удаленным подключением" Папка с SDK хранится отдельно от папки проекта и для подключения его к проекту требуется указать рабочии папки в настройках проекта.
      ПКМ по проекту->Свойства->Каталоги VC++: В графе "Каталоги включения" указываем путь к папке "Include" из SDK. В графе "Каталоги библиотек" указываем путь к папке "Lib\xXX", где ".хХХ" это папка с названием конечной платформы требуемого приложения(Win32либо Win64).
    2. "Компактное", именно его я и буду использовать: переносим папку с SDK в папку созданного проекта.
      у меня вышло так:
      Код:
      C:\Users\Sergey\Documents\Visual Studio 2015\Projects\GUI DX v.2017\GUI DX v.2017\SDK_Jun2010
      и так же в свойствах указываем пути к папкам, но после выбора вручную правим путь на следующий:
      Код:
      $(SolutionDir)\GUI DX v.2017\SDK_Jun2010\Include
      и соответственно для Lib:
      Код:
      $(SolutionDir)\GUI DX v.2017\SDK_Jun2010\Lib\x86

    Общий вес проекта увеличился, но это дало нам возможность "таскать" проект где хочется, без лишних подстроек путей.


    Остальные настройки ставим по желанию. Я оставил все в дефолте.

    Создал файл main.cpp (именно он будет у нас основным) и файл cInclude.h(он будет как дополнительный со всеми ссылками на последующие).
    В cInclude.h подключил необходимые зоголовки:
    Код:
    #pragma once
    #include <Windows.h>
    #include <process.h>
    в main.cpp подключил cInclude.h и описал точку входа и пустой поток:
    Код:
    #include "cInclude.h"
    
    
    unsigned APIENTRY GUIDX(LPVOID  lpParam)
    {
        
        return 0L;
    }
    
    
    BOOL APIENTRY DllMain(_In_ HINSTANCE hinstDLL,_In_ DWORD dwReason,_In_ LPVOID  lpvReserved)
    {
        DisableThreadLibraryCalls(hinstDLL);
        switch (dwReason) 
        {
        case DLL_PROCESS_ATTACH:  
        {
            _beginthreadex(NULL, NULL, GUIDX, NULL, NULL, NULL);
        }
                                 break;
        case DLL_THREAD_ATTACH:
    
            break;
        case DLL_THREAD_DETACH:
    
            break;
        case DLL_PROCESS_DETACH:
    
            break;
        }
        return TRUE;
    }
    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]

    ЗЫ: готовые проекты к каждому шагу прикреплять скорее всего не буду.
    Последний раз редактировалось qazwar; 20.02.2017 в 22:15.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  4. Сказали спасибо:

    MOPO3OB (25.11.2017) , Jefferson (26.09.2017) , Freedrikson (19.09.2017) , nx_always (24.08.2017) , Mick Rory (20.07.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (21.02.2017) , ropox (21.02.2017) , SKY (20.02.2017)

  5. #3
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 11 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #2: Универсальное решение хука
    В качестве основного решения для хука я выбрал open source библиотеку [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]. Что дает данное решение:
    • Работоспособность на всех актуальных ОС(Win7, 8.1,10)
    • Работоспособность для различных платформ (Win32, Win64)
    • Простота использования
    • Открытый исходный код
    Но для еще более удобного использования этой Lib, опишем для нее обвязку классом(в конце будет ссылка на архив с либой и готовой обвязкой).
    • Скачиваем исходник MiniHook.
    • Создаем папку "MiniHook" в папке с проектом.
    • Помешаем в нее папки "include" и "src" из скаченного архива
    Для того, что бы файлы с которыми мы не будем работать не мешались, добавим фильтр к проекту: ПКМ-Добавить-Новый фильтр (назвал его MHook. И добавил в него все скопированные файлы.

    Отмеченные красным - это файлы библиотеки MiniHook, отмеченные зеленым - файлы созданные мной. Фиолетовым - это бонус, который нам в этом проекте не пригодится, но будет весьма полезен для хука игровых интерфейсов и виртуальных функций.

    Содержимое cDetour.h:
    Код:
    #pragma once
    template<typename T>
    class cDetour
    {
    public:
    	explicit cDetour<T>(T target, T detour) : m_target(target), m_detour(detour)
    	{
    		MH_CreateHook(m_target, m_detour, reinterpret_cast<void**>(&m_trampoline));
    	}
    	~cDetour()
    	{
    		MH_DisableHook(m_target);
    	}
    	T GetTrampoline() const
    	{
    		return static_cast<T>(m_trampoline);
    	}
    	bool IsApplied() const
    	{
    		return m_isEnabled;
    	}
    	void Apply()
    	{
    		if (!m_isEnabled)
    		{
    			m_isEnabled = MH_EnableHook(m_target) == MH_OK;
    			if (m_isEnabled)
    				memcpy(m_hookBuffer, m_target, sizeof(m_hookBuffer));
    		}
    	}
    	void Remove()
    	{
    		m_isEnabled = !(m_isEnabled && MH_DisableHook(m_target) == MH_OK);
    	}
    	void EnsureApply()
    	{
    		if (memcmp(m_hookBuffer, m_target, sizeof(m_hookBuffer)) != 0)
    		{
    			DWORD oldProtect;
    			VirtualProtect(m_target, sizeof(m_hookBuffer), PAGE_READWRITE, &oldProtect);
    			memcpy(m_target, m_hookBuffer, sizeof(m_hookBuffer));
    			VirtualProtect(m_target, sizeof(T), oldProtect, &oldProtect);
    		}
    	}
    private:
    	T m_trampoline;
    	T m_target;
    	T m_detour;
    	bool m_isEnabled = false;
    	char m_hookBuffer[20];
    
    };
    содержимое cHookContext.h:
    Код:
    #pragma once
    #include "MinHook.h"
    #include "cDetour.h"
    #include "cVmt.h"
    
    class cContext
    {
    public:
    	static cContext& GetInstance();
    	 
    	template<typename T> cDetour<T>* CreateDetour(T target, T detour)
    	{
    		auto pDetour = new cDetour<T>(target, detour);
    		return pDetour;
    	}
    	template<typename T> bool        ApplyDetour(T target, T detour, cDetour<T>** ppDetour)
    	{
    		auto pDetour = CreateDetour(target, detour);
    		if (pDetour)
    		{
    			*ppDetour = pDetour;
    			pDetour->Apply();
    			return true;
    		}
    		return false;
    	}
    	
    	template<typename T> cVmt<T>* CreateVmt(void** ppVtable, size_t index, T detour)
    	{
    		auto pVmtHook = new cVmt<T>(ppVtable, index, detour);
    		return pVmtHook;
    	}
    	template<typename T> bool     ApplyVmt(void** ppVtable, size_t index, T detour, cVmt<T>** ppVmtHook)
    	{
    		auto pVmtHook = CreateVmt(ppVtable, index, detour);
    		if (pVmtHook)
    		{
    			*ppVmtHook = pVmtHook;
    			pVmtHook->Apply();
    			return true;
    		}
    		return false;
    	}
    	
    	
    	void CloseExit()
    	{
    		if (!(MH_Uninitialize() == MH_OK))
    			TerminateProcess(GetCurrentProcess(), -1);
    	}
    	cContext() {}
    	~cContext() {}
    };
    
    bool bInitialized = false;
    cContext& cContext::GetInstance()
    {
    	if (!bInitialized)
    		bInitialized = MH_Initialize() == MH_OK;
    	static cContext pCtx;
    	return pCtx;
    }
    в cInclude.h подключаем cHookContext.h
    Код:
    #include "MinHook\include\cHookContext.h"
    как видим все довольно просто. Пример для WinAPI функции с использованием этой обвязки можно посмотреть тут

    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  6. Сказали спасибо:

    MOPO3OB (25.11.2017) , Jefferson (26.09.2017) , Freedrikson (19.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (21.02.2017) , ropox (21.02.2017) , SKY (20.02.2017)

  7. #4
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 10 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #3: "DirectX Hooking Interface"

    Первым делом подключим к проекту заголовки и либы DX9:
    Код:
    #include <d3d9.h>
    #include <d3dx9.h>
    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")
    Для хука нам требуется прототип функции и указатель на нее относительно класса нашей обвязки MiniHook. Для всех необходимых нужд нам нужны две функции: Present и Reset. Present необходим для вывода на экран информации, а Reset для сброса и перегрузки интерфейсов DX.
    Код:
    typedef HRESULT(APIENTRY* PresentFn)(IDirect3DDevice9 *, CONST RECT*, CONST RECT*, HWND, CONST RGNDATA*);
    cDetour<PresentFn>* oPresent;
    typedef HRESULT(APIENTRY *ResetFn)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*);
    cDetour<ResetFn>* oReset;
    опишем наш метод подмены:
    Код:
    HRESULT APIENTRY myPresent(IDirect3DDevice9 * m_pDevice, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
    {
    	
    	return oPresent->GetTrampoline()(m_pDevice, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);;
    }
    HRESULT APIENTRY myReset(IDirect3DDevice9* m_pDevice, D3DPRESENT_PARAMETERS *pPresentationParameters)
    {
    	auto   result = oReset->GetTrampoline()(m_pDevice, pPresentationParameters);
    	return result;
    }
    ну и сам хук:
    Код:
    bool Init()
    {
    	bool    bResult = false;
    	HMODULE hD3d9 = NULL;
    	if (hD3d9 = GetModuleHandleA("d3d9.dll"))
    	{
    		typedef HRESULT(APIENTRY* Direct3DCreate9ExFn)(UINT, IDirect3D9Ex**);
    		Direct3DCreate9ExFn oDirect3DCreate9Ex = (Direct3DCreate9ExFn)GetProcAddress(hD3d9, "Direct3DCreate9Ex");
    		if (oDirect3DCreate9Ex)
    		{
    			HRESULT hr = D3D_OK;
    			LPDIRECT3D9EX m_pCreate9Ex = nullptr;
    			if (SUCCEEDED(hr = oDirect3DCreate9Ex(D3D_SDK_VERSION, &m_pCreate9Ex)))
    			{
    				D3DPRESENT_PARAMETERS dp;
    				ZeroMemory(&dp, sizeof(dp));
    				dp.Windowed = 1;
    				dp.SwapEffect = D3DSWAPEFFECT_FLIP;
    				dp.BackBufferFormat = D3DFMT_A8R8G8B8;
    				dp.BackBufferCount = 1;
    				dp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    
    				IDirect3DDevice9Ex *mDevice = nullptr;
    				if (SUCCEEDED(hr = m_pCreate9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &dp, NULL, &mDevice)))
    				{
    					bResult = true;
    					PVOID* vtbl = *reinterpret_cast<PVOID**>(mDevice);
    					auto& pContext = cContext::GetInstance();
    					pContext.ApplyDetour<PresentFn>(static_cast<PresentFn>(vtbl[17]), reinterpret_cast<PresentFn>(myPresent), &oPresent);
    					pContext.ApplyDetour<ResetFn>(static_cast<ResetFn>(vtbl[16]), reinterpret_cast<ResetFn>(myReset), &oReset);				
    					mDevice->Release();
    
    				}
    				m_pCreate9Ex->Release();
    			}
    		}
    	}
    	return bResult;
    }
    тут нет не чего сложного, просто создаем устройство DX по заданным параметрам.

    в нашем потоке стартуем ее с ожиданием положительного ответа:
    Код:
    unsigned APIENTRY GUIDX(LPVOID  lpParam)
    {
    	while (!Init())
    		Sleep(200);
    	return 0L;
    }
    ЗЫ: Данный метод 100% работает на Win7, Win8.1, Win10.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  8. Сказали спасибо:

    MOPO3OB (25.11.2017) , Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (21.02.2017) , ropox (21.02.2017) , SKY (20.02.2017)

  9. #5
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 10 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #4: Rendering. Графическая основа проекта

    Графическая часть "наше" все. именно она задаст стабильность и плавность выполнения остального составляющего. Если с ней ошибиться, то на выходе получим совершенно "неблагоприятны продукт".
    Это может выражаться в просадке FPS, утечке памяти и прочих нехороших финтов.

    Для общего использования опишем класс для хранения цвета(cColor.h):
    Код:
    class Color
    {
    
    #define DEFCOLOR_SRC(name, r, g, b) static Color name##(){ return Color(r, g, b); }
    public:
    	int a, r, g, b;
    
    	Color() 
    	{ 
    		Color(0, 0, 0, 0);
    	}
    	Color(int a, int r, int g, int b)
    	{
    		this->a = a;
    		this->r = r;
    		this->g = g;
    		this->b = b;
    	}
    	Color(int r, int g, int b)
    	{
    		this->a = 255;
    		this->r = r;
    		this->g = g;
    		this->b = b;
    	}
    	Color(unsigned long color)
    	{
    		this->b = (color & 0xff);
    		this->g = ((color >> 8) & 0xff);
    		this->r = ((color >> 16) & 0xff);
    		this->a = ((color >> 24) & 0xff);
    	}
    	
    
    	inline float* Base()
    	{
    		float fColor[3];
    		fColor[0] = this->r / 255.0f;
    		fColor[1] = this->g / 255.0f;
    		fColor[2] = this->b / 255.0f;
    		return &fColor[0];
    	}
    	inline float rBase() const { return this->r / 255.0f; }
    	inline float gBase() const { return this->g / 255.0f; }
    	inline float bBase() const { return this->b / 255.0f; }
    	inline float aBase() const { return this->a / 255.0f; }
    
    
    	inline operator unsigned long() const
    	{ 	
    		return (a << 24) | (r << 16) | (g << 8) | b;	
    	}
    
    
    	DEFCOLOR_SRC(Black, 0, 0, 0);
    	DEFCOLOR_SRC(White, 255, 255, 255);
    	DEFCOLOR_SRC(Red, 255, 0, 0);
    	DEFCOLOR_SRC(Green, 0, 128, 0);
    	DEFCOLOR_SRC(Blue, 0, 0, 255);
    	 
    };
    как видим у нас есть несколько конструкторов класса, которые позволяют задавать параметры для ARGB каналов, в виде целых чисел(0-255). Так же конструктор
    Код:
    Color(unsigned long color)
    и оператор
    Код:
    inline operator unsigned long() const
    дает возможность работать нам с HEX значениями цвета(x00 - xFF)
    а методы
    Код:
    inline float ##Base() const
    получить значение цвета во float(0.f-1.f).


    Теперь опишем класс нашего рисования:
    Создаем класс cRender и заполняем(как работает думаю не стоит объяснять. Кому нужно либо знают, либо самостоятельно найдут в интернете. а кому не нужно просто скопируют):
    cRender.h:
    Код:
    #pragma once
    #include <d3d9.h>
    #include <d3dx9.h>
    #include "Color.h"
    #include <stdio.h>
    #include <math.h>
    
    #define DT_SHADOW  0x0040
    
    struct DX_VERTEX
    {
    	DX_VERTEX(float X, float Y, float Z, DWORD Color) :
    		x(X), y(Y), z(Z), color(Color) {};
    	DX_VERTEX(){}
    
    
    	float x;
    	float y;
    	float z;
    	float rhw = 1.0f;
    	DWORD color;
    	static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
    };
    
    class cRender
    {
    public:
    	cRender(IDirect3DDevice9 *m_pDevice);
    	~cRender();
    
    	void LostDevice();
    	void ResetDevice();
    
    	void   render_Line(float x, float y, float x2, float y2, Color color);
    	void   render_Border(float x, float y, float w, float h, Color color);
    	void   render_Box(float x, float y, float w, float h, Color color);
    	void   render_Circle(float x, float y, float radius, Color color);
    	void   render_String(float x, float y, Color color, DWORD dwFlag, const TCHAR* fmt, ...);
    
    
    
    	HRESULT  GetTextExtent(const char* text, SIZE* pSize);
    private:
    	IDirect3DDevice9 *m_pDevice;
    	ID3DXFont        *m_pFont;
    	TCHAR            *szFomtName;
    };
    
    extern cRender *pRender;
    cRender.cpp:
    Код:
    #include "cRender.h"
    
    
    #pragma comment(lib, "d3d9.lib")
    #pragma comment(lib, "d3dx9.lib")
    
    cRender *pRender = nullptr;
    cRender::cRender(IDirect3DDevice9 *m_pDevice)
    {
    	this->m_pDevice = m_pDevice;
    	szFomtName = __TEXT("Tahoma");
    	
    	D3DXCreateFont(m_pDevice, 13, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, szFomtName , &m_pFont);
    
    }
    
    void cRender::LostDevice()
    {
    	if (m_pFont)
    		m_pFont->OnLostDevice();
    }
    void cRender::ResetDevice()
    {
    	if (m_pFont)
    		m_pFont->OnResetDevice();
    }
    
    void cRender::render_Line(float x, float y,float x2, float y2, Color color)
    {
    	DX_VERTEX Vertices[2] =
    	{
    		DX_VERTEX(x, y, 0.f, color),
    		DX_VERTEX(x2, y2, 0.f, color)
    	};
    
    	this->m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    	this->m_pDevice->SetFVF(DX_VERTEX::FVF);
    	this->m_pDevice->SetTexture(0, NULL);
    	this->m_pDevice->DrawPrimitiveUP(D3DPT_LINELIST, 1, Vertices, sizeof(DX_VERTEX));
    }
    void cRender::render_Border(float x, float y, float w, float h, Color color)
    {
    	 
    	DX_VERTEX Vertex[5] =
    	{
    		DX_VERTEX(x, y, 0.0f, color),
    		DX_VERTEX(x + w, y, 0.0f, color),
    		DX_VERTEX(x + w, y + h, 0.0f, color),
    		DX_VERTEX(x, y + h, 0.0f, color),
    		DX_VERTEX(x, y, 0.0f, color)
    	};
    	this->m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    	this->m_pDevice->SetFVF(DX_VERTEX::FVF);
    	this->m_pDevice->SetTexture(0, NULL);
    	this->m_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, Vertex, sizeof(DX_VERTEX));
    }
    void cRender::render_Box(float x, float y, float w, float h, Color color)
    {
    	DX_VERTEX Vertex[4] =
    	{
    		DX_VERTEX(x, y, 0.0f,        color),
    		DX_VERTEX(x + w, y, 0.0f,     color),
    		DX_VERTEX(x, y + h, 0.0f,     color),
    		DX_VERTEX(x + w, y + h, 0.0f,  color)
    	};
    	this->m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    	this->m_pDevice->SetFVF(DX_VERTEX::FVF);
    	this->m_pDevice->SetTexture(0, NULL);
    	m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, &Vertex[0], sizeof(DX_VERTEX));
    }
    void cRender::render_Circle(float x, float y, float radius, Color color)
    {
    	const int NUMPOINTS = 360/*24*/;
    	DX_VERTEX circle[NUMPOINTS + 1];
    	float theta;
    	float  wedgeAngle = (float)((2 * D3DX_PI) / NUMPOINTS);
    	for (int i = 0; i <= NUMPOINTS; i++) 
    	{
    		theta = i * wedgeAngle;
    		circle[i].x = (float)(x + radius * cos(theta));
    		circle[i].y = (float)(y - radius * sin(theta));
    		circle[i].z = 0;
    		circle[i].rhw = 1.0f;
    		circle[i].color = color;
    	}
    
    	this->m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
    	this->m_pDevice->SetFVF(DX_VERTEX::FVF);
    	this->m_pDevice->SetTexture(0, NULL);
    	this->m_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, NUMPOINTS, &circle[0], sizeof(DX_VERTEX/*circle[0]*/));
    
    }
    void cRender::render_String(float x, float y, Color color, DWORD dwFlag, const TCHAR* fmt, ...)
    {
    	TCHAR buffer[512];
    	va_list args;
    	va_start(args, fmt);
    
    #ifdef _UNICODE
    	vswprintf_s(buffer, fmt, args);
    #else
    	vsprintf_s(buffer, fmt, args);
    #endif
    	
    	va_end(args);
    
    	DWORD dwMainFlags = NULL;
    	RECT r,
    		rs[4];
    
    	dwMainFlags = dwFlag | DT_CALCRECT | DT_NOCLIP;
    
    	if (dwFlag & DT_SHADOW)
    	{
    		SetRect(&rs[0], (int)x - 1, (int)y, (int)x, 0);
    		SetRect(&rs[1], (int)x + 1, (int)y, (int)x, 0);
    		SetRect(&rs[2], (int)x, (int)y - 1, (int)x, 0);
    		SetRect(&rs[3], (int)x, (int)y + 1, (int)x, 0);
    		for (INT i = NULL; i < 4; i++)
    		{
    			this->m_pFont->DrawText(nullptr, buffer, -1, &rs[i], dwMainFlags, 0xFF000000);
    			if (dwMainFlags & DT_CALCRECT)
    				this->m_pFont->DrawText(nullptr, buffer, -1, &rs[i], NULL, 0xFF000000);
    		}
    	}
    	SetRect(&r, (int)x, (int)y, (int)x, 0);
    	this->m_pFont->DrawText(nullptr, buffer, -1, &r, dwMainFlags, color);
    	if (dwMainFlags & DT_CALCRECT)
    		this->m_pFont->DrawText(nullptr, buffer, -1, &r, NULL, color);
    }
    
    
    HRESULT cRender::GetTextExtent(const char* text, SIZE* pSize)
    {
    	if (NULL == text || NULL == pSize)
    		return E_FAIL;
    
    	RECT Rect = { 0, 0, 0, 0 };
    	this->m_pFont->DrawTextA(NULL, text, -1, &Rect, DT_CALCRECT, 0xff000000);
    	pSize->cx = Rect.right - Rect.left;
    	pSize->cy = Rect.bottom - Rect.top;
    	return S_OK;
    }
    cRender::~cRender()
    {
    }
    Как видим этот класс дает нам возможность нарисовать основные геометрические элементы.

    Теперь подключим все это к проекту и иницализируем:
    в cInclude.h подключаем заголовок и заведем переменную bool:
    Код:
    #include "cRender\cRender.h"
    bool     Create = false;
    в myPresent() инициализируем:
    Код:
    if (Create == false)
    	{
    		pRender = new cRender(m_pDevice);
    		Create = true;
    	}
    	else
    	{
    		//Тут рисуем все что хотим
    	}
    в myReset() перегружаем по условию:
    Код:
    if (!Create)
    		return m_pDevice->Reset(pPresentationParameters);
    
    	pRender->LostDevice();
    	auto   result = oReset->GetTrampoline()(m_pDevice, pPresentationParameters);
    
    	if (SUCCEEDED(result))
    	{
    		pRender->ResetDevice();
    	}
    Выведем все возможности cRender:
    Код:
    pRender->render_Line(10, 10, 10, 400, Color::Red());
    		pRender->render_Box(30, 30, 50, 50, Color(78, 78, 78));
    		pRender->render_Border(40, 40, 50, 50,0xFFFF0000);
    		pRender->render_String(100, 100, Color(255, 0, 255, 0), DT_LEFT | DT_SHADOW, L"Cheaton.ru");
    		
    		SIZE pSize;
    		pRender->GetTextExtent("Cheaton.ru", &pSize);
    		pRender->render_Line(100-2, 100, 100-2, 100 + pSize.cy, Color::Green());
    		pRender->render_Line(100, 102 + pSize.cy, 100 + pSize.cx, 102 + pSize.cy, Color::Green());



    [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке](в архиве присутствует собранная DLL и D3D9Test)
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  10. Сказали спасибо:

    MOPO3OB (25.11.2017) , Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (21.02.2017) , ropox (21.02.2017) , SKY (20.02.2017)

  11. #6
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 9 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #5: Menu. Начало.

    Основная площадка подготовлена, теперь предстоит самое сложное(на мой взгляд) - это определится с основной концепцией и общей реализацией.

    Для внешнего вида, я определил такую конфигурацию:

    Такая конфигурация уже зарекомендовала себя простотой и удобством, да и выглядит вполне пристойно.можно конечно изобретать сложные графические интерфейсы по типу ImGui, wxWidgets, CEF.... но поставленная цель: Написать простую и понятную графическую оболочку, которую может осилить новичок(wxWidgets и CEF я до сих пор не смог осилить(().

    В общем ближе к делу: Внешний вид определен и у нас уже есть "лекало". так что приступим)

    для реализации меню будем использовать отдельный класс( косим под ОПП). Тут встает вопрос: как использовать ранее описанный рендер? вариантов много, но на ум приходит всего два более подходящих: использовать глобальный указатель или передавать ссылку на объект класса рендера. Именно второй вариант более пригляден.В данном примере я все делаю на основе Dx9, но данный подход даст нам возможность просто портировать меню под другие версии рендеринга. а так же описав виртуальный класс использовать несколько видов способов рисовки(Dx9, Dx11,OpGL, vulkan....) не затрагивая сам класс меню.

    Создаем класс cMenu:
    в .h файле определяем заголовок ранее созданного рендера
    Код:
    #include "../cRender/cRender.h"
    а сам зоголовок меню прописываем в cInclude.h
    Код:
    #include "cMenu\cMenu.h"
    cMenu.h:
    Код:
    #pragma once
    #include "../cRender/cRender.h"
    
    class cMenu
    {
    public:
    	cMenu(cRender &Render);
    	virtual ~cMenu();
    	 
    private:
    	cRender *m_pRender;
    };
    extern cMenu *Menu;
    cMenu.cpp:
    Код:
    #include "cMenu.h"
    
    cMenu *Menu = nullptr;
    cMenu::cMenu(cRender &Render)
    {
    	m_pRender = &Render;
    }
    
    cMenu::~cMenu()
    {
    }
    Это будет основой нашего интерфейса.Тут конечно проще и целесообразней было бы использовать умные указатели, но будем обходиться, на сколько это возможно, без STL.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  12. Сказали спасибо:

    Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (22.02.2017) , $!№9@r (21.02.2017) , SKY (21.02.2017)

  13. #7
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 9 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #6: Menu. Общая реализация."TabControl".

    Для реализации легкого управления цветом и основными кнопками меню заведем в cMenu.h два перечисления за пределами класса:
    Код:
    /*перечисления для цветов интерфейса*/
    enum GUIColorScheme
    {
    	color_Background,
    	color_Border, 
    	color_Title,
    	color_Text,
    	color_Active,
    	color_Hover,
    	COUNT_COLOR
    };
    /*перечисления основных кнопок*/
    enum Button
    {
    	TAB_VISUAL,
    	TAB_WEAPON,
    	TAB_PLAYER,
    	TAB_OTHER,
    	COUNT_TAB
    };
    в приватные члены класса добавим массив для цветов:
    Код:
    Color GUIColor[COUNT_COLOR];
    для установки параметров цветовой гаммы описываем функцию:
    Код:
    void cMenu::SetColor(int iAlfa/* = 255*/)
    {
    	GUIColor[color_Background] = Color(iAlfa, 26, 26, 26);
    	GUIColor[color_Border]     = Color(iAlfa, 73, 73, 73);
    	GUIColor[color_Title]      = Color(iAlfa, 245, 239, 3);
    	GUIColor[color_Text]       = Color(iAlfa, 0, 204, 0);
    	GUIColor[color_Active]     = Color(iAlfa, 0, 255, 0);
    	GUIColor[color_Hover]      = Color(iAlfa, 0, 191, 255);
    }
    и вызываем ее в конструкторе класса cMenu.
    Теперь для установки параметров размера и положения опишем внутри класса структуры и указатели на них(под приватным флагом):
    Код:
    	struct MenuItem
    	{
    		float x;
    		float y;
    	};
    	struct Context
    	{
    		float WidthMain;
    		float HeightMain;
    		float WidthControl;
    		float HeightControl;
    		float HeightTitle;
    		Context()
    		{
    			WidthMain = 160.f;
    			HeightMain = 22.f;
    
    			WidthControl = 350.f;
    			HeightControl = 22.f;
    
    			HeightTitle = 26.f;
    		}
    	};
    private:
    	Context  m_pCtx;
    	MenuItem ItemMenu;
            float xPos;
    	float yPos;
    первая структура будет хранить каждое последующее положение контрола, а вторая все основные размеры меню. Это даст нам возможность быстро и без всяких трудностей оперировать внешним видом.
    Допишем параметры конструктора и зададим данные:
    Код:
    cMenu(cRender &Render, float xPos, float yPos)
    Код:
    cMenu::cMenu(cRender &Render, float xPos, float yPos)
    {
    	m_pRender  = &Render;
    	this->xPos = xPos;
    	this->yPos = yPos;
    	SetColor();
    }
    Добавим bool переменную для установки показа\скрытия меню и SIZE для получения размеров текста(private):
    Код:
    bool  ShowGUI;
      SIZE pSize;
    иницализировав ShowGUI в конструкторе мы получим следующее:
    true - меню сразу показывается при инжекте.
    false - нужно вызвать меню после инжекта для показа.
    Код:
    pRender->GetTextExtent("<<", &pSize);
    После всех действий у нас получается:
    Код:
    cMenu::cMenu(cRender &Render, float xPos, float yPos)
    {
    	m_pRender  = &Render;
    	ShowGUI    = true;
    	this->xPos = xPos;
    	this->yPos = yPos;
    	SetColor();
    	pRender->GetTextExtent("<<", &pSize);
    }
    Перейдем непосредственно к обрисовке задуманного:
    Добавим функцию которая нам вернет статус при наведении курсора на указанную область:
    Код:
    bool cMenu::IsInControl(float x, float y, float w, float h)
    {
    	POINT MousePosition;
    	GetCursorPos(&MousePosition);
    	ScreenToClient(GetForegroundWindow(), &MousePosition);
    	return(MousePosition.x >= x && MousePosition.x <= x + w && MousePosition.y >= y && MousePosition.y <= y + h);
    }
    добавим два вызова:
    Код:
    	void Draw();
    	void RenderMenu();
    Draw - это непосредственно наша отрисовка, ее мы будем вызывать в myPresent
    RenderMenu - это описание нашего меню

    В cMenu.cpp добавим контейнер и пару переменных, подключив заголовок <vector>:
    Код:
    std::vector<int> vTab(COUNT_TAB);
    int              Tab_Number = 0;
    int              Tab_Max = 0;
    и опишем:
    Код:
    void cMenu::Draw()
    {
    	if (GetAsyncKeyState(VK_END) & 1)ShowGUI ^= 1;
    	if (!ShowGUI)
    		return;
    
    	(ItemMenu).x =  this->xPos;
    	(ItemMenu).y =  this->yPos + m_pCtx.HeightTitle+4;
    
    	m_pRender->render_Box(this->xPos, this->yPos, m_pCtx.WidthMain, m_pCtx.HeightTitle, GUIColor[color_Background]);
    	m_pRender->render_Border(this->xPos, this->yPos, m_pCtx.WidthMain, m_pCtx.HeightTitle, GUIColor[color_Border]);
    	m_pRender->render_String(this->xPos + m_pCtx.WidthMain / 2, this->yPos+ m_pCtx.HeightTitle/2- pSize.cy/2, GUIColor[color_Title], DT_CENTER | DT_SHADOW, L"GUI DX v.2017");
    
    
    	RenderMenu();
    	Tab_Number = 0;
    }

    Теперь опишем основные кнопки, опираясь на описанные данные:
    Код:
    void cMenu::GuiTab(TCHAR* Text)
    {
    	Color isHover = GUIColor[color_Border];
    	if (IsInControl((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain))
    	{
    		isHover = GUIColor[color_Hover];
    		if (GetAsyncKeyState(VK_LBUTTON) & 1)
    		{
    			if (vTab[Tab_Number] != 1) 
    				vTab[Tab_Number] = 1;
    		}
    	}
    	if (vTab[Tab_Number])
    	{
    		isHover = GUIColor[color_Active];
    		for (int i = 0; i < COUNT_TAB; i++)
    			if (i != Tab_Number) vTab[i] = 0;
    	}
    	
    	m_pRender->render_Box((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain, isHover);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain / 2, (ItemMenu).y + m_pCtx.HeightMain / 2 - pSize.cy / 2, GUIColor[color_Text], DT_CENTER | DT_SHADOW, Text);
    
    
    	Tab_Number = Tab_Number + 1;
    	if (Tab_Max < Tab_Number)
    		Tab_Max = Tab_Number;
    	(ItemMenu).y = (ItemMenu).y + m_pCtx.HeightMain + 2;
    }
    а в RenderMenu() рисуем на экран:
    Код:
    void cMenu::RenderMenu()
    {
    	GuiTab(L"TAB_VISUAL");
    	GuiTab(L"TAB_WEAPON");
    	GuiTab(L"TAB_PLAYER");
    	GuiTab(L"TAB_OTHER");
    
    }
    в итоге мы получили:




    cMenu.h:
    Код:
    #pragma once
    #include "../cRender/cRender.h"
    #include <vector>
    /*перечисления для цветов интерфейса*/
    enum GUIColorScheme
    {
    	color_Background,
    	color_Border, 
    	color_Title,
    	color_Text,
    	color_Active,
    	color_Hover,
    	COUNT_COLOR
    };
    /*перечисления основных кнопок*/
    enum Button
    {
    	TAB_VISUAL,
    	TAB_WEAPON,
    	TAB_PLAYER,
    	TAB_OTHER,
    	COUNT_TAB
    };
    
    class cMenu
    {
    public:
    	cMenu(cRender &Render,float xPos,float yPos);
    	virtual ~cMenu();
    protected:
    	struct MenuItem
    	{
    		float x;
    		float y;
    	};
    	struct Context
    	{
    		float WidthMain;
    		float HeightMain;
    		float WidthControl;
    		float HeightControl;
    		float HeightTitle;
    		Context()
    		{
    			WidthMain = 160.f;
    			HeightMain = 22.f;
    
    			WidthControl = 350.f;
    			HeightControl = 22.f;
    
    			HeightTitle = 26.f;
    		}
    	};
    private:
    	Context  m_pCtx;
    	MenuItem ItemMenu;
    	Color    GUIColor[COUNT_COLOR];
    public:
    	void Draw();
    private:
    	void  RenderMenu();
    	bool  IsInControl(float x, float y, float w, float h);
    	void  SetColor(int iAlfa = 255);
    
    	void  GuiTab(TCHAR *Text);
    private:
    	cRender *m_pRender;
    	float xPos;
    	float yPos;
    	bool  ShowGUI;
    	SIZE pSize;
    };
    extern cMenu *Menu;
    Последний раз редактировалось qazwar; 23.02.2017 в 18:50.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  14. Сказали спасибо:

    Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , $!№9@r (23.02.2017) , SKY (23.02.2017) , BratokHR (22.02.2017)

  15. #8
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 9 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #7: Хранение переменных.Save\Load параметров.

    Для сохранения и загрузки настроек решил использовать минимальные возможности [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    На мой взгляд очень удобная и простая реализация и при этом очень гибкая(не нужно говорить об хамл, джейсон и подобного рода парсерах).
    Качаем, скидываем в папку проекта и добавляем все файлы кода к проекту.
    Добавляем фаил в котором будем описывать все действа(я назвал cSetting.h) и подключаем configfile.h из скачанного проекта:

    Код:
    #pragma once
    #include <windows.h>
    #include "cConfiguration\configfile.h"
    
    
    cfg::File::ConfigMap dfltOptions =
    {
        {
    		"BLOCK A",
    	  {
    		{ "FunBool_1",          cfg::makeOption(false) },
    		{ "FunBool_2"   ,       cfg::makeOption(false) }
    	  }	
    	},
    
    
        {
    		"BLOCK B",
    	  {
    		{ "FunBool_3",          cfg::makeOption(false) },
    		{ "FunBool_4"   ,       cfg::makeOption(false) }
    	  }
        }
    };
    
    
    
    class Setting
    {
    private:
    	cfg::File m_pOptions;
    public:
    	Setting()
    	{
    		m_pOptions.loadFromFile("GUI_DX.cfg");
    		m_pOptions.setDefaultOptions(dfltOptions);
    		m_pOptions.setFlag(cfg::File::Autosave);
    		
    		Load();
    	}
    
    	struct ConfigData
    	{
    		bool    FunBool_1;
    		bool    FunBool_2;
    		bool    FunBool_3;
    		bool    FunBool_4;
    	};
    
    	inline ConfigData& config() { return m_pConfig; }
    	void Save()
    	{
    		m_pOptions.useSection("BLOCK A");
    		  m_pOptions("FunBool_1") = m_pConfig.FunBool_1;
    		  m_pOptions("FunBool_2") = m_pConfig.FunBool_2;
    
    
    		m_pOptions.useSection("BLOCK B");
    		   m_pOptions("FunBool_3") = m_pConfig.FunBool_3;
    		   m_pOptions("FunBool_4") = m_pConfig.FunBool_4;
    		
    	    m_pOptions.writeToFile();
    		MessageBeep(3000);
    	}
    	void Load()
    	{
    		m_pOptions.useSection("BLOCK A");
    		  m_pConfig.FunBool_1 = m_pOptions("FunBool_1").toBool();
    		  m_pConfig.FunBool_2 = m_pOptions("FunBool_2").toBool();
    		
    		m_pOptions.useSection("BLOCK B");
    		  m_pConfig.FunBool_3 = m_pOptions("FunBool_3").toBool();
    		  m_pConfig.FunBool_4 = m_pOptions("FunBool_4").toBool();
    	
    		MessageBeep(3000);
    	}
    	void Reset()
    	{
    
    		Load();
    	}
    
    private:
    	ConfigData  m_pConfig;
    };
    extern Setting m_pSetting;
    dfltOptions - это дефолтные параметры на случай если не удалось загрузить файл или его не существует(+этим мы инициализируем переменные для функций).
    Структура очень проста и представляет из себя ассоциативный контейнер
    Код:
    std::map<"Имя Блока", std::map<"Имя переменной",Параметр>>
    ConfigData - структура в которой будут храниться переменные. Обращаться будет через метод сonfig(), который вернет нам указатель на эту структуру(можно и проще, но это на будущее).

    Save()\Load() - соответственно: Сохранение и загрузка параметров. Load вызывается в конструкторе класса при его инициализации. Save придется вызывать вручную, либо обыгрывать своими методами или методами самого "конфигуратора".


    Для использования изобретем немного цепочек))
    Создаем фаил в котором будем описывать все элементы меню(RenderMenu.h) и переносим в него
    Код:
     void cMenu::RenderMenu()
    {
    ......
    }
    Подключим к нему:
    Код:
    #include "cMenu.h"
    #include "../cUtilit/cSetting.h"
    и укажем переменную вектора, которая определена у нас в cMenu.cpp:
    Код:
    extern std::vector<int> vTab;
    получилось так:
    Код:
    #pragma once
    #include "cMenu.h"
    #include "../cUtilit/cSetting.h"
    extern std::vector<int> vTab;
    
    
    
    void cMenu::RenderMenu()
    {
    	GuiTab(L"TAB_VISUAL");
    	GuiTab(L"TAB_WEAPON");
    	GuiTab(L"TAB_PLAYER");
    	GuiTab(L"TAB_OTHER");
    	if (vTab[TAB_VISUAL])
    	{
    	}
    	if (vTab[TAB_WEAPON])
    	{
    	}
    	if (vTab[TAB_PLAYER])
    	{
    	}
    	if (vTab[TAB_OTHER])
    	{
    	}
    
    }
    Теперь из cInclude.h удалим ссылку на cMenu.h и укажем ссылку на RenderMenu.h. В main.cpp прописываем указатель на класс Setting:
    Код:
    Setting m_pSetting;
    Готово) Теперь при загрузке длл будет создан экземпляр класса Setting, который через свой конструктор задаст нашим переменным указанные дефолтные настройки, либо загруженные из ранее сохраненного файла.

    GUI_DX.cfg:
    Код:
    [BLOCK A]
    FunBool_1 = false
    FunBool_2 = false
    
    [BLOCK B]
    FunBool_3 = true
    FunBool_4 = false
    Последний раз редактировалось qazwar; 23.02.2017 в 23:53.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  16. Сказали спасибо:

    Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (26.02.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  17. #9
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 8 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #8: Menu. "CheckBox".

    В классе меню добавим:
    Код:
    void  GuiCheckBox(TCHAR * Text, void *value);
    так же добавим еще один метод, который отслеживает нажатие указанной клавиши с заданным интервалом:
    Код:
    bool  State_Key(int Key, DWORD dwTimeOut = 30);
    
    struct Keys
    	{
    		bool  bPressed;
    		DWORD dwStartTime;
    	};
    и описываем:
    Код:
    bool  cMenu::State_Key(int Key, DWORD dwTimeOut/* = 30*/)
    {
    	if (HIWORD(GetKeyState(Key)))
    	{
    		if (!m_pKeys[Key].bPressed || (m_pKeys[Key].dwStartTime && (m_pKeys[Key].dwStartTime + dwTimeOut) <= GetTickCount()))
    		{
    			m_pKeys[Key].bPressed = true;
    			if (dwTimeOut > NULL)
    				m_pKeys[Key].dwStartTime = GetTickCount();
    			return true;
    		}
    	}
    	else
    		m_pKeys[Key].bPressed = false;
    	return FALSE;
    }
    Код:
    void cMenu::GuiCheckBox(TCHAR * Text, void *value)
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Border]);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 7, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, GUIColor[color_Text], DT_LEFT| DT_SHADOW, Text);
    	
    	Color isDecrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx - 1, (ItemMenu).yCtrl + 2.f, pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isDecrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			*(bool*)value = true;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx/2 - 1, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isDecrement, DT_CENTER | DT_SHADOW, L">>");
    
    	Color isIncrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx - 80, (ItemMenu).yCtrl + 2, pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isIncrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			*(bool*)value = false;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80.f, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isIncrement, DT_CENTER | DT_SHADOW, L"<<");
    
    	Color isState = GUIColor[color_Text];
    	const TCHAR *buff = L"Off";
    	if (*(bool*)value)
    	{
    		isState = GUIColor[color_Active];
    		buff = L"On";
    	}	
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80 + pSize.cx + 25, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isState, DT_CENTER | DT_SHADOW, buff);
    
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + m_pCtx.HeightControl + 2;
    }
    в RenderMenu() дописываем вызов:
    Код:
    if (vTab[TAB_VISUAL])
    	{
    		GuiCheckBox(L"GuiCheckBox 1", &m_pSetting.config().FunBool_1);
    		GuiCheckBox(L"GuiCheckBox 2", &m_pSetting.config().FunBool_2);
    		GuiCheckBox(L"GuiCheckBox 3", &m_pSetting.config().FunBool_3);
    		GuiCheckBox(L"GuiCheckBox 4", &m_pSetting.config().FunBool_4);
    	}
    как видим все просто: задаем имя и даем ссылку на переменную)
    пропишем для теста вывод круга:
    Код:
    else
    	{
    		Menu->Draw();
    
    		if (m_pSetting.config().FunBool_3 == true)
    			pRender->render_Circle(70, 200, 50, Color::Red());
    }
    и результат:
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  18. Сказали спасибо:

    Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  19. #10
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 8 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #9: Menu. "Scroll".

    Задача: Сделать возможность редактирования параметров переменной по заданным критериям(min\max значения, шаг) и наглядно это отобразить в меню, посредством отображения реального значения указанной переменной или указанными маркерами.

    Добавляем:
    Код:
    void  GuiScroll(TCHAR * Text, void *value, std::vector<TCHAR*> const& temp);
    	void  GuiScroll(TCHAR * Text, void *value, float min, float max, float step = 1.f);
    Text - "имя"
    value - ссылка на переменную
    temp ссылка на вектор строк
    min - минимальное значение переменной, ниже которой значение не опустится
    max - максимальное значение переменной, выше которого значение не поднимется
    step - шаг перебора(на сколько будет увеличиваться\уменьшаться значение переменной при каждом клике)

    Описываем функции:
    Код:
    void cMenu::GuiScroll(TCHAR * Text, void *value, std::vector<TCHAR*> const& temp)
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Border]);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 7, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, GUIColor[color_Text], DT_LEFT | DT_SHADOW, Text);
    
    	Color isDecrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx - 1, (ItemMenu).yCtrl + 2.f, (float)pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isDecrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			if ((*(int*)value >= 0) && (*(int*)value < (temp.size() - 1)))
    				*(int*)value = *(int*)value + 1;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx / 2 - 1, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isDecrement, DT_CENTER | DT_SHADOW, L">>");
    
    	Color isIncrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx - 80, (ItemMenu).yCtrl + 2, (float)pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isIncrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			if (*(int*)value != 0)
    				*(int*)value = *(int*)value - 1;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80.f, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isIncrement, DT_CENTER | DT_SHADOW, L"<<");
    
    	Color isState = GUIColor[color_Text];
    	if (*(int*)value > 0)
    	{
    		isState = GUIColor[color_Active];
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80 + pSize.cx + 25, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isState, DT_CENTER | DT_SHADOW, temp[*(int*)value]);
    
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + m_pCtx.HeightControl + 2;
    }
    void cMenu::GuiScroll(TCHAR * Text, void *value, float min, float max, float step /*= 1.f*/)
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl, GUIColor[color_Border]);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 7, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, GUIColor[color_Text], DT_LEFT | DT_SHADOW, Text);
    
    	Color isDecrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx - 1, (ItemMenu).yCtrl + 2.f, (float)pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isDecrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			if (*(float*)value >= min && *(float*)value < (max))
    				*(float*)value += step;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx / 2 - 1, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isDecrement, DT_CENTER | DT_SHADOW, L">>");
    
    	Color isIncrement = GUIColor[color_Text];
    	if (IsInControl((ItemMenu).x + m_pCtx.WidthMain + 3.f + m_pCtx.WidthControl - pSize.cx - 80, (ItemMenu).yCtrl + 2, (float)pSize.cx, m_pCtx.HeightControl - 4.f))
    	{
    		isIncrement = GUIColor[color_Hover];;
    		if (State_Key(VK_LBUTTON))
    			if (*(float*)value > min)
    				*(float*)value -= step;
    	}
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80.f, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isIncrement, DT_CENTER | DT_SHADOW, L"<<");
    
    	Color isState = GUIColor[color_Text];
    
    #ifdef _UNICODE
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80 + pSize.cx + 25, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isState, DT_CENTER | DT_SHADOW, L"%.1f", *(float*)value);
    #else
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - pSize.cx / 2 - 80 + pSize.cx + 25, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, isState, DT_CENTER | DT_SHADOW, "%.1f", *(float*)value);
    #endif
    
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + m_pCtx.HeightControl + 2;
    }


    Пример использования:
    переменные
    Код:
    float   FunFloat;
    		int     FunInt;
    вектор строк(может быть любое количество строк внутри)
    Код:
    std::vector<TCHAR*>   temp = { L"Off",L"одЫн",L"Two",L"Three",L"Four" };
    вызываем в RenderMenu()
    Код:
    if (vTab[TAB_WEAPON])
    	{
    		GuiScroll(L"GuiScroll 1", &m_pSetting.config().FunInt, temp);
    		GuiScroll(L"GuiScroll 2", &m_pSetting.config().FunFloat, -5.f,5.f);
    	}
    И отобразим значение, переменных для наглядности, в myPresent:
    Код:
    pRender->render_String(150, 200, Color::Green(), DT_LEFT, L" GuiScroll 1:  %i\n GuiScroll 2:  %.1f", m_pSetting.config().FunInt, m_pSetting.config().FunFloat);
    В итоге получили:
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  20. Сказали спасибо:

    Jefferson (26.09.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (26.02.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  21. #11
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 9 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #10: Menu. "SelectColor".

    Задача: Позволить пользователю самостоятельно выбрать тот или иной цвет для указанного элемента.

    Определяем:
    Код:
    void  GuiColor(TCHAR * Text, Color *color);
    Описываем:
    Код:
    void cMenu::GuiColor(TCHAR * Text, Color *color)
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl * 3 - 9, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, m_pCtx.HeightControl * 3 - 9, GUIColor[color_Border]);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 7, (ItemMenu).yCtrl + m_pCtx.HeightControl / 2 - pSize.cy / 2, GUIColor[color_Text], DT_LEFT | DT_SHADOW, Text);
    
    	if (color->r > 255)color->r = 255;
    	if (color->r < 0)color->r = 0;
    
    	if (color->g  > 255)color->g = 255;
    	if (color->g < 0)color->g = 0;
    
    	if (color->b  > 255)color->b = 255;
    	if (color->b < 0)color->b = 0;
    
    	POINT CursorPos;
    	GetCursorPos(&CursorPos);
    	ScreenToClient(GetForegroundWindow(), &CursorPos);
    	float xS = (ItemMenu).x + m_pCtx.WidthMain + 3 + m_pCtx.WidthControl - 110;
    	
    	float width = 100;
    	float height = pSize.cy + 2;
    	
    	/*Red*/
    	float valueXR = xS + (color->r * width /255);
    	pRender->render_Box(xS, (ItemMenu).yCtrl + 5, valueXR - xS, height - 1, Color(255, 0, 0));
    	pRender->render_Border(xS, (ItemMenu).yCtrl + 4, width, height, GUIColor[color_Border]);
    	if (IsInControl(xS, (ItemMenu).yCtrl + 5, width + 2, height))
    	{
    		pRender->render_String(xS + width / 2, (ItemMenu).yCtrl +   pSize.cy/2, GUIColor[color_Text], DT_CENTER, L"%i", color->r);
    		if (GetKeyState(VK_LBUTTON) < 0)
    			color->r = (CursorPos.x - xS) *255/width;
    	}
    	/*Green*/
    	float valueXG = xS + (color->g * width /255);
    	pRender->render_Box(xS, (ItemMenu).yCtrl + 7+ height, valueXG - xS, height - 1, Color(0, 255, 0));
    	pRender->render_Border(xS, (ItemMenu).yCtrl + 6 + height, width, height, GUIColor[color_Border]);
    	if (IsInControl(xS, (ItemMenu).yCtrl + 7 + height, width + 2, height))
    	{
    		pRender->render_String(xS + width / 2, (ItemMenu).yCtrl + pSize.cy / 2 + height + 2, GUIColor[color_Text], DT_CENTER, L"%i", color->g);
    		if (GetKeyState(VK_LBUTTON) < 0)
    			color->g = (CursorPos.x - xS) * 255 / width;
    	}
    	/*Blue*/
    	float valueXB = xS + (color->b * width /255);
    	pRender->render_Box(xS, (ItemMenu).yCtrl + 9+ height*2 , valueXB - xS, height - 1, Color(0, 0, 255));
    	pRender->render_Border(xS, (ItemMenu).yCtrl + 8 + height * 2, width, height, GUIColor[color_Border]);
    	if (IsInControl(xS, (ItemMenu).yCtrl + 9 + height * 2, width + 2, height))
    	{
    		pRender->render_String(xS + width / 2, (ItemMenu).yCtrl + pSize.cy / 2 + height * 2 + 4, GUIColor[color_Text], DT_CENTER, L"%i", color->b);
    		if (GetKeyState(VK_LBUTTON) < 0)
    			color->b = (CursorPos.x - xS) * 255 / width;
    	}
    
    	pRender->render_Box(xS - 12, (ItemMenu).yCtrl + 5, 10, m_pCtx.HeightControl*3 - 18, *color);
    
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + m_pCtx.HeightControl*3 - 7;
    }

    Определяем переменные:
    Код:
    Color   PrwColor_1;
    		Color   PrwColor_2;
    под настройки придется каждый отдельный канал описывать:
    Код:
    "BLOCK C",
    		{
    			{ "IntRed_1",          cfg::makeOption(0) },
    			{ "IntGreen_1"   ,       cfg::makeOption(255) },
    			{ "IntBlue_1",          cfg::makeOption(0) },
    			{ "IntRed_2",          cfg::makeOption(255) },
    			{ "IntGreen_2"   ,       cfg::makeOption(0) },
    			{ "IntBlue_2",          cfg::makeOption(0) }
    		}
    вызываем в меню:
    Код:
    if (vTab[TAB_PLAYER])
    	{
    		GuiColor(L"GuiColor 1",&m_pSetting.config().PrwColor_1);
    		GuiColor(L"GuiColor 2", &m_pSetting.config().PrwColor_2);
    	}
    И прикрутим к рисовке:
    Код:
    pRender->render_Box(100, 200, 30, 30, m_pSetting.config().PrwColor_2); 
    		if (m_pSetting.config().FunBool_3 == true)
    			pRender->render_Circle(70, 200, 50, m_pSetting.config().PrwColor_1);
    Итог:



    ЗЫ: Код работает, но не совсем мне нравится. Другого решения пока не изобрел - поэтому пока так)))
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  22. Сказали спасибо:

    Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (26.02.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  23. #12
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 11 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Step #11: Menu. "Split".

    Простые разделители в виде текста или полоски.

    Определяем:
    Код:
    	void  GuiSplit();
    	void  GuiSplit(TCHAR *Text);
    Описываем:
    Код:
    void  cMenu::GuiSplit()
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, 3, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl, m_pCtx.WidthControl, 3, GUIColor[color_Border]);
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + 5;
    }
    void  cMenu::GuiSplit(TCHAR *Text)
    {
    	m_pRender->render_Box((ItemMenu).x + m_pCtx.WidthMain + 3,    (ItemMenu).yCtrl, m_pCtx.WidthControl,         pSize.cy + 4, GUIColor[color_Background]);
    	m_pRender->render_Border((ItemMenu).x + m_pCtx.WidthMain + 3, (ItemMenu).yCtrl,         m_pCtx.WidthControl, pSize.cy+4, GUIColor[color_Border]);
    	m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain + 7 + m_pCtx.WidthControl /2, (ItemMenu).yCtrl + (pSize.cy + 4) / 2 - pSize.cy / 2, GUIColor[color_Text], DT_CENTER | DT_SHADOW, Text);
    	(ItemMenu).yCtrl = (ItemMenu).yCtrl + (pSize.cy + 4) + 2;
    }
    а так выглядит это визуально и в коде:
    Код:
    if (vTab[TAB_VISUAL])
    	{
    		GuiCheckBox(L"GuiCheckBox 1", &m_pSetting.config().FunBool_1);
    		GuiCheckBox(L"GuiCheckBox 2", &m_pSetting.config().FunBool_2);
    		GuiSplit();
    		GuiCheckBox(L"GuiCheckBox 3", &m_pSetting.config().FunBool_3);
    		GuiCheckBox(L"GuiCheckBox 4", &m_pSetting.config().FunBool_4);
    		GuiSplit(L"Split::Color");
    		GuiColor(L"GuiColor 1", &m_pSetting.config().PrwColor_1);
    		GuiColor(L"GuiColor 2", &m_pSetting.config().PrwColor_2);
    		GuiSplit(L"Split::Scroll");
    		GuiScroll(L"GuiScroll 1", &m_pSetting.config().FunInt, temp);
    		GuiScroll(L"GuiScroll 2", &m_pSetting.config().FunFloat, -5.f, 5.f);
    	}
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  24. Сказали спасибо:

    FARTFARTA (09.03.2018) , Velasav (29.01.2018) , Jefferson (26.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (26.02.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  25. #13
    return false; qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима qazwar репутация неоспорима Аватар для qazwar
    Регистрация
    05.03.2012
    Адрес
    Сибирь
    Сообщений
    490
    Сказали 'Спасибо' за это сообщение.
    : 10 за это сообщение
    1,688 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Завершение:
    Всего, что описано выше, вполне хватит, что бы написать управление функционалам.
    В конечном итоге поправил несколько функций, немного изменил получение данных, которые не как ни влияют на работу.

    Результат виден в предыдущем посте.
    Думаю на этом можно закончить, а если появятся еще идеи, то они будут добавлены в тему и указаны в стартовом сообщении.



    Пробуйте, фантазируйте, реализовывайте

    Ну а полный исходный проект смогут получить пользователи Cheaton.ru, счетчик сообщений которых перевалил за 19 сообщений)


    Скрытый текст (вы должны войти под своим логином или зарегистрироваться и иметь 20 сообщение(ий)):
    У вас нет прав чтобы видеть скрытый текст, содержащийся здесь.
    Самый действенный инструмент для самообучения - грабли.
    Ответить с цитированием Ответить с цитированием
    Спасибо

  26. Сказали спасибо:

    Jefferson (26.09.2017) , Freedrikson (24.09.2017) , Mick Rory (20.07.2017) , prapor (18.04.2017) , ropox (31.03.2017) , Liman25 (03.03.2017) , grees (01.03.2017) , BratokHR (26.02.2017) , SKY (25.02.2017) , $!№9@r (24.02.2017)

  27. #14
    Администратор
    $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима $!№9@r репутация неоспорима Аватар для $!№9@r
    Регистрация
    14.07.2009
    Адрес
    Омск
    Сообщений
    1,439
    Сказали 'Спасибо' за это сообщение.
    : 7 за это сообщение
    2,461 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Цитата Сообщение от qazwar [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    Step #6: Menu. Общая реализация."TabControl".

    Теперь опишем основные кнопки, опираясь на описанные данные:
    Код:
    void cMenu::GuiTab(TCHAR* Text)
    {
        Color isHover = GUIColor[color_Border];
        if (IsInControl((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain))
        {
            isHover = GUIColor[color_Hover];
            if (GetAsyncKeyState(VK_LBUTTON) & 1)
            {
                if (vTab[Tab_Number] != 1) 
                    vTab[Tab_Number] = 1;
            }
        }
        if (vTab[Tab_Number])
        {
            isHover = GUIColor[color_Active];
            for (int i = 0; i < COUNT_TAB; i++)
                if (i != Tab_Number) vTab[i] = 0;
        }
        
        m_pRender->render_Box((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain, GUIColor[color_Background]);
        m_pRender->render_Border((ItemMenu).x, (ItemMenu).y, m_pCtx.WidthMain, m_pCtx.HeightMain, isHover);
        m_pRender->render_String((ItemMenu).x + m_pCtx.WidthMain / 2,  (ItemMenu).y + m_pCtx.HeightMain / 2 - pSize.cy / 2,  GUIColor[color_Text], DT_CENTER | DT_SHADOW, Text);
    
    
        Tab_Number = Tab_Number + 1;
        if (Tab_Max < Tab_Number)
            Tab_Max = Tab_Number;
        (ItemMenu).y = (ItemMenu).y + m_pCtx.HeightMain + 2;
    }
    Предлагаю немного модернизировать управление кнопками в шестом уроке, а именно:
    этот кусочек
    Код:
            if (GetAsyncKeyState(VK_LBUTTON) & 1)
            {
                if (vTab[Tab_Number] != 1) 
                    vTab[Tab_Number] = 1;
            }
    видоизменить на
    Код:
            if (GetAsyncKeyState(VK_LBUTTON) & 1) 
            { 
               vTab[Tab_Number] = !vTab[Tab_Number]; 
            }
    чтобы при нажатии не только открывалось табменю но и скрывалось.
    Какбы мелочь, но приятно. Хотя это на любителя...)))

    Skype - 011100110110100101101110001110010110000101110010
    ICQ - 00011110111000111101
    Ответить с цитированием Ответить с цитированием
    Спасибо

  28. Сказали спасибо:

    FARTFARTA (09.03.2018) , Mick Rory (20.07.2017) , prapor (18.04.2017) , grees (04.04.2017) , ropox (31.03.2017) , SKY (31.03.2017) , qazwar (31.03.2017)

  29. #15
    Новичок ADWHACK скоро придёт к известности
    Регистрация
    10.02.2017
    Сообщений
    1
    Сказали 'Спасибо' за это сообщение.
    : 4 за это сообщение
    4 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Цитата Сообщение от $!№9@r [Вы должны быть зарегистрированным и не заблокированным пользователем для того чтобы просматривать ссылки зарегистрироваться можно по этой ссылке]
    Предлагаю немного модернизировать управление кнопками в шестом уроке, а именно:
    этот кусочек
    Код:
            if (GetAsyncKeyState(VK_LBUTTON) & 1)
            {
                if (vTab[Tab_Number] != 1) 
                    vTab[Tab_Number] = 1;
            }
    видоизменить на
    Код:
            if (GetAsyncKeyState(VK_LBUTTON) & 1) 
            { 
               vTab[Tab_Number] = !vTab[Tab_Number]; 
            }
    чтобы при нажатии не только открывалось табменю но и скрывалось.
    Какбы мелочь, но приятно. Хотя это на любителя...)))

    if (GetAsyncKeyState(VK_LBUTTON) & 1) vTab[Tab_Number] ^= 1;
    Ответить с цитированием Ответить с цитированием
    Спасибо

  30. Сказали спасибо:

    ancup (29.06.2017) , AleksandrChern (06.06.2017) , prapor (18.04.2017) , $!№9@r (12.04.2017)

  31. #16
    Новичок Mick Rory на пути к лучшему
    Регистрация
    02.05.2017
    Сообщений
    1
    Сказали 'Спасибо' за это сообщение.
    : 1 за это сообщение
    1 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Это вам не трейнер на c#, здесь думать надо)))
    Спасибо большое за урок!!!Теперь хук то по лучше чем в прошлый раз)
    Ответить с цитированием Ответить с цитированием
    Спасибо

  32. Сказали спасибо:

    FARTFARTA (09.03.2018)

  33. #17
    Новичок саняВВ на пути к лучшему
    Регистрация
    05.08.2019
    Сообщений
    1
    Сказали 'Спасибо' за это сообщение.
    : 0 за это сообщение
    0 Всего

    По умолчанию Re: [C/C++] Graphical User Interface DirectX v.2017

    Мда... Это круто но я даже так всё запорол
    Ответить с цитированием Ответить с цитированием
    Спасибо

Похожие темы

  1. [Warface RU 24.01.2017]Отдача
    от Xed0sS в разделе Вопросы
    Ответов: 6
    Последнее сообщение: 13.03.2017, 05:03
  2. С Новым годом 2017
    от ANA608 в разделе Поздравлялки наших форумчан
    Ответов: 1
    Последнее сообщение: 02.01.2017, 02:17
  3. Ответов: 4
    Последнее сообщение: 30.08.2016, 13:03
  4. User JavaScript для Opera
    от Phantom в разделе Утилиты
    Ответов: 0
    Последнее сообщение: 22.12.2009, 14:47