<?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; tricky</title>
	<atom:link href="http://piotr.doniec.eu/devlog/tag/tricky/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Sun, 25 Jul 2010 12:54:10 +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>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>SOAP w Pythonie</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:13:44 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=396</guid>
		<description><![CDATA[Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-400" title="soap_python" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/01/soap_python-300x227.jpg" alt="soap_python" width="210" height="159" />Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez twórców, ale w wyniku tzw. forków w miarę często pojawiają się nowe wersje. Niestety był to błąd.<br />
<span id="more-396"></span><br />
Nowe wersje od niezależnych twórców charakteryzują się większą bądź mniejszą ilością błędów. Najlepszą wersją okazała się wersja <strong>cuker soaplib</strong>, nie spełniała tylko 1 wymogu &#8211; generowania jakiegokolwiek kodu na podstawie WSDL. Jest to pewne nadużycie z mojej strony, biblioteka dostarczyła skrypt o nazwie wsdl2py, ale potrafił on poprawnie sparsować i zinterpretować plik wsdl utworzony tylko przez soaplib, co trzeba przyznać jest lekką &#8222;kichą&#8221;. Szkoda, biblioteka aktywnie rozwijana, wiązałem z nią spore nadzieje &#8211; odpadła.<br />
<strong>Suds</strong> to druga biblioteka związana z SOAP, aktywnie rozwijana, chwalona za łatwość korzystania, niestety przykłady dotyczą tylko tworzenia klinetów, serwerów poprostu tworzyć się nie da? W połączeniu z soaplib mogł by to być całkiem ciekawy duet.<br />
Biblioteka webserwisów dla Pythona <strong>ZSI</strong>,  w założeniu ma umożliwiać tworzenie i korzystanie z różnych webserviców, niestety projekt został porzucony w 2007 roku. Ale mimo to miłe zaskoczenie, dostarczane skrypty wsdl2py i wsdl2dispatch bez problemu radzą sobie z przykładowy wsdl dostępnymi w internecie. Tworzone są 3 pliki które potem można wykorzystać do implementacji serwera i klienta. Jednakże żeby nie było zbyt miło, serwer dostarczony z biblioteką jest jedno wątkowy. Jeśli operacje obsługi żądania jednego klienta są czasochłonne, to na ten czas serwer nie odpowiada na żądania innych klientów. Fatalna sprawa, ale! światełko w tunelu, ZSI można połączyć z Apache&#8217;m poprzez wykorzystanie mod_python ( oczywiście nie mogło być wersji dla python 2.6, na szczęście VS poradziło sobie z kompilacją ). Kolejna ślepa uliczka &#8211; jak bym tworzył stronę WWW. Przychodzi żądanie tworzone są wszystkie klasy a po zakończeniu obsługi usuwane &#8211; nie tak sobie wyobrażałem mój system rozproszony, zamiast w Pythonie mógłbym go napisać w PHP (sic!). Powrót do ZSI i eureka, ktoś bardziej doświadczony w tym języku dopisał kilka linii kodu do źródła i serwer stał się wielowątkowy! Połączenie idealne, wielowątkowość obsługi żądań, nie niszczenie wszystkiego po zakończeniu obsługi, możliwośc wypisywania komunikatów na ekran konsoli.<br />
Źródło rozwiązania: http://osdir.com/ml/python.pywebsvcs.general/2008-06/msg00019.html . Autor wykorzystał co prawda ZSI-2.1-a1, ale poprawka działa również na ostatniej stabilnej wersji ZSI-2.0</p>
<p>Na wszelki, skopiowany kod poprawki poniżej:</p>
<blockquote><p>&#8212; ZSI-2.1-a1/ZSI/ServiceContainer.py 2007-08-08 00:56:37.000000000 +0200<br />
+++ ServiceContainer.py 2008-06-19 13:50:11.000000000 +0200<br />
@@ -5,6 +5,7 @@</p>
<p>import urlparse, types, os, sys, cStringIO as StringIO, thread,re<br />
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer<br />
+from SocketServer import ThreadingMixIn<br />
from ZSI import ParseException, FaultFromException,<br />
FaultFromZSIException, Fault<br />
from ZSI import _copyright, _seqtypes, _get_element_nsuri_name, resolvers<br />
from ZSI import _get_idstr<br />
@@ -30,6 +31,7 @@<br />
SimpleWSResource<br />
SOAPRequestHandler<br />
ServiceContainer<br />
+ ThreadedServiceContainer<br />
&#8222;&#8221;"<br />
class NoSuchService(Exception): pass<br />
class UnknownRequestException(Exception): pass<br />
@@ -141,12 +143,16 @@<br />
return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)</p>
<p>-def AsServer(port=80, services=()):<br />
+def AsServer(port=80, services=(), threaded=False):<br />
&#8221;&#8217;port &#8211;<br />
services &#8212; list of service instances<br />
+ threaded &#8212; in modo multithread ?<br />
&#8221;&#8217;<br />
address = (&#8221;, port)<br />
- sc = ServiceContainer(address, services)<br />
+ if threaded:<br />
+ sc = ThreadedServiceContainer(address, services)<br />
+ else:<br />
+ sc = ServiceContainer(address, services)<br />
sc.serve_forever()</p>
<p>@@ -467,6 +473,11 @@<br />
def removeNode(self, url):<br />
self._nodes.removeNode(url)</p>
<p>+class ThreadedServiceContainer(ThreadingMixIn, ServiceContainer):<br />
+ &#8221;&#8217;Multithreaded version of ServiceContainer.<br />
+ &#8221;&#8217;<br />
+ pass<br />
+</p>
<p>class SimpleWSResource(ServiceSOAPBinding):</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HSSPOJ &#8211; zadanie które nie dawało mi spokoju</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 19:37:11 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Algorytmika]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[spoj]]></category>
		<category><![CDATA[teoria gier]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[twierdzenie Sprague-Grundy'ego]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=381</guid>
		<description><![CDATA[Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na]]></description>
			<content:encoded><![CDATA[<p>Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na niczym. Co dodatkowo rozbudziło moją ciekawość to fakt że na forach poświęconych programowaniu, nikt nie szuka pomocy.<br />
Zadanie finalnie okazało się rozbudowaną grą Nim, ale bez znajomości jednego twierdzenia teorii gier prawdopodobnie siedziałbym na tym jeszcze dłuuuugo&#8230;<br />
Treść zadania dostępna pod adresem <a href="http://hs.spoj.pl/problems/HS09GAME/">http://hs.spoj.pl/problems/HS09GAME/</a><br />
<span id="more-381"></span><br />
Wspomniane twierdzenie to Twierdzenie Sprague-Grundy&#8217;ego. Gra przestawiona w zadaniu spełnia wszystkie założenia pozwalające na skorzystanie z twierdzenia. W połączeniu z dokładnie omówioną optymalną strategią, opisem pozycji wygrywających i przegrywających w grze Nim, pierwszą część zadania można rozwiązać w zaledwie 9 liniach</p>
<pre class="brush: python">
# gry - lista skladajaca sie z list reprezentujacych gre. Kazda reprezentacja
# gry to kolejna lista zaiwerajaca ilosc &#039;kijkow&#039; na kolejnych stosach
def graj(gry):
    sg = (0, 0, 1, 1, 2, 2, 3)
    for gra in gry:
        g = []
        reszty = []
        for stos in gra:
            reszta = int(stos)%7
            g.append(sg[reszta])
            reszty.append(reszta)
        wynik = reduce(lambda x,y: x^y, g)

        if wynik :
            print &quot;Julia wins.&quot;
        else :
            print &quot;Robert wins.\n&quot;
</pre>
<p>Lekki problem pojawia się przy ustalaniu ruchu wygrywającego. Nie wiem czy istnieje jakieś szybsze rozwiązanie niż takie trochę brute-force&#8217;owe która ja wykorzystałem. Polega ono na stwierdzeniu na jakiej pozycji ( wygrywającej czy przegrywającej ) znalazł by się gracz gdyby nie było jednego stosiku, a następnie obliczeniu czy da się odjąć taką liczbę patyczków żeby zostawić przeciwnika na pozycji przegrywającej.<br />
Dodatkowo oprócz wskazania ruchu wygrywającego należy wskazać ten podczas którego bierze się najwięcej patyczków ze stosu o najmniejszym numerze, co w lekki sposób komplikuje sprawę.:</p>
<pre class="brush: python">
        stos_wygrywajacy = 0;
        licznik = 0
        blokada_5 = False
        blokada_3 = False

        # odwrocenie list, sprawdzanie od konca
        gra_rev = gra[:]
        gra_rev.reverse()

        g_rev = g[:]
        g_rev.reverse()

        reszty.reverse()
        for reszta in reszty:
            # lista reszt bez kolejnych stosow
            tmpr = reszty[:]
            tmpr.pop(licznik)

            # xor wartosci f. Sprague-Grundy&#039;ego
            # bez kolejnych stosow
            tmpg = g_rev[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg ,0)

            if sg[reszta-5] == tmpw and int(gra_rev[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = len(reszty) - licznik
                blokada_5 = True
            elif sg[reszta-3] == tmpw and int(gra_rev[licznik]) &gt;= 3 and blokada_5 == False:
                wygrywajacy = 3
                stos_wygrywajacy = len(reszty) - licznik
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra_rev[licznik]) &gt;= 2 and blokada_5 == False and blokada_3 == False:
                wygrywajacy = 2
                stos_wygrywajacy = len(reszty) - licznik

            licznik += 1
</pre>
<p>Jeśli ktoś zna szybsze rozwiązanie chętnie je przeanalizuję <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Zaznaczam, że nie dam sobie głowy uciąć że algorytm jest poprawny, bo nie ma już możliwości zgłoszenia rozwiązania &#8211; upłynęły terminy.</p>
<p><strong><em>EDIT</em></strong>:<br />
Lekko poprawiona wersja, działa trochę szybciej, natomiast i tak nie umożliwia zdobycia maximum punktów. Jesli nie ma jakiejś sztuczki na ruch wygrywający, a podejrzewam że coś jest, to lepiej zakodzić to w C&#8230;</p>
<pre class="brush: python">
        stos_wygrywajacy = 0
        blokada_3 = False
        blokada_2 = False
        licznik = 0
        for reszta in reszty :
            tmpg = g[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg, 0)

            if sg[reszta-5] == tmpw and int(gra[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = licznik + 1
                break
            elif sg[reszta-3] == tmpw and int(gra[licznik]) &gt;= 3 and blokada_3 == False:
                wygrywajacy = 3
                stos_wygrywajacy = licznik + 1
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra[licznik]) &gt;= 2 and blokada_3 == False and blokada_2 == False:
                wygrywajacy = 2
                stos_wygrywajacy = licznik + 1
                blokada_2 = True
            licznik += 1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/feed/</wfw:commentRss>
		<slash:comments>6</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></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HWND CreateWindowEx<span style="color: #009900;">&#40;</span><br />
&nbsp; DWORD dwExStyle<span style="color: #339933;">,</span><br />
&nbsp; LPCTSTR lpClassName<span style="color: #339933;">,</span><br />
&nbsp; LPCTSTR lpWindowName<span style="color: #339933;">,</span><br />
&nbsp; DWORD dwStyle<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> x<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> y<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> nWidth<span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #993333;">int</span> nHeight<span style="color: #339933;">,</span><br />
&nbsp; HWND hWndParent<span style="color: #339933;">,</span><br />
&nbsp; HMENU hMenu<span style="color: #339933;">,</span><br />
&nbsp; HINSTANCE hInstance<span style="color: #339933;">,</span><br />
&nbsp; LPVOID lpParam<br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>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:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;windows.h&gt;</span><br />
<br />
LRESULT CALLBACK WndProc<span style="color: #009900;">&#40;</span>HWND<span style="color: #339933;">,</span> UINT<span style="color: #339933;">,</span> WPARAM<span style="color: #339933;">,</span> LPARAM<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #993333;">int</span> WINAPI WinMain<span style="color: #009900;">&#40;</span>HINSTANCE hInstance<span style="color: #339933;">,</span> &nbsp; HINSTANCE hPrevInstance<span style="color: #339933;">,</span><br />
LPSTR lpCmdLine<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> nCmdShow<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; MSG msg<span style="color: #339933;">;</span><br />
&nbsp; HWND hwnd<span style="color: #339933;">;</span><br />
&nbsp; WNDCLASSEX wcx<span style="color: #339933;">;</span><br />
&nbsp;<br />
&nbsp; wcx.<span style="color: #202020;">cbSize</span> <span style="color: #339933;">=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>wcx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">style</span> <span style="color: #339933;">=</span> CS_HREDRAW <span style="color: #339933;">|</span> CS_VREDRAW<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpfnWndProc</span> <span style="color: #339933;">=</span> WndProc<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">cbClsExtra</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">cbWndExtra</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hInstance</span> <span style="color: #339933;">=</span> hInstance<span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hIcon</span> <span style="color: #339933;">=</span> LoadIcon<span style="color: #009900;">&#40;</span>NULL<span style="color: #339933;">,</span> IDI_APPLICATION<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hCursor</span> <span style="color: #339933;">=</span> LoadCursor<span style="color: #009900;">&#40;</span>NULL<span style="color: #339933;">,</span> IDC_ARROW<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hbrBackground</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>HBRUSH<span style="color: #009900;">&#41;</span>GetStockObject<span style="color: #009900;">&#40;</span>WHITE_BRUSH<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpszMenuName</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainMenu&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">lpszClassName</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainWClass&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; wcx.<span style="color: #202020;">hIconSm</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>HICON<span style="color: #009900;">&#41;</span>LoadImage<span style="color: #009900;">&#40;</span>hInstance<span style="color: #339933;">,</span> MAKEINTRESOURCE<span style="color: #009900;">&#40;</span>5<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> IMAGE_ICON<span style="color: #339933;">,</span><br />
&nbsp; GetSystemMetrics<span style="color: #009900;">&#40;</span>SM_CXSMICON<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> GetSystemMetrics<span style="color: #009900;">&#40;</span>SM_CYSMICON<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>UINT<span style="color: #009900;">&#41;</span>LR_DEFAULTCOLOR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; RegisterClassEx<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>wcx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; hwnd <span style="color: #339933;">=</span> CreateWindowEx<span style="color: #009900;">&#40;</span>WS_EX_LAYERED<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;MainWClass&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPCSTR<span style="color: #009900;">&#41;</span><span style="color: #ff0000;">&quot;Sample&quot;</span><span style="color: #339933;">,</span> WS_OVERLAPPEDWINDOW<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> &nbsp;CW_USEDEFAULT<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> CW_USEDEFAULT<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>HWND<span style="color: #009900;">&#41;</span>NULL<span style="color: #339933;">,</span> &nbsp;<span style="color: #009900;">&#40;</span>HMENU<span style="color: #009900;">&#41;</span>NULL<span style="color: #339933;">,</span> hInstance<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>LPVOID<span style="color: #009900;">&#41;</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; ShowWindow<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> nCmdShow<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; SetLayeredWindowAttributes<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> 0<span style="color: #339933;">,</span> 180<span style="color: #339933;">,</span> LWA_ALPHA<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; UpdateWindow<span style="color: #009900;">&#40;</span>hwnd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>GetMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> &nbsp;0<span style="color: #339933;">,</span> 0<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; TranslateMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; DispatchMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; <span style="color: #b1b100;">return</span> msg.<span style="color: #202020;">wParam</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
LRESULT CALLBACK WndProc<span style="color: #009900;">&#40;</span>HWND hwnd<span style="color: #339933;">,</span> UINT uMsg<span style="color: #339933;">,</span> WPARAM wParam<span style="color: #339933;">,</span> LPARAM lParam<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>uMsg<span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_CREATE<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_PAINT<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">case</span> WM_DESTROY<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; PostQuitMessage<span style="color: #009900;">&#40;</span>0<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> DefWindowProc<span style="color: #009900;">&#40;</span>hwnd<span style="color: #339933;">,</span> uMsg<span style="color: #339933;">,</span> wParam<span style="color: #339933;">,</span> lParam<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<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:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HWND hDesktop <span style="color: #339933;">=</span> GetDesktopWindow<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
HWND hChild <span style="color: #339933;">=</span> GetWindow<span style="color: #009900;">&#40;</span>hDesktop<span style="color: #339933;">,</span> GW_CHILD<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
HWND hTemp<span style="color: #339933;">;</span><br />
<span style="color: #808080; font-style: italic;">/* ... */</span><br />
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>hTemp <span style="color: #339933;">!=</span> GetWindow<span style="color: #009900;">&#40;</span>hChild<span style="color: #339933;">,</span> GW_HWNDLAST<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #808080; font-style: italic;">/* ... */</span><br />
&nbsp; hTemp <span style="color: #339933;">=</span> GetWindow<span style="color: #009900;">&#40;</span>hChild<span style="color: #339933;">,</span> GW_HWNDNEXT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>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>:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">EnumWindows<span style="color: #009900;">&#40;</span>EnumWindowsProc<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #808080; font-style: italic;">/* ... */</span><br />
BOOL CALLBACK EnumWindowsProc<span style="color: #009900;">&#40;</span>HWND hwndChild<span style="color: #339933;">,</span> LPARAM lParam<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #993333;">char</span> buffer<span style="color: #009900;">&#91;</span>100<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #993333;">int</span> count <span style="color: #339933;">=</span> GetWindowText<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #339933;">,</span> buffer<span style="color: #339933;">,</span> 100<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&amp;&amp;</span> IsWindowVisible<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* ... */</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> TRUE<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<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>:</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SetWindowLong<span style="color: #009900;">&#40;</span>hwndChild<span style="color: #339933;">,</span> GWL_EXSTYLE<span style="color: #339933;">,</span> WS_EX_LAYERED<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<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>
		<item>
		<title>Z C++ zagadka nr 2</title>
		<link>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 11:49: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=188</guid>
		<description><![CDATA[Zagadka nr 2 bardzo blisko związana z zawiłościami języka programowania c++, choć okazuje się że dotyczy także innych, w tym np. Javy. Kod wydaje się banalnie prosty. Jednak jak mówi &#8222;stare chińskie przysłowie&#8221;  &#8211; &#8222;Diabeł tkwi w szczegółach&#8221;. Czego można by się spodziewać po wykonaniu takiego kodu ? #include &#60;iostream&#62; int main() { for(double i]]></description>
			<content:encoded><![CDATA[<p>Zagadka nr 2 bardzo blisko związana z zawiłościami języka programowania c++, choć okazuje się że dotyczy także innych, w tym np. Javy. Kod wydaje się banalnie prosty. Jednak jak mówi &#8222;stare chińskie przysłowie&#8221;  &#8211; &#8222;Diabeł tkwi w szczegółach&#8221;.<br />
<span id="more-188"></span><br />
Czego można by się spodziewać po wykonaniu takiego kodu ?</p>
<pre class="brush: cpp">
#include &lt;iostream&gt;

int main()
{
    for(double i = 0; i != 1; i+= 0.1)
    {
        std::cout &lt;&lt; &quot;Obrot petli i = &quot; &lt;&lt; i &lt;&lt; std::endl;
    }
}
</pre>
<p>Odpowiedź na to pytania wymaga trochę więcej niż tylko znajomości składni języka. Na pierwszy rzut oka wydawać się może że pętla dokona 10 obrotów a następnie program się skończy. Gdyby to był 1 kwietnia wiele osób uznało by za żart stwierdzenie że pętla będzie działać w nieskończoność, choć tak naprawdę jest !! Program nie zauważy że dobił do 1 i powinien przestać działać. Co więcej, na ekran zostanie wypisana liczba 1 a mimo to działanie nie zostanie przerwane. Wyjaśnienia tego przypadku, trzeba szukać w komputerowej reprezentacji liczby 0.1 <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/06/z-c-zagadka-nr-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Z C++ zagadka</title>
		<link>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 10:29:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[wirtualność]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=132</guid>
		<description><![CDATA[Na ostatnich inżynierskich targach pracy i praktytk trafiłem na dość trudny test z C++. Pojawiło się na nim zadanie co do którego miałem wątpliwości szczególnie że sprawdzający stwierdził że nie mam racji. Treść zapamiętałem i postanowiłem sprawdzić nie teoretycznie na kartce, ale po prostu jak się zachowa prawdziwy kompilator. Treść jest bardzo prosta, jaki będzie]]></description>
			<content:encoded><![CDATA[<p>Na ostatnich inżynierskich targach pracy i praktytk trafiłem na dość trudny test z C++. Pojawiło się na nim zadanie co do którego miałem wątpliwości szczególnie że sprawdzający stwierdził że nie mam racji. Treść zapamiętałem i postanowiłem sprawdzić nie teoretycznie na kartce, ale po prostu jak się zachowa prawdziwy kompilator. <span id="more-132"></span>Treść jest bardzo prosta, jaki będzie efekt kompilacji i uruchomienia poniższego kodu:</p>
<pre class="brush: cpp">
class A
{
public:
  A() {
    fun();
  }

  virtual void fun()  {
    std::cout &lt;&lt; &quot;A::fun&quot; &lt;&lt; std::endl;
  }

  void fun2()  {
    fun();
  }
};

class B : public A
{
  void fun()  {
    std::cout &lt;&lt; &quot;B::fun&quot; &lt;&lt; std::endl;
  }
};

int main() {
  A* a = new B();
}
</pre>
<p>Poprawna odpowiedź:<br />
<code>A::fun</code><br />
dlaczego? W konstruktorze nie działa wirtualność. Zatem to ja miałem racje !<br />
Za to gdyby dopisać jeszcze </p>
<pre class="brush: cpp">
a-&gt;fun2();
</pre>
<p>to byśmy zobaczyli już <code>B::fun</code>. Problem zapewne rzadko w praktyce występuje ale jest to genialne zadanie na wszelkiej maści testy mające sprawdzić zaawansowaną znajomość mechanizmów języka C++</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/03/z-c-zagadka/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
