Projekt: WebToImg
Program WetToImg służy do zapisywania stron internetowych w postaci plików png z dodanym efektem rosnącego w prawą stronę przyciemniania. Adresy stron są pobierane z pliku .csv. W tym momencie generowane są obrazki o rozmiarach 1000 x 400 pikseli. Okno programu prezentuje się następująco:
Jak widać można wybrać plik z listą stron oraz folder do którego będą zapisywane obrazki. Tak to wygląda w trakcie działania:
Poniżej plik wygenerowany przez WebToImg:
Jak się okazało najtrudniejszą sprawą było samo zapisanie strony wyświetlanej przez kontrolkę do pliku graficznego. W tym celu wykorzystałem funkcję SendMessage zaimportowaną z bibliotego user32.dll, która pozwala na wysyłanie poleceń WinApi do okien (kontrolki również są przez api traktowane jak okna). Trzeba było wysłać polecenie WM_PAINT i kazać kontrolce „namalować się” na bitmapie. Do wyświetlenia strony posłużył WebKit ponieważ, jak się okazało lepiej współpracował z poleceniem WM_PAINT niż standardowy WebBrowser z biblioteki .NET. W trakcie pisania okazało się, że kontrolka, którą chcę narysować nie może mieć ustawionego pola Visible na false bo wtedy wynikowe bitmapy były całe białe. Ten problem ominąłem przesuwając WebKitBrowser poza widoczny obszar okna aplikacji i wyłączyłem możliwość jego zmiany przez użytkownika. Dzięki temu strona cały czas ma włączoną widoczność, a jednak nie jest widoczna dla osoby korzystającej z programu.
Efekt przyciemniania jest to proste odejmowanie od składowych koloru odpowiedniej wartości zależnej od współrzędnej x.
Jako źródło z adresami stron wybrałem plik csv ponieważ jest bardzo łatwy do odczytania z poziomu i Excel pozwala na zapisanie w nim prostej tabeli bez potrzeby sięgania po dodatkowe konwertery.
Na początku zamiast napisu „ukończone” chciałem dać pasek postępu jednak nie udało mi się jak na razie zmusić go do pracy w takich sposób jak chciałem.
Przetwarzanie i zapisywanie na dysk bitmap jest umieszczone w funkcji wywoływanej przy zdarzeniu DocumentCompleted przeglądarki. Daje mi to pewność, że strona zostanie zapisana dopiero po jej całkowitym załadowaniu. Działa to w ten sposób, że pierwsze wywołanie funkcji przechodzącej do odpowiedniej strony jest w funkcji obsługującej kliknięcie przycisku „Generuj” co prowadzi do pierwszego wywołania zdarzenia DocumentCompleted. Następnie już w samej funkcji obsługującej to zdarzenie strona jest rysowana na bitmapie, dodawany jest efekt zaciemniania, bitmapa jest zapisywana na dysk, po czym ponownie jest wywoływana funkcja przenosząca pod kolejny adres co z kolei znowu prowadzi do wystąpienia zdarzenia DocumentComplited itd…
W tym momencie w kodzie brakuje jeszcze zabezpieczenia przed brakiem możliwości połączenia się z serwerem witryny. Przydało by się również przenieść cały proces zapisywania strony do osobnego wątku co pozwoliłoby na dodanie możliwości anulowania zadania. Teraz jest to możliwe jedynie poprzez zamknięcie aplikacji.
Projekt jest pisany w języku C# z wykorzystaniem środowiska Visual C# 2010 Express.
Poniżej film pokazujący działanie programu:
Tak żeby zrobić jakiś ruch w komentarzach na stronie: Jak program zachowuje się przy stronach które doczytują swoją zawartość już po załadowaniu (biorąc pierwszy przykład z brzegu webklient GMail – choć na tym trudno byłoby chyba wykonać test ze względu na konieczność zalogowania)?
Program robiłem wg podanej mi specyfikacji i np. ze względu na strony flashowe jest to rozwiązane tak, że każdy screen jest robiony z 2 sekundowym opóźnieniem tak żeby niektóre elementy zdążyły się wczytać(co zostało już dodane po publikacji tego posta). Poza tym screen jest robiony dopiero po otrzymaniu od przeglądarki zdarzenia załadowania strony.