Posts from 2010

Aby nie śmiecić

2010-03-20 19:32

Jako moderator forum Warsztatu mam wątpliwą przyjemność kontaktu z różnymi przejawami – nazwijmy to eufemistycznie – niepożądanych zachowań. A to mamy jakieś pytanie, na które odpowiedzią jest pierwszy rezultat, jaki wyszukiwarka wyrzuca w reakcji na prostą kwerendę. Innym razem może to być klasyczne “No i co tu jest źle?!”, opatrzone wysokim na kilka ekranów kawałkiem kodu, dla którego właściwym miejscem jest /dev/null. Kiedy indziej będzie to pojawiający się po raz 2512. problem w rodzaju unresolved external… I tak dalej, i tak dalej. Ot, zwyczajne przypadki, gdy napisanie posta poprzedza (lub zastępuje) myślenie.


Stuprocentowo uzasadnione.

Może nie jestem w stanie tego zrozumieć, ale przynajmniej potrafię się z tym pogodzić – po części pewnie dlatego, że sprzątanie po tego rodzaju twórczości nie jest specjalnie kłopotliwe. Jest jednak przynajmniej jedna rzecz, która skłania mnie do poważnych rozważań na temat intelektualnej kondycji rodzaju ludzkiego – a przynajmniej tej jego części, która się na forum pojawia – połączonych z co najmniej jednokrotnym wykonaniem znanego i lubianego gestu kapitana Picarda.

O co chodzi?… O dołączanie nowych pytań do istniejących wątków, z uzasadnieniem, że czyni się tak po to, aby nie zaśmiecać forum nowymi tematami. Czy jest to dobra praktyka? Czy ma to jakikolwiek sens? I wreszcie, czy skutkiem jej stosowania jest faktycznie większy porządek forum?
Otóż nie – i to po trzykroć nie. Paradoks tu występujący polega właśnie na tym, że – dokładnie przeciwnie do intencji osób tak postępujących – podczepianie się pod istniejące tematy skutkuje tylko i wyłącznie jeszcze większym bałaganem! Dzieje się tak co najmniej z kilku powodów:

  • Wprowadzanie nowego pytania w istniejący wątek odcina możliwość dodania czegokolwiek do oryginalnego tematu dyskusji. Jeśli ktoś mimo wszystko będzie próbował to robić, najprawdopodobniejszym rezultatem jest przeplatanka odpowiedzi na stare i nowe pytanie. Czytanie czegoś takiego to czysta przyjemność, nieprawdaż? 8-)
  • Jeśli jeden wątek zawiera więcej niż jeden temat/dyskusję/pytanie, to jego tytuł staje się mylący. Po niedługim czasie podczepione posty mogą być już zupełnie niezwiązane z tym, o czym wątek był oryginalnie. Istny synonim porządku, co nie? :)
  • Podczepione pytanie jest o wiele trudniejsze do znalezienia przez forumową wyszukiwarkę – jeśli to w ogóle jest możliwe. Co więcej, utrudnia ono też wyszukanie wszystkich informacji z oryginalnej dyskusji – choćby dlatego, że trzeba wpierw ustalić, gdzie się ona kończy…
  • Przywrócenie radośnie zepsutego wątku do stanu używalności jest pracochłonne: wymaga zlokalizowania wszystkich postów odnoszących się do nowego pytania (które mogą się przeplatać z tymi od pierwotnego), wydzielenia ich do nowego wątku i nadania mu sensownego tytułu. To wszystko da się zresztą zrobić tylko przy założeniu, że nie istnieją już posty, które odwołują się do obu pytań naraz. Jeszcze bardziej daleko idące jest przypuszczenie, że istnieje jakikolwiek moderator, któremu chciałoby się takich podziałów dokonywać :)

