218 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  *	Platform Specification Implementation
 | |
|  *	Nana C++ Library(http://www.nanapro.org)
 | |
|  *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
 | |
|  *
 | |
|  *	Distributed under the Boost Software License, Version 1.0.
 | |
|  *	(See accompanying file LICENSE_1_0.txt or copy at
 | |
|  *	http://www.boost.org/LICENSE_1_0.txt)
 | |
|  *
 | |
|  *	@file: nana/detail/platform_spec.cpp
 | |
|  *
 | |
|  *	@brief basis classes and data structures required by nana
 | |
|  */
 | |
| 
 | |
| #include "platform_spec_selector.hpp"
 | |
| #include "platform_abstraction.hpp"
 | |
| 
 | |
| #if defined(NANA_WINDOWS)
 | |
| 
 | |
| #include <stdexcept>
 | |
| #include <map>
 | |
| 
 | |
| #include <windows.h>
 | |
| #include <shellapi.h>
 | |
| 
 | |
| 
 | |
| 
 | |
| namespace nana
 | |
| {
 | |
| namespace detail
 | |
| {
 | |
| 	drawable_impl_type::drawable_impl_type()
 | |
| 	{
 | |
| 		pen.handle = nullptr;
 | |
| 		pen.color = 0xffffffff;
 | |
| 		pen.style = -1;
 | |
| 		pen.width = -1;
 | |
| 
 | |
| 		brush.handle = nullptr;
 | |
| 		brush.style = brush_spec::Solid;
 | |
| 		brush.color = 0xffffffff;
 | |
| 
 | |
| 		round_region.handle = nullptr;
 | |
| 		round_region.radius_x = round_region.radius_y = 0;
 | |
| 
 | |
| 		string.tab_length = 4;
 | |
| 		string.tab_pixels = 0;
 | |
| 		string.whitespace_pixels = 0;
 | |
| 	}
 | |
| 
 | |
| 	drawable_impl_type::~drawable_impl_type()
 | |
| 	{
 | |
| 		::DeleteDC(context);
 | |
| 		::DeleteObject(pixmap);
 | |
| 		::DeleteObject(pen.handle);
 | |
| 		::DeleteObject(brush.handle);
 | |
| 		::DeleteObject(round_region.handle);
 | |
| 	}
 | |
| 
 | |
| 	unsigned drawable_impl_type::get_color() const
 | |
| 	{
 | |
| 		return color_;
 | |
| 	}
 | |
| 
 | |
| 	unsigned drawable_impl_type::get_text_color() const
 | |
| 	{
 | |
| 		return text_color_;
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::set_color(const ::nana::color& clr)
 | |
| 	{
 | |
| 		color_ = (clr.px_color().value & 0xFFFFFF);
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::set_text_color(const ::nana::color& clr)
 | |
| 	{
 | |
| 		auto rgb = (clr.px_color().value & 0xFFFFFF);
 | |
| 		if (text_color_ != rgb)
 | |
| 		{
 | |
| 			::SetTextColor(context, NANA_RGB(rgb));
 | |
| 			text_color_ = rgb;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::update_pen()
 | |
| 	{
 | |
| 		if (pen.color != color_)
 | |
| 		{
 | |
| 			pen.handle = ::CreatePen(PS_SOLID, 1, NANA_RGB(color_));
 | |
| 			::DeleteObject(::SelectObject(context, pen.handle));
 | |
| 			pen.color = color_;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::update_brush()
 | |
| 	{
 | |
| 		if (brush.color != color_)
 | |
| 			brush.set(context, brush.style, color_);
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::pen_spec::set(HDC context, int style, int width, unsigned clr)
 | |
| 	{
 | |
| 		if (this->color != clr || this->width != width || this->style != style)
 | |
| 		{
 | |
| 			this->color = clr;
 | |
| 			this->width = width;
 | |
| 			this->style = style;
 | |
| 			this->handle = ::CreatePen(style, width, NANA_RGB(clr));
 | |
| 			::DeleteObject(::SelectObject(context, this->handle));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::brush_spec::set(HDC context, drawable_impl_type::brush_spec::t style, unsigned rgb)
 | |
| 	{
 | |
| 		if (this->color != rgb || this->style != style)
 | |
| 		{
 | |
| 			this->color = rgb;
 | |
| 			this->style = style;
 | |
| 			switch(style)
 | |
| 			{
 | |
| 			case brush_spec::HatchBDiagonal:
 | |
| 				this->handle = ::CreateHatchBrush(HS_BDIAGONAL, NANA_RGB(rgb));
 | |
| 				break;
 | |
| 			case brush_spec::Solid:
 | |
| 			default:
 | |
| 				this->style = brush_spec::Solid;
 | |
| 				this->handle = ::CreateSolidBrush(NANA_RGB(color));
 | |
| 				break;
 | |
| 			}
 | |
| 			::DeleteObject(::SelectObject(context, this->handle));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void drawable_impl_type::round_region_spec::set(const nana::rectangle& r, unsigned radius_x, unsigned radius_y)
 | |
| 	{
 | |
| 		if(this->r != r || this->radius_x != radius_x || this->radius_y != radius_y)
 | |
| 		{
 | |
| 			if(handle)
 | |
| 				::DeleteObject(this->handle);
 | |
| 			this->r = r;
 | |
| 			this->radius_x = radius_x;
 | |
| 			this->radius_y = radius_y;
 | |
| 			handle = ::CreateRoundRectRgn(r.x, r.y, r.x + static_cast<int>(r.width) + 1, r.y + static_cast<int>(r.height) + 1, static_cast<int>(radius_x + 1), static_cast<int>(radius_y + 1));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	//class platform_spec
 | |
| 	platform_spec::co_initializer::co_initializer()
 | |
| 		: ole32_(::LoadLibrary(L"OLE32.DLL"))
 | |
| 	{
 | |
| 		if(ole32_)
 | |
| 		{
 | |
| 			typedef HRESULT (__stdcall *CoInitializeEx_t)(LPVOID, DWORD);
 | |
| 			CoInitializeEx_t fn_init = reinterpret_cast<CoInitializeEx_t>(::GetProcAddress(ole32_, "CoInitializeEx"));
 | |
| 			if(0 == fn_init)
 | |
| 			{
 | |
| 				::FreeLibrary(ole32_);
 | |
| 				ole32_ = 0;
 | |
| 				throw std::runtime_error("Nana.PlatformSpec.Co_initializer: Can't locate the CoInitializeEx().");
 | |
| 			}
 | |
| 			else
 | |
| 				fn_init(0, COINIT_APARTMENTTHREADED | /*COINIT_DISABLE_OLE1DDE =*/0x4);
 | |
| 		}
 | |
| 		else
 | |
| 			throw std::runtime_error("Nana.PlatformSpec.Co_initializer: No Ole32.DLL Loaded.");
 | |
| 	}
 | |
| 
 | |
| 	platform_spec::co_initializer::~co_initializer()
 | |
| 	{
 | |
| 		if(ole32_)
 | |
| 		{
 | |
| 			typedef void (__stdcall *CoUninitialize_t)(void);
 | |
| 			CoUninitialize_t fn_unin = reinterpret_cast<CoUninitialize_t>(::GetProcAddress(ole32_, "CoUninitialize"));
 | |
| 			if(fn_unin)
 | |
| 				fn_unin();
 | |
| 			::FreeLibrary(ole32_);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	struct platform_spec::implementation
 | |
| 	{
 | |
| 		std::map<native_window_type, window_icons> iconbase;
 | |
| 	};
 | |
| 
 | |
| 	platform_spec::platform_spec()
 | |
| 		: impl_{ new implementation}
 | |
| 	{
 | |
| 		platform_abstraction::initialize();
 | |
| 	}
 | |
| 
 | |
| 	platform_spec::~platform_spec()
 | |
| 	{
 | |
| 		platform_abstraction::shutdown();
 | |
| 		delete impl_;
 | |
| 	}
 | |
| 
 | |
| 	platform_spec& platform_spec::instance()
 | |
| 	{
 | |
| 		static platform_spec object;
 | |
| 		return object;
 | |
| 	}
 | |
| 
 | |
| 	void platform_spec::keep_window_icon(native_window_type wd, const paint::image& sml_icon, const paint::image& big_icon)
 | |
| 	{
 | |
| 		auto & icons = impl_->iconbase[wd];
 | |
| 		icons.sml_icon = sml_icon;
 | |
| 		icons.big_icon = big_icon;
 | |
| 	}
 | |
| 
 | |
| 	void platform_spec::release_window_icon(native_window_type wd)
 | |
| 	{
 | |
| 		impl_->iconbase.erase(wd);
 | |
| 	}
 | |
| }//end namespace detail
 | |
| }//end namespace nana
 | |
| 
 | |
| #endif //NANA_WINDOWS
 | 
