<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cross-Platform Programming with wxWidgets &#187; Uncategorized</title>
	<atom:link href="http://wxwidgets.info/category/uncategorized/feed/" rel="self" type="application/rss+xml" />
	<link>http://wxwidgets.info</link>
	<description>Just Make It Cross-Platform</description>
	<lastBuildDate>Tue, 09 Mar 2010 20:50:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Работаем с Cairo в wxWidgets &#8211; Часть I &#8211; Компиляция CAIRO 1.8.6 на Visual C++ 8</title>
		<link>http://wxwidgets.info/rabotaem-s-cairo-v-wxwidgets-chast-i-kompilyaciya-cairo-186-na-visual-c-8/</link>
		<comments>http://wxwidgets.info/rabotaem-s-cairo-v-wxwidgets-chast-i-kompilyaciya-cairo-186-na-visual-c-8/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 17:57:06 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=540</guid>
		<description><![CDATA[Первая статья из цикла, повествующего о том, ка киспользовать библиотеку cairo (и обертку wxCairo) с wxWidgets. В этот раз речь пойдет о том, как собрать библиотеку cairo с помощью Visual C++ в Windows. Для начала определимся, что нам нужно: Mozilla Build 1.3 cairo 1.8.6 libpng 1.2.35 zlib 1.2.3 pixman 0.14.0 Устанавливаем Mozilla Build, распаковываем все [...]]]></description>
			<content:encoded><![CDATA[<p>Первая статья из цикла, повествующего о том, ка киспользовать библиотеку <strong>cairo</strong> (и обертку <strong>wxCairo</strong>) с wxWidgets.</p>
<p>В этот раз речь пойдет о том, как собрать библиотеку <strong>cairo</strong> с помощью Visual C++ в Windows.</p>
<p>Для начала определимся, что нам нужно:</p>
<ul>
<li>Mozilla Build 1.3</li>
<li>cairo 1.8.6</li>
<li>libpng 1.2.35</li>
<li>zlib 1.2.3</li>
<li>pixman 0.14.0</li>
</ul>
<p><span id="more-540"></span><br />
Устанавливаем Mozilla Build, распаковываем все библиотеки.</p>
<p>В переменных окружения прописываем пути к Visual Studio. Для того, чтобы все собралось успешно, необходимо, помимо Visual Studio установить Platform SDK.</p>
<pre class="brush: jscript;">
DevEnvDir = C:\Program Files\Microsoft Visual Studio 8\Common7\IDE
FrameworkDir = C:\WINDOWS\Microsoft.NET\Framework
FrameworkSDKDir = C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0
FrameworkVersion = v2.0.50727
INCLUDE = C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE;C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include
LIB = C:\Program Files\Microsoft Visual Studio 8\VC\ATLMFC\LIB;C:\Program Files\Microsoft Visual Studio 8\VC\LIB;C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\lib;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\lib
LIBPATH = C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 8\VC\ATLMFC\LIB
PATH = C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;C:\Program Files\Microsoft Visual Studio 8\VC\BIN;C:\Program Files\Microsoft Visual Studio 8\Common7\Tools;C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\bin;C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\bin;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 8\VC\VCPackages
SDKDIR = C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\
VCINSTALLDIR = C:\Program Files\Microsoft Visual Studio 8\VC
VSINSTALLDIR = C:\Program Files\Microsoft Visual Studio 8
VS80COMNTOOLS = C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\
</pre>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/04/build-cairo-01.png"><img class="alignnone size-full wp-image-541" title="Переменные окружения для сборки Cairo" src="http://wxwidgets.info//wp-content/uploads/2009/04/build-cairo-01.png" alt="Переменные окружения для сборки Cairo" /></a></p>
<p>Компилируем libpng и zlib</p>
<p>В папке, в которую мы установили Mozilla Build, запускаем скрипт <strong>start-msvc8.bat</strong>. В появившемся окне консоли переходим в папку, куда мы распаковали библиотеку <strong>pixman</strong>, и собираем ее командой</p>
<pre class="brush: cpp;">
make -f Makefile.win32 CFG=release
</pre>
<p>После сборки переносим файлы библиотек и заголовочные файлы для <strong>zlib</strong> и <strong>libpng</strong> в папку с <strong>cairo</strong>.</p>
<ul>
<li>zlib.h</li>
<li>zconf.in.h</li>
<li>zconf.h</li>
<li>pngconf.h</li>
<li>png.h</li>
<li>pixman.h</li>
<li>pixman-version.h</li>
<li>libpng.lib</li>
<li>zdll.lib</li>
</ul>
<p>В папке Cairo правим файл <strong>cairo-features.h</strong>:</p>
<pre class="brush: cpp;">
/* Generated by configure.  Do not edit. */
 #ifndef CAIRO_FEATURES_H
 #define CAIRO_FEATURES_H
 #define CAIRO_HAS_FT_FONT 0
 #define CAIRO_HAS_IMAGE_SURFACE 1
 #define CAIRO_HAS_PDF_SURFACE 1
 #define CAIRO_HAS_PNG_FUNCTIONS 1
 #define CAIRO_HAS_PS_SURFACE 1
 #define CAIRO_HAS_SVG_SURFACE 1
 #define CAIRO_HAS_USER_FONT 0
 #define CAIRO_HAS_XLIB_SURFACE 0
 #define CAIRO_HAS_XLIB_XRENDER_SURFACE 0
 /*#undef CAIRO_HAS_QUARTZ_FONT */
 /*#undef CAIRO_HAS_QUARTZ_SURFACE */
 #define CAIRO_HAS_WIN32_FONT 1
 #define CAIRO_HAS_WIN32_SURFACE 1
 #endif
</pre>
<p>В консоли MozillaBuild переходим в подкаталог src в папке с Cairo.<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/04/build-cairo-02.png"><img class="alignnone size-full wp-image-542" title="Собираем Cairo" src="http://wxwidgets.info//wp-content/uploads/2009/04/build-cairo-02.png" alt="Собираем Cairo" /></a></p>
<p>Собираем <strong>cairo</strong> командой</p>
<pre class="brush: cpp;">
make -f Makefile.win32 CFG=release
</pre>
<p>Если при сборке будет необходима библиотека <strong>pixman-1.lib</strong>, то копируем ее в эту же папку и повторно запускаем сборку.</p>
<p>После сборки <strong>cairo</strong> нам будут необходимы следующие файлы:</p>
<p>В результате нам для работы понадобятся только файлы:</p>
<ul>
<li>cairo-deprecated.h</li>
<li>cairo-features.h</li>
<li>cairo-pdf.h</li>
<li>cairo-ps.h</li>
<li>cairo-static.lib</li>
<li>cairo-svg.h</li>
<li>cairo-version.h</li>
<li>cairo-win32.h</li>
<li>cairo.dll</li>
<li>cairo.h</li>
<li>cairo.lib</li>
<li>zlib1.dll</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/rabotaem-s-cairo-v-wxwidgets-chast-i-kompilyaciya-cairo-186-na-visual-c-8/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Do You Need Data Access Layer Code Generator Tool?</title>
		<link>http://wxwidgets.info/what-about-data-access-layer-code-generator-tool/</link>
		<comments>http://wxwidgets.info/what-about-data-access-layer-code-generator-tool/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 15:01:43 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=537</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><!--  POLLIN 1 --></p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/what-about-data-access-layer-code-generator-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>А может поговорим вживую на CodeCamp?</title>
		<link>http://wxwidgets.info/a-mozhet-pogovorim-vzhivuyu-na-codecamp/</link>
		<comments>http://wxwidgets.info/a-mozhet-pogovorim-vzhivuyu-na-codecamp/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 10:59:52 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/a-mozhet-pogovorim-vzhivuyu-na-codecamp/</guid>
		<description><![CDATA[Зарегистрировался сегодня на CodeCamp, который пройдет 28-29 марта 2009г. в Киеве. Если у кого-то есть желание пообщаться на тему кросс-платформенной разработки на C++/wxWidgets, то можно об этом написать в каментах. Договоримся о встрече]]></description>
			<content:encoded><![CDATA[<p>Зарегистрировался сегодня на <a href="http://codecamp.org.ua/" title="CodeCamp 2009">CodeCamp</a>, который пройдет 28-29 марта 2009г. в Киеве. Если у кого-то есть желание пообщаться на тему кросс-платформенной разработки на C++/wxWidgets, то можно об этом написать в каментах. Договоримся о встрече <img src='http://wxwidgets.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/a-mozhet-pogovorim-vzhivuyu-na-codecamp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>wxGoogleTranslate</title>
		<link>http://wxwidgets.info/projects/wxgoogletranslate/</link>
		<comments>http://wxwidgets.info/projects/wxgoogletranslate/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 23:53:02 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?page_id=449</guid>
		<description><![CDATA[Overview wxGoogleTranslate provides wxWidgets-based API for accessing Google Translate service. Downloads wxGoogleTranslate Source Code, Sample Application and binaries for Win32 and Windows Mobile Supported Platforms Windows NT/2000/XP/Vista Windows Mobile 2003/5/6 Windows CE Linux Mac OS Screenshots Usage Retrieve Names of All Supported Languages void wxGoogleTranslateClientMainFrame::FillLanguageChoice(wxChoice * choice) { wxArrayString names; wxGoogleTranslate::GetLanguages(names); choice-&#62;Clear(); for(size_t i = [...]]]></description>
			<content:encoded><![CDATA[<h3>Overview</h3>
<p>wxGoogleTranslate provides wxWidgets-based API for accessing Google Translate service.</p>
<h3>Downloads</h3>
<ul>
<li><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxgoogletranslate.7z">wxGoogleTranslate Source Code, Sample Application and binaries for Win32 and Windows Mobile</a></li>
</ul>
<h3>Supported Platforms</h3>
<ul>
<li>Windows NT/2000/XP/Vista</li>
<li>Windows Mobile 2003/5/6</li>
<li>Windows CE</li>
<li>Linux</li>
<li>Mac OS</li>
</ul>
<h3>Screenshots</h3>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxgoogletranslate-win32.png"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/wxgoogletranslate-win32.png" alt="wxGoogleTranslate - C++ Wrapper for Google Translate - Sample Application for Windows Vista" title="wxGoogleTranslate - C++ Wrapper for Google Translate - Sample Application for Windows Vista" width="300" height="260" class="alignnone size-full wp-image-451" /></a><br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxgoogletranslate-winmobile.png"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/wxgoogletranslate-winmobile.png" alt="wxGoogleTranslate - C++ Wrapper for Google Translate - Sample Application for Windows Mobile" title="wxGoogleTranslate - C++ Wrapper for Google Translate - Sample Application for Windows Mobile" width="330" height="524" class="alignnone size-full wp-image-452" /></a></p>
<h3>Usage</h3>
<h4>Retrieve Names of All Supported Languages</h4>
<pre class="brush: cpp;">
void wxGoogleTranslateClientMainFrame::FillLanguageChoice(wxChoice * choice)
{
	wxArrayString names;
	wxGoogleTranslate::GetLanguages(names);
	choice-&gt;Clear();
	for(size_t i = 0; i &lt; names.Count(); i++)
	{
		choice-&gt;Append(names[i]);
	}
	if(choice-&gt;GetCount() &gt; 0)
	{
		choice-&gt;SetSelection(choice-&gt;GetCount()-1);
	}
}
</pre>
<h4>Translate Text</h4>
<pre class="brush: cpp;">
void wxGoogleTranslateClientMainFrame::OnTRANSLATEClick( wxCommandEvent&amp; event )
{
	do
	{
		wxString result;
		wxString details;
		int errorCode(0);
		int sourceLangselection = m_SourceLanguageChoice-&gt;GetSelection();
		int resultLangselection = m_ResultLanguageChoice-&gt;GetSelection();
		if((sourceLangselection &lt; 0) || (resultLangselection &lt; 0)) break;
		if(wxGoogleTranslate::Translate(m_SourceTextCtrl-&gt;GetValue(),
			result,
			wxGoogleTranslate::GetLanguageCode(
				m_SourceLanguageChoice-&gt;GetString(sourceLangselection)),
			wxGoogleTranslate::GetLanguageCode(
			m_ResultLanguageChoice-&gt;GetString(resultLangselection)),
				details, errorCode))
		{
			m_ResultTextCtrl-&gt;SetValue(result);
		}
		else
		{
			wxMessageBox(wxString::Format(_(&quot;Erorr occured: %s&quot;), details.GetData()));
		}
	}
	while(false);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/projects/wxgoogletranslate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wxYahooMaps</title>
		<link>http://wxwidgets.info/projects/wxyahoomaps/</link>
		<comments>http://wxwidgets.info/projects/wxyahoomaps/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 23:35:53 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?page_id=443</guid>
		<description><![CDATA[wxYahooMaps is wxWidgets-based wrapper around Yahoo! Maps Image API. wxYahooMaps allow downloading map images by specifying location details (such as coordinates, address or description). wxYahooMaps downloads images asynchronously, this means that each image is downloaded in separate thread and GUI thread receives notification when downloading is completed. This allows simultaneous downloading of multiple images whuch [...]]]></description>
			<content:encoded><![CDATA[<p>wxYahooMaps is wxWidgets-based wrapper around Yahoo! Maps Image API. wxYahooMaps allow downloading map images by specifying location details (such as coordinates, address or description). wxYahooMaps downloads images asynchronously, this means that each image is downloaded in separate thread and GUI thread receives notification when downloading is completed. This allows simultaneous downloading of multiple images whuch can be very convenient.</p>
<h3>Downloads</h3>
<ul>
<li><a title="Download wxYahooMaps Source Code" href="http://code.google.com/p/wxyahoomaps/source/checkout" target="_blank">Download wxYahooMaps Source Code</a></li>
</ul>
<h3>Related links</h3>
<ul>
<li><a title="wxYahooMaps at Google Code" href="http://code.google.com/p/wxyahoomaps/">wxYahooMaps homepage at Google Code</a></li>
<li><a href="http://developer.yahoo.com/maps/rest/V1/">Yahoo! Map Image API homepage</a></li>
<li><a href="http://developer.yahoo.com/wsregapp/">Retrieve Application ID for your software</a></li>
<li><a href="http://support.microsoft.com/kb/830482">Runtime Type Information Library for PPC 2003</a></li>
</ul>
<h3>Screenshots</h3>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxyahoomaps-win32.png"><img class="size-full wp-image-444" title="wxYahooMaps - Wrapper C++ Library for Yahoo!! Maps Image API - Smaple for Windows Vista" src="http://wxwidgets.info//wp-content/uploads/2009/01/wxyahoomaps-win32.png" alt="wxYahooMaps - Wrapper C++ Library for Yahoo!! Maps Image API - Smaple for Windows Vista" width="283" height="334" /></a></p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxyahoomaps-winmobile.png"><img class="alignnone size-full wp-image-445" title="wxYahooMaps - Wrapper C++ Library for Yahoo!! Maps Image API - Smaple for Windows Mobile" src="http://wxwidgets.info//wp-content/uploads/2009/01/wxyahoomaps-winmobile.png" alt="wxYahooMaps - Wrapper C++ Library for Yahoo!! Maps Image API - Smaple for Windows Mobile" width="293" height="454" /></a></p>
<h3>Usage</h3>
<pre class="brush: cpp;">
wxYahooMap * m_YahooMap;
...
BEGIN_EVENT_TABLE( wxYahooMapsTestMainFrame, wxFrame )
EVT_YAHOO_MAP_STATUS(wxID_ANY, wxYahooMapsTestMainFrame::OnYahooMapStatus)
END_EVENT_TABLE()
...
void wxYahooMapsTestMainFrame::OnYahooMapStatus(wxYahooMapStatusEvent &amp;amp; event)
{
	if(event.GetInt() == 0)
	{
		wxBitmap * bmp = event.GetBitmap();
		if(bmp)
		{
			m_Canvas-&gt;SetMap(*bmp);
			wxDELETE(bmp);
		}
	}
	else
	{
		wxMessageBox(event.GetString());
	}
}
...
void wxYahooMapsTestMainFrame::OnGOBUTTONClick( wxCommandEvent&amp;amp; event )
{
	TransferDataFromWindow();
	m_YahooMap-&gt;SetApplicationID(m_AppID);
	m_YahooMap-&gt;SetUsePosition(m_UsePosition);
	m_YahooMap-&gt;SetPosition(wxRealPoint(m_Longitude, m_Latitude));
	m_YahooMap-&gt;SetStreet(m_Street);
	m_YahooMap-&gt;SetCity(m_City);
	m_YahooMap-&gt;SetState(m_State);
	m_YahooMap-&gt;SetZIPCode(m_ZIPCode);
	m_YahooMap-&gt;SetImageType(wxYahooMap::IntToYahooMapImageType(m_ImageType));
	m_YahooMap-&gt;SetImageSize(wxSize(m_ImageWidth, m_ImageHeight));
	m_YahooMap-&gt;SetZoomLevel(m_ZoomLevel);
	m_YahooMap-&gt;StartDownloading();
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/projects/wxyahoomaps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links</title>
		<link>http://wxwidgets.info/links/</link>
		<comments>http://wxwidgets.info/links/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 23:15:10 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?page_id=438</guid>
		<description><![CDATA[wxWidgets-Related Sites wxWidgets Official Web-Site wxWidgets Download Page wxWidgets Forum wxCommunity wxWiki wxCode Free IDEs That Support Development with wxWidgets Code::Blocks Eclipse NetBeans CodeLite wxDev-CPP Tools wxFormBuilder &#8211; Free GUI designer for wxWidgets DialogBlocks &#8211; Proprietary GUI designer for wxWidgets wxGlade &#8211; Free GUI designer for wxWidgets Blogs Микроблог про wxWidgets wxBlog Блог &#8220;wxWidgets Programming&#8221; [...]]]></description>
			<content:encoded><![CDATA[<h3>wxWidgets-Related Sites</h3>
<ul>
<li><strong><a title="wxWidgets Official Web-Site" href="http://wxwidgets.org" target="_blank">wxWidgets Official Web-Site</a></strong></li>
<li><strong><a title="Download wxWidgets" href="http://wxwidgets.org/downloads/" target="_blank">wxWidgets Download Page</a><br />
</strong></li>
<li><a title="wxWidgets Forum" href="http://wxforum.shadonet.com" target="_blank">wxWidgets Forum</a></li>
<li><a title="wxCommunity - Site for wxWidgets-related downloads, news, reviews and other information" href="http://wxcommunity.com" target="_blank">wxCommunity</a></li>
<li><a title="wxWidgets Wiki Pages" href="http://wiki.wxwidgets.org" target="_blank">wxWiki</a></li>
<li><a title="wxWidgets 3-rd-Party Components and Libraries" href="http://wxcode.sourceforge.net" target="_blank">wxCode</a></li>
</ul>
<h3>Free IDEs That Support Development with wxWidgets</h3>
<ul>
<li><a title="Code::Blocks - Free cross-platform IDE written in wxWidgets" href="http://codeblocks.org" target="_blank">Code::Blocks</a></li>
<li><a title="Eclipse IDE" href="http://eclipse.org" target="_blank">Eclipse</a></li>
<li><a title="NetBeans IDE" href="http://netbeans.org" target="_blank">NetBeans</a></li>
<li><a title="CodeLite IDE" href="http://codelite.org" target="_blank">CodeLite</a></li>
<li><a title="wxDev-CPP" href="http://wxdsgn.sourceforge.net/" target="_blank">wxDev-CPP</a></li>
</ul>
<h3>Tools</h3>
<ul>
<li><a title="wxFormBuilder - Free GUI designer for wxWidgets" href="http://wxformbuilder.org/" target="_blank"><strong>wxFormBuilder</strong> &#8211; Free GUI designer for wxWidgets</a></li>
<li><a title="DialogBlocks - GUI Editor for wxWidgets" href="http://www.anthemion.co.uk/dialogblocks" target="_blank"><strong>DialogBlocks</strong> &#8211; Proprietary GUI designer for wxWidgets</a></li>
<li><a title="wxGlade - Free GUI designer for wxWidgets" href="http://wxglade.sourceforge.net/" target="_blank"><strong>wxGlade</strong> &#8211; Free GUI designer for wxWidgets</a></li>
</ul>
<h3>Blogs</h3>
<ul>
<li><a title="Микроблог про wxWidgets" href="http://begemotov.net/wxwidgets" target="_blank">Микроблог про wxWidgets</a></li>
<li><a title="wxWidgets Developers Blog" href="http://wxwidgets.blogspot.com" target="_blank">wxBlog</a></li>
<li><a title="Блог &quot;wxWidgets Programming&quot;" href="http://forums.realcoding.net/index.php?automodule=blog&amp;blogid=5&amp;" target="_blank">Блог &#8220;wxWidgets Programming&#8221; на форумах RealCoding.net (закрыт, не обновляется)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projects</title>
		<link>http://wxwidgets.info/projects/</link>
		<comments>http://wxwidgets.info/projects/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 22:48:51 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?page_id=431</guid>
		<description><![CDATA[wxToolBox wxToolBox is a powerful skinnable and customizable wxWidgets component which works like Visual Studio toolbox and/or OutlookBar. Each tab can contain a control (wxListBox, wxListView, wxTreeCtrl, wxPanel etc.) wxToolBox allows to load/save skins and structure of tabs and items from/to XML file. Visit project&#8217;s homepage&#8230; wxYahooMaps wxWidgets wrapper library for accessing Yahoo! Maps Image [...]]]></description>
			<content:encoded><![CDATA[<h3>wxToolBox</h3>
<p><strong>wxToolBox</strong> is a powerful skinnable and customizable wxWidgets component which works like Visual Studio toolbox and/or OutlookBar. Each tab can contain a control (wxListBox, wxListView, wxTreeCtrl, wxPanel etc.) wxToolBox allows to load/save skins and structure of tabs and items from/to XML file. <a title="Visit wxToolBox Homepage" href="http://wxtoolbox.wxwidgets.info" target="_blank">Visit project&#8217;s homepage&#8230;</a></p>
<h3>wxYahooMaps</h3>
<p>wxWidgets wrapper library for accessing<strong> Yahoo! Maps Image API</strong>. <a title="Visit wxYahooMaps Homepage" href="http://wxwidgets.info/wxyahoomaps" target="_blank">Visit ptoject&#8217;s homepage&#8230;</a></p>
<h3>wxGoogleTranslate</h3>
<p>wxWidgets-based Library for accessing <strong>Google Translate</strong> online service. <a title="wxGoogleTranslate" href="http://wxwidgets.info/wxgoogletranslate" target="_blank">Visit project&#8217;s homepage&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Разработка собственных компонентов &#8211; Захват мыши</title>
		<link>http://wxwidgets.info/mouse_capture_ru/</link>
		<comments>http://wxwidgets.info/mouse_capture_ru/#comments</comments>
		<pubDate>Sun, 02 Dec 2007 23:09:54 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=186</guid>
		<description><![CDATA[В продолжение темы о создании собственных компонентов wxWidgets решил написать эту заметку. Касается наш сегодняшний разговор обработки событий от мыши, а точнее, захвату мыши компонентом при нажатии. Что есть захват мыши? Это когда наш компонент продолжает обрабатывать события, поступающие при передвижении курсора мыши, даже когда сам курсор находится вне компонента. Для начала создадим простенький компонент [...]]]></description>
			<content:encoded><![CDATA[<p>В продолжение темы о создании собственных компонентов wxWidgets решил написать эту заметку. Касается наш сегодняшний разговор обработки событий от мыши, а точнее, захвату мыши компонентом при нажатии. Что есть захват мыши? Это когда наш компонент продолжает обрабатывать события, поступающие при передвижении курсора мыши, даже когда сам курсор находится вне компонента.<br />
Для начала создадим простенький компонент и хост-приложение для него:<br />
<span id="more-186"></span><br />
<b>MouseCaptureTestCtrl.h</b></p>
<pre class="brush: cpp;">
#ifndef _MOUSE_CAPTURE_TEST_CONTROL_H
#define _MOUSE_CAPTURE_TEST_CONTROL_H

#include &lt;wx/wx.h&gt;

class MouseCaptureTestControl : public wxControl
{
public:
	MouseCaptureTestControl(wxWindow * parent,
		wxWindowID id = wxID_ANY,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxNO_BORDER);
	DECLARE_EVENT_TABLE()
	void OnPaint(wxPaintEvent &amp; event);
	void OnEraseBackground(wxEraseEvent &amp; event);
	void OnMouseMove(wxMouseEvent &amp; event);
};

#endif
</pre>
<p><b>MouseCaptureTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;MouseCaptureTestControl.h&quot;
#include &lt;wx/dcbuffer.h&gt;

BEGIN_EVENT_TABLE(MouseCaptureTestControl, wxControl)
EVT_PAINT(MouseCaptureTestControl::OnPaint)
EVT_ERASE_BACKGROUND(MouseCaptureTestControl::OnEraseBackground)
EVT_MOTION(MouseCaptureTestControl::OnMouseMove)
END_EVENT_TABLE()

MouseCaptureTestControl::MouseCaptureTestControl(wxWindow * parent,
	wxWindowID id, const wxPoint &amp; pos, const wxSize &amp; size, long style)
	: wxControl(parent, id, pos, size, style)
{
}

void MouseCaptureTestControl::OnPaint(wxPaintEvent &amp; event)
{
	wxBufferedPaintDC dc(this);
	dc.SetBackground(wxBrush(GetBackgroundColour()));
	dc.Clear();
	wxPoint pos = ScreenToClient(wxGetMousePosition());
	dc.SetFont(GetFont());
	dc.SetTextForeground(GetForegroundColour());
	dc.DrawLabel(wxString::Format(wxT(&quot;%i,%i&quot;), pos.x, pos.y), wxNullBitmap,
		GetClientRect(), wxALIGN_CENTER);
}

void MouseCaptureTestControl::OnEraseBackground(wxEraseEvent &amp; event)
{
}

void MouseCaptureTestControl::OnMouseMove(wxMouseEvent &amp; event)
{
	Refresh();
}
</pre>
<p><b>wxTest.cpp</b></p>
<pre class="brush: cpp;">
#include &lt;wx/wx.h&gt;
#include &quot;MouseCaptureTestControl.h&quot;

class MyApp : public wxApp
{
	virtual bool OnInit();
};

DECLARE_APP(MyApp);

class MyFrame : public wxFrame
{
	void CreateControls();
public:
	bool Create(wxWindow * parent)
	{
		bool res = wxFrame::Create(parent, wxID_ANY, wxT(&quot;Da, Yo!&quot;),
			wxDefaultPosition, wxSize(400, 300));
		if(res)
		{
			CreateControls();
		}
		return res;
	}
	MyFrame()
	{
		Create(NULL);
	}
	DECLARE_EVENT_TABLE()
	void OnExit(wxCommandEvent &amp; event)
	{
		Close();
	}
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
END_EVENT_TABLE()

void MyFrame::CreateControls()
{
	wxMenuBar * menuBar = new wxMenuBar;
	SetMenuBar(menuBar);

	wxMenu * fileMenu = new wxMenu;
	fileMenu-&gt;Append(wxID_EXIT, _(&quot;Exit\tAlt+F4&quot;));
	menuBar-&gt;Append(fileMenu, _(&quot;File&quot;));

	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	MouseCaptureTestControl * control = new MouseCaptureTestControl(this, wxID_ANY);
	sizer-&gt;Add(control, 1, wxEXPAND);

	CreateStatusBar();
}

bool MyApp::OnInit()
{
	MyFrame * frame = new MyFrame;
	SetTopWindow(frame);
	frame-&gt;Centre();
	frame-&gt;Show();
	return true;
}

IMPLEMENT_APP(MyApp);
</pre>
<p>Итак, что же у нас получилось. У нас получился новый компонент, который при перемещении над ним курсора мыши отображает координаты мыши.</p>
<p><center><img src="http://wxwidgets.info//wp-content/uploads/2009/01/mouse_capture_1.png"></center></p>
<p>Для того чтобы наш компонент продолжал обрабатывать событие <code>wxEVT_MOTION</code> даже когда курсор находится вне компонента нам необходимо добавить пару обработчиков – обработчики нажатия и отжатия левой кнопки мыши.</p>
<p><b>MouseCaptureTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
class MouseCaptureTestControl : public wxControl
{
	DECLARE_EVENT_TABLE()
	...
	void OnLeftMouseDown(wxMouseEvent &amp; event);
	void OnLeftMouseUp(wxMouseEvent &amp; event);
};
...
</pre>
<p><b>MouseCaptureTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
BEGIN_EVENT_TABLE(MouseCaptureTestControl, wxControl)
...
EVT_LEFT_DOWN(MouseCaptureTestControl::OnLeftMouseDown)
EVT_LEFT_UP(MouseCaptureTestControl::OnLeftMouseUp)
END_EVENT_TABLE()
...
void MouseCaptureTestControl::OnLeftMouseDown(wxMouseEvent &amp; event)
{
	CaptureMouse();
}

void MouseCaptureTestControl::OnLeftMouseUp(wxMouseEvent &amp; event)
{
	ReleaseMouse();
}
</pre>
<p>Когда пользователь нажимает левой кнопкой мыши на компоненте, происходит захват мыши, и пока кнопка не будет отжата, компонент будет отрисовывать новые значения координат мыши при перемещении курсора. Такой функционал может быть востребован при разработке, например, графических редакторов, когда курсор мыши может выходить за пределы области рисования. Вот это мы сейчас и рассмотрим на простеньком примере.</p>
<p><b>MouseCaptureTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
#include &lt;wx/dynarray.h&gt;

class MyLine
{
	wxPoint start;
	wxPoint end;
	MyLine(wxPoint s, wxPoint e) : start(s), end(e) {}
	void Draw(wxDC &amp; dc)
	{
		dc.DrawLine(start, end);
	}
};

WX_DECLARE_OBJARRAY(MyLine, MyLineArray);

class MouseCaptureTestControl : public wxControl
{
	wxPoint m_LineStart;
	MyLineArray m_Lines;
...
};
...
</pre>
<p><b>MouseCaptureTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
#include &lt;wx/arrimpl.cpp&gt;

WX_DEFINE_OBJARRAY(MyLineArray)

...
void MouseCaptureTestControl::OnPaint(wxPaintEvent &amp; event)
{
	wxBufferedPaintDC dc(this);
	dc.SetBackground(wxBrush(GetBackgroundColour()));
	dc.Clear();
	wxPoint pos = ScreenToClient(wxGetMousePosition());
	dc.SetFont(GetFont());
	dc.SetTextForeground(GetForegroundColour());
	dc.DrawLabel(wxString::Format(wxT(&quot;%i,%i&quot;), pos.x, pos.y), wxNullBitmap,
		GetClientRect(), wxALIGN_CENTER);
	for(size_t i = 0; i &lt; m_Lines.Count(); i++)
	{
		m_Lines[i].Draw(dc);
	}
}
...
void MouseCaptureTestControl::OnLeftMouseDown(wxMouseEvent &amp; event)
{
	CaptureMouse();
	m_LineStart = event.GetPosition();
}

void MouseCaptureTestControl::OnLeftMouseUp(wxMouseEvent &amp; event)
{
	if(GetCapture() == this)
	{
		m_Lines.Add(MyLine(m_LineStart, event.GetPosition()));
	}
	ReleaseMouse();
	Refresh();
}
</pre>
<p>Итак, что у нас получилось. Мы создали новый класс <code>MyLine</code> и добавили в наш компонент массив объектов этого класса. При нажатии кнопки мыши мы запоминаем координату, где было произведено нажатие, а пи отжатии добавляем в массив новую линию, концы которой соответствуют точке нажатия и отжатия кнопки мыши. Ну и сам компонент отрисовывает все линии в обработчике события <code>wxEVT_PAINT</code>.</p>
<p><center><img src="http://wxwidgets.info//wp-content/uploads/2009/01/mouse_capture_2.png"></center><br />
Все это чудесно, но чего-то не хватает. А не хватает у нас отрисовки создаваемой линии в процессе перемещения курсора при нажатой левой кнопке.  Для того чтобы добавить эту отрисовку нужно дописать несколько строк:</p>
<p><b>MouseCaptureTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
void MouseCaptureTestControl::OnPaint(wxPaintEvent &amp; event)
{
	...
	if(GetCapture() == this)
	{
		MyLine(m_LineStart, pos).Draw(dc);
	}
}
...
</pre>
<p>Ну вот, как видно, линия продолжает отрисовываться даже когда курсор находится за пределами компонента, что, собственно, и нужно было продемонстрировать.</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxmousecapturetest.7z" title="Скачать исходник: Разработка собственных компонентов. Захват мыши">Скачать исходный код примера</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/mouse_capture_ru/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Разработка собственных компонентов &#8211; Оптимизация отрисовки графики</title>
		<link>http://wxwidgets.info/painting_optimization_ru/</link>
		<comments>http://wxwidgets.info/painting_optimization_ru/#comments</comments>
		<pubDate>Mon, 28 May 2007 17:39:53 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[wxPaintDC]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=191</guid>
		<description><![CDATA[У каждого из нас бывают ситуации, когда кажется что того набора компонент, которые доступны в стандартной поставке, недостаточно для комфортной работы. Иногда написание своих компонентов является фатальной необходимостью. Так, например, в моей практике часто возникали ситуации, когда необходимо было разрабатывать новые элементы управления, которые по своей функциональности заменяли бы несколько стандартных элементов. Зачастую к созданию [...]]]></description>
			<content:encoded><![CDATA[<p>У каждого из нас бывают ситуации, когда кажется что того набора компонент, которые доступны в стандартной поставке, недостаточно для комфортной работы. Иногда написание своих компонентов является фатальной необходимостью. Так, например, в моей практике часто возникали ситуации, когда необходимо было разрабатывать новые элементы управления, которые по своей функциональности заменяли бы несколько стандартных элементов. Зачастую к созданию новых элементов управления нас подталкивает мода на всякого рода красивости, которые так любят обычные пользователи.<br />
Но так ли часто мы задумываемся о том, правильно ли выбрана реализация того или иного компонента, на сколько быстро и эффективно работает наш компонент и не будет ли его использование замедлять работу нашей программы? Конечно, сегодня аппаратное обеспечение позволяет всё реже и реже задумываться о таких вещах, но в случаях, когда недоработок слишком много, быстродействие может снижаться очень заметно.<br />
Сегодня я хочу рассказать о том, как же все-таки избавить себя от головной боли при разработке элементов управления и обеспечить максимальное быстродействие при отрисовке графики.<br />
<span id="more-191"></span><br />
Представим себе ситуацию, что мы решили создать свой компонент и уже определились с его функционалом (у нас это будут аналоговые часы). Прежде чем начинать работу над компонентом, неплохо было бы создать небольшое тестовое приложение, которое позволило бы проверить его работоспособность. Ничего сложного мы делать не будем, и создадим обычное GUI-приложение с одной формой:</p>
<p><b>PaintingTestMainFrame.h</b></p>
<pre class="brush: cpp;">
#ifndef _PAINTING_TEST_MAINFRAME_H
#define _PAINTING_TEST_MAINFRAME_H

#include &lt;wx/wx.h&gt;
#include &quot;wxPaintingTestCtrl.h&quot;

class PaintingTestMainFrame : public wxFrame
{
	void CreateControls();
public:
	PaintingTestMainFrame(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString &amp; title = _(&quot;Painting Optimization Test&quot;));
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString &amp; title = wxEmptyString,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxCAPTION|wxSYSTEM_MENU|
					 wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX|
					 wxRAISED_BORDER|wxRESIZE_BORDER);
};

#endif
</pre>
<p><b>PaintingTestMainFrame.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;PaintingTestMainFrame.h&quot;

PaintingTestMainFrame::PaintingTestMainFrame(wxWindow * parent, wxWindowID id, const wxString &amp; title)
{
	Create(parent, id, title);
}

bool PaintingTestMainFrame::Create(wxWindow * parent, wxWindowID id, const wxString &amp; title,
	const wxPoint &amp; pos, const wxSize &amp; size, long style)
{
	bool res = wxFrame::Create(parent, id, title, pos, size, style);
	if(res)
	{
		SetMinSize(wxSize(450, 300));
		CreateControls();
	}
	return res;
}

void PaintingTestMainFrame::CreateControls()
{
}
</pre>
<p><b>PaintingTestApp.h</b></p>
<pre class="brush: cpp;">
#ifndef _PAINTING_TEST_APP_H
#define _PAINTING_TEST_APP_H

#include &lt;wx/wx.h&gt;

class PaintingTestApp : public wxApp
{
public:
	virtual bool OnInit();
};

#endif
</pre>
<p><b>PaintingTestApp.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;PaintingTestApp.h&quot;
#include &quot;PaintingTestMainFrame.h&quot;
#include &lt;wx/image.h&gt;

IMPLEMENT_APP(PaintingTestApp);

bool PaintingTestApp::OnInit()
{
	wxImage::AddHandler(new wxPNGHandler);
	PaintingTestMainFrame * frame = new PaintingTestMainFrame(NULL);
	SetTopWindow(frame);
	frame-&gt;Centre();
	frame-&gt;Show();
	return true;
}
</pre>
<p>Теперь можно приступать к написанию класса компонента:</p>
<p><b>wxPaintingTestCtrl.h</b></p>
<pre class="brush: cpp;">
#ifndef _WX_PAINTING_TEST_CTRL_H
#define _WX_PAINTING_TEST_CTRL_H

#include &lt;wx/wx.h&gt;

#ifndef wxPaintingTestCtrlName
#define wxPaintingTestCtrlName wxT(&quot;wxPaintingTestCtrl&quot;)
#endif

class wxPaintingTestCtrl : public wxControl
{
protected:
	wxBitmap m_BackgroundBitmap;
	wxBitmap m_CenterBitmap;
	virtual wxSize DoGetBestSize() const;
	void DoDraw(wxDC &amp; dc);
public:
	wxPaintingTestCtrl(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxBitmap &amp; bitmap = wxNullBitmap,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxSIMPLE_BORDER,
		const wxString name = wxPaintingTestCtrlName);
	~wxPaintingTestCtrl();
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxBitmap &amp; bitmap = wxNullBitmap,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxSIMPLE_BORDER,
		const wxString name = wxPaintingTestCtrlName);

	void SetBackgroundBitmap(wxBitmap &amp; bitmap);
	const wxBitmap &amp; GetBackgroundBitmap();

	void SetCenterBitmap(wxBitmap &amp; bitmap);
	const wxBitmap &amp; GetCenterBitmap();

	DECLARE_EVENT_TABLE()
	void OnPaint(wxPaintEvent &amp; event);
};
</pre>
<p>Класс компонента содержит два объекта класса wxBitmap – первый хранит себе фоновое изображение (m_BackgroundBitmap), а второй – изображение циферблата (m_CenterBitmap).</p>
<p>Метод DoGetBestSize() позволяет переопределить размер компонента по умолчанию (у нас это будет wxSize(100,100), см. ниже)</p>
<p>Get/SetBackgroundBitmap и Get/SetCenterBitmap – это, соответственно, aceessor-методы для фонового изображения и для изображения циферблата</p>
<p>OnPaint – Обработчик события wxEVT_PAINT (отвечает за отрисовку графики)</p>
<p><b>wxPaintingTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;wxPaintingTestCtrl.h&quot;
#include &lt;wx/valgen.h&gt;
#include &lt;wx/datetime.h&gt;
#include &lt;algorithm&gt;

using namespace std;

BEGIN_EVENT_TABLE(wxPaintingTestCtrl, wxControl)
EVT_PAINT(wxPaintingTestCtrl::OnPaint)
END_EVENT_TABLE()

wxPaintingTestCtrl::wxPaintingTestCtrl(wxWindow * parent, wxWindowID id, const wxBitmap &amp; bitmap,
	const wxPoint &amp; pos, const wxSize &amp; size, long style, const wxString name)
{
	Create(parent, id, bitmap, pos, size, style, name);
}

wxPaintingTestCtrl::~wxPaintingTestCtrl()
{

}

bool wxPaintingTestCtrl::Create(wxWindow * parent, wxWindowID id, const wxBitmap &amp; bitmap,
	const wxPoint &amp; pos, const wxSize &amp; size, long style, const wxString name)
{
	bool res = wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name);
	if(res)
	{
		m_BackgroundBitmap = bitmap;
	}
	return res;
}

wxSize wxPaintingTestCtrl::DoGetBestSize() const
{
	if(m_CenterBitmap.Ok())
	{
		return wxSize(m_CenterBitmap.GetWidth(), m_CenterBitmap.GetHeight());
	}
	return wxSize(100,100);
}

void wxPaintingTestCtrl::SetBackgroundBitmap(wxBitmap &amp; bitmap)
{
	m_BackgroundBitmap = bitmap;
}

const wxBitmap &amp; wxPaintingTestCtrl::GetBackgroundBitmap()
{
	return m_BackgroundBitmap;
}

void wxPaintingTestCtrl::SetCenterBitmap(wxBitmap &amp; bitmap)
{
	m_CenterBitmap = bitmap;
}

const wxBitmap &amp; wxPaintingTestCtrl::GetCenterBitmap()
{
	return m_CenterBitmap;
}

void wxPaintingTestCtrl::OnPaint(wxPaintEvent &amp; event)
{
	wxPaintDC dc(this);
	DoDraw(dc);
}

void wxPaintingTestCtrl::DoDraw(wxDC &amp; dc)
{
	int x, y, w, h, i;
	double angle;
	GetClientSize(&amp;w, &amp;h);
	int cx(w/2), cy(h/2), radius(min(cx,cy)-10);
	if(m_BackgroundBitmap.Ok())
	{
		for(y = 0; y &lt; h; y += m_BackgroundBitmap.GetHeight())
		{
			for(x = 0; x &lt; w; x += m_BackgroundBitmap.GetWidth())
			{
				dc.DrawBitmap(m_BackgroundBitmap, x, y, true);
			}
		}
	}
	else
	{
		dc.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID));
		dc.Clear();
	}
	if(m_CenterBitmap.Ok())
	{
		radius = (m_CenterBitmap.GetWidth()/2) * 5.0 / 6.0;
		dc.DrawBitmap(m_CenterBitmap, cx-m_CenterBitmap.GetWidth()/2,
			cy-m_CenterBitmap.GetHeight()/2, true);
	}
	wxPen linePen(*wxBLACK, 2, wxSOLID);
	dc.SetPen(linePen);
	for(i = 0; i &lt; 12; i++)
	{
		angle = 2.0*3.1415926/12.0*(double)i;
		dc.DrawLine(cx+radius*cos(angle), cy+radius*sin(angle),
			cx+(radius/5.0*4.0)*cos(angle), cy+(radius/5.0*4.0)*sin(angle));
	}
	wxDateTime now = wxDateTime::Now();
	linePen.SetColour(*wxRED);
	linePen.SetWidth(3);
	dc.SetPen(linePen);
	angle = 2.0*3.1415926/12.0*(double)now.GetHour()-3.1415926/2;
	dc.DrawLine(cx, cy, cx+radius*cos(angle), cy+radius*sin(angle));
	linePen.SetWidth(2);
	dc.SetPen(linePen);
	angle = 2.0*3.1415926/60.0*(double)now.GetMinute()-3.1415926/2;
	dc.DrawLine(cx, cy, cx+radius*cos(angle), cy+radius*sin(angle));
	linePen.SetColour(wxColour(0,0,127));
	linePen.SetWidth(1);
	dc.SetPen(linePen);
	angle = 2.0*3.1415926/60.0*(double)now.GetSecond()-3.1415926/2;
	dc.DrawLine(cx, cy, cx+radius*cos(angle), cy+radius*sin(angle));
}
</pre>
<p>Теперь нам нужно добавить наш компонент на форму</p>
<p><b>PaintingTestMainFrame.h</b></p>
<pre class="brush: cpp;">
...
class PaintingTestMainFrame : public wxFrame
{
	wxPaintingTestCtrl * m_TestCtrl1;
	...
public:
	...
};
...

PaintingTestMainFrame.cpp

...
void PaintingTestMainFrame::CreateControls()
{
	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);
	wxBitmap background(wxT(&quot;background.png&quot;), wxBITMAP_TYPE_PNG);
	wxBitmap center(wxT(&quot;center.png&quot;), wxBITMAP_TYPE_PNG);
	m_TestCtrl1 = new wxPaintingTestCtrl(this, ID_TEST_CTRL1, background);
	m_TestCtrl1-&gt;SetCenterBitmap(center);

	sizer-&gt;Add(m_TestCtrl1, 1, wxGROW|wxALL, 5);
}
...
</pre>
<p>Запускаем наше приложение и смотрим<br />
При изменении размеров формы наблюдаем артефакты отрисовки<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image1.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image1.jpg" alt="Оптимизация отрисовки графики в wxWidgets - 1" title="Оптимизация отрисовки графики в wxWidgets - 1" width="552" height="394" class="alignnone size-full wp-image-192" /></a><br />
Для того чтобы убрать эти артефакты, нам необходимо переопределить обработчик события изменения размеров нашего компонента</p>
<p><b>wxPaintingTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
class wxPaintingTestCtrl : public wxControl
{
...
	DECLARE_EVENT_TABLE()
	...
	void OnSize(wxSizeEvent &amp; event);
};
...
</pre>
<p><b>wxPaintingTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
BEGIN_EVENT_TABLE(wxPaintingTestCtrl, wxControl)
...
EVT_SIZE(wxPaintingTestCtrl::OnSize)
END_EVENT_TABLE()
...
void wxPaintingTestCtrl::OnSize(wxSizeEvent &amp; event)
{
	Refresh();
}
...
</pre>
<p>Отлично. Собираем наше приложение, запускаем. И что мы видим: сильное мерцание при изменении размеров. Но с этой проблемой мы тоже можем довольно легко справиться, сделав небольшие изменения в исходном коде</p>
<p><b>wxPaintingTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
class wxPaintingTestCtrl : public wxControl
{
...
	DECLARE_EVENT_TABLE()
	...
	void OnEraseBackground(wxEraseEvent &amp; event);
};
...
</pre>
<p><b>wxPaintingTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
#include &lt;wx/dcbuffer.h&gt;

BEGIN_EVENT_TABLE(wxPaintingTestCtrl, wxControl)
...
EVT_ERASE_BACKGROUND(wxPaintingTestCtrl::OnEraseBackground)
...
END_EVENT_TABLE()
...
void wxPaintingTestCtrl::OnPaint(wxPaintEvent &amp; event)
{
	wxBufferedPaintDC dc(this);
	DoDraw(dc);
}
...
</pre>
<p>Класс wxBufferedPaintDC обеспечивает doublebuffering при отрисовке, что позволяет избавиться от мерцания.<br />
Пустой обработчик события wxEVT_ERASE_BACKGROUND также позволяет немного ускорить отрисовку.</p>
<p>Собираем приложение, запускаем…. отлично, мерцание исчезло. Но стрелки наших аналоговых часов изменяют положение только при перерисовке содержимого компонента. Это значит, что нам не обходимо добавить таймер, который будет инициировать отрисовку  через определенный промежуток времени</p>
<p><b>wxPaintingTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
class wxPaintingTestCtrl : public wxControl
{
protected:
	...
	wxTimer * m_Timer;
	...
	DECLARE_EVENT_TABLE()
	void OnRefreshTimer(wxTimerEvent &amp; event);
};
...
</pre>
<p><b>wxPaintingTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...

enum
{
	ID_PAINTING_TEST_CTRL_TIMER = 10001
};
...

BEGIN_EVENT_TABLE(wxPaintingTestCtrl, wxControl)
...
EVT_TIMER(ID_PAINTING_TEST_CTRL_TIMER, wxPaintingTestCtrl::OnRefreshTimer)
END_EVENT_TABLE()
...
void wxPaintingTestCtrl::OnRefreshTimer(wxTimerEvent &amp; event)
{
	Refresh();
}
</pre>
<p>Собираем, запускаем.<br />
Отлично. Видно что часы идут. Но на этом работа не заканчивается. Разворачиваем окно программы на весь экран, запускаем Task Manager и начинаем перемещать окно Task Manager над компонентом</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image2.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image2-300x238.jpg" alt="Оптимизация отрисовки графики в wxWidgets - 2" title="Оптимизация отрисовки графики в wxWidgets - 2" width="300" height="238" class="alignnone size-medium wp-image-193" /></a></p>
<p>В результате получаем загрузку процессора на 100%. Это происходит потому что при каждой перерисовке объект класса wxBufferedPaintDC создает изображение размером с наш компонент, отрисовка производится на это изображение в памяти, а потом это изображение отрисовывается на компонент.<br />
Попробуем сделать так, чтобы наш компонент работал быстрее и не потреблял такое огромное количество ресурсов. Для этого мы попробуем реализовать doublebuffering вручную.<br />
Добавим новуые переменные в класс компонента</p>
<p><b>wxPaintingTestCtrl.h</b></p>
<pre class="brush: cpp;">
...
class wxPaintingTestCtrl : public wxControl
{
protected:
	wxBitmap m_DoubleBuffer;
	wxMemoryDC m_DoubleBufferDC;
	...
};
...
</pre>
<p><b>wxPaintingTestCtrl.cpp</b></p>
<pre class="brush: cpp;">
...
void wxPaintingTestCtrl::OnPaint(wxPaintEvent &amp; event)
{
	wxPaintDC dc(this);
	dc.Blit(0,0, dc.GetSize().GetWidth(), dc.GetSize().GetHeight(), &amp;m_DoubleBufferDC, 0, 0);
}
...
void wxPaintingTestCtrl::OnSize(wxSizeEvent &amp; event)
{
	m_DoubleBufferDC.SelectObject(wxNullBitmap);
	m_DoubleBuffer = wxBitmap(event.GetSize().GetWidth(), event.GetSize().GetHeight());
	m_DoubleBufferDC.SelectObject(m_DoubleBuffer);
	DoDraw(m_DoubleBufferDC);
	Refresh();
}

void wxPaintingTestCtrl::OnRefreshTimer(wxTimerEvent &amp; event)
{
	DoDraw(m_DoubleBufferDC);
	Refresh();
}
</pre>
<p>Как видно, при изменении размеров мы пересоздаем изображение, используемое для doublebuffering’а,  ассоциируем с ним контекст устройства  m_DoubleBuffer и производим отрисовку на изображение в памяти. А в обработчике OnPaint производим копирование из контекста устройства изображения на контекст устройства компонента. В результате загрузка процессора значительно снизилась<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image3.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image3-300x225.jpg" alt="Оптимизация отрисовки графики в wxWidgets - 3" title="Оптимизация отрисовки графики в wxWidgets - 3" width="300" height="225" class="alignnone size-medium wp-image-194" /></a><br />
Ну и результатом всей нашей работы будет вот такой компонент – аналоговые часы<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image4.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/painting_test_image4-300x256.jpg" alt="Оптимизация отрисовки графики в wxWidgets - 4" title="Оптимизация отрисовки графики в wxWidgets - 4" width="300" height="256" class="alignnone size-medium wp-image-195" /></a><br />
Хотелось бы заметить, что реализация doublebuffering&#8217;а вручную не всегда является самым удачным выбором. Для компонентов, которые будут иметь небольшой размер на форме, можно использовать wxBufferedPaintDC (или даже wxPaintDC если не требуется отрисовка большого количества графических объектов)</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/paintingtest.7z" title="Скачать исходник: Оптимизация отрисовки графики в wxWidgets">Скачать исходный код примера и проект для VisualStudio 2005 и wxDev-CPP</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/painting_optimization_ru/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Привязка данных к элементам управления и проверка корректности ввода данных в wxWidgets</title>
		<link>http://wxwidgets.info/data_validation_tutorial_ru/</link>
		<comments>http://wxwidgets.info/data_validation_tutorial_ru/#comments</comments>
		<pubDate>Mon, 28 May 2007 17:16:47 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[wxValidator]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=198</guid>
		<description><![CDATA[Несколько раз пытался начать писать эту статью, но находил все новые и новые варианты доработки примера к ней, поэтому времени ушло много. Надеюсь, материал, изложенный ниже, принесет кому-нибудь пользу. В этот раз я хочу рассказать о таком полезном явлении, как привязка данных и проверка вводимых значений. Многие из нас помнят, какими неудобными были установка и [...]]]></description>
			<content:encoded><![CDATA[<p>Несколько раз пытался начать писать эту статью, но находил все новые и новые варианты доработки примера к ней, поэтому времени ушло много. Надеюсь, материал, изложенный ниже, принесет кому-нибудь пользу.</p>
<p>В этот раз я хочу рассказать о таком полезном явлении, как привязка данных и проверка вводимых значений.<br />
<span id="more-198"></span><br />
Многие из нас помнят, какими неудобными были установка и получение значений, отображаемых элементами управления, с использованием WinAPI. Все эти <code>GetWindowText/SetWindowText</code> с последующей проверкой значений вручную… это ведь так долго. На это уходит столько времени.</p>
<p>К счастью для нас, в wxWidgets для обеспечения привязки данных и их автоматического отображения существуют специальная группа классов, называемых валидаторами (Validators). </p>
<p>Большинство элементов управления в wxWidgets поддерживают обмен данными через валидаторы. В wxWidgets существует механизм привязки данных к стандартным элементам управления (такие как <code>wxTextCtrl</code>, <code>wxListBox</code>, <code>wxListCtrl</code>, <code>wxSpinCtrl</code> и др.). Для этой цели используются классы <code>wxGenericValidator</code> и <code>wxTextValidator</code>.<br />
С помощью класса <code>wxGenericValidator</code> возможна привязка данных типа <code>int</code>, <code>bool</code>, <code>wxString</code>, <code>wxArrayInt</code> (<code>wxArrayInt</code> используется для получения списка выделенных элементов например в <code>wxListBox</code>).</p>
<p>Для того, чтобы обеспечить привязку данных к элементу управления, необходимо<br />
- Создать переменную-член класса формы<br />
- После того, как элемент управления создан, привязать к нему данные с помощью метода <code>SetValidator</code><br />
- Валидатор можно задать и при создании элемента управления (в качестве параметра конструктора или метода <code>Create</code>)<br />
Делается это довольно просто</p>
<pre class="brush: cpp;">
class MyDialog : public wxDialog
{
	double m_Width;
...
};
...
wxTextCtrl width_textctrl = new wxTextCtrl(this, ID_QUANTITY_TEXTCTRL,
wxEmptyString, wxDefaultPosition, wxSize(150,-1),
0, wxFPValidator(&amp;m_Width));
</pre>
<p>Давайте создадим небольшое тестовое приложение и посмотрим, как работает механизм привязки данных.</p>
<p><b>Application.h</b></p>
<pre class="brush: cpp;">
#ifndef _APPLICATION_H
#define _APPLICATION_H

#include &lt;wx/wx.h&gt;

class MyApp : public wxApp
{
	wxImageList m_ImageList;
public:
	virtual bool OnInit();
	wxImageList &amp; GetImageList()
	{
		return m_ImageList;
	}
};

DECLARE_APP(MyApp);

#endif
</pre>
<p><b>Application.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;Application.h&quot;
#include &quot;MainFrame.h&quot;
#include &lt;wx/image.h&gt;

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
	wxImage::AddHandler(new wxXPMHandler);
	m_ImageList.Create(15, 15);
	m_ImageList.Add(wxBitmap(wxT(&quot;package_ok.xpm&quot;), wxBITMAP_TYPE_XPM));
	m_ImageList.Add(wxBitmap(wxT(&quot;package_error.xpm&quot;), wxBITMAP_TYPE_XPM));
	MainFrame * frame = new MainFrame;
	SetTopWindow(frame);
	frame-&gt;Centre();
	frame-&gt;Show();
	return true;
}
</pre>
<p><b>MainFrame.h</b></p>
<pre class="brush: cpp;">
#ifndef _MAIN_FRAME_H
#define _MAIN_FRAME_H

#include &lt;wx/wx.h&gt;

class MainFrame : public wxFrame
{
public:
	MainFrame();
	DECLARE_EVENT_TABLE();
	void OnShowStandardValidators(wxCommandEvent &amp; event);
};

#endif
</pre>
<p><b>MainFrame.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;MainFrame.h&quot;

#include &quot;DefaultValidatorsDialog.h&quot;

enum
{
	ID_MANUAL_VALIDATION_BUTTON = 10001,
	ID_STANDARD_VALIDATORS_BUTTON,
	ID_EXTENDED_VALIDATORS_BUTTON
};

BEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_BUTTON(ID_MANUAL_VALIDATION_BUTTON, MainFrame::OnShowManualValidation)
EVT_BUTTON(ID_STANDARD_VALIDATORS_BUTTON, MainFrame::OnShowStandardValidators)
EVT_BUTTON(ID_EXTENDED_VALIDATORS_BUTTON, MainFrame::OnShowExtendedValidators)
END_EVENT_TABLE()

MainFrame::MainFrame()
: wxFrame(NULL, wxID_ANY, _(&quot;wxFPValidator Test&quot;), wxDefaultPosition, wxDefaultSize,
		  wxCAPTION|wxCLOSE_BOX|wxSYSTEM_MENU|wxRAISED_BORDER)
{
#ifdef __WXMSW__
	SetIcon(wxIcon(wxT(&quot;MAIN_ICON&quot;), wxBITMAP_TYPE_ICO_RESOURCE));
#else
	SetIcon(wxIcon(wxT(&quot;wxwin.ico&quot;), wxBITMAP_TYPE_ICO));
#endif

	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	wxButton * standard_validators_button = new wxButton(this,
 ID_STANDARD_VALIDATORS_BUTTON, _(&quot;Standard Validators&quot;));
	sizer-&gt;Add(standard_validators_button, 0, wxGROW|wxALL, 5);

	sizer-&gt;Fit(this);
	SetMinSize(GetSize());

	SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
}

void MainFrame::OnShowStandardValidators(wxCommandEvent &amp; event)
{
	DefaultValidatorsDialog * dlg = new DefaultValidatorsDialog(this);
	if(dlg-&gt;ShowModal() == wxID_OK)
	{
		wxString result;
		double salary(0);
		if(!dlg-&gt;GetSalary().ToDouble(&amp;salary))
		{
			wxMessageBox(wxT(&quot;Illagal value of 'Salary' field&quot;));
			return;
		}
		result = wxString::Format(
_(&quot;Name = %s\r\nAge = %i\r\nSalary = %1.2f\r\nMarital Status = %s\r\nSkills = &quot;),
			dlg-&gt;GetName().GetData(),
			dlg-&gt;GetAge(),
			salary,
			dlg-&gt;GetMaritalStatus() ?
wxT(&quot;married&quot;) : wxT(&quot;not married&quot;));
		wxString skill_list;
		for(size_t i = 0; i &lt; dlg-&gt;GetSkills().Count(); i++)
		{
			if(!skill_list.IsEmpty()) skill_list += wxT(&quot;,&quot;);
			skill_list += wxString::Format(
wxT(&quot;%i&quot;), dlg-&gt;GetSkills()[i]);
		}
		result += skill_list;
		wxMessageBox(result);
	}
	dlg-&gt;Destroy();
}
</pre>
<p><b>DefaultValidatorsDialog.h</b></p>
<pre class="brush: cpp;">
#ifndef _DEFAULT_VALIDATORS_DIALOG_H
#define _DEFAULT_VALIDATORS_DIALOG_H

#include &lt;wx/wx.h&gt;

#define DefaultValidatorsDialogName _(&quot;Default Validators&quot;)

class DefaultValidatorsDialog : public wxDialog
{
	wxString m_Name;
	int m_Age;
	wxString m_Salary;
	bool m_Married;
	wxArrayInt m_Skills;
	void CreateControls();
public:
	DefaultValidatorsDialog();
	DefaultValidatorsDialog(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = DefaultValidatorsDialogName);
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = DefaultValidatorsDialogName);

	wxString GetName() {return m_Name;}
	int GetAge() {return m_Age;}
	wxString GetSalary() {return m_Salary;}
	bool GetMaritalStatus() {return m_Married;}
	wxArrayInt &amp; GetSkills() {return m_Skills;}
};

#endif
</pre>
<p><b>DefaultValidatorsDialog.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;DefaultValidatorsDialog.h&quot;
#include &lt;wx/textctrl.h&gt;
#include &lt;wx/spinctrl.h&gt;
#include &lt;wx/checkbox.h&gt;
#include &lt;wx/listbox.h&gt;
#include &lt;wx/valgen.h&gt;

enum
{
	ID_NAME_TEXTCTRL = 10001,
	ID_AGE_SPINCTRL,
	ID_SALARY_TEXTCTRL,
	ID_MARITAL_CHECKBOX,
	ID_SKILLS_LISTBOX
};

DefaultValidatorsDialog::DefaultValidatorsDialog()
{
}

DefaultValidatorsDialog::DefaultValidatorsDialog(wxWindow * parent, wxWindowID id, const wxString title)
{
	Create(parent, id, title);
}

bool DefaultValidatorsDialog::Create(wxWindow * parent, wxWindowID id, const wxString title)
{
	bool res = wxDialog::Create(parent, id, title);
	if(res)
	{
		m_Name = wxEmptyString;
		m_Age = 20;
		m_Married = false;
		m_Skills.Clear();
		CreateControls();
		Centre();
	}
	return res;
}

void DefaultValidatorsDialog::CreateControls()
{
	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	wxFlexGridSizer * flexgrid_sizer = new wxFlexGridSizer(2,5);
	flexgrid_sizer-&gt;AddGrowableCol(1);

	wxStaticText * name_label = new wxStaticText(this, wxID_ANY, _(&quot;Name:&quot;));
	wxStaticText * age_label = new wxStaticText(this, wxID_ANY, _(&quot;Age:&quot;));
	wxStaticText * salary_label = new wxStaticText(this, wxID_ANY, _(&quot;Salary:&quot;));
	wxStaticText * marital_label = new wxStaticText(this, wxID_ANY, _(&quot;Marital Status:&quot;));
	wxStaticText * skills_label = new wxStaticText(this, wxID_ANY, _(&quot;Skills:&quot;));

	wxTextCtrl * name_textctrl = new wxTextCtrl(this, ID_NAME_TEXTCTRL, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1));
	wxSpinCtrl * age_spinctrl = new wxSpinCtrl(this, ID_AGE_SPINCTRL);
	wxTextCtrl * salary_textctrl = new wxTextCtrl(this, ID_SALARY_TEXTCTRL, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1));
	wxCheckBox * marital_checkbox = new wxCheckBox(this, ID_MARITAL_CHECKBOX, wxT(&quot;Married&quot;));
	wxArrayString skills;
	skills.Add(wxT(&quot;C/C++&quot;));
	skills.Add(wxT(&quot;C#&quot;));
	skills.Add(wxT(&quot;Delphi&quot;));
	skills.Add(wxT(&quot;Visual Basic&quot;));
	skills.Add(wxT(&quot;ASP.NET&quot;));
	skills.Add(wxT(&quot;SQL&quot;));
	wxListBox * skills_listbox = new wxListBox(this, ID_SKILLS_LISTBOX,
		wxDefaultPosition, wxDefaultSize, skills, wxLB_MULTIPLE);

	name_textctrl-&gt;SetValidator(wxGenericValidator(&amp;m_Name));
	age_spinctrl-&gt;SetValidator(wxGenericValidator(&amp;m_Age));
	salary_textctrl-&gt;SetValidator(wxGenericValidator(&amp;m_Salary));
	marital_checkbox-&gt;SetValidator(wxGenericValidator(&amp;m_Married));
	skills_listbox-&gt;SetValidator(wxGenericValidator(&amp;m_Skills));

	flexgrid_sizer-&gt;Add(name_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flexgrid_sizer-&gt;Add(name_textctrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(age_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flexgrid_sizer-&gt;Add(age_spinctrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(salary_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flexgrid_sizer-&gt;Add(salary_textctrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(marital_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
	flexgrid_sizer-&gt;Add(marital_checkbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(skills_label, 0, wxALIGN_LEFT|wxALIGN_TOP|wxALL|wxADJUST_MINSIZE, 5);
	flexgrid_sizer-&gt;Add(skills_listbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	sizer-&gt;Add(flexgrid_sizer, 0, wxEXPAND|wxALL, 10);

	wxBoxSizer * button_sizer = new wxBoxSizer(wxHORIZONTAL);
	wxButton * ok_button = new wxButton(this, wxID_OK, _(&quot;OK&quot;));
	wxButton * cancel_button = new wxButton(this, wxID_CANCEL, _(&quot;Cancel&quot;));
	button_sizer-&gt;Add(ok_button, 0, wxLEFT|wxBOTTOM, 5);
	button_sizer-&gt;Add(cancel_button, 0, wxLEFT|wxRIGHT|wxBOTTOM, 5);

	sizer-&gt;Add(button_sizer, 0, wxALIGN_CENTER|wxBOTTOM, 5);

	sizer-&gt;Fit(this);
}
</pre>
<p>У нас должно получиться что-то подобное:</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_1.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_1.jpg" alt="Double value validator for wxWidgets - 1" title="Double value validator for wxWidgets - 1" width="370" height="361" class="alignnone size-full wp-image-199" /></a></p>
<ul>
<li><b>Name</b> – привязка строковой переменной</li>
<li><b>Age</b> – привязка целочисленной переменной</li>
<li><b>Salary</b> – к сожалению wxWidgets не предоставляет возможности привязать к элементу управления переменную типа <code>double</code>, поэтому мы делаем привязку строковой переменной и преобразуем ее в double после закрытия окна диалога.</li>
<li><b>Marital Status</b> – привязка переменной типа <code>bool</code></li>
<li><b>Skills</b> – привязка массива индексов</li>
</ul>
<p>Давайте проанализируем, что же у нас получилось.<br />
1. В поле <b>Name</b> и <b>Age</b> ведем любое значение, в поле <b>Salary</b> введем корректное значение для типа double (например 123.25), отметим флаг <b>Marital Status</b>, выделим несколько элементов в списке <b>Skills</b>. </p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_2.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_2.jpg" alt="Double value validator for wxWidgets - 2" title="Double value validator for wxWidgets - 2" width="256" height="350" class="alignnone size-full wp-image-200" /></a></p>
<p>Теперь жмем OK и наблюдаем результат</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_3.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_3.jpg" alt="Double value validator for wxWidgets - 3" title="Double value validator for wxWidgets - 3" width="191" height="152" class="alignnone size-full wp-image-201" /></a></p>
<p>2. Теперь проделаем те же действия, но в поле <b>Salary</b> введем заведомо некорректное значение</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_4.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_4.jpg" alt="Double value validator for wxWidgets - 4" title="Double value validator for wxWidgets - 4" width="256" height="350" class="alignnone size-full wp-image-202" /></a></p>
<p>Жмем ОК и смотрим, что же у нас получилось.</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_5.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_5.jpg" alt="Double value validator for wxWidgets - 5" title="Double value validator for wxWidgets - 5" width="206" height="119" class="alignnone size-full wp-image-203" /></a></p>
<p>Данное сообщение мы имеем возможность лицезреть только потому, что мы самостоятельно в тексте программы делаем проверку корректности преобразования <code>wxString</code> в <code>double</code></p>
<pre class="brush: cpp;">
double salary(0);
if(!dlg-&gt;GetSalary().ToDouble(&amp;salary))
{
	wxMessageBox(wxT(&quot;Illagal value of 'Salary' field&quot;));
	return;
}
</pre>
<p>И только так мы можем узнать о том, что пользователь ввел некорректное значение.<br />
Из этого следует вывод: стандартные валидаторы wxWidgets обеспечивают привязку данных, но не обеспечивают их проверку в процессе ввода данных, что само по себе не очень удобно т.к. требует написания кода проверки значения для каждой переменной.</p>
<p>Что можно сделать? Можно немного «доработать напильником» и избавить себя от большого количества проблем в будущем. Этим мы сейчас и займемся.</p>
<p>Под «этим» я имею в виду написание собственного валидатора с поддкржкой типа double.</p>
<p><b>wxFPValidator.h</b></p>
<pre class="brush: cpp;">
#ifndef _WX_FP_VALIDATOR_H
#define _WX_FP_VALIDATOR_H

#include &lt;wx/wx.h&gt;
#include &lt;/validate.h&gt;

class wxFPValidator : public wxValidator
{
protected:
	double * m_pDouble;
	int * m_pInt;
	wxString * m_pString;
	void Initialize();
public:
	wxFPValidator(double * valPtr);
	wxFPValidator(int * valPtr);
	wxFPValidator(wxString * valPtr);
	wxFPValidator(const wxFPValidator &amp; validator);
	~wxFPValidator();
	virtual wxValidator* Clone() const;
	virtual bool TransferFromWindow();
	virtual bool TransferToWindow();
	virtual bool Validate(wxWindow * parent);
};

#endif
</pre>
<p>Описание методов:</p>
<ul>
<li><b>TransferToWindow</b> – предназначен для отображения значения переменной в элементе управления</li>
<li><b>TransfedFromWindow</b> &#8211; предназначен для получения значения из элемента управления в переменную</li>
<li><b>Validate</b> – предназначен для проверки значения введеного пользователем</li>
</ul>
<p>Метод <code>TransferToWindow</code> вызывается когда мы в нашей программе после установки значений переменных вызываем <code>TransferDataToWindow>/code? чтобы отобразить значения в элементах управления. Например</p>
<pre class="brush: cpp;">
m_Name = wxEmptyString;
m_Age = 20;
m_Married = false;
m_Skills.Clear();
TransferDataToWindow();
</pre>
<p>Метод <code>TransferToWindow</code> вызывается когда мы в нашей программе вызываем <code>TransferDataFromWindow</code> чтобы получить значения, введенные пользователем.</p>
<p>При работе с диалогами, после закрытия диалогового окна, введенные значения автоматически записываются в переменные, ассоциированные с элементами управления.</p>
<pre class="brush: cpp;">
DefaultValidatorsDialog * dlg = new DefaultValidatorsDialog(this);
if(dlg-&gt;ShowModal() == wxID_OK)
{
	wxString result;
	double salary(0);
	if(!dlg-&gt;GetSalary().ToDouble(&amp;salary))
	{
		wxMessageBox(wxT(&quot;Illagal value of 'Salary' field&quot;));
		return;
	}
	...
}
</pre>
<p><b>wxFPValidator.cpp</b></p>
<pre class="brush: cpp;">
#include &lt;/wxFPValidator/wxFPValidator.h&gt;
#include &lt;math.h&gt;

wxFPValidator::wxFPValidator(double * valPtr)
{
	Initialize();
	m_pDouble = valPtr;
}

wxFPValidator::wxFPValidator(int * valPtr)
{
	Initialize();
	m_pInt = valPtr;
}

wxFPValidator::wxFPValidator(wxString * valPtr)
{
	Initialize();
	m_pString = valPtr;
}

wxFPValidator::wxFPValidator(const wxFPValidator &amp; validator)
: m_pDouble(validator.m_pDouble), m_pInt(validator.m_pInt),
m_pString(validator.m_pString)
{
}

wxFPValidator::~wxFPValidator()
{
}

void wxFPValidator::Initialize()
{
	m_pDouble = NULL;
	m_pInt = NULL;
	m_pString = NULL;
}

wxValidator* wxFPValidator::Clone() const
{
	return new wxFPValidator(*this);
}

bool wxFPValidator::TransferFromWindow()
{
	if(!m_validatorWindow)
	{
		return false;
	}
#if wxUSE_TEXTCTRL
    if (m_validatorWindow-&gt;IsKindOf(CLASSINFO(wxTextCtrl)) )
    {
        wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow;
		if(m_pDouble)
		{
			return pControl-&gt;GetValue().ToDouble(m_pDouble);
		}
		else if(m_pInt)
		{
			double tmp;
			bool res = pControl-&gt;GetValue().ToDouble(&amp;tmp);
			if(tmp &gt;= INT_MIN &amp;&amp; tmp &lt;= INT_MAX &amp;&amp; (fmod(tmp,1) == 0))
			{
				*m_pInt = (int)tmp;
			} else res = false;
			return res;
		}
		else if(m_pString)
		{
			wxString tmp = pControl-&gt;GetValue();
			if(!tmp.IsEmpty())
			{
				*m_pString = tmp;
				return true;
			}
			return false;
		}
	}
#endif
	return false;
}

bool wxFPValidator::TransferToWindow()
{
	if(!m_validatorWindow)
	{
		return false;
	}
#if wxUSE_TEXTCTRL
    if (m_validatorWindow-&gt;IsKindOf(CLASSINFO(wxTextCtrl)) )
    {
        wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow;
		if(m_pDouble)
		{
			pControl-&gt;SetValue(wxString::Format(wxT(&quot;%1.2f&quot;), *m_pDouble));
			return true;
		}
		else if(m_pInt)
		{
			pControl-&gt;SetValue(wxString::Format(wxT(&quot;%i&quot;), *m_pInt));
			return true;
		}
		else if(m_pString)
		{
			pControl-&gt;SetValue(*m_pString);
			return true;
		}
	}
#endif
	return false;
}

bool wxFPValidator::Validate(wxWindow * parent)
{
	if(!m_validatorWindow)
	{
		return false;
	}
#if wxUSE_TEXTCTRL
    if (m_validatorWindow-&gt;IsKindOf(CLASSINFO(wxTextCtrl)) )
    {
        wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow;
		if(m_pDouble != NULL)
		{
			return pControl-&gt;GetValue().ToDouble(m_pDouble);
		}
		else if(m_pInt != NULL)
		{
			double tmp;
			bool res = pControl-&gt;GetValue().ToDouble(&amp;tmp);
			if(tmp &gt;= INT_MIN &amp;&amp; tmp &lt;= INT_MAX &amp;&amp; (fmod(tmp,1) == 0))
			{
				*m_pInt = (int)tmp;
			} else res = false;
			return res;
		}
		else if(m_pString != NULL)
		{
			return !pControl-&gt;GetValue().IsEmpty();
		}
	}
#endif
	return false;
}
</pre>
<p>Как видно из исходного кода, наш валидатор позволяет выполнять привязку переменных типа <code>wxString</code>, int и <code>double</code>.<br />
Обработка выполняется только для элементов управления типа <code>wxTextCtrl</code>. Для этого существует соответствующая проверка с помощью RTTI</p>
<pre class="brush: cpp;">
if (m_validatorWindow-&gt;IsKindOf(CLASSINFO(wxTextCtrl)) )
{
      wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow;
if(m_pDouble != NULL)
	{
		return pControl-&gt;GetValue().ToDouble(m_pDouble);
	}
	...
}
</pre>
<p>Для других типов элементов управления соответветствующий функционал необходимо писать самостоятельно (или же посмотреть реализацию класса <code>wxGenericValidator</code> и взять исходный код оттуда).</p>
<p>Хотелось бы заметить, что для стандартного <code>wxGenericValidator</code> метод Validate всегда возвращает true не зависимо от того, коррктно ли введенное значение. Функционал проверки значений просто не реализован и его реализация ложится на плечи разработчика (т.е. на наши с вами).</p>
<p>Теперь у нас есть валидатор с привязкой переменных типа <code>double</code> да еще и с проверкой введенного значения. Но было бы неплохо организовать проверку прямо при вводе данных. Это намного удобнее чем выдавать сообщение об ошибке уже после закрытия окна ввода (такая ситуация особенно неприятна при заполнении больших форм).</p>
<p><b>MainFrame.h</b></p>
<pre class="brush: cpp;">
#ifndef _MAIN_FRAME_H
#define _MAIN_FRAME_H

#include &lt;/wx.h&gt;

class MainFrame : public wxFrame
{
	...
	void OnShowManualValidation(wxCommandEvent &amp; event);
	...
};

#endif
</pre>
<p><b>MainFrame.cpp</b></p>
<pre class="brush: cpp;">
...
#include &quot;ManualValidationDialog.h&quot;
...
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
...
EVT_BUTTON(ID_MANUAL_VALIDATION_BUTTON, MainFrame::OnShowManualValidation)
...
END_EVENT_TABLE()
...
MainFrame::MainFrame()
: wxFrame(NULL, wxID_ANY, _(&quot;wxFPValidator Test&quot;), wxDefaultPosition, wxDefaultSize,
		  wxCAPTION|wxCLOSE_BOX|wxSYSTEM_MENU|wxRAISED_BORDER)
{
...
	wxButton * manual_validation_button = new wxButton(this,
 ID_MANUAL_VALIDATION_BUTTON, _(&quot;Extended Validators - Manual Validation&quot;));
	sizer-&gt;Add(manual_validation_button, 0, wxGROW|wxALL, 5);
	...
}
...
void MainFrame::OnShowManualValidation(wxCommandEvent &amp; event)
{
	ManualValidationDialog * dlg = new ManualValidationDialog(this);
	if(dlg-&gt;ShowModal())
	{
	}
	dlg-&gt;Destroy();
}
</pre>
<p><b>ManualValidationDialog.h</b></p>
<pre class="brush: cpp;">
#ifndef _MANUAL_VALIDATION_DIALOG_H
#define _MANUAL_VALIDATION_DIALOG_H

#include &lt;/wx.h&gt;

#define ManualValidationDialogName _(&quot;Manual Validation&quot;)

class ManualValidationDialog : public wxDialog
{
	double m_Width;
	double m_Height;
	int m_Quantity;

	wxStaticBitmap * m_WidthStatusBitmap;
	wxStaticBitmap * m_HeightStatusBitmap;
	wxStaticBitmap * m_QuantityStatusBitmap;
	wxTextCtrl * m_WidthTextCtrl;
	wxTextCtrl * m_HeightTextCtrl;
	wxTextCtrl * m_QuantityTextCtrl;

	void CreateControls();
public:
	ManualValidationDialog();
	ManualValidationDialog(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = ManualValidationDialogName);
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = ManualValidationDialogName);

	double GetWidth() {return m_Width;}
	double GetHeight() {return m_Height;}
	int GetQuantity() {return m_Quantity;}

	DECLARE_EVENT_TABLE();
	void OnTextCtrlUpdate(wxCommandEvent &amp; event);
	void OnSubmitButtonUpdateUI(wxUpdateUIEvent &amp; event);
	void OnSubmit(wxCommandEvent &amp; event);

};

#endif
</pre>
<p><b>ManualValidationDialog.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;ManualValidationDialog.h&quot;

#include &lt;/imaglist.h&gt;
#include &lt;/valgen.h&gt;
#include &lt;/wxFPValidator/wxFPValidator.h&gt;

#include &quot;Application.h&quot;

enum
{
	ID_WIDTH_TEXTCTRL = 10001,
	ID_HEIGHT_TEXTCTRL,
	ID_QUANTITY_TEXTCTRL,
	ID_WIDTH_STATIC_BITMAP,
	ID_HEIGHT_STATIC_BITMAP,
	ID_QUANTITY_STATIC_BITMAP,
	ID_SUBMIT_BUTTON,
};

BEGIN_EVENT_TABLE(ManualValidationDialog, wxDialog)
EVT_TEXT(ID_WIDTH_TEXTCTRL, ManualValidationDialog::OnTextCtrlUpdate)
EVT_TEXT(ID_HEIGHT_TEXTCTRL, ManualValidationDialog::OnTextCtrlUpdate)
EVT_TEXT(ID_QUANTITY_TEXTCTRL, ManualValidationDialog::OnTextCtrlUpdate)
EVT_UPDATE_UI(ID_SUBMIT_BUTTON, ManualValidationDialog::OnSubmitButtonUpdateUI)
EVT_BUTTON(ID_SUBMIT_BUTTON, ManualValidationDialog::OnSubmit)
END_EVENT_TABLE()

ManualValidationDialog::ManualValidationDialog(wxWindow * parent,
						wxWindowID id, const wxString title)
{
	m_Width = 1024;
	m_Height = 768;
	m_Quantity = 10;
	Create(parent, id, title);
}

bool ManualValidationDialog::Create(wxWindow * parent,
					wxWindowID id, const wxString title)
{
	bool res = wxDialog::Create(parent, id, title);
	if(res)
	{
		SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
		CreateControls();
		Centre();
	}
	return res;
}

void ManualValidationDialog::CreateControls()
{
	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	wxFlexGridSizer * flex_grid_sizer = new wxFlexGridSizer(2, 3, 2, 2);	

	wxStaticText * label_width = new wxStaticText(this, wxID_ANY, _(&quot;Width:&quot;));
	wxStaticText * label_height = new wxStaticText(this, wxID_ANY, _(&quot;Height:&quot;));
	wxStaticText * label_quantity = new wxStaticText(this, wxID_ANY, _(&quot;Quantity:&quot;));

	m_WidthTextCtrl = new wxTextCtrl(this, ID_WIDTH_TEXTCTRL, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1), 0, wxFPValidator(&amp;m_Width));
	m_HeightTextCtrl = new wxTextCtrl(this, ID_HEIGHT_TEXTCTRL, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1), 0, wxFPValidator(&amp;m_Height));
	m_QuantityTextCtrl = new wxTextCtrl(this, ID_QUANTITY_TEXTCTRL, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1), 0, wxFPValidator(&amp;m_Quantity));

	wxBitmap tmp_bitmap(15, 15);
	m_WidthStatusBitmap = new wxStaticBitmap(this,
		ID_WIDTH_STATIC_BITMAP, tmp_bitmap);
	m_HeightStatusBitmap = new wxStaticBitmap(this,
		ID_HEIGHT_STATIC_BITMAP, tmp_bitmap);
	m_QuantityStatusBitmap = new wxStaticBitmap(this,
		ID_HEIGHT_STATIC_BITMAP, tmp_bitmap);

    flex_grid_sizer-&gt;Add(label_width, 0,
		wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flex_grid_sizer-&gt;Add(m_WidthTextCtrl, 0,
		wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
    flex_grid_sizer-&gt;Add(m_WidthStatusBitmap, 0,
		wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);

	flex_grid_sizer-&gt;Add(label_height, 0,
		wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flex_grid_sizer-&gt;Add(m_HeightTextCtrl, 0,
		wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
    flex_grid_sizer-&gt;Add(m_HeightStatusBitmap, 0,
		wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);

	flex_grid_sizer-&gt;Add(label_quantity, 0,
		wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
    flex_grid_sizer-&gt;Add(m_QuantityTextCtrl, 0,
		wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);
    flex_grid_sizer-&gt;Add(m_QuantityStatusBitmap, 0,
		wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);

	flex_grid_sizer-&gt;AddGrowableCol(1);
	sizer-&gt;Add(flex_grid_sizer, 0, wxEXPAND);

	wxButton * submit_button = new wxButton(this, ID_SUBMIT_BUTTON, _(&quot;Submit&quot;));
	sizer-&gt;Add(submit_button, 0, wxGROW|wxALL, 5);

	sizer-&gt;Fit(this);
	SetMinSize(GetSize());
}

void ManualValidationDialog::OnTextCtrlUpdate(wxCommandEvent &amp; event)
{
	wxWindow * target = wxDynamicCast(event.GetEventObject(), wxWindow);
	int bitmapIndex(0);
	wxStaticBitmap * static_bitmap(NULL);
	if(target)
	{
		wxValidator * validator = target-&gt;GetValidator();
		if(validator)
		{
			if(!validator-&gt;Validate(target))
			{
				bitmapIndex = 1;
			}
			switch(target-&gt;GetId())
			{
			case ID_WIDTH_TEXTCTRL:
				static_bitmap = m_WidthStatusBitmap;
				break;
			case ID_HEIGHT_TEXTCTRL:
				static_bitmap = m_HeightStatusBitmap;
				break;
			case ID_QUANTITY_TEXTCTRL:
				static_bitmap = m_QuantityStatusBitmap;
				break;
			default:
				wxLogTrace(wxTraceMask(),
					_(&quot;Illegal call of ManualValidationDialog::OnTextCtrlUpdate&quot;));
				break;
			}
			if(static_bitmap)
			{
				static_bitmap-&gt;SetBitmap(
					wxGetApp().GetImageList().GetBitmap(bitmapIndex));
			}
		}
	}
}

void ManualValidationDialog::OnSubmitButtonUpdateUI(wxUpdateUIEvent &amp; event)
{
	event.Enable(Validate());
}

void ManualValidationDialog::OnSubmit(wxCommandEvent &amp; event)
{
	if(TransferDataFromWindow())
	{
		wxString message = wxString::Format(
			wxT(&quot;Width = %1.2f\r\nHeight = %1.2f\r\nQuantity = %i&quot;),
			m_Width, m_Height, m_Quantity);
		wxMessageBox(message);
	}
}
</pre>
<p>Теперь пробуем собрать проект. Должно получиться что-то подобное</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_6.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_6.jpg" alt="Double value validator for wxWidgets - 6" title="Double value validator for wxWidgets - 6" width="361" height="199" class="alignnone size-full wp-image-204" /></a></p>
<p>Теперь пытаемся ввести некорректное значение в поле <b>Width</b> (например буквы) и в поле <b>Quantity</b> (буквы или дробное значение)</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_7.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_7.jpg" alt="Double value validator for wxWidgets - 7" title="Double value validator for wxWidgets - 7" width="241" height="155" class="alignnone size-full wp-image-205" /></a></p>
<p>Теперь немного о том, как это работает:</p>
<p>Мы сделали обработчик нажатия клавиш для каждого поля ввода <code> ManualValidationDialog::OnTextCtrlUpdate</code> и в этом обработчике изменяем картинку для соответствующего элемента<code>wxStaticBitmap</code>.<br />
Также мы сделали обработчик события <code>wxEVT_UPDATE_UI</code> для кнопки <b>Submit</b> где делаем кнопку активной только в случае успешной проверки введенных значений во всех дочерних элементах управления.</p>
<p>Смотрим на окошки – красиво. Смотрим на исходник – не очень, т.к. опять много кода не связанного напрямую с функционалом приложения.</p>
<p>Сейчас мы попробуем немного автоматизировать отображенис коррекнтости ввода значения. Для этого создадим компонент, которые будет содержать в себе элемент управления и пиктограмму для отображения текущего статуса</p>
<p><b>wxInputBox.h</b></p>
<pre class="brush: cpp;">
#ifndef _WX_INPUT_BOX_H
#define _WX_INPUT_BOX_H

#include &lt;wx/wx.h&gt;
#include &lt;wx/validate.h&gt;

#define wxInputBoxName wxT(&quot;wxInputBox&quot;)

enum wxInputBoxBitmapType
{
	wxINPUTBOX_OK,
	wxINPUTBOX_ERROR
};

class wxInputBox : public wxControl
{
	DECLARE_DYNAMIC_CLASS(wxInputBox);
	wxStaticBitmap * m_StatusBitmap;
	wxWindow * m_Editor;
	wxBitmap m_OKBitmap;
	wxBitmap m_ErrorBitmap;
public:
	wxInputBox();
	wxInputBox(wxWindow * parent, wxWindowID id,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxNO_BORDER,
		const wxValidator &amp; validator = wxDefaultValidator,
		const wxString &amp; name = wxInputBoxName);
	wxInputBox(wxWindow * parent, wxWindowID id, wxWindow * editor,
		const wxBitmap &amp; ok_bitmap = wxNullBitmap,
		const wxBitmap &amp; error_bitmap = wxNullBitmap,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxNO_BORDER,
		const wxValidator &amp; validator = wxDefaultValidator,
		const wxString &amp; name = wxInputBoxName);
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		wxWindow * editor = NULL,
		const wxBitmap &amp; ok_bitmap = wxNullBitmap,
		const wxBitmap &amp; error_bitmap = wxNullBitmap,
		const wxPoint &amp; pos = wxDefaultPosition,
		const wxSize &amp; size = wxDefaultSize,
		long style = wxNO_BORDER,
		const wxValidator &amp; validator = wxDefaultValidator,
		const wxString &amp; name = wxInputBoxName);

	virtual bool Validate();
	virtual void SetValidator(const wxValidator&amp; validator);

	static wxBitmap GetDefaultStatusBitmap(wxInputBoxBitmapType bitmap_type);
	void SetEditor(wxWindow * editor);

	wxBitmap GetStatusBitmap(wxInputBoxBitmapType bitmap_type);
	void SetStatusBitmap(wxInputBoxBitmapType bitmap_type,
		const wxBitmap &amp; bitmap);

	wxValidator * GetValidator() const;

	DECLARE_EVENT_TABLE()
	void OnValueChanged(wxCommandEvent &amp; event);
	void OnSize(wxSizeEvent &amp; event);
};

#endif
</pre>
<p><b>wxInputBox.cpp</b></p>
<pre class="brush: cpp;">
#include &lt;/wxInputBox/wxInputBox.h&gt;
#include &lt;/image.h&gt;

#include &quot;inputbox_ok.xpm&quot;
#include &quot;inputbox_error.xpm&quot;

IMPLEMENT_DYNAMIC_CLASS(wxInputBox, wxControl);

BEGIN_EVENT_TABLE(wxInputBox, wxControl)
EVT_SIZE(wxInputBox::OnSize)
END_EVENT_TABLE()

wxInputBox::wxInputBox()
: wxControl(), m_Editor(NULL)
{
}

wxInputBox::wxInputBox(wxWindow * parent, wxWindowID id, wxWindow * editor,
		const wxBitmap &amp; ok_bitmap, const wxBitmap &amp; error_bitmap,
		const wxPoint &amp; pos, const wxSize &amp; size, long style,
		const wxValidator &amp; validator, const wxString &amp; name)
: m_Editor(NULL)
{
	Create(parent, id, editor, ok_bitmap, error_bitmap,
		pos, size, style, validator, name);
}

wxInputBox::wxInputBox(wxWindow * parent, wxWindowID id, const wxPoint &amp; pos,
		const wxSize &amp; size, long style,
		const wxValidator &amp; validator, const wxString &amp; name)
: m_Editor(NULL)
{
	Create(parent, id, NULL, wxNullBitmap, wxNullBitmap,
		pos, size, style, wxDefaultValidator, name);
}

bool wxInputBox::Create(wxWindow * parent, wxWindowID id, wxWindow * editor,
		const wxBitmap &amp; ok_bitmap, const wxBitmap &amp; error_bitmap,
		const wxPoint &amp; pos, const wxSize &amp; size, long style,
		const wxValidator &amp; validator, const wxString &amp; name)
{
	bool res = wxWindow::Create(parent, id, pos, size, style, name);
	if(res)
	{
		m_OKBitmap = ok_bitmap;
		m_ErrorBitmap = error_bitmap;
		if(!m_OKBitmap.Ok()) m_OKBitmap =
			wxInputBox::GetDefaultStatusBitmap(wxINPUTBOX_OK);
		if(!m_ErrorBitmap.Ok()) m_ErrorBitmap =
			wxInputBox::GetDefaultStatusBitmap(wxINPUTBOX_ERROR);
		wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
		SetSizer(sizer);
		if(editor)
		{
			SetEditor(editor);
			m_Editor-&gt;SetValidator(validator);
		}
	}
	return res;
}

void wxInputBox::SetEditor(wxWindow * editor)
{
	if(GetSizer())
	{
		GetSizer()-&gt;Clear(true);
	}
	wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
	SetSizer(sizer);
	wxBitmap bitmap;
	m_StatusBitmap = new wxStaticBitmap(this, wxID_ANY, bitmap);
	if(editor)
	{
		m_Editor = editor;
		m_Editor-&gt;Reparent(this);
		sizer-&gt;Add(m_Editor, 1, wxEXPAND|wxRIGHT, 5);
		if(m_Editor-&gt;IsKindOf(CLASSINFO(wxTextCtrl)))
		{
			m_Editor-&gt;Connect(m_Editor-&gt;GetId(),
				wxEVT_COMMAND_TEXT_UPDATED,
				(wxObjectEventFunction)&amp;wxInputBox::OnValueChanged);
		}
		if(m_Editor-&gt;IsKindOf(CLASSINFO(wxListBox)))
		{
			m_Editor-&gt;Connect(m_Editor-&gt;GetId(),
				wxEVT_COMMAND_LISTBOX_SELECTED,
				(wxObjectEventFunction)&amp;wxInputBox::OnValueChanged);
		}
		if(m_Editor-&gt;GetValidator())
		{
			if(m_Editor-&gt;GetValidator()-&gt;TransferFromWindow())
			{
				bitmap = GetStatusBitmap(wxINPUTBOX_OK);
			}
			else bitmap = GetStatusBitmap(wxINPUTBOX_ERROR);
		} else bitmap = GetStatusBitmap(wxINPUTBOX_OK);
	}
	else
	{
		bitmap = wxInputBox::GetStatusBitmap(wxINPUTBOX_ERROR);
		sizer-&gt;Add(100, -1, 1, wxEXPAND|wxRIGHT, 5);
	}
	sizer-&gt;Add(m_StatusBitmap, 0, wxALIGN_CENTER);
	sizer-&gt;Fit(this);
	SetBestSize(GetSize());
}

wxBitmap wxInputBox::GetStatusBitmap(wxInputBoxBitmapType bitmap_type)
{
	switch(bitmap_type)
	{
	case wxINPUTBOX_OK:
		if(m_OKBitmap.Ok())
		{
			return m_OKBitmap;
		}
	case wxINPUTBOX_ERROR:
		if(m_ErrorBitmap.Ok())
		{
			return m_ErrorBitmap;
		}
	default:
		break;
	}
	return wxInputBox::GetDefaultStatusBitmap(bitmap_type);
}

void wxInputBox::SetStatusBitmap(wxInputBoxBitmapType bitmap_type,
								 const wxBitmap &amp; bitmap)
{
	switch(bitmap_type)
	{
	case wxINPUTBOX_OK:
		m_OKBitmap = bitmap;
		break;
	case wxINPUTBOX_ERROR:
		m_ErrorBitmap = bitmap;
		break;
	default:
		break;
	}
}

wxBitmap wxInputBox::GetDefaultStatusBitmap(wxInputBoxBitmapType bitmap_type)
{
	if(!wxImage::FindHandler(wxBITMAP_TYPE_XPM))
	{
		wxImage::AddHandler(new wxXPMHandler);
	}
	switch(bitmap_type)
	{
	case wxINPUTBOX_OK:
		return wxBitmap(inputbox_ok_xpm);
	case wxINPUTBOX_ERROR:
		return wxBitmap(inputbox_error_xpm);
	default:
		break;
	}

	return wxBitmap(16,16);
}

void wxInputBox::OnValueChanged(wxCommandEvent &amp; event)
{
	wxWindow * target = wxDynamicCast(event.GetEventObject(), wxWindow);
	if(target)
	{
		wxInputBox * parent = wxDynamicCast(target-&gt;GetParent(), wxInputBox);
		if(parent)
		{
			wxValidator * validator = target-&gt;GetValidator();
			wxInputBoxBitmapType bitmap_type = wxINPUTBOX_ERROR;
			if(validator)
			{
				if(validator-&gt;Validate(this))
				{
					bitmap_type = wxINPUTBOX_OK;
				}
				parent-&gt;m_StatusBitmap-&gt;SetBitmap(
					parent-&gt;GetStatusBitmap(bitmap_type));
			}
		}
	}
}

void wxInputBox::OnSize(wxSizeEvent &amp; event)
{
	Layout();
}

bool wxInputBox::Validate()
{
	if(m_Editor)
	{
		wxValidator * validator = m_Editor-&gt;GetValidator();
		if(validator)
		{
			return validator-&gt;Validate(this);
		}
	}
	return true;
}

void wxInputBox::SetValidator(const wxValidator&amp; validator)
{
	if(m_Editor)
	{
		m_Editor-&gt;SetValidator(validator);
	}
}
</pre>
<p>Как видно из исходного кода, наш компонент производит замену обработчика события <code>wxEVT_COMMAND_TEXT_UPDATED</code> (или <code>wxEVT_COMMAND_LISTBOX_SELECTED</code>) в ассоциированном с ним элементе управления. Это значит, что если ваш элемент управления имеет функционально важный обработчик указанного выше типа, то применять такой подход нельзя. Вместо этого можно, например переопределить обработку события <code>wxEVT_UPDATE_UI</code> для пиктограммы (и в нем выполнять проверку введенного значения) и этим решить проблему. Но такой подход более ресурсоемкий.<br />
Внесем дополнительные изменения в класс окна</p>
<p><b>MainFrame.h</b></p>
<pre class="brush: cpp;">
#ifndef _MAIN_FRAME_H
#define _MAIN_FRAME_H
...
class MainFrame : public wxFrame
{
public:
	...
DECLARE_EVENT_TABLE();
	...
	void OnShowExtendedValidators(wxCommandEvent &amp; event);
};

#endif
</pre>
<p><b>MainFrame.cpp</b></p>
<pre class="brush: cpp;">
...
#include &quot;ExtendedValidatorsDialog.h&quot;
...
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
...
EVT_BUTTON(ID_EXTENDED_VALIDATORS_BUTTON, MainFrame::OnShowExtendedValidators)
END_EVENT_TABLE()
...
MainFrame::MainFrame()
: wxFrame(NULL, wxID_ANY, _(&quot;wxFPValidator Test&quot;), wxDefaultPosition, wxDefaultSize,
		  wxCAPTION|wxCLOSE_BOX|wxSYSTEM_MENU|wxRAISED_BORDER)
{

	...
	wxButton * extended_validators_button = new wxButton(this,
ID_EXTENDED_VALIDATORS_BUTTON, _(&quot;Extended Validators - wxInputBox&quot;));
	sizer-&gt;Add(extended_validators_button, 0, wxGROW|wxALL, 5);
...
}
...
void MainFrame::OnShowExtendedValidators(wxCommandEvent &amp; event)
{
	ExtendedValidatorsDialog * dlg = new ExtendedValidatorsDialog(this);
	if(dlg-&gt;ShowModal() == wxID_OK)
	{
		wxString result;
		result = wxString::Format(
			_(&quot;Name = %s\r\nAge = %i\r\nSalary = %1.2f\r\nMarital Status = %s\r\nSkills = &quot;),
			dlg-&gt;GetName().GetData(),
			dlg-&gt;GetAge(),
			dlg-&gt;GetSalary(),
			dlg-&gt;GetMaritalStatus() ? wxT(&quot;married&quot;) : wxT(&quot;not married&quot;));
		wxString skill_list;
		for(size_t i = 0; i &lt; dlg-&gt;GetSkills().Count(); i++)
		{
			if(!skill_list.IsEmpty()) skill_list += wxT(&quot;,&quot;);
			skill_list += wxString::Format(wxT(&quot;%i&quot;), dlg-&gt;GetSkills()[i]);
		}
		result += skill_list;
		wxMessageBox(result);
	}
	dlg-&gt;Destroy();
}
</pre>
<p><b>ExtendedValidatorsDialog.h</b></p>
<pre class="brush: cpp;">
#ifndef _EXTENDED_VALIDATORS_DIALOG_H
#define _EXTENDED_VALIDATORS_DIALOG_H

#include &lt;/wx.h&gt;

#define ExtendedValidatorsDialogName _(&quot;Extended Validators&quot;)

class ExtendedValidatorsDialog : public wxDialog
{
	wxString m_Name;
	int m_Age;
	double m_Salary;
	bool m_Married;
	wxArrayInt m_Skills;
	void CreateControls();
public:
	ExtendedValidatorsDialog();
	ExtendedValidatorsDialog(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = ExtendedValidatorsDialogName);
	bool Create(wxWindow * parent, wxWindowID id = wxID_ANY,
		const wxString title = ExtendedValidatorsDialogName);

	wxString GetName() {return m_Name;}
	int GetAge() {return m_Age;}
	double GetSalary() {return m_Salary;}
	bool GetMaritalStatus() {return m_Married;}
	wxArrayInt &amp; GetSkills() {return m_Skills;}
	DECLARE_EVENT_TABLE()
	void OnOKUpdateUI(wxUpdateUIEvent &amp; event);
};

#endif
</pre>
<p><b>ExtendedValidatorsDialog.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;ExtendedValidatorsDialog.h&quot;
#include &lt;wx/textctrl.h&gt;
#include &lt;wx/spinctrl.h&gt;
#include &lt;wx/checkbox.h&gt;
#include &lt;wx/listbox.h&gt;
#include &lt;wx/valgen.h&gt;
#include &lt;wx/wxFPValidator/wxFPValidator.h&gt;
#include &lt;wx/wxInputBox/wxInputBox.h&gt;

enum
{
	ID_NAME_TEXTCTRL_EX = 11001,
	ID_AGE_SPINCTRL_EX,
	ID_SALARY_TEXTCTRL_EX,
	ID_MARITAL_CHECKBOX_EX,
	ID_SKILLS_LISTBOX_EX
};

BEGIN_EVENT_TABLE(ExtendedValidatorsDialog, wxDialog)
EVT_UPDATE_UI(wxID_OK, ExtendedValidatorsDialog::OnOKUpdateUI)
END_EVENT_TABLE()

ExtendedValidatorsDialog::ExtendedValidatorsDialog()
{
}

ExtendedValidatorsDialog::ExtendedValidatorsDialog(wxWindow * parent, wxWindowID id, const wxString title)
{
	Create(parent, id, title);
}

bool ExtendedValidatorsDialog::Create(wxWindow * parent, wxWindowID id, const wxString title)
{
	bool res = wxDialog::Create(parent, id, title);
	if(res)
	{
		SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
		m_Name = wxEmptyString;
		m_Age = 20;
		m_Salary = 500;
		m_Married = false;
		m_Skills.Clear();
		CreateControls();
		Centre();
	}
	return res;
}

void ExtendedValidatorsDialog::CreateControls()
{
	wxBoxSizer * sizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(sizer);

	wxFlexGridSizer * flexgrid_sizer = new wxFlexGridSizer(2,5);
	flexgrid_sizer-&gt;AddGrowableCol(1);

	wxStaticText * name_label = new wxStaticText(this, wxID_ANY, _(&quot;Name:&quot;));
	wxStaticText * age_label = new wxStaticText(this, wxID_ANY, _(&quot;Age:&quot;));
	wxStaticText * salary_label = new wxStaticText(this, wxID_ANY, _(&quot;Salary:&quot;));
	wxStaticText * marital_label = new wxStaticText(this, wxID_ANY, _(&quot;Marital Status:&quot;));
	wxStaticText * skills_label = new wxStaticText(this, wxID_ANY, _(&quot;Skills:&quot;));

	wxTextCtrl * name_textctrl = new wxTextCtrl(this, ID_NAME_TEXTCTRL_EX, wxEmptyString,
		wxDefaultPosition, wxSize(150,-1));
	wxTextCtrl * age_textctrl = new wxTextCtrl(this, ID_AGE_SPINCTRL_EX, wxEmptyString);
	wxTextCtrl * salary_textctrl = new wxTextCtrl(this, ID_SALARY_TEXTCTRL_EX, wxEmptyString);
	wxCheckBox * marital_checkbox = new wxCheckBox(this, ID_MARITAL_CHECKBOX_EX, wxT(&quot;Married&quot;));
	wxArrayString skills;
	skills.Add(wxT(&quot;C/C++&quot;));
	skills.Add(wxT(&quot;C#&quot;));
	skills.Add(wxT(&quot;Delphi&quot;));
	skills.Add(wxT(&quot;Visual Basic&quot;));
	skills.Add(wxT(&quot;ASP.NET&quot;));
	skills.Add(wxT(&quot;SQL&quot;));
	wxListBox * skills_listbox = new wxListBox(this, ID_SKILLS_LISTBOX_EX,
		wxDefaultPosition, wxDefaultSize, skills, wxLB_MULTIPLE);

	name_textctrl-&gt;SetValidator(wxFPValidator(&amp;m_Name));
	age_textctrl-&gt;SetValidator(wxFPValidator(&amp;m_Age));
	salary_textctrl-&gt;SetValidator(wxFPValidator(&amp;m_Salary));
	marital_checkbox-&gt;SetValidator(wxGenericValidator(&amp;m_Married));
	skills_listbox-&gt;SetValidator(wxGenericValidator(&amp;m_Skills));

	wxInputBox * name_inputbox = new wxInputBox(this, wxID_ANY);
	wxInputBox * age_inputbox = new wxInputBox(this, wxID_ANY);
	wxInputBox * salary_inputbox = new wxInputBox(this, wxID_ANY);
	wxInputBox * skills_inputbox = new wxInputBox(this, wxID_ANY);

	name_inputbox-&gt;SetEditor(name_textctrl);
	age_inputbox-&gt;SetEditor(age_textctrl);
	salary_inputbox-&gt;SetEditor(salary_textctrl);
	skills_inputbox-&gt;SetEditor(skills_listbox);

	flexgrid_sizer-&gt;Add(name_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);

    flexgrid_sizer-&gt;Add(name_inputbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(age_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
	flexgrid_sizer-&gt;Add(age_inputbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(salary_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);

    flexgrid_sizer-&gt;Add(salary_inputbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(marital_label, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);
	flexgrid_sizer-&gt;Add(marital_checkbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	flexgrid_sizer-&gt;Add(skills_label, 0, wxALIGN_LEFT|wxALIGN_TOP|wxALL|wxADJUST_MINSIZE, 5);

	flexgrid_sizer-&gt;Add(skills_inputbox, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

	sizer-&gt;Add(flexgrid_sizer, 0, wxEXPAND|wxALL, 10);

	wxBoxSizer * button_sizer = new wxBoxSizer(wxHORIZONTAL);
	wxButton * ok_button = new wxButton(this, wxID_OK, _(&quot;OK&quot;));
	wxButton * cancel_button = new wxButton(this, wxID_CANCEL, _(&quot;Cancel&quot;));
	button_sizer-&gt;Add(ok_button, 0, wxLEFT|wxBOTTOM, 5);
	button_sizer-&gt;Add(cancel_button, 0, wxLEFT|wxRIGHT|wxBOTTOM, 5);

	sizer-&gt;Add(button_sizer, 0, wxALIGN_CENTER|wxBOTTOM, 5);

	TransferDataToWindow();

	sizer-&gt;Fit(this);
}

void ExtendedValidatorsDialog::OnOKUpdateUI(wxUpdateUIEvent &amp; event)
{
	event.Enable(Validate());
}
</pre>
<p>Запускаем, смотрим:<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/validators_8.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/validators_8.jpg" alt="Double value validator for wxWidgets - 8" title="Double value validator for wxWidgets - 8" width="277" height="350" class="alignnone size-full wp-image-206" /></a></p>
<p>Как видно, из дополнительного кода остался только обработчик события <code>wxEVT_UPDATE_UI</code> для кнопки. Все остальное реализует наш новій компонент <code>wxInputBox</code></p>
<p><b>Подведем итоги</b></p>
<ul>
<li>Мы создали новый валидатор, позволяющий выполнять привязку переменных типа double и выполнять проверку корректности ввода значений</li>
<li>Создали динамическую индикацию корректности ввода данных</li>
<li>Разработали компонент, позволяющий автоматизировать работу, связанную с индикацией корректности ввода данных</li>
<li>Продемонстрировали работу компонента на примере <img src='http://wxwidgets.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>К слову сказать, что попмимо стандартных валидаторов, существуют еще валидаторы от сторонних разработчиков:</p>
<p><a href="ftp://biolpc22.york.ac.uk/pub/contrib/formatvalidator/">wxFormatValidator</a><br />
и<br />
<a href="ftp://biolpc22.york.ac.uk/pub/contrib/formatvalidator/">wxRegExValidator</a></p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxfpvalidator.7z" title="Скачать исходник: Привязка данных к элементам управления и проверка корректности ввода данных в wxWidgets">Скачать исходный код примера к этой статье</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/data_validation_tutorial_ru/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