Widać zatem wyraźnie, że skutek doczepiania się do istniejących wątków jest dokładnie odwrotny do zamierzonego. Nie ma to najmniejszego sensu i jest wybitnie niepożądane. Wciąż jednak nie mogę się nadziwić, jakaż to dziwna logika podsuwa ludziom pomysły, że może być inaczej…

Tags:
Author: Xion, posted under Internet, Thoughts » 3 comments

Domyślna inicjalizacja zmiennych

2010-03-17 1:57

Używanie zmiennych bez uprzedniego nadania im wartości to stosunkowo częsty błąd. Wiele języków kompilowanych będzie z tego powodu stroiło fochy wahające się od ostrzeżeń podczas kompilacji przez błędy tejże aż po wyjątki w czasie wykonania programu (przynajmniej w wersji debugowej). To zresztą bardzo dobrze, gdyż alternatywą jest korzystanie ze zmiennej, której zawartością są jakieś losowe śmieci w pamięci.

Tak więc zmienne trzeba inicjalizować i w niemal każdym języku da się to zrobić mniej więcej tak:

  1. int x = 5;

W C++ oczywiście też. Jednak w C++ mamy też feature, który nazywa się inicjalizacją domyślną. Opiera się on założeniu, że dany typ (tj. obiekt tego typu) może się sam zainicjalizować bez żadnych dodatkowych informacji – czyli że np. ma rozsądną wartość domyślną albo bezparametrowy konstruktor. Stąd T() będzie “domyślnym obiektem typu T“, który możemy łatwo uzyskać, nie mając w ogóle pojęcia, czym ów typ T w istocie jest (codzienność szablonów, swoją drogą).
Inicjalizacja zmiennej tego typu domyślną wartością będzie więc wyglądała mniej więcej tak:

  1. T foo = T();

Co bardziej spostrzegawczy zauważą jednak, że mamy tutaj dwie operacje: konstrukcję obiektu i kopiowanie go. Nie radzę jednak próby “optymalizacji” w postaci zamiany na deklarację T foo(); – można się nielicho zaskoczyć. Najlepiej pozostawić to zadanie kompilatorowi; przynajmniej w teorii powinien on sobie z nim bez problemu poradzić.

W powyższy sposób możemy domyślnie inicjalizować dowolne typy zmiennych. Dla pewnej ich podgrupy – zwanej agregatami – możemy jednak zastosować inne rozwiązanie. Cóż to jednak są te agregaty? Otóż są to typy złożone (tablice, struktury, itp.), które nie posiadają zdefiniowanych przez programistę konstruktorów. Mimo że instrukcja T() działa zupełnie dobrze również dla nich, dopuszczalne jest stosowanie nieco innej formy inicjalizacji.
Formą ta jest lista inicjalizacyjna. Można ją niekiedy spotkać w kodzie korzystającym z jakiegoś API, które operuje na dużych strukturach:

  1. WNDCLASSEX wc = { sizeof(WNDCLASSEX) }; // {...} to inicjalizator
  2. wc.lpszClassName = TEXT("MyVeryOwnAndCuteWindow");
  3. wc.hInstance = hInstance;
  4. // itd.

Chodzi tu po prostu o podanie wartości dla kolejnych elementów agregatu, czyli pól w strukturze/klasie lub komórek tablicy; całą tę listę zamykamy w nawiasy klamrowe. Nie musi ona być przy tym pełna: jeśli jakieś pozycje zostaną pominięte, to odpowiadające im pola/komórki zostaną automatycznie zainicjalizowane w sposób domyślny. W przykładzie powyżej inicjalizujemy więc strukturę tak, że pierwsze pole zawiera jej rozmiar, a reszta domyślne wartości (czyli pewnie zera).
Dane dla pierwszego pola zostały wprawdzie tutaj podane jawnie, jednak w ogólności nie jest to wymogiem. Na liście inicjalizacyjnej możemy równie dobrze opuścić wszystkie pozycje i to właśnie jest ten drugi, uniwersalny sposób inicjalizacji agregatu. Wygląda on więc po prostu tak:

  1. D3DVECTOR v = {};

