<?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>pamiętnik programisty &#187; C++</title>
	<atom:link href="http://piotr.doniec.eu/devlog/category/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Wed, 28 Dec 2011 23:52:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Małoznany modyfikator [ dla scanf</title>
		<link>http://piotr.doniec.eu/devlog/2011/10/maloznany-modyfikator-dla-scanf/</link>
		<comments>http://piotr.doniec.eu/devlog/2011/10/maloznany-modyfikator-dla-scanf/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 09:32:15 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=617</guid>
		<description><![CDATA[Funkcja scanf z biblioteki standardowej C umożliwia odczyt i parsowanie danych z stdin zgodnie z określonym formatem. Większość modyfikatorów jest opisana na stronie cppreference, która nomen omen pojawia się jako pierwsza po wpisaniu &#8222;scanf&#8221; w wyszukiwarce. Jak się jednak okazuje nie są to wszystkie dostępne modyfikatory. Brakuje jednego istotnego, który umożliwia np. czytanie standardowego wejścia [...]]]></description>
			<content:encoded><![CDATA[<p>Funkcja scanf z biblioteki standardowej C umożliwia odczyt i parsowanie danych z stdin zgodnie z określonym formatem. Większość modyfikatorów jest opisana na <a href="http://www.cplusplus.com/reference/clibrary/cstdio/scanf/">stronie cppreference</a>, która nomen omen pojawia się jako pierwsza po wpisaniu &#8222;scanf&#8221; w wyszukiwarce. Jak się jednak okazuje nie są to wszystkie dostępne modyfikatory. Brakuje jednego istotnego, który umożliwia np. czytanie standardowego wejścia póki składa się z prawidłowych/dozwolonych znaków &#8211; tym modyfikatorem jest &#8222;[ ]&#8222;. W nawiasach należy umieścić wszystkie znaki które sanf może odczytać. W przypadku napotkania znaku niewystępującego w zbiorze, scanf zaprzestaje dalszego działania.<br />
Możliwe jest również zdefiniowanie zakresu poprzez wykluczenie niektórych znaków, do tego celu należy użyć &#8222;^&#8221;. Dzięki temu przy wykorzystaniu scanf można odczytać całe zdanie ignorując białe znaki za wyjątkiem znaku końca linii:</p>
<pre class="brush: cpp">
char str[512];
scanf(&quot; [^\n]&quot;, &amp;str);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2011/10/maloznany-modyfikator-dla-scanf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Methods for getting root access on Android phone</title>
		<link>http://piotr.doniec.eu/devlog/2011/04/methods-for-getting-root-access-on-android-phone/</link>
		<comments>http://piotr.doniec.eu/devlog/2011/04/methods-for-getting-root-access-on-android-phone/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 13:43:41 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=611</guid>
		<description><![CDATA[Recently I got more interested in Android platform. I was wondering what are methods to obtain &#8222;root&#8221; rights. After few minutes of googling I found two possible solutions. First method make use of udev bug. Basically this service does not check source of message, so it is possible to run code on behalf of root [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I got more interested in Android platform. I was wondering what are methods to obtain &#8222;root&#8221; rights. After few minutes of googling I found two possible solutions.<br />
First method make use of udev bug. Basically this service does not check source of message, so it is possible to run code on behalf of root user. Second method is a bit more sophisticated in my opinion. It purpose is to block adb from dropping root privileges to normal user. It is done by creating maximum number of processes and then restarting adb.<br />
More detailed information an sample code can be found here: http://intrepidusgroup.com/insight/2010/09/android-root-source-code-looking-at-the-c-skills/</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2011/04/methods-for-getting-root-access-on-android-phone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problem with timestamps in libnetfilter_queue solved</title>
		<link>http://piotr.doniec.eu/devlog/2010/12/problem-with-timestamps-in-libnetfilter_queue-solved/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/12/problem-with-timestamps-in-libnetfilter_queue-solved/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 21:45:09 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[issue]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[solution]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=561</guid>
		<description><![CDATA[My BSc Thesis is to implement steganography algorithm that use VoIP packets as a transport. The main aim is to modify delay of RTP packets without noticeable impact on transmission quality. I create hidden channel by sending two packets that average delay is 20ms. For example if we send 1 packet 10ms after previous and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/12/netfilter-logo2.png"><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/12/netfilter-logo2.png" alt="" title="netfilter-logo2" width="265" height="72" class="alignleft size-full wp-image-576" /></a>My BSc Thesis is to implement steganography algorithm that use VoIP packets as a transport. The main aim is to modify delay of RTP packets without noticeable impact on transmission quality. I create hidden channel by sending two packets that average delay is 20ms. For example if we send 1 packet 10ms after previous and second 30ms after first the average delay is 20ms. Calling parties will not notice so small difference, but software should recognize such situation as sending the bit with value 1. When we want to send bit 0 we can just switch delays, then first packet will be sent after 30ms and another 10ms later. The time the packet was received is very important for Receiver. The network can add a random delay but Receiver should still be able to collect all sent bits.<br />
For implementation I used libnetfilter_queue and iptables. This two powerful tools are more than enough for my need. Everything was fine until and got to point where I had to read packet delay. Although libnetfilter_queue provide function for reading timestamp when packet was queued (nfq_get_timestamp) it&#8217;s not working without additional tweaks. For kernel performance reason timestamping network packets is by default disabled. After digging through kernel source I found functions responsible from toggling this setting, it&#8217;s a net_enable_timestamp() and net_disable_timestamp(). I had no idea how to execute each of them but MarkR from stackoverflow.org helped me. There is no need to enable timestamping globally for all packets instead it can be enabled for particular socket by using setsockopt. The call sequence is then setsockopt() -> sock_setsockopt() -> sock_enable_timestamp(&#8230;) -> net_enable_timestamp(). It is possible to get file descriptor connected with particular queue and treat it as it would be socket. This means that following code is valid and can be used to enable timestamping incoming packets:</p>
<pre class="brush: cpp">
int ena = 1;
if( setsockopt(queuefd, SOL_SOCKET, SO_TIMESTAMP, &amp;ena, sizeof(ena)) )
{
    SYS_LOG(E_WARNING, &quot;Unable to enable timestamping&quot;);
}
</pre>
<p>and then in queue handle function:</p>
<pre class="brush: cpp">
int handle_queue(struct nfq_q_handle *pQh, struct nfgenmsg *pNfmsg, struct nfq_data *pNfa, void *pData)
{
    struct nfqnl_msg_packet_hdr *ph;
    struct timeval tv;
    int id;

    ph = nfq_get_msg_packet_hdr(pNfa);
    if(ph)
    {
        id = ntohl(ph-&gt;packet_id);
    }

    nfq_get_timestamp(pNfa, &amp;tv);
    /* do sth. with read timestamp */

    return nfq_set_verdict(pQh, id, NF_ACCEPT, 0, NULL);
}
</pre>
<p>This is a solution for a issue, that as far as i know, have not been solved since this post:<br />
&#8222;So far the biggest issues I&#8217;ve run into are that marking doesn&#8217;t work in 2.6.15 (I think it should in 2.6.16), and I can&#8217;t seem to ever read the timestamp for a packet, no matter  hat hook it comes in on.  I&#8217;ve just been using gettimeofday for that for now.&#8221;<br />
<a href="http://lists.netfilter.org/pipermail/netfilter-devel/2006-February/023490.html">http://lists.netfilter.org/pipermail/netfilter-devel/2006-February/023490.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/12/problem-with-timestamps-in-libnetfilter_queue-solved/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka nr 5</title>
		<link>http://piotr.doniec.eu/devlog/2010/08/z-c-zagadka-nr-5/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/08/z-c-zagadka-nr-5/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 20:22:26 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=549</guid>
		<description><![CDATA[Wrednie podchwytliwe zadanie czasami w tej czy innej postaci spotykane na różnych testach ze znajomości języka. Jaki będzie efekt wykonania poniższego programu: #include &#60;iostream&#62; int foo(int x, int y) { return x + y; } int main() { int z, k; z = 10; k = foo(z = 20, z += 1); std::cout &#60;&#60; k [...]]]></description>
			<content:encoded><![CDATA[<p>Wrednie podchwytliwe zadanie czasami w tej czy innej postaci spotykane na różnych testach ze znajomości języka.<br />
Jaki będzie efekt wykonania poniższego programu:</p>
<pre class="brush: cpp">
#include &lt;iostream&gt;

int foo(int x, int y)
{
    return x + y;
}

int main()
{
    int z, k;
    z = 10;
    k = foo(z = 20, z += 1);
    std::cout &lt;&lt; k &lt;&lt; std::endl;
}
</pre>
<p>Najłatwiej zweryfikować korzystając z kompilatora. Na rozważanie przyczyna takie czy innego wyniku nie warto poświęcać zbyt wiele czasu, ponieważ dodanie flagi -Wall rozwiewa wszystkie wątpliwości:</p>
<blockquote><p>
zadanie.cpp: In function &#8216;int main()&#8217;:<br />
zadanie.cpp:14: warning: operation on &#8216;z&#8217; may be undefined
</p></blockquote>
<p>Zatem poprawna odpowiedź na pytanie: &#8222;to zależy od kompilatora, sprzętu, systemu&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/08/z-c-zagadka-nr-5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka nr 4</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:50:24 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[common error]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=532</guid>
		<description><![CDATA[Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem: class Foo { public: methodA() { printf(&#34;Wykonano...\n&#34;); } } struct data_t { int i_; Foo* obj_; } std::list&#60;data_t*&#62; data_; for(std::list&#60;data_t*&#62;::iterator i = data_.begin(); i != data_.end(); i++ ) { // operacje } W jaki sposób wykonać [...]]]></description>
			<content:encoded><![CDATA[<p>Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem:</p>
<pre class="brush: cpp">
class Foo {
public:
  methodA() {
    printf(&quot;Wykonano...\n&quot;);
  }
}

struct data_t {
  int i_;
  Foo* obj_;
}

std::list&lt;data_t*&gt; data_;

for(std::list&lt;data_t*&gt;::iterator i  = data_.begin(); i != data_.end(); i++ ) {
   // operacje
}
</pre>
<p>W jaki sposób wykonać blok operacji ? Możliwości mamy kilka:</p>
<pre class="brush: cpp">
/* 1 */ i-&gt;obj_-&gt;methodA();
/* 2 */ *i-&gt;obj_-&gt;methodA();
/* 3 */ (*i)-&gt;obj_-&gt;methodA();
</pre>
<p>Rozwiązanie zagadki jest proste, ale wymaga znajomości priorytetów operatorów. Pierwsze wywołania jest całkowicie błędne, ponieważ lista przecowuje wskaźniki do strkutury, a nie samą strukturę. Zatem należy najpier wyłuskać strukturę znajdującą się pod wskazywanym adresem i dopiero wtedy wykonać metodę. Okazuje się że rowiązania 2 również jest nie poprawne, właśnie ze względu na priorytety operatorów. Dopiero numer 3 daje zamierzony efekt. Na szczęście błąd ujawnia się na etapie kompilacji&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uruchamianie metod klas w nowych wątkach w c++ i pthreads</title>
		<link>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 10:47:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[pthreads]]></category>
		<category><![CDATA[qnx]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[wielowątkowość]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=471</guid>
		<description><![CDATA[Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/04/logo.gif" alt="qnx_rtos" title="qnx_rtos" width="106" height="45" class="alignright size-full wp-image-483" />Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale po kolei&#8230;<br />
<span id="more-471"></span><br />
Każdy kto programował w C++ korzystając z biblioteki Boost::Threads napewno wie że aby uruchomić metodę obiektu w nowym wątku wystarczy przeciążyć operator () i każdy obiekt takiej klasy zaczyna z powodzeniem udawać funkcję. Dzięki temu można taki obiekt przekazać do konstruktora boost::thread. Poniższy przykład obrazuje taką sposób działania:</p>
<pre class="brush: cpp">
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided &quot;as is&quot; without express or implied warranty.

#include &lt;boost/thread/thread.hpp&gt;;
#include &lt;;boost/thread/xtime.hpp&gt;;
#include &lt;iostream&gt;;

struct thread_alarm
{
    thread_alarm(int secs) : m_secs(secs) { }
    void operator()()
    {
        boost::xtime xt;
        boost::xtime_get(&amp;xt, boost::TIME_UTC);
        xt.sec += m_secs;

        boost::thread::sleep(xt);

        std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl;
    }

    int m_secs;
};

int main(int argc, char* argv[])
{
    int secs = 5;
    std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl;
    thread_alarm alarm(secs);
    boost::thread thrd(alarm);
    thrd.join();
}
</pre>
<p>Jednak ten sposób nie działa w przypadku korzystania z natywnego mechanizmu wielowątkowości dostępnego w każdym systemie *nix. Biblioteka pthreads nie radzi sobie z wywołaniem przeciążonego operatora (). Problem trzeba było rozwiązać jak najszybciej, żeby projekt mógł ruszy dalej. Dlatego powstał ten sprytny &#8222;work-around&#8221; umożliwiający uruchomienie dowolnej metody obiektu w nowym wątku. Jest to właściwie funkcja proxy, takie proste a ułatwia życie:</p>
<pre class="brush: cpp">
template&lt;class T&gt;
struct ThreadParams
{
	T *obj;
	void *params;
};

template&lt;class T, void* (T::*method)(void*)&gt;
void* run_thread(void *params)
{
	ThreadParams&lt;T&gt; *t = static_cast&lt;ThreadParams&gt;&lt;T*&gt;(params);
	T* obj = static_cast&lt;T*&gt;(t-&gt;obj);
	(obj-&gt;*method)(t-&gt;params);
	return NULL;
}
</pre>
<p>Dodatkowy wkład pracy jaki należy włożyć aby wykorzystać powyższy kod ogranicza się właściwie tylko do wypełnienia struktury ThreadParams:</p>
<pre class="brush: cpp">
class Test
{
public:
	void* fun(void* params) {
	printf(&quot;Hello World! \n&quot;);
	printf(&quot;Params: %d\n&quot;, reinterpret_cast&lt;int&gt;(params));
	pthread_exit(NULL);
	}
 };

 int main() {

	pthread_t tid;
	void* status;
	Test test;
	ThreadParams&lt;Test&gt; params;

	params.obj = &amp;test;
	params.params = reinterpret_cast&lt;void&gt;(123);

	pthread_create(&amp;tid, NULL, run_thread&lt;Test, &amp;Test::fun&gt;, (void*)(&amp;params));
	pthread_join(tid, &amp;status);
 }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scons &#8211; alternatywa dla Make, Qmake i podobnych</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 12:35:20 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=404</guid>
		<description><![CDATA[Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować. Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual [...]]]></description>
			<content:encoded><![CDATA[<p>Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować.<br />
Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual C++ Compiler, można zadecydować który z nich ma zostać użyty.<br />
Najprostszy plik z instrukcją zdudowania programu to 1 linia:</p>
<pre class="brush: python">
Program(&#039;main.cpp&#039;)
</pre>
<p>Na Windows domyślnie zostanie wykorzystany (o ile dostępny) kompilator Microsoftu. Jeśli jednak chcemy użyć g++, wystarczy dopisać jeszcze jedną linię:</p>
<pre class="brush: python">
env = Environment(tools = [&#039;mingw&#039;], CC = &#039;gcc&#039;, CCFLAGS = &#039;-O2&#039;)
env.Program(&#039;main.cpp&#039;)
</pre>
<p>Piewsze lody przełamane, kolejne próby będą sprawdzały łatwość dołączania zewnętrzych bibliotek jak boost czy qt.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Przezroczyste okienka z WinAPI</title>
		<link>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 12:24:08 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[winapi]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=270</guid>
		<description><![CDATA[Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-339 alignleft" title="transparent_windows2" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2009/10/transparent_windows21.jpg" alt="Przezroczyste okna z winAPI" width="244" height="220" />Wraz z pojawieniem się systemu Windows 2000, pojawiły się nowe funkcje systemowego API. Jedną z nich jest możliwość tworzenia okien o dowolnym stopniu przezroczystości. Efekt jest dość ciekawy i sporo programów ma możliwość ustawienia przezroczystości własnego okienka. Moim celem było umożliwienie sterowania przezroczystością okien centralnie z jednego programu i to nie zależnie od tego czy okno takie zostało do tego przystosowane czy też nie. Po przeczytaniu tego wpisu, każdy samodzielnie będzie mógł napisać podobną aplikację</p>
<p><span id="more-270"></span></p>
<p>Aby istniała możliwość ustawiania przezroczystości dla okna, musi być ono utworzone w sposób do tego przystosowany. Wystarczy skorzystać z innej funkcji tworzącej okno, nie <code>CreateWindow</code>, a <code>CreateWindowEx</code><br />
[cc lang="c"]<br />
HWND CreateWindowEx(<br />
  DWORD dwExStyle,<br />
  LPCTSTR lpClassName,<br />
  LPCTSTR lpWindowName,<br />
  DWORD dwStyle,<br />
  int x,<br />
  int y,<br />
  int nWidth,<br />
  int nHeight,<br />
  HWND hWndParent,<br />
  HMENU hMenu,<br />
  HINSTANCE hInstance,<br />
  LPVOID lpParam<br />
);<br />
[/cc]<br />
To co umożliwia później modyfikacje przezroczystości jest ukryte w ramach dodatkowego stylu okna, podawanego poprzez argument <code>dwExStyle</code>. Lista dopuszczalnych wartości jest długa, ale warto się z nią zapoznać. W tym konkretnym przypadku należy zainteresować się wartością <code>WS_EX_LAYERED</code>, utworzone wtedy okno będzie tzw. Layered Window, które obsługuje modyfikacje przezroczystości. Do ustawienia nowej wartości kanału alpha służy <code>SetLayeredWindowAttributes(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWROD dwFlags)</code> &#8211; szczegóły w dokumentacji.<br />
Pełny kod tworzący przykładowe, półprzezroczyste okno:<br />
[cc lang="c"]<br />
#include <windows.h></p>
<p>LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);</p>
<p>int WINAPI WinMain(HINSTANCE hInstance,	HINSTANCE hPrevInstance,<br />
LPSTR lpCmdLine, int nCmdShow)<br />
{<br />
  MSG msg;<br />
  HWND hwnd;<br />
  WNDCLASSEX wcx;</p>
<p>  wcx.cbSize = sizeof(wcx);<br />
  wcx.style = CS_HREDRAW | CS_VREDRAW;<br />
  wcx.lpfnWndProc = WndProc;<br />
  wcx.cbClsExtra = 0;<br />
  wcx.cbWndExtra = 0;<br />
  wcx.hInstance = hInstance;<br />
  wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);<br />
  wcx.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
  wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);<br />
  wcx.lpszMenuName = (LPCSTR)&#8221;MainMenu&#8221;;<br />
  wcx.lpszClassName = (LPCSTR)&#8221;MainWClass&#8221;;<br />
  wcx.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(5), IMAGE_ICON,<br />
  GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), (UINT)LR_DEFAULTCOLOR);</p>
<p>  RegisterClassEx(&#038;wcx);</p>
<p>  hwnd = CreateWindowEx(WS_EX_LAYERED, (LPCSTR)&#8221;MainWClass&#8221;, (LPCSTR)&#8221;Sample&#8221;, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL,  (HMENU)NULL, hInstance, (LPVOID) NULL);</p>
<p>  ShowWindow(hwnd, nCmdShow);<br />
  SetLayeredWindowAttributes(hwnd, 0, 180, LWA_ALPHA);<br />
  UpdateWindow(hwnd);</p>
<p>  while(GetMessage(&#038;msg, NULL,  0, 0))<br />
  {<br />
    TranslateMessage(&#038;msg);<br />
    DispatchMessage(&#038;msg);<br />
  }</p>
<p>  return msg.wParam;<br />
}</p>
<p>LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)<br />
{<br />
  switch(uMsg)<br />
  {<br />
    case WM_CREATE:<br />
      return 0;</p>
<p>    case WM_PAINT:<br />
      return 0;</p>
<p>    case WM_DESTROY:<br />
      PostQuitMessage(0);<br />
      return 0;</p>
<p>    default:<br />
      return DefWindowProc(hwnd, uMsg, wParam, lParam);<br />
  }<br />
  return 0;<br />
}<br />
[/cc]</p>
<p>To co należy zrobić, aby kontrolować przezroczystość okien innych niż własne przedstawia się następująco:</p>
<ol>
<li>1. Pobrać wszystkie otwarte okna typu top-level</li>
<li>2. Nadać oknom styl <code>dwExStyle</code></li>
<li>3. Zmienić wartość kanału alpha</li>
</ol>
<p><strong>1. Pobrać wszystkie otwarte okna typu top-level</strong><br />
Dobrym pomysłem wydaje się pobranie uchwytu do rodzica wszystkich okien(Desktop/Pulpit) i przejście w pętli po liście jego dzieci (jak wiadomo każde okno ma kilka przydatnych wskaźników, między innymi do okna-brata). Mogłoby to wyglądać tak:<br />
[cc lang="c"]<br />
HWND hDesktop = GetDesktopWindow();<br />
HWND hChild = GetWindow(hDesktop, GW_CHILD);<br />
HWND hTemp;<br />
/* &#8230; */<br />
while(hTemp != GetWindow(hChild, GW_HWNDLAST))<br />
{<br />
  /* &#8230; */<br />
  hTemp = GetWindow(hChild, GW_HWNDNEXT);<br />
}<br />
[/cc]<br />
Pomysł <strong>zły</strong> ! Okazuje się że taka pętla może działać w nieskończoność. Wzmianaka na temat takiego przypadku znajduje się nawet w dokumentacji. Dlatego należy wykorzystać inny sposób, polegający na użyciu funkcji <code>BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)</code>:<br />
[cc lang="c"]<br />
EnumWindows(EnumWindowsProc, NULL);<br />
/* &#8230; */<br />
BOOL CALLBACK EnumWindowsProc(HWND hwndChild, LPARAM lParam)<br />
{<br />
  char buffer[100];</p>
<p>  int count = GetWindowText(hwndChild, buffer, 100);<br />
  if(count &#038;&#038; IsWindowVisible(hwndChild))<br />
  {<br />
    /* &#8230; */<br />
  }<br />
  return TRUE;<br />
}<br />
[/cc]</p>
<p><strong>2. Nadać oknom styl <code>dwExStyle</code></strong><br />
Wydaje się najtrudniejsze, przecież dodatkowy styl należy podać przy tworzeniu okna, a okna które widzimy zostały już przecież utworzone. Na szczęście z pomocą przychodzi funkcja <code>LONG SetWindowLong(HWND hWnd, int iIndex, LONG dwNewLong)</code>:<br />
[cc lang="c"]<br />
SetWindowLong(hwndChild, GWL_EXSTYLE, WS_EX_LAYERED);<br />
[/cc]</p>
<p><strong>3. Zmienić wartość kanału alpha</strong><br />
Bardziej uważni czytelnicy już na pewno wiedzą jak wygląda zestaw parametrów i jak skorzystać z <code>SetLayeredWindowAttributes</code>. Wykorzystanie pokazane 3 listingi wyżej, przy okazji tworzenia &#8222;własnego&#8221; przezroczystego okna.</p>
<p>I to tyle  tym temacie, wypada jeszcze stworzyć GUI, może obsługę tray&#8217;a. Program wydaje się &#8222;magiczny&#8221; a korzysta raptem z 4 funkcji API systemowego.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/10/przezroczyste-okienka-z-winapi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Magiczne delete []</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 18:09:35 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=209</guid>
		<description><![CDATA[Prawdopodobnie nikt się nie zastanawiał jak dokładnie działa delete [], wystarczy wiedzieć że usuwa wszystkie obiekty umieszczone w dynamicznie zaalokowanej tablicy. Jeżeli obiekty posiadają destruktor to jest on uruchamiany, a jeśli nie to pamięć jest po prostu zwalniana. Muszę przyznać że mnie samemu też nigdy nie przyszło na myśl że może się tam kryć coś [...]]]></description>
			<content:encoded><![CDATA[<p>Prawdopodobnie nikt się nie zastanawiał jak dokładnie działa <code>delete []</code>, wystarczy wiedzieć że usuwa wszystkie obiekty umieszczone w dynamicznie zaalokowanej tablicy. Jeżeli obiekty posiadają destruktor to jest on uruchamiany, a jeśli nie to pamięć jest po prostu zwalniana. Muszę przyznać że mnie samemu też nigdy nie przyszło na myśl że może się tam kryć coś &#8222;magicznego&#8221;. Trawało to do czasu aż zupełnie przypadkiem trafiłem na wpis na blogu który opisuje SKĄD DELETE [] WIE ILE OBIEKTÓW NALEŻY USUNĄĆ.<br />
Nie będę kopiował cudzego wpisy/odkrycia jedynie po przetłumaczeniu na język ojczysty więc odsyłam do źródła oraz zachęcam do lektury (tytuł dodatkowo mówi sam za siebie): <a href="http://mdzahidh.wordpress.com/2007/08/24/a-little-cc-recipe-you-can-live-without-knowing/">http://mdzahidh.wordpress.com/2007/08/24/a-little-cc-recipe-you-can-live-without-knowing/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/magiczne-delete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka nr 3</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 23:40:33 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=197</guid>
		<description><![CDATA[Kompilator zrobi dokładnie to co chcesz. DOKŁADNIE! i właśnie dlatego trzeba uważać. Ta zagadka jak i pozostałe ma na celu zwrócenie uwagi na miejsca które wydają się oczywiste a moga wprowadzić wiele zamieszania i niepotrzebnych nerwów. W końcu nie od dziś wiadomo że najgroźniejsze błędy znajdują się w &#8222;kodzie który napewno jest dobrze&#8221;. Tym razem [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Kompilator zrobi dokładnie to co chcesz. DOKŁADNIE!</p></blockquote>
<p> i właśnie dlatego trzeba uważać. Ta zagadka jak i pozostałe ma na celu zwrócenie uwagi na miejsca które wydają się oczywiste a moga wprowadzić wiele zamieszania i niepotrzebnych nerwów. W końcu nie od dziś wiadomo że najgroźniejsze błędy znajdują się w &#8222;kodzie który napewno jest dobrze&#8221;. Tym razem zagadka wymaga trochę więcej od czytelnika, nie wystarczy znajmość C++, trzeba się jeszcze wykazać odrobiną znajomości biblioteki boost. <span id="more-197"></span><br />
Na problem oczywiście musiałem trafić na klika godzin przed oddaniem projektu, była godzina 5:14 i nie trudno zgadnąć że odchodził istny eXtreme programming &#8211; programowanie gry sieciowej &#8211; 2 osoby &#8211; 24h. Dojście do tego co jest źle zajęło dobrą godzinę&#8230;<br />
Poniższy kod przdstawia 4 najprostsze możliwe przypadki użycia boost::bind w połączeniu z boost::signal, nie różnią się między sobą bardzo:</p>
<pre class="brush: cpp">
#include &lt;boost/signal.hpp&gt;
#include &lt;boost/bind.hpp&gt;

#include &lt;iostream&gt;	

class Test
{
public:
  Test(int x) : x_(x)
  {}

  void metoda1(int i);

  int x_;
};

void Test::metoda1(int i)
{
  x_ += i;
}

int main()
{
  typedef boost::signal&lt;void (int)&gt; event_sig;
  event_sig signal;

  Test* t1 = new Test(0);
  Test* t2 = new Test(0);
  Test t3(0);
  Test t4(0);

  signal.connect(boost::bind(&amp;Test::metoda1, *t1, _1));
  signal.connect(boost::bind(&amp;Test::metoda1,  t2, _1));
  signal.connect(boost::bind(&amp;Test::metoda1, &amp;t3, _1));
  signal.connect(boost::bind(&amp;Test::metoda1,  t4, _1));

  for(int i = 0; i &lt; 10; ++i)
  {
    signal(1);
  }

  std::cout &lt;&lt; &quot;t1::x = &quot; &lt;&lt; t1-&gt;x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t2::x = &quot; &lt;&lt; t2-&gt;x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t3::x = &quot; &lt;&lt; t3.x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;t4::x = &quot; &lt;&lt; t4.x_ &lt;&lt; std::endl;
  std::cout &lt;&lt; &quot;Powinno(?) byc 10&quot; &lt;&lt; std::endl;
}
</pre>
<p>Mogło by się wydawać że w wyniku, na ekran zostanie wypisana 4 razy liczba 10. Ci bardziej podejrzliwi zaczną się zastanawiać, jaki wpływ mogą mieć te &#8222;dodatkowe&#8221; symbole dostawione wewnątrz boost::bind. Okazuje się że w przypadkach 1 i 4 ( t1 i t4 ), mimo wysyłania sygnału, wartość pola x_ nie ulega zmianie, natomiast w pozostałych ulega. Dlaczego ?<br />
Rozwiązanie tego problemu jest bardo proste, otóż tworząc binda, biblioteka boost w zależności od sposobu przekazania obiektu na rzecz którego zostanie wywołana metoda, utworzy jego kopię (internal copy) lub będzie operować na przekazanym obiekcie.<br />
Niby proste, ale trzeba mieć świadomość o istnieniu takiego mechanizmu. Nie trudno się &#8222;przejechać&#8221; na złym przekazaniu obiektu, a tu nie będzie sugestywnego &#8222;segmentation fault&#8221;&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

