Wiele programów z sieci wciąż jeszcze ściąga się w postaci archiwów do samodzielnego wypakowania, jak choćby w formacie .zip. Ma to swoje zalety i wady – do tych drugich należy fakt, że nie bardzo wiadomo, jak wygląda wewnętrzna struktura katalogów takiej paczki. Używając opcji typu Wypakuj tutaj ryzykujemy zaśmiecenie folderu Downloads plikami programu. Dlatego osobiście zawsze stosuję polecenie Wypakuj do nowego katalogu.
I tu czasem jest mały zonk, gdy twórca archiwum zdecydował się na spakowanie całego folderu, a nie tylko zawartych w nim plików. Powstają wtedy nadmiarowe katalogi, wydłużające ścieżki do plików (co widać obok – w wersji trochę przesadzonej ;)).
Ponieważ podobne sytuacje zdarzają mi się dość często, postanowiłem im zaradzić przy pomocy najlepszego narzędzia na takie okazje, czyli PowerShella rzecz jasna :) Wynikiem jest poniższy skrypt do sprytniejszego rozpakowywania archiwów:
Jego działanie polega wpierw na zwykłej dekompresji archiwum. Jak można zauważyć, używa do tego obiektu COM-owskiego Shell.Application
. To sprawia, że skrypt ma pod tym względem te same możliwości co zwykły windowsowy Eksplorator (dla większych plików pokaże nawet pasek postępu ;]).
Później wypakowana zawartość jest poddawana operacji, którą nazywam tutaj ‘skróceniem ścieżki’. Polega ona wyrzuceniu jednego poziomu drzewa folderów, o ile tylko pewien katalog jest jedynym elementem swojego katalogu nadrzędnego. Takie właśnie sytuacje powstają przy dekompresji do nowego folderu archiwów źle zapakowanych (przynajmniej z mojego punktu widzenia ;P). Wynikiem działania skryptu będzie więc w sumie jeden nowy podkatalog zawierający bezpośrednio całą interesującą zawartość archiwum.
Oczywiście używanie powyższego skryptu tylko z poziomu linii komend PowerShella nie jest specjalnie wygodne; lepiej jest dodać go do menu kontekstowego archiwów, czyli np. plików .
Jednym z bardziej zauważalnych składników Windows 7, które odróżniają ten system od Visty, jest nowy wygląd paska zadań. Jest szerszy, wyświetla duże ikony i przesunięcie go z dołu na bok ekranu w końcu ma sens (hurra dla monitorów wide-screen). Ale nowy wygląd to w tym przypadku nie wszystko, bo pasek ten zyskał też trochę na funkcjonalnościach.
Wśród nich mamy tzw. listy skoków (Jump Lists), zastępujące tradycyjne menu sterowania. Listy te pojawiają się po kliknięciu prawym przyciskiem na ikonkę na pasku zadań.
Co zawierają takie listy? Jak widać z boku, ich elementami mogą być skróty do ostatnio otwartych w programie dokumentów. Żeby było zabawniej, będzie ona wygenerowana automatycznie nawet dla tych aplikacji, których twórcy w momencie ich pisania nie mieli bladego pojęcia o tym, że kiedyś będziemy mieli taki system jak Windows 7 :) W tej wersji bowiem sam Windows zarządza listami MRU (Most Recenty Used) dla poszczególnych programów, o ile tylko wywołują one funkcję ShAddToRecentDocs
przy otwieraniu poszczególnych plików.
A to wbrew pozorom nie jest takie duże wymaganie, gdyż jest automatycznie ono spełnione, jeśli zachodzi jedna z poniższych sytuacji:
GetOpenFileName
z WinAPI albo OpenFileDialog
z .NET)Na listę skoków możemy też dodawać własne pozycje w postaci tak zwanych zadań (tasks), działających jak zwykłe systemowe skróty i tworzonych w ten sam sposób (interfejs IShellLink
). Szczegóły i przykładowy kod można znaleźć na przykład w tym artykule na CodeProject.
Wszyscy znamy doskonale funkcję Sleep
, która w Windows API służy do zawieszania działania wątku na określony czas (podawany w milisekundach). Wydawałoby się, że musi to być najprostsza funkcja z tego API, jaką tylko można sobie wyobrazić – bo co może być skomplikowanego w “zwykłej pauzie”? A okazuje się, że jak najbardziej może :)
Używając Sleep
– zwłaszcza w swej zwykłej wersji – musimy bowiem pamiętać przynajmniej o dwóch sprawach:
Sleep(INFINITE);
sprawi, że właściwie możemy ów wątek wyrzucić do kosza, gdyż nie da się już go odwiesić (funkcja ResumeThread
wywołana z innego wątku nic tu nie pomoże).MsgWaitForMultipleObjectsEx
albo po prostu GetTickCount
wraz z wewnętrzną pętlą komunikatów).Ex
funkcji Sleep
. Różni się on od oryginału tym, że rozpoczęte przez niego oczekiwanie można przerwać, jeśli sobie tego zażyczymy. Wątek uśpiony przez SleepEx
może być przedwcześnie obudzony, gdy otrzyma informacje o zakończeniu asynchronicznej operacji I/O lub asynchronicznego wywołania procedury (APC).Sleep
. Jest on bowiem determinowany przez długość tzw. kwantów czasu (time slices), jakie system operacyjny przydziela kolejnym wątkom, by zapewnić złudzenie ich jednoczesnego wykonania. Działanie Sleep
polega w rzeczywistości na oddaniu systemowi reszty kwantu czasu, który został przydzielony wątkowi; przestawienie wątku w stan “nieuruchamialności” na podaną ilość milisekund; a następnie na wznowieniu jego pracy, gdy ponownie otrzyma czas procesora od systemowego schedulera. W sumie więc czas uśpienia będzie równy:PozostałyKwantCzasu + ParametrSleep + CzasDoUaktywnieniaWątku
Stąd wynikają dwa wnioski. Po pierwsze, nie powinniśmy nigdy używać Sleep
jako sposobu na mierzenie czasu – już poczciwy GetTickCount
sprawi się tu znacznie lepiej. Po drugie, wywołanie Sleep(0);
jest jak najbardziej dopuszczalne i oznacza przedwczesne zrzeczenie się kwantu czasu, jaki wątek dostał od systemu. W czasach 16-bitowych wersji Windows i wielowątkowości bez wywłaszczała była od tego specjalna funkcja Yield
, którą należało często wywoływać, aby przełączanie wątków w ogóle było możliwe. Teraz rzecz jasna nie jest to konieczne, ale nadal może być przydatne dla zasygnalizowania, że nasz wątek nie robi nic pożytecznego, a tylko w brzydki sposób na coś czeka (tzw. busy waiting).
O tych dwóch szczegółach odnośnie funkcji Sleep
dobrze jest pamiętać, jeśli nasze wątki chcemy usypiać. Jako programiści Windows możemy się aczkolwiek podbudować tym, że nie mamy przy tym takich problemów jak koderzy piszący pod Linuksem. Tam sleep
może być potencjalnie zaimplementowany na sygnałach, co wymaga ostrożności przy stosowaniu go razem z funkcjami alarm
i signal
.
Zajmę się dzisiaj pewnym rodzajem aplikacji, którą przeciętny programista wykorzystuje rzadko, ale którą mimo tego powinien mieć. Mam tu na myśli program graficzny służący do edycji ikon, czyli tych małych (a od niedawna i większych) obrazków, które w Windows (i nie tylko) pojawiają się na każdym kroku – zwłaszcza na pulpicie czy w menu Start. Może nieczęsto zdarza się konieczność stworzenia ikonki dla własnej aplikacji, lecz kiedy już trzeba to zrobić, warto posłużyć się w tym celu odpowiednim narzędziem (a nie Paintem na przykład :]).
Znalezienie dobrej i darmowej aplikacji do edycji ikon nie jest jednak takie łatwe, jako że najlepsze i najpopularniejsze z nich są licencjonowane jako shareware. Istnieje jednak przynajmniej jeden darmowy i wart polecenia program tego typu; sam dowiedziałem się o nim od Rega.
Nazywa się on IcoFX i ze względu na swą niepozorną wielkość (1.5 MB) ma chyba jedną z lepszych proporcji użyteczności do rozmiaru. Zawiera on bowiem zdecydowaną większość funkcji (jeśli nie wszystkie), jakie można wymagać od tego rodzaju aplikacji.
Program ten obsługuje oczywiście wszystkie używane obecnie rozmiary (od 16×16 do 256×256), głębie kolorów (od 1 do 32 bitów z kanałem alfa) i formaty ikon (łącznie z PNG wykorzystywanym od Visty wzwyż). Oprócz całego wachlarza typowych narzędzi graficznych oferuje też wiele predefiniowanych filtrów (rozmycie, detekcja krawędzi itp.) wraz z możliwością definiowania własnych. Generalnie część “graficzna” programu jest bez zarzutu. Jedynym mankamentem, na jaki się zdołałem dotąd natknąć, jest brak możliwości określania tolerancji kolorów dla wypełniania typu flood fill.
Część “narzędziowa” też prezentuje się dobrze. Przy pomocy programu możemy nie tylko ekstrahować ikony z plików .exe i .dll (w razie potrzeby masowo przy pomocy batch processing), ale także edytować takie pliki (w zakresie ikon, rzecz jasna). Taka edycja mogłaby być wprawdzie nieco lepiej pomyślana (dodanie nowej ikony do pliku .exe/.dll jest możliwe tylko poprzez import z .ico), ale w sumie da się z nią wytrzymać.
Tak więc na te niezbyt częste okazje, gdy musimy/chcemy pobawić z ikonami, IcoFX wydaje się ogólnie całkiem dobrym rozwiązaniem. Zwłaszcza ze tę cenę :)
Jeśli oprócz systemu okienkowego rodem z Microsoftu mamy też jakiegoś *niksa, to reinstalacja Windows będzie dla nas miała jeden nieprzyjemny efekt uboczny. Otóż instalatory Okienek radośnie nadpisują sektor startowy dysku (czyli MBR – Master Boot Sector), przez co Windows staje się jedynym systemem dającym się uruchomić w zwykły sposób. Ot, zwyczajowe MS-owe praktyki monopolistyczne ;-)
Jak temu zaradzić? Trzeba oczywiście przywrócić boot sector do właściwego stanu, co oznacza ponowne zainstalowanie używanego przez nas wcześniej bootloadera. W większości przypadków (jeśli mówimy o Linuksie jako drugim systemie) jest nim GRUB; w takim wypadku jego ponowne zainstalowanie wymaga:
Tyle powinno wystarczyć, by po ponownym uruchomieniu komputera z tego dysku pojawiło się nam menu bootowania GRUB-a. Przy odrobinie szczęścia oba systemy będą więc uruchamiały się normalnie ;)
Wczorajsza premiera Windows 7 to dobry pretekst, żeby nowy system w końcu przetestować – zwłaszcza, że większość opinii, których o nim słyszałem, była zdecydowanie przychylna. W połączeniu z faktem, iż system operacyjny na moim laptopie już od dobrych paru miesięcy domaga się skrócenia swoich cierpień, otrzymujemy tylko jeden logiczny wniosek: czas zakasać rękawy i zabrać się za reinstalację!
Ktokolwiek choć raz zajmował się ponownym stawianiem systemu od zera wie, że czynność ta nie należy do relaksujących. Chociaż drobne komplikacje są praktycznie gwarantowane: a to zapomnimy o jakimś sterowniku, a to zapodziejemy gdzieś numer seryjny systemu, i tak dalej. Posiadanie komputera “zapasowego” (w moim przypadku tradycyjnego – stacjonarnego) znacznie redukuje dolegliwość takich problemów, ale nawet i w tej sytuacji warto się do całej operacji dobrze przygotować.
I właśnie dlatego sporządziłem poniższą listę kontrolną czynności, które dobrze jest wykonać przed rozpoczęciem zabawy w reinstalację systemu. Nie gwarantuję oczywiście, że da się przy jej użyciu uniknąć wszelkich kłopotów. Powinna być ona jednak w dużym stopniu pomocna. A wygląda ona następująco:
Pamiętaj też o wszelkich kluczach produktów czy numerach seryjnych, jeśli któryś z systemów ich wymaga.
Uff, spora ta lista. Jej rygorystyczne przestrzeganie może nie zawsze jest konieczne, ale nie wydaje mi się, żeby mogło komukolwiek zaszkodzić :) Akurat w przypadku tej nieczęsto (i coraz rzadziej) wykonywanej czynności, jaką jest reinstalacja systemu, zbytnia przezorność na pewno nie zawadzi.
System Windows pozwala tworzyć okna o różnych niestandardowych właściwościach – między innymi takich, które nie zawierają żadnego standardowego elementu, jak pasek tytułu czy przycisk zamknięcia. Kiedy zechcemy umożliwić przesuwanie takiego okna, to natrafimy na klasyczny problem Windows API, który posiada kilka rozwiązań. I jak to często bywa, mało które jest dobre ;)
Najkrótszym jest obsłużenie komunikatu WM_NCHITTEST
. Przy jego pomocy system pyta okno, w jaką jego część “trafia” (stąd nazwa hit test) podany punkt. Trik polega na oszustwie poprzez udawanie, że prawie całe nasze okno (a przynajmniej jego obszar klienta) jest paskiem tytułu:
Jest to jednak na tyle skuteczne, że wówczas nasze okno naprawdę zacznie składać z samego paska tytułu. Najpoważniejszym (acz wcale nie jedynym) skutkiem ubocznym tego faktu jest niemożność jakiejkolwiek interakcji z kontrolkami zawartymi w oknie. Jeśli więc mamy takowe, to mamy też kłopot :)
Można oczywiście załatwić wszystko ręcznie: wykryć przeciąganie (WM_LBUTTONDOWN
), “złapać” myszkę (SetCapture
), odpowiednio przesuwać okno (np. SetWindowPos
) o różnicę początkowej oraz aktualnej pozycji kursora (w WM_MOUSEMOVE
), a na koniec zwolnić gryzonia (ReleaseCapture
) w odpowiedzi na koniec przeciągania (WM_LBUTTONUP
). Uff… Sporo roboty, nieprawdaż? Tak to jest, kiedy oszustwo nie popłaca :)
A może jednak?… Pomysł z podszyciem się pod pasek tytułu wydawał się dobry, lecz sęk w tym, że nie potrzebujemy (wręcz nie chcemy) całej jego funkcjonalności. Dlatego zamiast dużego przekrętu posłużmy się małym: symulujmy tylko i wyłącznie wciśnięcia lewego przycisku myszy:
Wciśnięcia kierowane w pasek tytułu, rzecz jasna. W ten sposób “wywołamy” niejako tę część jego możliwości, która nas interesuje – czyli przesuwanie okna. Jednocześnie, ponieważ robimy to dopiero w WM_LBUTTONDOWN
, nie przeszkadzamy innym kontrolkom w odpowiadaniu na zdarzenia myszy.
To rozwiązanie ma jeszcze jedną zaletę: daje się je zastosować także w środowiskach, które nie dają łatwego dostępu do procedury zdarzeniowej okna – jak np. Windows Forms. W nich wystarczy wywołać SendMessage
wewnątrz zdarzenia w rodzaju OnMouseDown
(wciśnięcie przycisku myszy nad oknem).