Jakkolwiek nietypowo (jak na kod C++) linijka ta wygląda, jest ona najzupełniej poprawna. W wyniku jej wykonania nowo zadeklarowany wektor v będzie miał wszystkie współrzędne wyzerowane.

Tags: , ,
Author: Xion, posted under Programming » 10 comments

mi pu facki fi la lojban.

2010-03-11 15:40

Przeglądanie Wikipedii może mieć jeden ciekawy efekt uboczny. Otóż wystarczy kliknąć jeden lub dwa linki “w złym kierunku” i już lądujemy w obszarze wiedzy znajdującym się kilometry od tego, z którego zaczynaliśmy. To ma swoje wady (bardzo, bardzo łatwo jest stracić mnóstwo czasu na niezupełnie pożyteczne lektury – co obrazowo pokazuje jeden z komiksów na xkcd), ale ma i jedną podstawową zaletę: można przy okazji odkryć coś ciekawego.

Znalezisko, na jakie natrafiłem ostatnio, to dość nietypowy język. I bynajmniej nie mam tu wcale na myśli języka programowania; chodzi tu jak najbardziej o język naturalny (chociaż pewnie niektórym to określenie będzie się wydawało nadużyciem…).
Delikwent nazywa się lojban (wym. lożban) i należy do klasy tzw. języków logicznych. Zanim wyjaśnię, co w nim jest takiego nietypowego, wspomnę o tym, czego w nim nie ma. Liczby pojedynczej i mnogiej, odmiany wyrazów, czasów, podziału na rodzaje gramatyczne, jak również interpunkcji i ortografii, a nawet… tradycyjnych części mowy (czasowniki, przymiotniki, itp.) – tego wszystkiego w nim nie ma i nie jest to brak specjalnie zauważalny. Wręcz przeciwnie: lojban ma – przynajmniej częściowo dzięki temu – niezaprzeczalne zalety:

  • jest jednoznaczny pod względem gramatyki, tzn. zawsze można dokładnie powiedzieć, co dana wypowiedź znaczy
  • jest jednoznaczny pod względem sposobu zapisu słów (czyli ortografii), który jest fonetyczny (zgodny z wymową)
  • jest regularny – od jego zasad nie ma żadnych wyjątków

Wszystko to brzmi całkiem obiecująco. Teraz jednak nasuwa się pewnie pytanie: skoro w tym języku tylu rzeczy nie ma, to co tak naprawdę w nim jest?…

Już spieszę z odpowiedzią. Odpowiedniki zdań w lojbanie (zwane bridi) wyrażają mianowicie pewne relacje między pojęciami. Związki te nazywamy selbri i mogą one odpowiadać zarówno czasownikom, jak i przymiotnikom czy nawet rzeczownikom (wtedy są to relacje ‘bycia czymś’) z “normalnych” języków. Z kolei argumenty dla tych relacji nazywają się sumti. Mówiąc o lojbanie używa się powszechnie tych, jak i kilku innych terminów.
W tym momencie jest doskonały czas na przykład – a jakim lepszym zdaniem przykładowym można się posłużyć niż tradycyjne “Ala ma kota.”? Proszę bardzo, oto jego odpowiednik w lojbanie:

la .alas. ponse le mlatu

Kropka nie oznacza tu końca zdania, ale krótką przerwę w wypowiedzi na końcu nazwy własnej (którą jest bez wątpienia ‘Ala’). Poprzedzające ją ‘s’ jest wymogiem gramatyki: wszystkie nazwy (cmene, wym. szmene) w lojbanie muszą kończyć się spółgłoską. ponse, jak nietrudno się domyślić, oznacza “mieć”, tj. relację posiadania czegoś przez coś/kogoś. A le mlatu to “coś, co zwiemy kotem”. Czemu nie po prostu “kot”? Ano dlatego, że pod tym słowem może się kryć wiele różnych osobników, a nam chodzi o pewnego, ale konkretnego kota. To między innymi z takich konstrukcji – na początek niezbyt może intuicyjnych – bierze się jednoznaczność lojbanu.

