<?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; wxWidgets</title>
	<atom:link href="http://wxwidgets.info/category/wxwidgets/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>wxJSON 1.1.0 Released</title>
		<link>http://wxwidgets.info/wxjson-1-1-0-released/</link>
		<comments>http://wxwidgets.info/wxjson-1-1-0-released/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 14:07:08 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Libraries]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[wxJSON]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=580</guid>
		<description><![CDATA[JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition &#8211; December 1999. JSON is a text format that is completely language independent [...]]]></description>
			<content:encoded><![CDATA[<p>JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition &#8211; December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.</p>
<p>The wxJSON library is a complete implementation of the JSON data-interchange format. All JSON specifications are implemented in this library plus some extensions in the writer and in the parser class.</p>
<p>Today <strong>wxJSON 1.1.0</strong> was announced. This release is compatible with both wxWidgets 2.8 and 2.9. It is also compatible with wxWidgets SVN HEAD. N<span>ow JSON reader and writer only process UTF-8 encoded text as a stream.<br />
Also added a new wxJSONValue&#8217;s member function to get values and fixed the bugs in wxJSONValue::IsSameAs()</span></p>
<ul>
<li><a href="http://wxcode.sourceforge.net/docs/wxjson/" target="_blank">Official home page of wxJSON</a></li>
<li><span><a title="wxJSON 1.1 Release Notes" href="http://luccat.users.sourceforge.net/wxjson/docs/wxjson_whatsnew.html" target="_blank">Read complete list of changes in this version</a><br />
</span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/wxjson-1-1-0-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>wxRuby. Оно даже работает!</title>
		<link>http://wxwidgets.info/wxruby-ono-dazhe-rabotaet/</link>
		<comments>http://wxwidgets.info/wxruby-ono-dazhe-rabotaet/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 10:57:56 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[wxRuby]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=566</guid>
		<description><![CDATA[Вдохновленнный читаемой нынче книгой My Job Went to India: 52 Ways to Save Your Job решил покорять новые горизонты. Наткнулся несколько дней назад на вводную статью о wxRuby и сегодня решил попробовать. Оказывается это не так страшно. Что понравилось: Под Windows ставится просто. После инсталляции не требует никаких настроек. Кодишь, запускаешь &#8211; работает. Документация, как [...]]]></description>
			<content:encoded><![CDATA[<p>Вдохновленнный читаемой нынче книгой <a href="http://www.amazon.com/gp/product/0976694018?ie=UTF8&amp;tag=wxwidginfoart-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0976694018">My Job Went to India: 52 Ways to Save Your Job</a><img class=" asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk asbeyqewjweushpscdfk" style="border:none !important; margin:0px !important;" src="http://www.assoc-amazon.com/e/ir?t=wxwidginfoart-20&amp;l=as2&amp;o=1&amp;a=0976694018" border="0" alt="" width="1" height="1" /> решил покорять новые горизонты. Наткнулся несколько дней назад на <a title="Вводная статья о wxRuby" href="http://ruby-ua.blogspot.com/2009/09/wxruby-welcome-to-wxruby.html" target="_blank">вводную статью о wxRuby</a> и сегодня решил попробовать. Оказывается это не так страшно.<br />
<span id="more-566"></span><br />
Что понравилось:</p>
<ul>
<li>Под Windows ставится просто. После инсталляции не требует никаких настроек. Кодишь, запускаешь &#8211; работает.</li>
<li>Документация, как всегда у wxWidgets, позволяет решить все вопросы.</li>
<li>Синтаксис&#8230; на вид &#8211; вменяемо (учитывая что для меня это новый язык программирования, минимальное приложение получилось создать минут за 15).</li>
<li>Есть бесплатные средства разработки.</li>
</ul>
<p>Что не понравилось:</p>
<ul>
<li>Бесплатные средства разработки немного&#8230;. унылые. Скорее напоминают просто текстовый редактор с подсветкой синтаксиса и возможностью запуска скриптов.</li>
<li>Без интеллисенса тяжело <img src='http://wxwidgets.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li>Хочу документацию в CHM, а есть только в HTML что не очень удобно</li>
</ul>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/09/freeride.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/09/freeride.jpg" alt="FreeRIDE wxRuby IDE" title="FreeRIDE wxRuby IDE" width="556" height="586" class="alignnone size-full wp-image-567" /></a><br />
И вот&#8230; минимальное приложение. Как оно получилось:</p>
<pre class="brush: jscript;">
# -*- encoding: utf-8 -*-

require 'wx'

class HelloFrame &amp;lt; Wx::Frame
  def initialize
    super(nil, :title =&amp;gt; 'Hello World!')

    panel = Wx::Panel.new(self)

    sizer = Wx::BoxSizer.new(Wx::VERTICAL)
    panel.set_sizer(sizer)

    button = Wx::Button.new(panel, :label =&amp;gt; 'Press me')
    text = Wx::TextCtrl.new(panel, :value =&amp;gt; 'Sample', :style =&amp;gt; Wx::TE_MULTILINE)

    sizer.add(button, 0, Wx::EXPAND | Wx::ALL, 5)
    sizer.add(text, 1, Wx::EXPAND | Wx::LEFT | Wx::RIGHT | Wx::BOTTOM, 5)

    evt_button(button.get_id, <img src='http://wxwidgets.info/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> n_button_click)
  end

  def on_button_click
    Wx::MessageDialog.new(self, &amp;quot;Hello world!&amp;quot;, &amp;quot;Test&amp;quot;, Wx::OK).show_modal
  end
end

class HelloApp &amp;lt; Wx::App
  def on_init
    frame = HelloFrame.new
    frame.centre
    frame.show
  end
end

app = HelloApp.new
app.main_loop()
</pre>
<p>Немного странно называются классы, без префикса &#8220;wx&#8221;, зато с неймспейсом. Немного странным кажется способ привязки обработчиков событий. Очень понравилась возможность указывать значения только необходимых параметров. По сравнению с wxJavaScript мне wxRuby кажется более приятным т.к. все работает без дополнительной настройки. Сравнения по скорости работы пока не проводил. Есть поддержка wxAUI, wxGCDC/GdiPlus, Document/View, GLCanvas, что очень приятно.</p>
<p>Вместе с wxRuby поставляется довольно большое количество примеров, которые могут помочь разобраться как в синтаксисе так и в особенностях использования API.</p>
<ul>
<li><a href="http://rubyforge.org/frs/?group_id=35" target="_blank">Скачать wxRuby</a></li>
<li><a title="Скачать FreeRIDE" href="http://rubyforge.org/project/showfiles.php?group_id=31" target="_blank">Скачать FreeRIDE</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/wxruby-ono-dazhe-rabotaet/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Дааа! Ribbon Bar для wxWidgets не за горами!</title>
		<link>http://wxwidgets.info/daaa-ribbon-bar-dlya-wxwidgets-ne-za-gorami/</link>
		<comments>http://wxwidgets.info/daaa-ribbon-bar-dlya-wxwidgets-ne-za-gorami/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 19:24:17 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[wxWidgets]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=563</guid>
		<description><![CDATA[Надо же,в wxBlog такое рассказывают. Оказывается Google Summer of Code для wxWidgets принес много полезного в этом году. Обещают поддержку нотификаций об изменениях файловой системы &#8211; wxFSWatcher, а также (внимание!) Ribbon для wxWidgets &#8211; wxRibbonBar. А еще&#8230;. апгрейды всевозможные для wxAUI (жду не дождусь collapsible panes и tabbed docking). Все это будет в svn trunk [...]]]></description>
			<content:encoded><![CDATA[<p>Надо же,в wxBlog такое <a href="http://wxwidgets.blogspot.com/2009/09/august-news.html" target="_blank">рассказывают</a>. Оказывается Google Summer of Code для wxWidgets принес много полезного в этом году. Обещают поддержку нотификаций об изменениях файловой системы &#8211; wxFSWatcher, а также (внимание!) Ribbon для wxWidgets &#8211; wxRibbonBar. А еще&#8230;. апгрейды всевозможные для wxAUI (жду не дождусь collapsible panes и tabbed docking).</p>
<p>Все это будет в svn trunk и не факт что появится в ветке 2.8. Так что &#8220;кто куды, а мы к зайцам&#8221; (с), пойду качать svn trunk. Там кстати еще много чего полезного появилось. Если вы пользуетесь стабильной версией 2.8, рекомендую хотя бы попробовать trunk.</p>
<p>Еще вскользь упомянули, что потихоньку развивается wxSymbian и wxQNX. Порт для Symbian мне кажется очень перспективным, да.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/daaa-ribbon-bar-dlya-wxwidgets-ne-za-gorami/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cross-Platform Way of Obtaining MAC Address of Your Machine</title>
		<link>http://wxwidgets.info/cross-platform-way-of-obtaining-mac-address-of-your-machine/</link>
		<comments>http://wxwidgets.info/cross-platform-way-of-obtaining-mac-address-of-your-machine/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 12:04:45 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Components]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[wxWinCE]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=557</guid>
		<description><![CDATA[In one of my current projects I had to implement client-server communication and protection by MAC address when client machine can&#8217;t connect to server if its MAC address is not allowed, regardless of network or broadband connection. But what was a surprise that wxWidgets does not have API which allows obtaining MAC address in cross-platform [...]]]></description>
			<content:encoded><![CDATA[<p>In one of my current projects I had to implement client-server communication and protection by MAC address when client machine can&#8217;t connect to server if its MAC address is not allowed, regardless of network or <a href="http://www.o2.co.uk/">broadband</a> connection. But what was a surprise that wxWidgets does not have API which allows obtaining MAC address in cross-platform way. So, I decided to write a small class which allows obtainig MAC address for Windows, Linux, Mac OS and Windows Mobile. Here it is:<br />
<span id="more-557"></span><br />
<strong>MACAddressUtility.h</strong></p>
<pre class="brush: cpp;">
#ifndef _MACADDRESS_UTILITY_H
#define _MACADDRESS_UTILITY_H

class MACAddressUtility
{
public:
	static long GetMACAddress(unsigned char * result);
private:
#if defined(WIN32) || defined(UNDER_CE)
	static long GetMACAddressMSW(unsigned char * result);
#elif defined(__APPLE__)
	static long GetMACAddressMAC(unsigned char * result);
#elif defined(LINUX) || defined(linux)
	static long GetMACAddressLinux(unsigned char * result);
#endif
};

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

#include &lt;stdio.h&gt;

#if defined(WIN32) || defined(UNDER_CE)
#	include &lt;windows.h&gt;
#	if defined(UNDER_CE)
#		include &lt;Iphlpapi.h&gt;
#	endif
#elif defined(__APPLE__)
#	include &lt;CoreFoundation/CoreFoundation.h&gt;
#	include &lt;IOKit/IOKitLib.h&gt;
#	include &lt;IOKit/network/IOEthernetInterface.h&gt;
#	include &lt;IOKit/network/IONetworkInterface.h&gt;
#	include &lt;IOKit/network/IOEthernetController.h&gt;
#elif defined(LINUX) || defined(linux)
#	include &lt;string.h&gt;
#	include &lt;net/if.h&gt;
#	include &lt;sys/ioctl.h&gt;
#   include &lt;sys/socket.h&gt;
#   include &lt;arpa/inet.h&gt;
#endif

long MACAddressUtility::GetMACAddress(unsigned char * result)
{
	// Fill result with zeroes
	memset(result, 0, 6);
	// Call appropriate function for each platform
#if defined(WIN32) || defined(UNDER_CE)
	return GetMACAddressMSW(result);
#elif defined(__APPLE__)
	return GetMACAddressMAC(result);
#elif defined(LINUX) || defined(linux)
	return GetMACAddressLinux(result);
#endif
	// If platform is not supported then return error code
	return -1;
}

#if defined(WIN32) || defined(UNDER_CE)

inline long MACAddressUtility::GetMACAddressMSW(unsigned char * result)
{

#if defined(UNDER_CE)
	IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information
	DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
	if(GetAdaptersInfo(AdapterInfo, &amp;dwBufLen) == ERROR_SUCCESS)
	{
		memcpy(result, AdapterInfo-&gt;Address, 6);
	}
	else return -1;
#else
	UUID uuid;
	if(UuidCreateSequential(&amp;uuid) == RPC_S_UUID_NO_ADDRESS) return -1;
	memcpy(result, (char*)(uuid.Data4+2), 6);
#endif
	return 0;
}

#elif defined(__APPLE__)

static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices)
{
    kern_return_t		kernResult;
    CFMutableDictionaryRef	matchingDict;
    CFMutableDictionaryRef	propertyMatchDict;

    matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);

    if (NULL != matchingDict)
	{
        propertyMatchDict =
			CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
				&amp;kCFTypeDictionaryKeyCallBacks,
				&amp;kCFTypeDictionaryValueCallBacks);

        if (NULL != propertyMatchDict)
		{
            CFDictionarySetValue(propertyMatchDict,
				CFSTR(kIOPrimaryInterface), kCFBooleanTrue);
            CFDictionarySetValue(matchingDict,
				CFSTR(kIOPropertyMatchKey), propertyMatchDict);
            CFRelease(propertyMatchDict);
        }
    }
    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
		matchingDict, matchingServices);
    return kernResult;
}

static kern_return_t GetMACAddress(io_iterator_t intfIterator,
								   UInt8 *MACAddress, UInt8 bufferSize)
{
    io_object_t		intfService;
    io_object_t		controllerService;
    kern_return_t	kernResult = KERN_FAILURE;

	if (bufferSize &lt; kIOEthernetAddressSize) {
		return kernResult;
	}

    bzero(MACAddress, bufferSize);

    while (intfService = IOIteratorNext(intfIterator))
    {
        CFTypeRef	MACAddressAsCFData;        

        // IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call,
        // since they are hardware nubs and do not participate in driver matching. In other words,
        // registerService() is never called on them. So we've found the IONetworkInterface and will
        // get its parent controller by asking for it specifically.

        // IORegistryEntryGetParentEntry retains the returned object,
		// so release it when we're done with it.
        kernResult =
			IORegistryEntryGetParentEntry(intfService,
				kIOServicePlane,
				&amp;controllerService);

        if (KERN_SUCCESS != kernResult) {
            printf(&quot;IORegistryEntryGetParentEntry returned 0x%08x\n&quot;, kernResult);
        }
        else {
            // Retrieve the MAC address property from the I/O Registry in the form of a CFData
            MACAddressAsCFData =
				IORegistryEntryCreateCFProperty(controllerService,
					CFSTR(kIOMACAddress),
					kCFAllocatorDefault,
					0);
            if (MACAddressAsCFData) {
                CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr

                // Get the raw bytes of the MAC address from the CFData
                CFDataGetBytes((CFDataRef)MACAddressAsCFData,
					CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
                CFRelease(MACAddressAsCFData);
            }

            // Done with the parent Ethernet controller object so we release it.
            (void) IOObjectRelease(controllerService);
        }

        // Done with the Ethernet interface object so we release it.
        (void) IOObjectRelease(intfService);
    }

    return kernResult;
}

long MACAddressUtility::GetMACAddressMAC(unsigned char * result)
{
	io_iterator_t	intfIterator;
	kern_return_t	kernResult = KERN_FAILURE;
	do
	{
		kernResult = ::FindEthernetInterfaces(&amp;intfIterator);
		if (KERN_SUCCESS != kernResult) break;
	    kernResult = ::GetMACAddress(intfIterator, (UInt8*)result, 6);
    }
	while(false);
    (void) IOObjectRelease(intfIterator);
}

#elif defined(LINUX) || defined(linux)

long MACAddressUtility::GetMACAddressLinux(unsigned char * result)
{
	struct ifreq ifr;
    struct ifreq *IFR;
    struct ifconf ifc;
    char buf[1024];
    int s, i;
    int ok = 0;

    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == -1)
	{
        return -1;
    }

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    ioctl(s, SIOCGIFCONF, &amp;ifc);

    IFR = ifc.ifc_req;
    for (i = ifc.ifc_len / sizeof(struct ifreq); --i &gt;= 0; IFR++)
	{
        strcpy(ifr.ifr_name, IFR-&gt;ifr_name);
        if (ioctl(s, SIOCGIFFLAGS, &amp;ifr) == 0)
		{
            if (! (ifr.ifr_flags &amp; IFF_LOOPBACK))
			{
                if (ioctl(s, SIOCGIFHWADDR, &amp;ifr) == 0)
				{
                    ok = 1;
                    break;
                }
            }
        }
    }

    shutdown(s, SHUT_RDWR);
    if (ok)
	{
        bcopy( ifr.ifr_hwaddr.sa_data, result, 6);
    }
    else
	{
        return -1;
    }
    return 0;
}

#endif
</pre>
<p><strong>wxMACAddressUtility.h</strong></p>
<pre class="brush: cpp;">
#ifndef _WX_MACADDRESS_UTILITY_H
#define _WX_MACADDRESS_UTILITY_H

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

class wxMACAddressUtility
{
public:
	static wxString GetMACAddress()
	{
		unsigned char result[6];
		if(MACAddressUtility::GetMACAddress(result) == 0)
		{
			return wxString::Format(wxT(&quot;%02X:%02X:%02X:%02X:%02X:%02X&quot;),
				(unsigned int)result[0], (unsigned int)result[1], (unsigned int)result[2],
				(unsigned int)result[3], (unsigned int)result[4], (unsigned int)result[5]);
		}
		return wxEmptyString;
	}
};

#endif
</pre>
<p><strong>Sample of usage:</strong></p>
<pre class="brush: cpp;">
m_MACAddress = wxMACAddressUtility::GetMACAddress();
</pre>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/08/macaddr.jpg"><img src="http://wxwidgets.info//wp-content/uploads/2009/08/macaddr.jpg" alt="Get MAC address programmatically" title="Get MAC address programmatically" width="226" height="67" class="alignnone size-full wp-image-558" /></a></p>
<p>As you can see, core class does not depend on wxWidgets and can be used in native applications written without wxWidgets.</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/08/wxMACAddressUtility.7z" title="How to get MAC address in C++: Windows, Linux, Mac OS, Windows Mobile">Download sample application</a></p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/cross-platform-way-of-obtaining-mac-address-of-your-machine/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using wxFlatNotebook in Code::Blocks Project</title>
		<link>http://wxwidgets.info/using-wxflatnotebook-in-codeblocks-project/</link>
		<comments>http://wxwidgets.info/using-wxflatnotebook-in-codeblocks-project/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 21:25:13 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Video]]></category>
		<category><![CDATA[wxWidgets]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=521</guid>
		<description><![CDATA[This tutorial shows how to: Create wxFlatNotebook static library in Code::Blocks. Configure and compile wxFlatNotebook library. Create small wxWidgets project which uses wxFlatNotebook. Configure project and add support of 3rd-party library. Download video: &#8220;Using wxFlatNotebook in Code::Blocks Project&#8221;.]]></description>
			<content:encoded><![CDATA[<p>This tutorial shows how to:</p>
<ul>
<li>Create wxFlatNotebook static library in Code::Blocks.</li>
<li>Configure and compile wxFlatNotebook library.</li>
<li>Create small wxWidgets project which uses wxFlatNotebook.</li>
<li>Configure project and add support of 3rd-party library.</li>
</ul>
<p><a title="Download video: Using wxFlatNotebook in Code::Blocks Project" href="http://depositfiles.com/files/y933gi746" target="_blank">Download video: &#8220;Using wxFlatNotebook in Code::Blocks Project&#8221;</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/using-wxflatnotebook-in-codeblocks-project/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Create Nice About Box in wxWidgets</title>
		<link>http://wxwidgets.info/how-to-create-nice-about-box-in-wxwidgets/</link>
		<comments>http://wxwidgets.info/how-to-create-nice-about-box-in-wxwidgets/#comments</comments>
		<pubDate>Sun, 25 Jan 2009 12:59:33 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Components]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorilas]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info/?p=480</guid>
		<description><![CDATA[After taking a look at wxWidgets samples I noticed that all of them have simple message box instaed of normal about box. However in real applications About dialog is important enough part of GUI. So, in this post I&#8217;m going to tell a bit about creating About boxes for your software. wxWidgets has builf-in API [...]]]></description>
			<content:encoded><![CDATA[<p>After taking a look at wxWidgets samples I noticed that all of them have simple message box instaed of normal about box. However in real applications About dialog is important enough part of GUI.</p>
<p>So, in this post I&#8217;m going to tell a bit about creating About boxes for your software.</p>
<p>wxWidgets has builf-in API for creating &#8220;standard&#8221; dialog boxes. <a title="wxAboutBox function documentation" href="http://docs.wxwidgets.org/stable/wx_dialogfunctions.html#wxaboutbox" target="_blank">wxAboutBox()</a> function is used for displaying About box and <a title="wxAboutDialogInfo class documentation" href="http://docs.wxwidgets.org/stable/wx_wxaboutdialoginfo.html" target="_blank">wxAboutDialogInfo</a> object, which contains all necessary information, should be passed to wxAboutBox() function.<br />
<span id="more-480"></span><br />
wxAboutDialogInfo can contain such information as:</p>
<ul>
<li>Application name</li>
<li>Application icon</li>
<li>Application description</li>
<li>Application version</li>
<li>List of developers</li>
<li>List of artists</li>
<li>List of documentation writers</li>
<li>List of translators</li>
<li>Copyright message</li>
<li>Web-site URL</li>
<li>Application license</li>
</ul>
<p>Only wxGTK port supports native way of displaying application license. On other platforms generic implementation will be used and it is better to create a separate dialog for this purpose.</p>
<p>Well, here is a small example of using API described above:</p>
<pre class="brush: cpp;">
#include
...
// This object will contain all information displayed in About box
wxAboutDialogInfo info;
// Call of AddDeveloper() method adds a record to list of developers
info.AddDeveloper(_(&quot;John Doe&quot;));
// Call of AddDocWriter() method adds a record to list of documentation writers
info.AddDocWriter(_(&quot;Donald Duck&quot;));
// Call of AddArtist() method adds a record to list of artists
info.AddArtist(_(&quot;Scrooge Mc.Duck&quot;));
// Call of AddTranslator() method adds a record to list of translators
info.AddTranslator(_(&quot;Mickey Mouse&quot;));
// This method adds application description.
info.SetDescription(_(&quot;Sample wxWidgets application for testing wxAboutBox() function.&quot;));
// This method sets application version string
info.SetVersion(wxT(&quot;1.0.0 beta 1&quot;));
// SetName() method sets application name displayed in About box.
// It is better to pass wxApp::GetAppName() to this method
info.SetName(wxTheApp-&gt;GetAppName());
// Sets application Web-site URL
info.SetWebSite(wxT(&quot;http://wxwidgets.info&quot;));
// Sets the icon which will be displayed in About box.
info.SetIcon(wxICON(wxICON_AAA));
// Sets application license string. Only wxGTK port has native way of
// displaying application license. All other ports will use generic way for this purpose.
info.SetLicence(_(&quot;Public Domain&quot;));

// At last, we can display about box
wxAboutBox(info);
</pre>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_1.png"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_1.png" alt="wxAboutBox and wxAboutDialogLinfo usage sample - Collapsed" title="wxAboutBox and wxAboutDialogLinfo usage sample - Collapsed" width="379" height="318" class="alignnone size-full wp-image-481" /></a><br />
As you can see, there are several collapsible panels placed to dialog. The amount of these panels changes according theinformation specified in wxAboutDialogInfo object.<br />
After expanding collapsible panels we&#8217;ll get something like this:<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_2.png"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_2.png" alt="wxAboutBox Sample - Expanded" title="wxAboutBox Sample - Expanded" width="379" height="450" class="alignnone size-full wp-image-482" /></a><br />
Looks nice but a bit boring. So I decided to create more fancy About box. In fact, I was inspired by <a href="http://wxforum.shadonet.com/viewtopic.php?t=21498">this post at wxForum</a> but used my own way and also made some changes.</p>
<p><strong>wxMozillaLikeAboutBoxDialog.h</strong></p>
<pre class="brush: cpp;">
#ifndef _WXMOZILLALIKEABOUTBOXDIALOG_H_
#define _WXMOZILLALIKEABOUTBOXDIALOG_H_

#include &quot;wx/gbsizer.h&quot;
#include &quot;wx/statline.h&quot;

#define SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_STYLE wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL
#define SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_TITLE _(&quot;About &quot;)
#define SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_IDNAME ID_WXMOZILLALIKEABOUTBOXDIALOG
#define SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_SIZE wxSize(400, 300)
#define SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_POSITION wxDefaultPosition

class wxMozillaLikeAboutBoxDialog: public wxDialog
{
    DECLARE_DYNAMIC_CLASS( wxMozillaLikeAboutBoxDialog )
    DECLARE_EVENT_TABLE()
public:
    wxMozillaLikeAboutBoxDialog();
    wxMozillaLikeAboutBoxDialog( wxWindow* parent,
		wxWindowID id = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_IDNAME,
		const wxString&amp; caption = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_TITLE,
		const wxPoint&amp; pos = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_POSITION,
		const wxSize&amp; size = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_SIZE,
		long style = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_STYLE );

    bool Create( wxWindow* parent,
		wxWindowID id = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_IDNAME,
		const wxString&amp; caption = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_TITLE,
		const wxPoint&amp; pos = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_POSITION,
		const wxSize&amp; size = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_SIZE,
		long style = SYMBOL_WXMOZILLALIKEABOUTBOXDIALOG_STYLE );

    ~wxMozillaLikeAboutBoxDialog();

    void Init();
    void CreateControls();

    wxString GetAppName() const { return m_AppName ; }
    void SetAppName(wxString value) { m_AppName = value ; }

    wxString GetVersion() const { return m_Version ; }
    void SetVersion(wxString value) { m_Version = value ; }

    wxString GetCopyright() const { return m_Copyright ; }
    void SetCopyright(wxString value) { m_Copyright = value ; }

    wxString GetCustomBuildInfo() const { return m_CustomBuildInfo ; }
    void SetCustomBuildInfo(wxString value) { m_CustomBuildInfo = value ; }

    wxBitmap GetBitmapResource( const wxString&amp; name );
    wxIcon GetIconResource( const wxString&amp; name );

    enum wxBuildInfoFormat
    {
        wxBUILDINFO_SHORT,
        wxBUILDINFO_LONG
    };

    static wxString GetBuildInfo(wxBuildInfoFormat format);

    void SetHeaderBitmap(const wxBitmap &amp; value);
    void ApplyInfo();

private:
    wxPanel* m_ContentPanel;
    wxStaticBitmap* m_HeaderStaticBitmap;
    wxStaticText* m_AppNameStaticText;
    wxStaticText* m_CopyrightStaticText;
    wxStaticText* m_VersionStaticText;
    wxStaticText* m_BuildInfoStaticText;
    wxString m_AppName;
    wxString m_Version;
    wxString m_Copyright;
    wxString m_CustomBuildInfo;
    /// Control identifiers
    enum {
        ID_WXMOZILLALIKEABOUTBOXDIALOG = 10000,
        ID_ContentPanel = 10001
    };
};

wxBitmap wxGetBitmapFromMemory(const void * data, size_t length);

#endif
</pre>
<p><strong>wxMozillaLikeAboutBoxDialog.cpp</strong></p>
<pre class="brush: cpp;">
#include &quot;wx/wxprec.h&quot;

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include &quot;wx/wx.h&quot;
#endif

#include &quot;wxMozillaLikeAboutBoxDialog.h&quot;
#include &lt;wx/mstream.h&gt;

IMPLEMENT_DYNAMIC_CLASS( wxMozillaLikeAboutBoxDialog, wxDialog )

BEGIN_EVENT_TABLE( wxMozillaLikeAboutBoxDialog, wxDialog )
END_EVENT_TABLE()

wxMozillaLikeAboutBoxDialog::wxMozillaLikeAboutBoxDialog()
{
    Init();
}

wxMozillaLikeAboutBoxDialog::wxMozillaLikeAboutBoxDialog( wxWindow* parent, wxWindowID id, const wxString&amp; caption, const wxPoint&amp; pos, const wxSize&amp; size, long style )
{
    Init();
    Create(parent, id, caption, pos, size, style);
}

bool wxMozillaLikeAboutBoxDialog::Create( wxWindow* parent, wxWindowID id, const wxString&amp; caption, const wxPoint&amp; pos, const wxSize&amp; size, long style )
{
    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
    wxDialog::Create( parent, id, caption, pos, size, style );
    CreateControls();
    if (GetSizer())
    {
        GetSizer()-&gt;SetSizeHints(this);
    }
    Centre();
    return true;
}

wxMozillaLikeAboutBoxDialog::~wxMozillaLikeAboutBoxDialog()
{
}

void wxMozillaLikeAboutBoxDialog::Init()
{
    m_ContentPanel = NULL;
    m_HeaderStaticBitmap = NULL;
    m_AppNameStaticText = NULL;
    m_CopyrightStaticText = NULL;
    m_VersionStaticText = NULL;
    m_BuildInfoStaticText = NULL;
}

void wxMozillaLikeAboutBoxDialog::CreateControls()
{
    wxMozillaLikeAboutBoxDialog* itemDialog1 = this;
    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
    itemDialog1-&gt;SetSizer(itemBoxSizer2);
    m_ContentPanel = new wxPanel( itemDialog1, ID_ContentPanel, wxDefaultPosition, wxSize(200, 300), wxNO_BORDER|wxTAB_TRAVERSAL );
    m_ContentPanel-&gt;SetBackgroundColour(wxColour(255, 255, 255));
    itemBoxSizer2-&gt;Add(m_ContentPanel, 0, wxGROW, 0);
    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxVERTICAL);
    m_ContentPanel-&gt;SetSizer(itemBoxSizer4);
    m_HeaderStaticBitmap = new wxStaticBitmap( m_ContentPanel, wxID_STATIC, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer4-&gt;Add(m_HeaderStaticBitmap, 0, wxGROW, 0);
    wxGridBagSizer* itemGridBagSizer6 = new wxGridBagSizer(0, 0);
    itemGridBagSizer6-&gt;AddGrowableRow(2);
    itemGridBagSizer6-&gt;AddGrowableRow(3);
    itemGridBagSizer6-&gt;SetEmptyCellSize(wxSize(10, 20));
    itemBoxSizer4-&gt;Add(itemGridBagSizer6, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 10);
    m_AppNameStaticText = new wxStaticText( m_ContentPanel, wxID_STATIC, _T(&quot;&quot;), wxDefaultPosition, wxDefaultSize, 0 );
    m_AppNameStaticText-&gt;SetForegroundColour(wxColour(255, 0, 0));
    m_AppNameStaticText-&gt;SetFont(wxFont(28, wxSWISS, wxNORMAL, wxNORMAL, false, wxT(&quot;Arial Narrow&quot;)));
    itemGridBagSizer6-&gt;Add(m_AppNameStaticText, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALIGN_LEFT|wxALIGN_BOTTOM|wxLEFT|wxRIGHT|wxTOP, 5);
    wxStaticText* itemStaticText8 = new wxStaticText( m_ContentPanel, wxID_STATIC, _(&quot;version&quot;), wxDefaultPosition, wxDefaultSize, 0 );
    itemStaticText8-&gt;SetForegroundColour(wxColour(192, 192, 192));
    itemStaticText8-&gt;SetFont(wxFont(8, wxSWISS, wxNORMAL, wxBOLD, false, wxT(&quot;Arial&quot;)));
    itemGridBagSizer6-&gt;Add(itemStaticText8, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_RIGHT|wxALIGN_TOP|wxLEFT|wxBOTTOM, 5);
    m_CopyrightStaticText = new wxStaticText( m_ContentPanel, wxID_STATIC, _T(&quot;&quot;), wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE );
    itemGridBagSizer6-&gt;Add(m_CopyrightStaticText, wxGBPosition(2, 0), wxGBSpan(1, 2), wxGROW|wxGROW|wxALL, 5);
    m_VersionStaticText = new wxStaticText( m_ContentPanel, wxID_STATIC, _T(&quot;&quot;), wxDefaultPosition, wxDefaultSize, 0 );
    m_VersionStaticText-&gt;SetForegroundColour(wxColour(192, 192, 192));
    m_VersionStaticText-&gt;SetFont(wxFont(8, wxSWISS, wxNORMAL, wxBOLD, false, wxT(&quot;Arial&quot;)));
    itemGridBagSizer6-&gt;Add(m_VersionStaticText, wxGBPosition(1, 1), wxGBSpan(1, 1), wxALIGN_LEFT|wxALIGN_TOP|wxLEFT|wxRIGHT|wxBOTTOM, 5);
    m_BuildInfoStaticText = new wxStaticText( m_ContentPanel, wxID_STATIC, _T(&quot;&quot;), wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE );
    itemGridBagSizer6-&gt;Add(m_BuildInfoStaticText, wxGBPosition(3, 0), wxGBSpan(1, 2), wxGROW|wxGROW|wxALL, 5);
    itemBoxSizer4-&gt;Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
    wxStaticLine* itemStaticLine13 = new wxStaticLine( itemDialog1, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
    itemBoxSizer2-&gt;Add(itemStaticLine13, 0, wxGROW, 0);
    wxStdDialogButtonSizer* itemStdDialogButtonSizer14 = new wxStdDialogButtonSizer;
    itemBoxSizer2-&gt;Add(itemStdDialogButtonSizer14, 0, wxALIGN_RIGHT|wxALL, 5);
    wxButton* itemButton15 = new wxButton( itemDialog1, wxID_OK, _(&quot;&amp;OK&quot;), wxDefaultPosition, wxDefaultSize, 0 );
    itemStdDialogButtonSizer14-&gt;AddButton(itemButton15);
    itemStdDialogButtonSizer14-&gt;Realize();
    m_BuildInfoStaticText-&gt;SetLabel(wxMozillaLikeAboutBoxDialog::GetBuildInfo(wxBUILDINFO_LONG));
}
</pre>
<p>And here is a method which returns a string with build information</p>
<pre class="brush: cpp;">
wxString wxMozillaLikeAboutBoxDialog::GetBuildInfo(wxBuildInfoFormat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == wxBUILDINFO_LONG)
    {
#if defined(__WXMSW__)
        wxbuild &lt;&lt; _T(&quot;-Windows&quot;);
#elif defined(__WXMAC__)
        wxbuild &lt;&lt; _T(&quot;-Mac&quot;);
#elif defined(__UNIX__)
        wxbuild &lt;&lt; _T(&quot;-Linux&quot;);
#endif

#if wxUSE_UNICODE
        wxbuild &lt;&lt; _T(&quot;-Unicode&quot;);
#else
        wxbuild &lt;&lt; _T(&quot;-ANSI&quot;);
#endif // wxUSE_UNICODE
    }
	wxbuild &lt;&lt; _(&quot; build&quot;);
    return wxbuild;
}
</pre>
<p>This method utilizes <code>wxVERSION_STRING</code> macro which returns a string with wxWidgets version.</p>
<pre class="brush: cpp;">
wxBitmap wxGetBitmapFromMemory(const void * data, size_t length)
{
	wxMemoryInputStream stream(data, length);
	return wxBitmap(stream, wxBITMAP_TYPE_ANY);
}

void wxMozillaLikeAboutBoxDialog::SetHeaderBitmap(const wxBitmap &amp; value)
{
    m_HeaderStaticBitmap-&gt;SetBitmap(value);
}
</pre>
<p><code>wxGetBitmapFromMemory()</code> method creates wxBitmap from memory buffer using <code>wxMemoryInputStream</code>.</p>
<pre class="brush: cpp;">
void wxMozillaLikeAboutBoxDialog::ApplyInfo()
{
	wxASSERT_MSG(m_HeaderStaticBitmap-&gt;GetBitmap().IsOk(), _(&quot;Header bitmap for About box is empty&quot;));
	SetTitle(wxString::Format(wxT(&quot;%s %s&quot;), _(&quot;About&quot;), m_AppName.GetData()));
    m_AppNameStaticText-&gt;SetLabel(m_AppName);
    m_VersionStaticText-&gt;SetLabel(m_Version);
    m_CopyrightStaticText-&gt;SetLabel(m_Copyright);
	wxString buildInfo;
	if(m_CustomBuildInfo.IsEmpty())
	{
		buildInfo = wxMozillaLikeAboutBoxDialog::GetBuildInfo(wxBUILDINFO_LONG);
	}
	else
	{
		buildInfo = m_CustomBuildInfo;
	}
	m_BuildInfoStaticText-&gt;SetLabel(buildInfo);
	int labelWidth = m_HeaderStaticBitmap-&gt;GetSize().GetWidth() - 20;
	m_VersionStaticText-&gt;Wrap(labelWidth);
	m_CopyrightStaticText-&gt;Wrap(labelWidth);
	m_BuildInfoStaticText-&gt;Wrap(labelWidth);
	m_ContentPanel-&gt;Layout();
	m_ContentPanel-&gt;GetSizer()-&gt;Fit(m_ContentPanel);
    GetSizer()-&gt;Fit(this);
	Centre();
}
</pre>
<p>ApplyInfo method sets labels of all wxStaticText controls, applies header image and then fixes the layout according to changes.</p>
<p>Here is an example of usage of our Mozilla-like About box:</p>
<p><strong>wxAboutBoxTestMainFrame.cpp</strong></p>
<pre class="brush: cpp;">
void wxAboutBoxTestMainFrame::OnMOZILLALIKEABOUTBOXClick( wxCommandEvent&amp; event )
{
	// Create About box
	wxMozillaLikeAboutBoxDialog * dlg = new wxMozillaLikeAboutBoxDialog(this);
	// Set application name
	dlg-&gt;SetAppName(wxTheApp-&gt;GetAppName());
	// Set application version
	dlg-&gt;SetVersion(wxT(&quot;1.0.0 b1&quot;));
	// Set copyright message
	dlg-&gt;SetCopyright(wxString::Format(wxT(&quot;%c %i %s&quot;),
		(wxChar) 0x00A9, wxDateTime::Now().GetYear(),
		_(&quot;Volodymir (T-Rex) Tryapichko. All rights reserved. Please contact author if you have any copyright-related questions.&quot;)));
	// Set build info message. This is optional step. If you don't specify build info message then
	// default one will be used
	dlg-&gt;SetCustomBuildInfo(wxString::Format(wxT(&quot;%s. %s&quot;),
		wxMozillaLikeAboutBoxDialog::GetBuildInfo(wxMozillaLikeAboutBoxDialog::wxBUILDINFO_LONG).GetData(),
		_(&quot;Compiled by T-Rex personally <img src='http://wxwidgets.info/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &quot;)));
	// Set header bitmap
	dlg-&gt;SetHeaderBitmap(wxGetBitmapFromMemory(header_png, sizeof(header_png)));
	// Apply changes
	dlg-&gt;ApplyInfo();
	// Show dialog
	dlg-&gt;ShowModal();
	// Destroy dialog
	dlg-&gt;Destroy();
}
</pre>
<p><code>header_png</code> is a char array created from PNG image using Bin2C utility:</p>
<pre class="brush: cpp;">
unsigned char header_png[] ={
	0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,
	...
};
</pre>
<p>And here is a screenshot of what we get after compiling the source code listed above:<br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_3.png"><img src="http://wxwidgets.info//wp-content/uploads/2009/01/aboutbox_in_wxwidgets_3.png" alt="Mozilla-like About Box in wxWidgets" title="Mozilla-like About Box in wxWidgets" width="310" height="401" class="alignnone size-full wp-image-483" /></a><br />
<a href="http://wxwidgets.info//wp-content/uploads/2009/01/wxaboutboxtest.7z" title="Doanload Source Code: Mozilla-like About Box for wxWidgets">Download the source code for this tutorial</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/how-to-create-nice-about-box-in-wxwidgets/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Создание собственных валидаторов значения текстового поля в wxWidgets</title>
		<link>http://wxwidgets.info/sozdanie-sobstvennyx-validatorov-znacheniya-tekstovogo-polya-v-wxwidgets/</link>
		<comments>http://wxwidgets.info/sozdanie-sobstvennyx-validatorov-znacheniya-tekstovogo-polya-v-wxwidgets/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 19:18:13 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[wxValidator]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=465</guid>
		<description><![CDATA[Еще одна статья от Александра (sandy) Илюшенко о создании собственного валидатора для wxTextCtrl. Наверное каждый сталкивался с проблемой ввода логина пользователя, особенно если необходимо запретить ввод кириллических букв. Для реализации этой столь простой задачи напрашивается использовать wxTextValidator и его метод SetExcludes. Но, как по мне, не очень элегантно перед объявлением wxTextCtrl создавать экземпляр wxTextValidator и [...]]]></description>
			<content:encoded><![CDATA[<p>Еще одна статья от <a onclick="urchinTracker('/outgoing/www.sandyhip.net.ua/?referer=http://wxwidgets.info//wp-admin/post-new.php');urchinTracker('/outgoing/www.sandyhip.net.ua?referer=http://wxwidgets.info//');" href="http://www.sandyhip.net.ua/">Александра (sandy) Илюшенко</a> о создании собственного валидатора для wxTextCtrl.</p>
<p>Наверное каждый сталкивался с проблемой ввода логина пользователя, особенно если необходимо запретить ввод кириллических букв. Для реализации этой столь простой задачи напрашивается использовать <code>wxTextValidator</code> и его метод <code>SetExcludes</code>. Но, как по мне, не очень элегантно перед объявлением <code>wxTextCtrl</code> создавать экземпляр <code>wxTextValidator</code> и впихивать в него запрещенные для ввода символы. По-моему, гораздо удобнее использовать унаследованный от <code>wxTextValidator</code> класс. К тому же, его использование может быть неоднократным.<br />
<span id="more-465"></span><br />
Вот потому лучше не полениться и один раз реализовать такой класс.</p>
<p><strong>wxLoginValidator.h</strong></p>
<pre class="brush: cpp;">
#pragma once
#include &lt;wx/valtext.h&gt;

class wxLoginValidator : public wxTextValidator {
public:
    wxLoginValidator() : wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST)
    {
        wxArrayString a;
        wxString s=wxT(&quot;АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁёЄєЇїІі&quot;);
        for (size_t i=0;i&lt;s.Len();i++) {
            a.Add(wxString(s[i]));
        }
        SetExcludes(a);
    }
};
</pre>
<p>И использовать это уже гораздо проще.</p>
<p><strong>Example.cpp</strong></p>
<pre class="brush: cpp;">
#include &quot;wxLoginValidator.h&quot;
/* ... */
wxTextCtrl* m_LoginCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
	wxDefaultPosition, wxSize( 120,20 ), 0, wxLoginValidator());
m_LoginCtrl-&gt;SetMaxLength(8);
/* ... */
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/sozdanie-sobstvennyx-validatorov-znacheniya-tekstovogo-polya-v-wxwidgets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Кастомизация класса wxHtmlEasyPrinting для печати отчетов в wxWidgets</title>
		<link>http://wxwidgets.info/kastomizaciya-klassa-wxhtmleasyprinting-dlya-pechati-otchetov-v-wxwidgets/</link>
		<comments>http://wxwidgets.info/kastomizaciya-klassa-wxhtmleasyprinting-dlya-pechati-otchetov-v-wxwidgets/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 19:08:09 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[Printing]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=461</guid>
		<description><![CDATA[Александр (sandy) Илюшенко любезно предоставил статью о кастомизации класса для печати отчетов wxHtmlEasyPrinting: В этой статье я опишу еще один переопределенный класс для своих нужд. Думаю, что не только для моих нужд. Началось все с того, что мне пришлось выводить нокоторые свои данные на печать в табличном представлении. Но перед этим, как сами понимаете, не [...]]]></description>
			<content:encoded><![CDATA[<p><a onclick="urchinTracker('/outgoing/www.sandyhip.net.ua?referer=http://wxwidgets.info//');" href="http://www.sandyhip.net.ua/">Александр (sandy) Илюшенко</a> любезно предоставил статью о кастомизации класса для печати отчетов <strong>wxHtmlEasyPrinting</strong>:</p>
<p>В этой статье я опишу еще один переопределенный класс для своих нужд. Думаю, что не только для моих нужд. Началось все с того, что мне пришлось выводить нокоторые свои данные на печать в табличном представлении. Но перед этим, как сами понимаете, не лишним будет и предварительный просмотр.<br />
<span id="more-461"></span><br />
Для реализации этой простой задачи мне приглянулся класс <strong>wxHtmlEasyPrinting</strong>, которому дастаточно передать строку, содержащую html-код. Вот небольшой пример его использования.</p>
<p><strong>Example1.cpp</strong></p>
<pre class="brush: cpp;">
#include &lt;wx/html/htmprint.h&gt;
 /*... */
 wxHtmlEasyPrinting* prn = new wxHtmlEasyPrinting(wxT(&quot;Довідник користувачів&quot;));
 prn-&gt;GetPrintData()-&gt;SetOrientation(wxLANDSCAPE);
 prn-&gt;GetPageSetupData()-&gt;SetMarginTopLeft(wxPoint(10,10));
 prn-&gt;GetPageSetupData()-&gt;SetMarginBottomRight(wxPoint(5,5));
 prn-&gt;SetFooter(sFooter);
 prn-&gt;PreviewText(sText);
 /*... */
</pre>
<p>Для пояснения: <strong>sFooter</strong> &#8211; это строка, содержащая html-код нижнего колонтитула; <strong>sText</strong> &#8211; строка, содержащая html-код содержания документа, выводимого на печать.</p>
<p>Выглядит все это довольно неплохо:</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/htmlprint-1.png"><img class="alignnone size-full wp-image-462" title="wxHtmlEasyPrinting" src="http://wxwidgets.info//wp-content/uploads/2009/01/htmlprint-1.png" alt="wxHtmlEasyPrinting" /></a></p>
<p>Но мне, как всегда нашлось что-то, что не понравилось. Первое, что мне захотелось улучшить, &#8211; это кнопки навигации. Второе, &#8211; мне (вернее пользователю) нужно было все написать &#8220;на родном языке&#8221;. Чтобы долго не рассказывать, посмотрите на рисунок ниже, и ощутите разницу.</p>
<p><a href="http://wxwidgets.info//wp-content/uploads/2009/01/htmlprint-2.png"><img class="alignnone size-full wp-image-463" title="wxHtmlPrint" src="http://wxwidgets.info//wp-content/uploads/2009/01/htmlprint-2.png" alt="wxHtmlPrint" /></a></p>
<p>Теперь, как это мне удалось. Для начала, посмотрите на заголовочный файл.</p>
<p><strong>wxHtmlPrint.h</strong></p>
<pre class="brush: cpp;">
#pragma once
#include &lt;wx/html/htmprint.h&gt;
#include &lt;wx/choice.h&gt;
#include &lt;wx/numdlg.h&gt;
#include &lt;wx/bmpbuttn.h&gt;
#include &lt;wx/sizer.h&gt;

class wxPreviewCtrlBar : public wxPreviewControlBar {
    wxBitmapButton* m_bPrint;
    wxBitmapButton* m_bRewind;
    wxBitmapButton* m_bPreview;
    wxBitmapButton* m_bNext;
    wxBitmapButton* m_bLast;
public:
    wxPreviewCtrlBar(wxPrintPreviewBase* preview,
                     long buttons,
                     wxWindow* parent,
                     const wxPoint&amp; pos = wxDefaultPosition,
                     const wxSize&amp; size = wxDefaultSize,
                     long style = wxTAB_TRAVERSAL,
                     const wxString&amp; name = wxT(&quot;panel&quot;));
    void CreateButtons();
    void OnGoto();
};

class wxPreviewCtrl : public wxPreviewFrame {
    wxPreviewCtrlBar* m_ctrlBar;
public:
    wxPreviewCtrl(wxPrintPreviewBase* preview,
                  wxWindow* parent,
                  const wxString&amp; title = wxT(&quot;Print Preview&quot;),
                  const wxPoint&amp; pos = wxDefaultPosition,
                  const wxSize&amp; size = wxDefaultSize,
                  long style = wxDEFAULT_FRAME_STYLE,
                  const wxString&amp; name = wxT(&quot;frame&quot;));
    inline wxPreviewControlBar* GetControlBar() const {return (wxPreviewControlBar*)m_ctrlBar;}
    void Initialize();
    void CreateControlBar();
};

class wxHtmlPrint : public wxHtmlEasyPrinting {
    wxString m_sTitle;
    wxWindow* m_wParent;
protected:
    bool DoPreview(wxHtmlPrintout* printout1, wxHtmlPrintout* printout2);
public:
    wxHtmlPrint::wxHtmlPrint(const wxString&amp; name, wxWindow* parentWindow = NULL);
};
</pre>
<p>Как видите, переопределить пришлось не один класс. а целых три. Теперь, по-порядку. Класс <code>wxPreviewCtrlBar</code>, наследуемый от <code>wxPreviewControlBar</code> нужен больше всего, так как именно в этом классе переопределены кнопки и их названия. Подробнее, вместо <code>wxButton</code> для навигации используются <code>wxBitmapButton</code>, а для кнопки &#8220;Close&#8221; написано &#8220;Закрити&#8221;. (Интерфейс программы был написан на украинском языке. Кому необходимо, &#8211; перепишите по-русски сами) Для реализации этой задачи и нужно было переписать функцию <code>CreateButtons()</code>. Функция <code>OnGoto()</code> переписана для того, чтобы в функцию <code>wxGetNumberFromUser</code> передать строки на украинском языке, а не на английском.</p>
<p>Класс <code>wxPreviewCtrl</code>, наследуемый от <code>wxPreviewFrame</code>, имеет член экземпляра <code>wxPreviewCtrlBar* m_ctrlBar</code>. Его предок использовал предка этого члена. Потому пришлось переписать функции, в которых использовался <code>wxPreviewControlBar</code>, почти полностью, изменив лишь использование <code>wxPreviewControlBar*</code> на <code>wxPreviewCtrlBar*</code>.</p>
<p>В классе <code>wxHtmlPrint</code>, наследнике <code>wxHtmlEasyPrinting</code>, надо было переопределить только функцию <code>DoPreview</code>. Но, так как члены предка <code>wxWindow* m_ParentWindow</code> и <code>wxString m_Name</code> &#8211; закрытые, то пришлось ввести их альтернативы: <code>wxWindow* m_wParent</code> и <code>wxString m_sTitle</code>.</p>
<p><strong>wxHtmlPrint.cpp</strong></p>
<pre class="brush: cpp;">
#include &quot;wxHtmlPrint.h&quot;

/// XPM
static char * btn_rew_xpm[] = {
&quot;16 16 2 1&quot;,
&quot; 	c None&quot;,
&quot;.	c #000000&quot;,
&quot;                &quot;,
&quot; ..       .     &quot;,
&quot; ..      ..     &quot;,
&quot; ..     ...     &quot;,
&quot; ..    ....     &quot;,
&quot; ..   .....     &quot;,
&quot; ..  ......     &quot;,
&quot; .. .......     &quot;,
&quot; .. .......     &quot;,
&quot; ..  ......     &quot;,
&quot; ..   .....     &quot;,
&quot; ..    ....     &quot;,
&quot; ..     ...     &quot;,
&quot; ..      ..     &quot;,
&quot; ..       .     &quot;,
&quot;                &quot;};

static char * btn_prev_xpm[] = {
&quot;16 16 2 1&quot;,
&quot; 	c None&quot;,
&quot;.	c #000000&quot;,
&quot;                &quot;,
&quot;       .      . &quot;,
&quot;      ..     .. &quot;,
&quot;     ...    ... &quot;,
&quot;    ....   .... &quot;,
&quot;   .....  ..... &quot;,
&quot;  ...... ...... &quot;,
&quot; .............. &quot;,
&quot; .............. &quot;,
&quot;  ...... ...... &quot;,
&quot;   .....  ..... &quot;,
&quot;    ....   .... &quot;,
&quot;     ...    ... &quot;,
&quot;      ..     .. &quot;,
&quot;       .      . &quot;,
&quot;                &quot;};

static char * btn_next_xpm[] = {
&quot;16 16 2 1&quot;,
&quot; 	c None&quot;,
&quot;.	c #000000&quot;,
&quot;                &quot;,
&quot; .      .       &quot;,
&quot; ..     ..      &quot;,
&quot; ...    ...     &quot;,
&quot; ....   ....    &quot;,
&quot; .....  .....   &quot;,
&quot; ...... ......  &quot;,
&quot; .............. &quot;,
&quot; .............. &quot;,
&quot; ...... ......  &quot;,
&quot; .....  .....   &quot;,
&quot; ....   ....    &quot;,
&quot; ...    ...     &quot;,
&quot; ..     ..      &quot;,
&quot; .      .       &quot;,
&quot;                &quot;};

static char * btn_last_xpm[] = {
&quot;16 16 2 1&quot;,
&quot; 	c None&quot;,
&quot;.	c #000000&quot;,
&quot;                &quot;,
&quot;     .       .. &quot;,
&quot;     ..      .. &quot;,
&quot;     ...     .. &quot;,
&quot;     ....    .. &quot;,
&quot;     .....   .. &quot;,
&quot;     ......  .. &quot;,
&quot;     ....... .. &quot;,
&quot;     ....... .. &quot;,
&quot;     ......  .. &quot;,
&quot;     .....   .. &quot;,
&quot;     ....    .. &quot;,
&quot;     ...     .. &quot;,
&quot;     ..      .. &quot;,
&quot;     .       .. &quot;,
&quot;                &quot;};

static char *print_xpm[] = {
/* columns rows colors chars-per-pixel */
&quot;16 15 39 1&quot;,
&quot;&lt; c #E3E4E6&quot;,
&quot;+ c #C3C3C4&quot;,
&quot;i c #FFFFFF&quot;,
&quot;: c #74879B&quot;,
&quot;# c #5A89A6&quot;,
&quot;a c #F1F4F7&quot;,
&quot;r c #5A809C&quot;,
&quot;@ c #BDCCD9&quot;,
&quot;e c #7A92A4&quot;,
&quot;% c #3F6F93&quot;,
&quot;t c #9FA2A6&quot;,
&quot;3 c #939495&quot;,
&quot;w c #5F666D&quot;,
&quot;9 c #65839E&quot;,
&quot;5 c #4A7291&quot;,
&quot;$ c #4B7F9E&quot;,
&quot;  c None&quot;,
&quot;O c #DFE0E2&quot;,
&quot;o c #F3F3F3&quot;,
&quot;; c #84A5BB&quot;,
&quot;&amp; c #467291&quot;,
&quot;. c #7897AD&quot;,
&quot;* c #407598&quot;,
&quot;4 c #CFCFD0&quot;,
&quot;7 c #6F90A6&quot;,
&quot;y c #6A89A2&quot;,
&quot;0 c #AAADB2&quot;,
&quot;1 c #D2D3D4&quot;,
&quot;u c #4F7592&quot;,
&quot;, c #BCBDBE&quot;,
&quot;p c #57778E&quot;,
&quot;q c #979BA0&quot;,
&quot;2 c #ABABAC&quot;,
&quot;- c #E7E7E7&quot;,
&quot;= c #D6DEE6&quot;,
&quot;&gt; c #9FA0A0&quot;,
&quot;8 c #829EB5&quot;,
&quot;X c #8FB0C3&quot;,
&quot;6 c #5D7C93&quot;,
/* pixels */
&quot;   .XXXXXXXX    &quot;,
&quot;   .oooooooX    &quot;,
&quot;   .OOOOOOOX    &quot;,
&quot;   .+++++++X    &quot;,
&quot;@##$%&amp;&amp;&amp;&amp;&amp;%*##@ &quot;,
&quot;$=-;:&gt;,&lt;123$-=$ &quot;,
&quot;.44.5678.96$44. &quot;,
&quot;7,,,,,,,,,,,,,7 &quot;,
&quot;900qwwwwwwwe009 &quot;,
&quot;rtt9ryyyyyyuttr &quot;,
&quot;6qq6iiiiiii%qq6 &quot;,
&quot;633paiiiiii%336 &quot;,
&quot;XXX*iiiiiii%XXX &quot;,
&quot;   6iiiiiii%    &quot;,
&quot;   $XXXXXXX#    &quot;
};

/// wxPreviewCtrlBar
wxPreviewCtrlBar::wxPreviewCtrlBar(wxPrintPreviewBase* preview,
                                   long buttons,
                                   wxWindow* parent,
                                   const wxPoint&amp; pos,
                                   const wxSize&amp; size,
                                   long style,
                                   const wxString&amp; name) :
    wxPreviewControlBar(preview, buttons, parent, pos, size, style, name)
{
    m_bPrint = (wxBitmapButton*)NULL;
    m_bRewind = (wxBitmapButton*)NULL;
    m_bPreview = (wxBitmapButton*)NULL;
    m_bNext = (wxBitmapButton*)NULL;
    m_bLast = (wxBitmapButton*)NULL;
}

void wxPreviewCtrlBar::CreateButtons()
{
    SetSize(0, 0, 400, 40);

    wxBoxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );

    m_closeButton = new wxButton(this, wxID_PREVIEW_CLOSE, wxT(&quot;Закрити&quot;),
                                 wxDefaultPosition, wxDefaultSize, 0);
    item0-&gt;Add(m_closeButton, 0, wxALIGN_CENTRE | wxALL, 5);

    if (m_buttonFlags &amp; wxPREVIEW_PRINT) {
        m_bPrint = new wxBitmapButton(this, wxID_PREVIEW_PRINT, wxBitmap(print_xpm),
                                      wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
        item0-&gt;Add(m_bPrint, 0, wxALIGN_CENTRE|wxALL, 5);
    }

    // Exact-fit buttons are too tiny on wxUniversal
    int navButtonStyle;
    wxSize navButtonSize;
#ifdef __WXUNIVERSAL__
    navButtonStyle = 0;
    navButtonSize = wxSize(40, m_closeButton-&gt;GetSize().y);
#else
    navButtonStyle = wxBU_EXACTFIT;
    navButtonSize = wxDefaultSize;
#endif

    if (m_buttonFlags &amp; wxPREVIEW_FIRST) {
        m_bRewind = new wxBitmapButton(this, wxID_PREVIEW_FIRST, wxBitmap(btn_rew_xpm),
                                       wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
        item0-&gt;Add(m_bRewind, 0, wxALIGN_CENTRE | wxALL, 5);
    }
    if (m_buttonFlags &amp; wxPREVIEW_PREVIOUS) {
        m_bPreview = new wxBitmapButton(this, wxID_PREVIEW_PREVIOUS, wxBitmap(btn_prev_xpm),
                                        wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
        item0-&gt;Add(m_bPreview, 0, wxALIGN_CENTRE |wxRIGHT | wxTOP | wxBOTTOM, 5);
    }
    if (m_buttonFlags &amp; wxPREVIEW_NEXT) {
        m_bNext = new wxBitmapButton(this, wxID_PREVIEW_NEXT, wxBitmap(btn_next_xpm),
                                     wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
        item0-&gt;Add(m_bNext, 0, wxALIGN_CENTRE | wxRIGHT | wxTOP | wxBOTTOM, 5);
    }
    if (m_buttonFlags &amp; wxPREVIEW_LAST) {
        m_bLast = new wxBitmapButton(this, wxID_PREVIEW_LAST, wxBitmap(btn_last_xpm),
                                     wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
        item0-&gt;Add(m_bLast, 0, wxALIGN_CENTRE | wxRIGHT | wxTOP | wxBOTTOM, 5);
    }

    if (m_buttonFlags &amp; wxPREVIEW_GOTO) {
        m_gotoPageButton = new wxButton(this, wxID_PREVIEW_GOTO, wxT(&quot;Сторінка...&quot;),
                                        wxDefaultPosition, wxDefaultSize, 0);
        item0-&gt;Add(m_gotoPageButton, 0, wxALIGN_CENTRE | wxALL, 5);
    }

    if (m_buttonFlags &amp; wxPREVIEW_ZOOM) {
        wxString choices[] = {
            wxT(&quot;10%&quot;),
            wxT(&quot;15%&quot;),
            wxT(&quot;20%&quot;),
            wxT(&quot;25%&quot;),
            wxT(&quot;30%&quot;),
            wxT(&quot;35%&quot;),
            wxT(&quot;40%&quot;),
            wxT(&quot;45%&quot;),
            wxT(&quot;50%&quot;),
            wxT(&quot;55%&quot;),
            wxT(&quot;60%&quot;),
            wxT(&quot;65%&quot;),
            wxT(&quot;70%&quot;),
            wxT(&quot;75%&quot;),
            wxT(&quot;80%&quot;),
            wxT(&quot;85%&quot;),
            wxT(&quot;90%&quot;),
            wxT(&quot;95%&quot;),
            wxT(&quot;100%&quot;),
            wxT(&quot;110%&quot;),
            wxT(&quot;120%&quot;),
            wxT(&quot;150%&quot;),
            wxT(&quot;200%&quot;)};
        int n = WXSIZEOF(choices);
        m_zoomControl = new wxChoice(this, wxID_PREVIEW_ZOOM, wxDefaultPosition,
			wxSize(70,wxDefaultCoord), n, choices, 0);
        item0-&gt;Add(m_zoomControl, 0, wxALIGN_CENTRE | wxALL, 5);
        SetZoomControl(m_printPreview-&gt;GetZoom());
    }
    SetSizer(item0);
    item0-&gt;Fit(this);
}

void wxPreviewCtrlBar::OnGoto()
{
    wxPrintPreviewBase *preview = GetPrintPreview();
    long nPage=0;
    if (preview) {
        if (preview-&gt;GetMinPage() &gt; 0) {
            nPage=wxGetNumberFromUser(
                wxString::Format(&quot;Введіть номер сторінки між %d та %d:&quot;,
					preview-&gt;GetMinPage(),preview-&gt;GetMaxPage()),
                wxString::Format(&quot;%d&quot;,preview-&gt;GetCurrentPage()),
                wxT(&quot;Перейти на сторінку&quot;),
                preview-&gt;GetCurrentPage());
            if (preview-&gt;GetPrintout()-&gt;HasPage(nPage)) {
                preview-&gt;SetCurrentPage(nPage);
            }
        }
    }
}

/// wxPreviewCtrl
wxPreviewCtrl::wxPreviewCtrl(wxPrintPreviewBase* preview,
                             wxWindow* parent,
                             const wxString&amp; title,
                             const wxPoint&amp; pos,
                             const wxSize&amp; size,
                             long style,
                             const wxString&amp; name) :
    wxPreviewFrame(preview, parent, title, pos, size, style, name)
{
    m_ctrlBar = NULL;
}

void wxPreviewCtrl::Initialize()
{
#if wxUSE_STATUSBAR
    CreateStatusBar();
#endif
    CreateCanvas();
    CreateControlBar();

    m_printPreview-&gt;SetCanvas(m_previewCanvas);
    m_printPreview-&gt;SetFrame(this);

    wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );

    item0-&gt;Add(m_ctrlBar, 0, wxGROW | wxALIGN_CENTER_VERTICAL, 5);
    item0-&gt;Add(m_previewCanvas, 1, wxGROW | wxALIGN_CENTER_VERTICAL, 5);

    SetAutoLayout( true );
    SetSizer( item0 );

    m_windowDisabler = new wxWindowDisabler(this);

    Layout();

    m_printPreview-&gt;AdjustScrollbars(m_previewCanvas);
    m_previewCanvas-&gt;SetFocus();
    m_ctrlBar-&gt;SetFocus();
}

void wxPreviewCtrl::CreateControlBar()
{
    long buttons = wxPREVIEW_DEFAULT;
    if (m_printPreview-&gt;GetPrintoutForPrinting())
        buttons |= wxPREVIEW_PRINT;

    m_ctrlBar = new wxPreviewCtrlBar(m_printPreview, buttons, this, wxPoint(0,0), wxSize(400,40));
    m_ctrlBar-&gt;CreateButtons();
}

/// wxHtmlPrint
wxHtmlPrint::wxHtmlPrint(const wxString&amp; name, wxWindow* parentWindow) :
    wxHtmlEasyPrinting(name, parentWindow),
    m_sTitle(name),
    m_wParent(parentWindow)
{
}

bool wxHtmlPrint::DoPreview(wxHtmlPrintout* printout1, wxHtmlPrintout* printout2)
{
    wxPrintDialogData printDialogData(*GetPrintData());
    wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &amp;printDialogData);
    if (!preview-&gt;Ok())
    {
        delete preview;
        return false;
    }

    wxPreviewCtrl* frame = new wxPreviewCtrl(preview, m_wParent,
                                             m_sTitle + wxT(&quot; (Попередній перегляд)&quot;),
                                             wxPoint(100, 100), wxSize(650, 500));

    frame-&gt;Centre(wxBOTH);
    frame-&gt;Initialize();
    frame-&gt;Show(true);
    return true;
}
</pre>
<p>Теперь, для красивого предварительного просмотра, Вы можете использовать <strong>wxHtmlPrint</strong>. Использование аналогично его предку &#8211; <strong>wxHtmlEasyPrinting</strong>.</p>
<p><strong>Example2.cpp</strong></p>
<pre class="brush: cpp;">
#include &lt;wxHtmlPrint.h&gt;
/* ... */
 wxHtmlPrint* prn = new wxHtmlPrint(wxT(&quot;Довідник користувачів&quot;));
 prn-&gt;GetPrintData()-&gt;SetOrientation(wxLANDSCAPE);
 prn-&gt;GetPageSetupData()-&gt;SetMarginTopLeft(wxPoint(10,10));
 prn-&gt;GetPageSetupData()-&gt;SetMarginBottomRight(wxPoint(5,5));
 prn-&gt;SetFooter(sFooter);
/// Предварительный просмотр
 prn-&gt;PreviewText(sText);
 /// Печать без предварительного просмотра
 prn-&gt;PrintText(sText);
 /* ... */
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/kastomizaciya-klassa-wxhtmleasyprinting-dlya-pechati-otchetov-v-wxwidgets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Классы редактирования даты и времени в ячейках wxGrid</title>
		<link>http://wxwidgets.info/klassy-redaktirovaniya-daty-i-vremeni-v-yachejkax-wxgrid/</link>
		<comments>http://wxwidgets.info/klassy-redaktirovaniya-daty-i-vremeni-v-yachejkax-wxgrid/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 15:31:21 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Components]]></category>
		<category><![CDATA[Controls]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[wxGrid]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=12</guid>
		<description><![CDATA[Александр (sandy) Илюшенко любезно предоставил статью о создании редактора ячеек wxGrid: Данная статья посвящена внедрению в грид ячеек для редактирования дат и времени. Сам котрол для дат существует &#8211; wxDatePickerCtrl. Остается вопрос, как прикрутить его к гриду. Я позаимствовал готовый контрол, за что спасибо автору, и переделал его под свои нужды, а именно, мне нужно [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sandyhip.net.ua">Александр (sandy) Илюшенко</a> любезно предоставил статью о создании редактора ячеек wxGrid:</p>
<p>Данная статья посвящена внедрению в грид ячеек для редактирования дат и времени. Сам котрол для дат существует &#8211; <code>wxDatePickerCtrl</code>. Остается вопрос, как прикрутить его к гриду.<br />
<span id="more-12"></span><br />
Я позаимствовал <a href="http://coding.moris.org/archives/2004/04/22/wxwidgets-time-control/">готовый контрол</a>, за что спасибо автору, и переделал его под свои нужды, а именно, мне нужно было время в 24-часовом формате. Реализацию самого эдитора времени, который я назвал Бcode>wxTimeCtrl</code> я приводить в статье не буду, т.к. много текста. Но обращу Ваше внимание на то, что макрос <code>GRID_TIME_EDITOR</code>, объявленный в <code>wxTextCtrl.h</code>, нужен исключительно для использования контрола в гриде, потому, если нужно будет использовать его в ином качестве, закоментируйте строку <code>#define GRID_TIME_EDITOR</code>.<br />
<b>wxGridCell.h</b></p>
<pre class="brush: cpp;">
#pragma once
#include &lt;wx/grid.h&gt;
#include &lt;wx/generic/gridctrl.h&gt;
#include &lt;wx/datectrl.h&gt;
#include &lt;wx/dateevt.h&gt;
#include &quot;wxTimeCtrl.h&quot;

/*** Renderers ***/
/*** Date Renderer ***/
class wxGridCellDateRenderer: public wxGridCellDateTimeRenderer {
public:
    wxGridCellDateRenderer(wxString sOutFormat = wxT(&quot;%d.%m.%Y&quot;),
                           wxString sInputFormat = wxT(&quot;%Y%m%d&quot;));
};
/*** Time Renderer ***/
class wxGridCellTimeRenderer: public wxGridCellDateTimeRenderer {
public:
    wxGridCellTimeRenderer();
};

/*** Editors ***/
/*** Date Editor ***/
class wxGridCellDateEditor: public wxGridCellEditor {
    const wxString m_Format;
    wxString m_startValue;

    void SetDateValue();
    wxDatePickerCtrl* DateCtrl() const;
protected:
//    void OnDateChanged(wxDateEvent&amp; event);
    DECLARE_NO_COPY_CLASS(wxGridCellDateEditor)
public:
    wxGridCellDateEditor(const wxString&amp; format=wxT(&quot;%d.%m.%Y&quot;));
    ~wxGridCellDateEditor();

    void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);
    void PaintBackground(const wxRect&amp; rectCell, wxGridCellAttr* attr);
    void SetSize(const wxRect&amp; rectOrig);
    void BeginEdit(int row, int col, wxGrid* grid);
    bool EndEdit(int row, int col, wxGrid* grid);
    bool IsAcceptedKey(wxKeyEvent&amp; event);
    void Reset();
    wxString GetValue() const;
    wxGridCellEditor* Clone() const;
};

/*** Time Editor ***/
class wxGridCellTimeEditor: public wxGridCellEditor {
    wxString m_startValue;

    void SetTimeValue();
    wxTimeCtrl* TimeCtrl() const;
protected:
    DECLARE_NO_COPY_CLASS(wxGridCellTimeEditor)
public:
    wxGridCellTimeEditor();
    ~wxGridCellTimeEditor();

    void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);
    void PaintBackground(const wxRect&amp; rectCell, wxGridCellAttr* attr);
    void SetSize(const wxRect&amp; rectOrig);
    void BeginEdit(int row, int col, wxGrid* grid);
    bool EndEdit(int row, int col, wxGrid* grid);
    bool IsAcceptedKey(wxKeyEvent&amp; event);
    void Reset();
    wxString GetValue() const;
    wxGridCellEditor* Clone() const;
};
</pre>
<p>Теперь несколько слов о предоставленных классах:</p>
<ul>
<li><code>wxGridCellDateRenderer</code> - нужен для отображения дат, в том виде, как это нужно программисту, что определяется параметрами <code>wxString sOutFormat</code> - это формат собственно отображения даты, например, <code>wxT("%d.%m.%Y")</code>, т.е. ДД.ММ.ГГГГ, и <code>wxString sInputFormat</code> - это формат, в котором помещается в грид строка, содержащая дату</li>
<li><code>wxGridCellTimeRenderer</code> - нужен для отображения времени. Пераметров он не имеет, принимает и отображает время в формате ЧЧ:ММ:СС</li>
<li><code>wxGridCellDateEditor</code> - это редактор дат, который параметром принимает формат даты</li>
<li><code>wxGridCellTimeEditor</code> - это редактор времени</li>
</ul>
<p><b>wxGridCell.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;wxGridCell.h&quot;

/*** Renderers ***/
/*** Date Renderer ***/
wxGridCellDateRenderer::wxGridCellDateRenderer(wxString sOutFormat,
                                               wxString sInputFormat)
    : wxGridCellDateTimeRenderer(sOutFormat,sInputFormat)
{
}
/*** Time Renderer ***/
wxGridCellTimeRenderer::wxGridCellTimeRenderer()
    : wxGridCellDateTimeRenderer(wxT(&quot;%H:%M:%S&quot;),wxT(&quot;%H:%M:%S&quot;))
{
}

/*** Editors ***/
/*** Date Editor ***/
wxGridCellDateEditor::wxGridCellDateEditor(const wxString&amp; format)
    : wxGridCellEditor(),
    m_Format(format),
    m_startValue(wxT(&quot;&quot;))
{
}

wxGridCellDateEditor::~wxGridCellDateEditor()
{
    if (m_control) {
        m_control-&gt;Destroy();
        m_control = NULL;
    }
}

void wxGridCellDateEditor::Create(wxWindow* parent,
                                  wxWindowID id,
                                  wxEvtHandler* evtHandler)
{
    m_control = new wxDatePickerCtrl(parent, id,
        wxDefaultDateTime, wxDefaultPosition, wxDefaultSize,
        wxDP_SPIN | wxDP_SHOWCENTURY);
    wxGridCellEditor::Create(parent, id, evtHandler);
}

wxDatePickerCtrl* wxGridCellDateEditor::DateCtrl() const
{
    return (wxDatePickerCtrl*)m_control;
}

void wxGridCellDateEditor::PaintBackground(const wxRect&amp; rectCell,
                                           wxGridCellAttr* attr)
{
    wxGridCellEditor::PaintBackground(rectCell, attr);
}

void wxGridCellDateEditor::SetSize(const wxRect&amp; rectOrig)
{
    wxRect rect(rectOrig);
#if defined(__WXGTK__)
    if (rect.x != 0) {
        rect.x+=1;
        rect.y+=1;
        rect.width-=1;
        rect.height-=1;
    }
#elif defined(__WXMSW__)
//    rect.x-=2;
//    rect.y-=2;
//    rect.width+=2;
    rect.height+=2;
#else
    int extra_x=(rect.x&gt;2)?2:1;
    int extra_y=(rect.y&gt;2)?2:1;
    #if defined(__WXMOTIF__)
        extra_x*=2;
        extra_y*=2;
    #endif
    rect.SetLeft(wxMax(0, rect.x-extra_x));
    rect.SetTop(wxMax(0, rect.y-extra_y));
    rect.SetRight(rect.GetRight()+2*extra_x);
    rect.SetBottom(rect.GetBottom()+2*extra_y);
#endif
    wxGridCellEditor::SetSize(rect);
}

void wxGridCellDateEditor::SetDateValue()
{
    wxDateTime tmp;
    if (!tmp.ParseFormat(m_startValue.c_str(),m_Format.c_str())) {
        tmp.SetToCurrent();
    }
    DateCtrl()-&gt;SetValue(tmp);
}

void wxGridCellDateEditor::BeginEdit(int row, int col, wxGrid* grid)
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));

    m_startValue = grid-&gt;GetTable()-&gt;GetValue(row, col);
    SetDateValue();
    DateCtrl()-&gt;SetFocus();
}

bool wxGridCellDateEditor::EndEdit(int row, int col, wxGrid* grid)
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));
    bool changed = false;
    wxDateTime tmp = DateCtrl()-&gt;GetValue();
    wxString s=tmp.Format(m_Format.c_str());

    if (s != m_startValue)
        changed = true;
    if (changed)
        grid-&gt;GetTable()-&gt;SetValue(row, col, s);

    m_startValue = wxEmptyString;
    tmp.SetToCurrent();
    DateCtrl()-&gt;SetValue(tmp);

    return changed;
}

bool wxGridCellDateEditor::IsAcceptedKey(wxKeyEvent&amp; event)
{
    if (wxGridCellEditor::IsAcceptedKey(event)) {
        int keycode=event.GetKeyCode();
        if (keycode&lt;128 &amp;&amp; (wxIsdigit(keycode) || keycode=='.')) {
            return true;
        }
    }
    return false;
}

void wxGridCellDateEditor::Reset()
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));
    SetDateValue();
}

wxString wxGridCellDateEditor::GetValue() const
{
    wxDateTime tmp = DateCtrl()-&gt;GetValue();
    wxString s=tmp.Format(m_Format.c_str());
    return s;
}

wxGridCellEditor* wxGridCellDateEditor::Clone() const
{
    return new wxGridCellDateEditor(m_Format);
}

/*** Time Editor ***/
wxGridCellTimeEditor::wxGridCellTimeEditor()
    : wxGridCellEditor(),
    m_startValue(wxT(&quot;&quot;))
{
}

wxGridCellTimeEditor::~wxGridCellTimeEditor()
{
    if (m_control) {
        m_control-&gt;Destroy();
        m_control = NULL;
    }
}

void wxGridCellTimeEditor::Create(wxWindow* parent,
                                  wxWindowID id,
                                  wxEvtHandler* evtHandler)
{
    m_control = new wxTimeCtrl(parent, id);
    wxGridCellEditor::Create(parent, id, evtHandler);
}

void wxGridCellTimeEditor::PaintBackground(const wxRect&amp; rectCell,
                                           wxGridCellAttr* attr)
{
    wxGridCellEditor::PaintBackground(rectCell, attr);
}

wxTimeCtrl* wxGridCellTimeEditor::TimeCtrl() const
{
    return (wxTimeCtrl*)m_control;
}

void wxGridCellTimeEditor::SetSize(const wxRect&amp; rectOrig)
{
    wxRect rect(rectOrig);
#if defined(__WXGTK__)
    if (rect.x != 0) {
        rect.x+=1;
        rect.y+=1;
        rect.width-=1;
        rect.height-=1;
    }
#elif defined(__WXMSW__)
//    rect.x-=2;
//    rect.y-=2;
//    rect.width+=2;
    rect.height+=2;
#else
    int extra_x=(rect.x&gt;2)?2:1;
    int extra_y=(rect.y&gt;2)?2:1;
    #if defined(__WXMOTIF__)
        extra_x*=2;
        extra_y*=2;
    #endif
    rect.SetLeft(wxMax(0, rect.x-extra_x));
    rect.SetTop(wxMax(0, rect.y-extra_y));
    rect.SetRight(rect.GetRight()+2*extra_x);
    rect.SetBottom(rect.GetBottom()+2*extra_y);
#endif
    wxGridCellEditor::SetSize(rect);
}

void wxGridCellTimeEditor::SetTimeValue()
{
    wxString s=m_startValue;
    if (s.IsEmpty()) {
        s=wxTimeCtrl::GetCurrentTime();
    }
    TimeCtrl()-&gt;SetValue(s);
}

void wxGridCellTimeEditor::BeginEdit(int row, int col, wxGrid* grid)
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));

    m_startValue = grid-&gt;GetTable()-&gt;GetValue(row, col);
    SetTimeValue();
    TimeCtrl()-&gt;SetFocus();
}

bool wxGridCellTimeEditor::EndEdit(int row, int col, wxGrid* grid)
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));

    bool changed = false;
    wxString s=TimeCtrl()-&gt;GetValue();

    if (s != m_startValue)
        changed = true;
    if (changed)
        grid-&gt;GetTable()-&gt;SetValue(row, col, s);

    m_startValue = wxEmptyString;
    TimeCtrl()-&gt;SetValue(m_startValue);

    return changed;
}

bool wxGridCellTimeEditor::IsAcceptedKey(wxKeyEvent&amp; event)
{
    if (wxGridCellEditor::IsAcceptedKey(event)) {
        int keycode=event.GetKeyCode();
        if (keycode&lt;128 &amp;&amp; (wxIsdigit(keycode) || keycode=='.')) {
            return true;
        }
    }
    return false;
}

void wxGridCellTimeEditor::Reset()
{
    wxASSERT_MSG(m_control, wxT(&quot;The wxGridCellEditor must be created first!&quot;));
    SetTimeValue();
}

wxString wxGridCellTimeEditor::GetValue() const
{
    return TimeCtrl()-&gt;GetValue();
}

wxGridCellEditor* wxGridCellTimeEditor::Clone() const
{
    return new wxGridCellTimeEditor();
}
</pre>
<p>Как это все работает? Вот пример, в котором я использую wxGridCtrl из <a href="http://wxwidgets.info/change_behavior_of_wxgrid_ru">предыдущей статьи</a>.<br />
<b>Example.cpp</b></p>
<pre class="brush: cpp;">
#include &quot;wxGridCtrl.h&quot;
#include &quot;wxGridCell.h&quot;
/* ... */
    m_pGrid = new wxGridCtrl(this, IDC_CHILD_GRID);
    m_pGrid-&gt;CreateGrid(0,0);
    m_pGrid-&gt;SetRowLabelSize(20);
    m_pGrid-&gt;SetColLabelSize(20);
    m_pGrid-&gt;DisableDragRowSize();
    m_pGrid-&gt;SetDefaultCellBackgroundColour(wxColour(128,128,128));

    m_pGrid-&gt;AppendCols(3);

    wxGridCellAttr* pDateAttr = new wxGridCellAttr;
    pDateAttr-&gt;SetBackgroundColour(wxColour(255,255,255));
    pDateAttr-&gt;SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE);
    pDateAttr-&gt;SetRenderer(new wxGridCellDateRenderer());
    pDateAttr-&gt;SetEditor(new wxGridCellDateEditor(wxT(&quot;%Y%m%d&quot;)));

    wxGridCellAttr* pTimeAttr = new wxGridCellAttr;
    pTimeAttr-&gt;SetBackgroundColour(wxColour(255,255,255));
    pTimeAttr-&gt;SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE);
    pTimeAttr-&gt;SetRenderer(new wxGridCellTimeRenderer());
    pTimeAttr-&gt;SetEditor(new wxGridCellTimeEditor());

    m_pGrid-&gt;SetColLabelValue(0,wxT(&quot;DateCells&quot;));
    m_pGrid-&gt;SetColLabelValue(1,wxT(&quot;TimeCells&quot;));
    m_pGrid-&gt;SetColAttr(0,pDateAttr);
    m_pGrid-&gt;SetColAttr(1,pTimeAttr);
    m_pGrid-&gt;Refresh();
/* ... */
</pre>
<p>Вот так в результате будет выглядеть наше приложение:<br />
<img src="http://wxwidgets.info//wp-content/uploads/2008/12/custom-gridcelleditor.png" alt="Классы редактирования даты и времени в ячейках wxGrid" title="Классы редактирования даты и времени в ячейках wxGrid" width="447" height="151" class="alignnone size-full wp-image-11" /></p>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/klassy-redaktirovaniya-daty-i-vremeni-v-yachejkax-wxgrid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Переопределение поведения стандартных компонентов. Делаем свой wxGrid</title>
		<link>http://wxwidgets.info/pereopredelenie-povedeniya-standartnyx-komponentov-delaem-svoj-wxgrid/</link>
		<comments>http://wxwidgets.info/pereopredelenie-povedeniya-standartnyx-komponentov-delaem-svoj-wxgrid/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 14:14:52 +0000</pubDate>
		<dc:creator>T-Rex</dc:creator>
				<category><![CDATA[Components]]></category>
		<category><![CDATA[Controls]]></category>
		<category><![CDATA[wxWidgets]]></category>
		<category><![CDATA[wxGrid]]></category>
		<category><![CDATA[Статьи]]></category>

		<guid isPermaLink="false">http://wxwidgets.info//?p=3</guid>
		<description><![CDATA[Александр (sandy) Илюшенко любезно предоставил статью о том, как настроить класc wxGrid под свои нужды: Захотелось мне как-то, чтобы в гриде были не номера строк, а маркер. К тому же очень хотелось, чтобы незаполненное пространство грида было не белым, а, примерно, как на рисунке ниже. Навеяно это было в основном аналогичными и другими классами, предоставляемыми [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sandyhip.net.ua">Александр (sandy) Илюшенко</a> любезно предоставил статью о том, как настроить класc <code>wxGrid</code> под свои нужды:</p>
<p>Захотелось мне как-то, чтобы в гриде были не номера строк, а маркер.<br />
К тому же очень хотелось, чтобы незаполненное пространство грида было не белым, а, примерно, как на рисунке ниже.<br />
<img src="http://wxwidgets.info//wp-content/uploads/2008/12/custom-gridctrl.png" alt="Делаем собственный wxGrid" title="Делаем собственный wxGrid" width="336" height="204" class="alignnone size-full wp-image-6" /><br />
Навеяно это было в основном аналогичными и другими классами, предоставляемыми MFC. Тут же и вспомнилось, что подобные классы также прдоставляют очень полезные методы для хранения дополнительных не отображаемых данных, такие как <code>SetData()</code> или <code>GetData()</code>.<br />
<span id="more-3"></span><br />
Вначеле даже была мысль, использовать для этого <code>wxGrid::SetRowLabelValue()</code>, с учетом того, что перерисовку лэйбла я собирался переопределить. Но, покурив исходники грида, я обнаружил, что в функциях <code>bool InsertRows(int pos = 0, int numRows = 1, bool updateLabels = true)</code> и <code>bool DeleteRows(int pos = 0, int numRows = 1, bool updateLabels = true)</code>, третий аргумент не используется. А это значит, что при вставке или удалении строки у меня все посыпется. К тому же неизвестно, как в будущем этот аргумент будет использоваться.</p>
<p>Потому не нашел я ничего лучшего, как переопределить грид и снабдить его необходимыми функциями.<br />
<b>wxGridCtrl.h</b></p>
<pre class="brush: cpp;">
#pragma once
#include &lt;wx/wx.h&gt;
#include &lt;wx/grid.h&gt;
#include &lt;map&gt;

class wxGridCtrl: public wxGrid {
    std::map&lt;int,int&gt; m_mRowData;
    DECLARE_DYNAMIC_CLASS(wxGridCtrl)
protected:
    virtual void DrawRowLabel(wxDC&amp; dc, int row);
    virtual void OnLabelLeftClick(wxGridEvent&amp; event);
    virtual void OnSelectCell(wxGridEvent&amp; event);

    DECLARE_EVENT_TABLE();
public:
    wxGridCtrl();
    wxGridCtrl(wxWindow* parent, const long&amp; id);
/// Override
    bool CreateGrid(int numRows, int numCols,
                    wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
    bool AppendRows(int numRows = 1, bool updateLabels = true);
    bool InsertRows(int pos = 0, int numRows = 1, bool updateLabels = true);
    bool DeleteRows(int pos = 0, int numRows = 1, bool updateLabels = true);
/// New
    void SetRowData(const int&amp; row, const int&amp; data);
    int GetRowData(const int&amp; row);
};
</pre>
<p>Теперь, как это все реализовано:</p>
<ul>
<li><code>DrawRowLabel</code> &#8211; это функция, реализующая перерисовку лэйбла грида, а именно, рисующая маркер в лэйбле.</li>
<li><code>OnLabelLeftClick</code> &#8211; усталавливает визуальный курсор в первую колонку, выделенной строки.</li>
<li>Это понадобилось для того, чтобы маркер не оставался на предыдущей строке, когда кликаем по следующей.</li>
<li><code>OnSelectCell</code> &#8211; функция, без которой я не смог обойтись, чтобы все хорошо работало:)</li>
</ul>
<p>Несколько слов о контейнере std::map<int,int> m_mRowData:</p>
<p>Этот контейнер, имеющий ключем номер строки, и содержит значения, присваиваемые функцией <code>SetRowData</code>. И, чтобы данные соответствовали строками после создания грида, добаления, вставки и удаления записей, пришлось переопределить соответсвующие функции: <code>CreateGrid, AppendRows, InsertRows, DeleteRows</code>. Получить данные для соответствующей строки, как и сами догадываетесь, можно функцией <code>GetRowData</code>.<br />
<b>wxGridCtrl.cpp</b></p>
<pre class="brush: cpp;">

#include &quot;wxGridCtrl.h&quot;
#include &quot;cursor.xpm&quot;

IMPLEMENT_DYNAMIC_CLASS(wxGridCtrl, wxGrid);

wxGridCtrl::wxGridCtrl()
{
}

wxGridCtrl::wxGridCtrl(wxWindow* parent, const long&amp; id):
    wxGrid(parent,id,wxDefaultPosition,wxDefaultSize)
{
}

BEGIN_EVENT_TABLE(wxGridCtrl, wxGrid)
    EVT_GRID_LABEL_LEFT_CLICK(wxGridCtrl::OnLabelLeftClick)
    EVT_GRID_SELECT_CELL(wxGridCtrl::OnSelectCell)
END_EVENT_TABLE();

void wxGridCtrl::DrawRowLabel(wxDC&amp; dc, int row)
{
    if (GetRowHeight(row)&lt;=0 || m_rowLabelWidth&lt;=0)
        return;
    wxRect rect;
#ifdef __WXGTK20__
    rect.SetX(1);
    rect.SetY(GetRowTop(row)+1);
    rect.SetWidth(m_rowLabelWidth-2);
    rect.SetHeight(GetRowHeight(row)-2);
    CalcScrolledPosition(0, rect.y, NULL, &amp;rect.y);
    wxWindowDC *win_dc=(wxWindowDC*)&amp;dc;
    wxRendererNative::Get().DrawHeaderButton(win_dc-&gt;m_owner, dc, rect, 0);
#else
    int rowTop=GetRowTop(row),
        rowBottom=GetRowBottom(row)-1;
    dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID));
    dc.DrawLine(m_rowLabelWidth - 1, rowTop, m_rowLabelWidth - 1, rowBottom);
    dc.DrawLine(0, rowTop, 0, rowBottom);
    dc.DrawLine(0, rowBottom, m_rowLabelWidth, rowBottom);
    dc.SetPen(*wxWHITE_PEN);
    dc.DrawLine(1, rowTop, 1, rowBottom);
    dc.DrawLine(1, rowTop, m_rowLabelWidth - 1, rowTop);
#endif
    if (row==GetGridCursorRow()) {
        dc.DrawBitmap(wxBitmap(cursor_xpm),0,GetRowTop(row),true);
    }
}

void wxGridCtrl::OnLabelLeftClick(wxGridEvent&amp; event)
{
    if (event.GetRow() != -1) {
        SetGridCursor(event.GetRow(),0);
    }
    event.Skip();
}

void wxGridCtrl::OnSelectCell(wxGridEvent&amp; event)
{
    GetGridRowLabelWindow()-&gt;Refresh();
    event.Skip();
}

/// Override
bool wxGridCtrl::CreateGrid(int numRows, int numCols,
                            wxGrid::wxGridSelectionModes selmode)
{
    bool bCreate=wxGrid::CreateGrid(numRows,numCols,selmode);
    if (bCreate) {
        for (int i=0;i&lt;numRows;i++) {
            m_mRowData[i]=0;
        }
    }
    return bCreate;
}

bool wxGridCtrl::AppendRows(int numRows, bool updateLabels)
{
    int nRow=GetNumberRows();
    bool bAdd=wxGrid::AppendRows(numRows,updateLabels);
    if (bAdd) {
        while (nRow&lt;GetNumberRows()) {
            m_mRowData[nRow]=0;
            nRow++;
        }
    }
    return bAdd;
}

bool wxGridCtrl::InsertRows(int pos, int numRows, bool updateLabels)
{
    std::map&lt;int,int&gt; mRow;
    for (int i=0;i&lt;GetNumberRows();i++) {
        mRow[i]=GetRowData(i);
    }
    bool bIns=wxGrid::InsertRows(pos,numRows,updateLabels);
    if (bIns) {
        for (int i=pos+numRows;i&lt;GetNumberRows();i++) {
            m_mRowData[i]=mRow[i-numRows];
        }
        for (int i=pos;i&lt;pos+numRows;i++) {
            m_mRowData[i]=0;
        }
    }
    return bIns;
}

bool wxGridCtrl::DeleteRows(int pos, int numRows, bool updateLabels)
{
    std::map&lt;int,int&gt; mRow;
    for (int i=0;i&lt;GetNumberRows();i++) {
        mRow[i]=GetRowData(i);
    }
    bool bDel=wxGrid::DeleteRows(pos,numRows,updateLabels);
    if (bDel) {
        for (int i=pos;i&lt;GetNumberRows();i++) {
            m_mRowData[i]=mRow[i+numRows];
        }
    }
    return bDel;
}

/// New
void wxGridCtrl::SetRowData(const int&amp; row, const int&amp; data)
{
    if (row&lt;GetNumberRows()) {
        m_mRowData[row]=data;
    }
}

int wxGridCtrl::GetRowData(const int&amp; row)
{
    int data=0;
    if (row&lt;GetNumberRows() &amp;&amp; m_mRowData.find(row)!=m_mRowData.end()) {
        data=m_mRowData[row];
    }
    return data;
}

Что касается цветов, это я не включил в класс. Мало ли как кому нужно будет?

Пример использования примерно следующий:

Exmple.cpp

#include &quot;wxGridCtrl.h&quot;
/* ... */
    m_pGrid = new wxGridCtrl(this, wxID_ANY);
    m_pGrid-&gt;CreateGrid(0,0);
    m_pGrid-&gt;SetRowLabelSize(20);
    m_pGrid-&gt;SetColLabelSize(20);
    m_pGrid-&gt;DisableDragRowSize();
    m_pGrid-&gt;SetDefaultCellBackgroundColour(wxColour(128,128,128));

    m_pGrid-&gt;AppendCols(3);
    m_pGrid-&gt;SetColLabelValue(0,wxT(&quot;A&quot;));
    m_pGrid-&gt;SetColLabelValue(1,wxT(&quot;B&quot;));
    m_pGrid-&gt;SetColLabelValue(2,wxT(&quot;C&quot;));

    wxGridCellAttr* pAttr = new wxGridCellAttr;
    pAttr-&gt;SetBackgroundColour(wxColour(255,255,255));

    wxGridCellAttr* pAttrBool = new wxGridCellAttr;
    pAttrBool-&gt;SetBackgroundColour(wxColour(255,255,255));
    pAttrBool-&gt;SetRenderer(new wxGridCellBoolRenderer());
    pAttrBool-&gt;SetEditor(new wxGridCellBoolEditor());
    pAttrBool-&gt;SetAlignment(wxALIGN_CENTRE,wxALIGN_CENTRE);

    m_pGrid-&gt;SetColAttr(0,pAttr);
    m_pGrid-&gt;SetColAttr(1,pAttr);
    m_pGrid-&gt;SetColAttr(2,pAttrBool);
/* ... */
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wxwidgets.info/pereopredelenie-povedeniya-standartnyx-komponentov-delaem-svoj-wxgrid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