Oczywiście ponse i mlatu to nie jedyne słowa, mogące służyć jako selbri. Są one tylko dwoma z około 1300 podstawowych wyrazów tego typu (nazywanych gismu), które mogą być łączone na wiele sposobów w celu otrzymywania bardziej złożonych znaczeń. Wspominany kot Ali może być na przykład biały i wtedy możemy go określić jako le blabi mlatu. Tak swoją drogą, jeśli ktoś się zastanawia, skąd właściwie wzięły się te wszystkie słowa, to spieszę z odpowiedzią, iż zostały one wygenerowane algorytmicznie z odpowiednich wyrazów w którychś z sześciu najpopularniejszych językach świata: chińskim, angielskim, hiszpańskim, hinduskim, arabskim i rosyjskim.
Ważną cechą lojbanu jest też to, że selbri mają w nim określoną strukturę związaną z położeniem argumentów. Innymi słowy, to nie przypadek, że w naszym bridi Ala jest pierwsza, a kot drugi; gdyby było odwrotnie, to kot miałby Alę. selbri mogą mieć jednak zarówno mniej, jak i więcej argumentów niż dwa. Chcąc na przykład wysłać naszą Alę na wycieczkę samochodem z Krakowa do Wrocławia, powiedzieliśmy coś w stylu:

la .alas. klama la vrotsuav. la krakuf. zo’e lo karce

gdzie lo karce (wym. lo karsze) jest samochodem. klama znaczy “iść/jechać” (jak angielskie go) i ma aż 5 sumti (argumentów), z których każdy ma ściśle określone znaczenie. Jeśli komuś w tej chwili skojarzyło się to z prototypem funkcji w języku programowania, to podpowiem, że skojarzenie jest jak najbardziej słuszne :) lojban ma nawet swojego nulla: zo’e (wym. zohe) oznacza opuszczenie danego sumti, w tym przypadku czwartego. Nie trzeba jednak z niego korzystać; zdanie powyżej da się również powiedzieć i bez “wypełniacza”.

Naturalnie mógłbym kontynuować ten wywód jeszcze bardzo długo – i kto wie, może później to zrobię :) W tym miejscu jednak każdy powinien mieć już jako-takie pojęcie o tym, jak wygląda język lojban – i przy okazji znać już sporą część jego gramatyki. Zachęcam aczkolwiek do przejrzenia poniższych źródeł:

albo przynajmniej zerknięcia na wspomniany na początku artykuł na Wikipedii. Jeśli zaś komuś przez cały czas na końcu języka gnieździ się pytanie “A po co mi to?”, to jako odpowiedź rzucę… oczywiście kolejny komiks z xkcd :) co’o

…co oczywiście znaczy “do widzenia”. A tytuł notki? “Odkryłem lojban”, rzecz jasna :)

Tags: ,
Author: Xion, posted under Culture » 3 comments

Pakowanie w przestrzenie

2010-03-09 17:05

Jeśli w C++ piszemy jakąś bibliotekę (albo nawet ogólniej: kod wielorazowego użytku), to zgodnie z dobrymi praktykami powinniśmy jej symbole zamknąć przynajmniej w jedną osobną przestrzeń nazw (namespace). Dzięki temu zapobiegniemy zminimalizujemy możliwość kolizji identyfikatorów w kodzie, który z naszego dzieła będzie korzystał – a także potencjalnie z innych bibliotek.
Nie wszystkie z nich jednak mogą być tak ładnie napisane – choćby dlatego, że któraś może być przeznaczona oryginalnie dla języka C. Najbardziej typowy przykład? Windows API. Dołączenie windows.h zasypuje globalną przestrzeń nazw istną lawiną symboli odpowiadających tysiącom funkcji czy typów zadeklarowanych w tym nagłówku. Nie jest to specjalnie dobre.

Jak temu zaradzić? Bardzo prostą, ale nierozwiązującą wszystkich problemów metodą jest stworzenie własnego nagłówka “opakowującego” ten biblioteczny w nową przestrzeń nazw:

  1. #ifndef FOO_H
  2. #define FOO_H
  3.  
  4. namespace foo
  5. {
  6.     #include <foobar.h>
  7. }
  8.  
  9. #endif

Założenie jest takie, żeby wynikowego pliku nagłówkowego (foo.h) używać następnie w miejsce oryginalnego (foobar.h). Wtedy wszystkie symbole w nim zadeklarowane znajdą się wewnątrz nowej przestrzeni nazw, foo.

Wszystkie?… Nie! Pakując kod napisany w stylu C bezpośrednio do przestrzeni nazw nie osiągniemy bowiem wszystkich celów, którym namespace‘y przyświecają. Owszem, da się co nieco poprawić: jeśli np. wspomniany windows.h zamknęlibyśmy w przestrzeni win, to poniższy kod będzie jak najbardziej działał:

  1. win::HWND hNotepad;
  2. hNotepad = win::FindWindow("Notepad", 0);

podczas gdy wersja bez przedrostków win:: już niezupełnie. Jednak nie jest to całkowity – nomen omen – win, bo z kolei takie wywołanie:

  1. win::ShowWindow (hNotepad, win::SW_MINIMIZE);

skutkuje już niestety failem :) Nasza przestrzeń nie może bowiem zamknąć wszystkiego, gdyż nie podlegają jej dyrektywy preprocesora – a w szczególności #define. Pech polega na tym, że właśnie #define jest w C podstawowym sposobem definiowania stałych, więc użyta wyżej nazwa SW_MINIMIZE jest (w windows.h) określona po prostu jako:

  1. #define SW_MINIMIZE 6

Próba jej kwalifikowania powoduje zatem powstanie nieprawidłowego ciągu win::6 i słuszne narzekania kompilatora.

Nasz pojemnik (na nazwy) jest więc dziurawy i niestety nic z tym nie da się zrobić. Tak to już jest, gdy wciąż trzeba mieć do czynienia z API, które w tym przypadku liczy sobie – bagatelka – ponad 20 lat!

Tags: , ,
Author: Xion, posted under Programming » 4 comments

Narzędzia do DirectX

2010-03-06 17:38

Zasadniczą i najważniejszą częścią DirectX SDK są pliki nagłówkowe oraz biblioteki (statyczne i dynamiczne), które pozwalają na pisanie programów korzystających z tego API. Do tego mamy jeszcze niezbędną dokumentację oraz przykładowe aplikacje (samples), pokazujące wykorzystanie poszczególnych jego elementów lub prezentujących implementacje różnych efektów graficznych.
Ale to nie wszystko, co można znaleźć w tym kilkusetmegabajtowym (i ciągle rosnącym) pakiecie. Niemal równie ważne są narzędzia pomocnicze, które można tam znaleźć. Podczas tworzenia aplikacji wykorzystujących zwłaszcza Direct3D umiejętność korzystania z tych programów jest niekiedy prawie tak samo ważna, jak znajomość samego API czy zagadnień z dziedziny grafiki.

Dlatego też postanowiłem pokrótce opisać niektóre z nich, żeby co mniej zaawansowani programiści DirectX mogli przynajmniej dowiedzieć się, że takowe istnieją :) Oto więc rzeczone aplikacje:

  • DirectX Caps Viewer pozwala na podejrzenie możliwości naszego sprzętu, czyli jego capsów (od capabilities) – normalnie zwracanych przez metodę GetDeviceCaps urządzenia – w postaci przejrzystego interfejsu drzewiastego. Dobrze jest rzecz jasna wiedzieć, czego szukamy, ale w większości przypadków programistów grafiki 3D interesować będzie gałąź Direct3D9/10 Devices/<model karty graficznej>/D3D Device Types/HAL/Caps.
  • DirectX Control Panel to, jak sama jego nazwa wskazuje, panel kontrolny całego DirectX-a, którym możemy kontrolować zachowanie poszczególnych jego elementów. Pewnie najbardziej interesującym dla programistów elementem jest “magiczny” suwak Debug Output Level, dzięki któremu możemy regulować ilość komunikatów wysyłanych do debugera przez runtime DirectX, co przy wyższych ustawieniach ułatwia znajdowanie (przyczyn) błędów.
  • DirectX Error Lookup to z kolei małe sprytne narzędzie tłumaczące liczbowe kody błędów funkcji DX (typu HRESULT) na odpowiadające im stałe i komunikaty. To pierwsze potrafi też częściowo zrobić debuger Visual Studio (czujką $err,hr lub $eax,hr), ale mimo to programik ten bywa niekiedy przydatny.
  • DirectX Texture Tool jest natomiast już bardziej skomplikowaną aplikacją. Jej ogólnym przeznaczeniem jest tworzenie i edycja tekstur w dedykowanym dla DirectX formacie .dds. Oczywiście nasze programy mogą korzystać z tekstur w innych formatach graficznych, ale użycie Texture Tool jest niekiedy niezbędne – chociażby wtedy, gdy musimy stworzyć mapy sześcienne (cubemaps).
  • DirectX Viewer to podglądacz – przy jego pomocy możemy obejrzeć w 3D modele zapisane w plikach .x, a także rezultaty uruchomienia efektów (z plików .fx). Napisanie czegoś podobnego nie byłoby trudne, ale dzięki istnieniu Viewera nie musimy tego robić :)
  • Wreszcie, PIX for Windows to zdecydowanie największa aplikacja w tym zestawie. Jej przeznaczeniem jest wszechstronne (także wydajnościowe) debugowanie aplikacji wykorzystujących Direct3D. Na jej temat można by napisać sporo, więc całkiem możliwe, że nie omieszkam tego zrobić w przyszłości :)

Niektóre z tych narzędzi są na tyle użyteczne, że warto zrobić sobie do nich skróty w łatwo dostępnych miejscach (dotyczy to chociażby Control Panelu). Wszystkie zaś możemy znaleźć wśród linków tworzonych w menu Start przez instalator SDK, w podkatalogu DirectX Utilities.

Tags: ,
Author: Xion, posted under Programming » Comments Off on Narzędzia do DirectX

AI na Warsztacie

2010-02-28 12:03

O niezadowalającym poziomie forum Warsztatu słyszałem już wielokrotnie. Że pytania dotyczą głównie podstaw programowania, że wiele z nich to mniej lub bardziej zakamuflowane “No i co tu jest źle?”, że odpowiedzi na większość z nich znajdują się na drugim końcu wyszukiwarki – i tym podobne. A jeśli już jakiś wątek nie podpada pod którąś z tych kategorii, to albo jest kolejnym “genialnym” pomysłem na grę, albo off-topikiem, albo w najlepszym razie dotyczy jakiegoś zagadnienia z zakresu programowania grafiki.

Pewnie coś w tym jest. Jednak ostatnio ku mojemu zaskoczeniu (i pełnej aprobacie) pojawiło się też kilka dyskusji na tematy związane ze sztuczną inteligencją. Niby taki dział też jest, ale jakoś dotąd nie zauważyłem, by był zanadto aktywny.
A tu proszę: kilka ciekawych wątków w ciągu paru dni. Może to nic wielkiego i może niespecjalnie nawet jest tu o czym pisać, bo ich tematyka jest dość ograniczona (głównie sieci neuronowe), a dziedzina raczej akademicka i pewnie nawet niekoniecznie związana z gamedevem. Ale…

Ale myślę, że jednak warto o tym wspomnieć :) Przede wszystkim po to, by nikt nie zapomniał, że gry to nie tylko ładna grafika i że w dzisiejszych czasach powinny one być choć trochę – z braku lepszego słowa – ‘inteligentne’.
A poza tym miałem też ochotę zwrócić uwagę na istnienie tego właśnie działu forum Warsztatu – więc niniejszym właśnie to czynię :]

Tags: , ,
Author: Xion, posted under Internet, Programming » 2 comments

Szpieg++

2010-02-26 16:41

Pakiet Visual Studio to nie tylko samo środowisko programistyczne (IDE), ale i kilka mniejszych narzędzi. Większość z nich dotyczy albo programowania na platformy mobilne, albo .NET, ale jest przynajmniej jedno, które może okazać się przydatne dla każdego programisty Windows. Chodzi o program Spy++ (spyxx.exe).

Co ta aplikacja potrafi? Otóż pozwala ona na podgląd różnych obiektów w systemie, tj. okien, wątków i procesów wraz z ich właściwościami (jak na przykład wartości uchwytów czy ilość zaalokowanych bajtów). Na pierwszy rzut oka może nie wydawać się to jakoś wybitnie zachwycające, jako że zwykły Menedżer zadań potrafi (prawie) to samo, z dokładnością do mniejszej liczby szczegółów.
Wyróżniającym i znacznie przydatniejszym feature’em Spy++ jest bowiem co innego. Umożliwia on mianowicie podglądanie, filtrowanie i logowanie wszystkich lub wybranych komunikatów Windows (WM_PAINT, WM_LBUTTONDOWN, itd.) dochodzących do wskazanego okna lub grupy okien, wraz z ich parametrami (wParam, lParam) oraz wartościami zwróconymi przez okno w odpowiedzi na nie.

Działa to przy tym prosto i intuicyjnie. Najpierw wybieramy sobie okno do podglądania (Spy > Log Messages lub Spy > Find Window), co możemy zrobić przy pomocy przeciągnięcia celownika myszą w jego obszar. Potem możemy określić, jakiego rodzaju komunikaty potrzebujemy przechwytywać oraz jakie informacje chcemy z nich wyciągnąć. Wynikiem będzie log mniej więcej takiej postaci:

<00694> 0002009C P WM_MOUSEMOVE fwKeys:0000 xPos:51 yPos:259
<00695> 0002009C P WM_MOUSELEAVE
<00696> 0002009C P WM_PAINT hdc:00000000
<00697> 0002009C P WM_TIMER wTimerID:5 tmprc:00000000
<00698> 0002009C P WM_TIMER wTimerID:2 tmprc:00000000

która to, jak sądzę, powinna być zrozumiała dla każdego średnio zaawansowanego programisty Windows :]

Po co nam jednak coś takiego?… Ano odpowiedź jest prosta: do debugowania :) Można oczywiście podchodzić do tego w “tradycyjny” sposób przy pomocy pracy krokowej tudzież breakpointów, ale często ogranicza nas tutaj swego rodzaju zasada nieoznaczoności, gdy samo debugowanie zmienia działanie programu – chociażby ze względu na ciągłe przełączenia między nim a IDE. To oczywiście znacznie utrudnia wykrycie i poprawienie usterek.
Jak nietrudno się domyślić, istnieją też inne programy oferujące podobną funkcjonalność co Spy++, jak np. Winspector. Z Visual Studio otrzymujemy jednak dobre narzędzie out-of-the-box, więc czegóż można by chcieć więcej? ;]

Hmm… pewnie tego, by dowiedzieć się mniej więcej, jak ono działa. O tym można przeczytać na blogu jego autora.

Tags: , ,
Author: Xion, posted under Applications, Programming » 2 comments
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.