Nowa polska strona Imagine Cup

Od wczoraj dostępna jest nowa polska strona o Imagine Cup. Jak wiecie w tym roku finały Imagine Cup odbędą się w Polsce. Na stronie możecie się dowiedzieć więcej o kategoriach i zasadach konkursu. Zapraszam do czytania i oczywiście do udziału w konkursie.

icpl

Tagi:

Microsoft Windows 7 Summit

Już za około miesiąc na sklepowych półkach pojawi się Microsoft Windows 7. Od miesiąca studenci uczelni techniczny, których wydziały posiadają MSDN AA mogą korzystać z najnowszego systemu z Redmond. Zapewne większość z Was chciała by się dowiedzieć lub poszerzyć swoją wiedzę na temat Windows 7. Już za niedługo będzie taka okazja.

windows7summit

7 października pięciu MVP we współpracy z Microsoftem zaprezentuje nowy system podczas wydarzenia on-line Microsoft Windows 7 Summit. Agenda tej mini konferencji zapowiada się bardzo ciekawie. Dlatego każdy, kto w tej chwili nie ma planów na wieczór 7 października, nie już dziś zarezerwuje sobie wolnych czas oraz zarejestruje się na wydarzenie.

Tagi: ,

Ruszyła strona cyklu konferencji IT Academic Day - ankieta

Przed chwilą ruszyła strona cyklu konferencji IT Academic Day. Na niej będą znajdować się wszelkie informacje dotyczące wszystkich ITADów organizowanych na uczelniach techniczny w Polsce.

stronaitad

W tej chwili organizatorzy planują tematykę najbliższego cyklu konferencji (listopad-grudzień 2009). Na stronie cyklu IT Academic Day pojawiła się ankieta, w której każdy może podzielić się  tym, o czym chciałby posłuchać na ITADach. Dlatego zapraszam to wypełniana ankiety. Pamiętajcie każdy głos jest ważny!!!

Tagi: ,

WPF Webbrowser, Frame i WebBrowser w WinForms - porównanie

Chcąc wczytać stronę www do naszej aplikacji w WPF'ie mamy trzy możliwości (pod warunkiem posiadania .net 3.5 SP1)

  1. wykorzystać kontrolkę WebBrowser (System.Windows.Controls.WebBrowser)
  2. wykorzystać kontrolkę Frame (System.Windows.Controls.Frame)
  3. oraz skorzystać w kontrolki WebBrowser z winforms (System.Windows.Forms.WebBrowser)

Dzisiejszy wpis będzie porównaniem tych trzech sposobów w kontekście pobierania i przetworznia kodu wczytanej strony.

Zacznijmy od stworzenia projektu (lub ściągnięcia gotowego kodu) gdzie dodajemy Grida z trzema kolumnami, w których kolejno będą kontrolki z punktów 1,2,3. Z dodaniem kontrolek WebBrowser i Frame z WPF'a nie powinno być żadnych problemów (przeciągamy je z ToolBox'a), lecz aby dodać WebBrowser z WinForms na początku musimy dodać dwie referencje do naszego projektu:System.Windows.Forms i WindowsFormsIntegration a następnie kontrolkę WindowsFormsHost w której to umieścimy WebBrowser'a z WinForms.

 

   1: <Grid>
   2:        <Grid.ColumnDefinitions>
   3:            <ColumnDefinition Width="*"></ColumnDefinition>
   4:            <ColumnDefinition Width="*"></ColumnDefinition>
   5:            <ColumnDefinition Width="*"></ColumnDefinition>
   6:        </Grid.ColumnDefinitions>
   7:        <Grid.RowDefinitions>
   8:            <RowDefinition Height="*"></RowDefinition>
   9:        </Grid.RowDefinitions>
  10:        
  11:        <DockPanel Grid.Column="0" Grid.Row="0" >
  12:            <TextBlock x:Name="tbWpfWBDesc" DockPanel.Dock="Top" Height="25" Margin="2" FontWeight="Bold" HorizontalAlignment="Center">Wpf WebBrowser Control</TextBlock>
  13:            <Button x:Name="btnWBPageLoad" DockPanel.Dock="Bottom">New Page</Button>
  14:            <WebBrowser x:Name="wbPage" ></WebBrowser>
  15:            
  16:        </DockPanel>
  17:        
  18:        <DockPanel Grid.Column="1" Grid.Row="0">
  19:            <TextBlock x:Name="tbFrameDesc" DockPanel.Dock="Top" Height="25"  Margin="2" FontWeight="Bold" HorizontalAlignment="Center">Wpf Frame Control</TextBlock>
  20:           <Button x:Name="btnFrmPageLoad" DockPanel.Dock="Bottom" >New Page</Button> 
  21:            <Frame x:Name="frmPage"></Frame>
  22:           
  23:        </DockPanel>
  24:        
  25:        <DockPanel Grid.Column="2" Grid.Row="0">
  26:            <TextBlock x:Name="tbWinWBDesc" DockPanel.Dock="Top" Height="25" Margin="2"  FontWeight="Bold" HorizontalAlignment="Center">Wpf Frame Control</TextBlock>
  27:            <Button x:Name="btnWinFormPageLoad" DockPanel.Dock="Bottom">New Page</Button>
  28:            <WindowsFormsHost>
  29:                <wf:WebBrowser x:Name="wbWinFormPage" />
  30:                
  31:            </WindowsFormsHost>
  32:            
  33:        </DockPanel>
  34:    </Grid>

Mamy już nasz widok, teraz aby wczytać stronę do naszych kontrolek wystarczy wywołać metodę Navigate z adresem strony (każda kontrolka ma trochę inną sygnaturę tej metody, lecz wszystkie udostępniają przeciążoną wersję  Navigate(Uri source) ). Wywołajmy ją zaraz po załadowaniu okna wczytując losową stronę z wikipedi (http://pl.wikipedia.org/wiki/special:random), gdy uruchomimy nasz projekt zobaczymy że załadują się trzy różne strony dodatkowo warto zauważyć że możemy przechodzić do innych stron klikając linki. Do tej pory różnic raczej nie zauważymy (prócz innych pasków przewijania w ostatniej kontrolce) i jeżeli w waszej aplikacji zależy wam tylko na prezentacji danej strony to wszystkie kontrolki są dobre. Warto także zauważyć że wszystkie obsługują historię przeglądanych stron.
Przejdźmy teraz do meritum, czyli po załadowaniu strony chcemy pobrać jej kod i tutaj pojawiają się już znaczące różnice.

WebBrowser z WPF

Pozwala na wyświetlanie strony www, wykonuje kod javascript oraz obsługuje flash’a jeżeli jest zainstalowany. Warto zwrócić na kilka eventów do których możemy się podpiąć:

  • Navigating – pozwala na podjęcie jakiejś akcji przed żądaniem strony, pomocna przy anulowaniu żądania (ustawiająć e.Cancel=true), parametr typu NavigatingCancelEventArgs dostarczy nam podstawowych informacji o żądaniu, lecz co się okazuje jedna z ważniejszych właściwości WebRequest jest ustawiana na NULL :)

NavigatinCancelArgs 

  • Navigated – nawiązano połączenie, rozpoczęto ściąganie dokumentu, może nie być jeszcze w całości
  • LoadCompleted – ściąganie dokumentu już się zakończyło, powinien być w całości (w praktyce korzystać z tego zdarzenia)
  • Dwa kolejne zdarzenia wywoływane po nawiązaniu już połączenia z serwerem, obie w parametrze dostają obiekt NavigationEventArgs. Po przyjrzeniu się jego właściwościom ucieszymy się na widok WebResponse, z którego możemy pobrać strumień i go odczytać (będziemy mieli upragniony kod strony) np. takim kodem

       1: if(e.WebResponse!=null)
       2: {
       3:     //always false
       4:     var response = e.WebResponse;
       5:     var responseStream = (Stream)response.GetResponseStream();
       6:     var readStream = new StreamReader(responseStream, true);
       7:  
       8:  
       9:     //absolut URI 
      10:     var address = response.ResponseUri.AbsoluteUri;
      11:     var webContent = readStream.ReadToEnd();
      12: }

    lecz życie byłoby zbyt piękne gdyż okazuje się że on także jest ustawiany na NULL

    NavigationEventArgs

    co nam zostaje, a może sama kontrolka ma właściwość z której pobierzemy kod? Otóż okazuje się że tak jest to właściwość Document, a więc do dzieła, trzeba dodać referencję do Microsoft.mshtml

       1: mshtml.HTMLDocument document = wbPage.Document as mshtml.HTMLDocument;
       2: string pageHtml = document.documentElement.outerHTML;

    No pięknie jesteśmy w domu mamy pobrany kod HTML. Przyjrzyjmy mu się bliżej, pobraliśmy stronę z wikipedii zgodną z XHTML a tutaj dostajemy HTML’a bez zamkniętych tagów bez DocType itp. jednak nie o to nam chodziło. Kod jest automatycznie modyfikowany i transformowany właśnie do HTML.

       1: <HTML dir=ltr lang=pl xml:lang="pl" xmlns="http://www.w3.org/1999/xhtml"><HEAD><TITLE>Akademia Świętego Łukasza – Wikipedia, wolna encyklopedia</TITLE>
       2: <META content="text/html; charset=utf-8" http-equiv=Content-Type>
       3: <META content=text/css http-equiv=Content-Style-Type>
       4: <META name=generator content="MediaWiki 1.16alpha-wmf">
       5: <META name=keywords content="Akademia Świętego Łukasza,1577,Architekt,Cech,Europa,Haft,Malarstwo,Papież Grzegorz XIII,Rzeźba,Rzym,Wł."><LINK title=Edytuj rel=alternate type=application/x-wiki href="/w/index.php?title=Akademia_%C5%9Awi%C4%99tego_%C5%81ukasza&amp;action=edit">
       6: ....

    Wobec powyższego powstaje pytanie, czy istnieje możliwość pobrania kodu załadowanej strony z kontrolki WebBrowser z WPF’a? Ja nie znalazłem jak to można zrobić :)

    Frame

    Pozwala na wczytywanie stron www oraz WPF Pages. Posiada eventy podobne do WebBrowser, mają one także podobną sygnaturę

    • Navigating
    • Navigated
    • LoadCompleted

    Lecz tym razem obiekty WebRequest i WebResponse w zdarzeniach są ustawiane, hura :)

    frmNavigationEventArgs 

    Zabieramy się do pobierania kodu strony, czytając z strumienia korzystając z kodu

       1: if (e.WebResponse != null)
       2: {
       3:     var response = e.WebResponse;
       4:     var responseStream = (Stream)response.GetResponseStream();
       5:  
       6:     //uwaga wyrzuca wyjątek
       7:     //throw ArgumentException Stream was not readable.
       8:     var readStream = new StreamReader(responseStream, true);
       9:     string webContent = readStream.ReadToEnd();
      10:  
      11:     var address = response.ResponseUri.AbsoluteUri;
      12:  
      13: }

    lecz dostaniemy wyjątek “Stream was not readable” czyli nie odczytamy kodu strony. Poza tym pojawia się drugi problem iż zdarzenia (Navigating, Navigated, LoadCompleted) są wywoływane tylko za pierwszym razem, gdy klikamy w linki i przechodzimy do nowych stron żaden handler nie jest wywoływany. Gdy jawnie wywołamy metodę Navigate to handlery zadziałają lecz obiekt WebResponse będzie równy Null i strona w kontrolce się nie zmieni pomaga wywołanie metody Refresh. Wobec powyższych i ta kontrolka nie pozwala na pobranie kodu załadowanej strony.

    WebBrowser from WinForms

    Działa podobnie jak WebBrowser z WPF’a pozwala załadowanie strony, wykonuje javascript oraz flash’a. Nas będą interesowały zdarzenia:

    • Navigating
    • Navigated
    • DocumentCompleted

    Zdarzenia wywoływane są w podobnych okolicznościach co w powyższych przykładach, lecz dostają inne obiekty odpowiednio WebBrowserNavigatingEventArgs, WebBrowserNavigatedEventArgs, WebBrowserDocumentCompletedEventArgs. Zbadajmy ostatnie zdarzenie i parametry jakie dostaje

    winDocumentCompletedEventArgs

    niestety nie ma obiektu WebResponse tylko sam Url strony którą pobrano. Ale nie załamujmy się otóż okazuje się że WebBrowser z WinForms ma jedną cenną właściowść DocumentText, która zwraca tekst pobranej strony (bez żadnych modyfikacji) aby go pobrać wystarczy

       1: void wbWinFormPage_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
       2: {
       3:     string webContent = wbWinFormPage.DocumentText;
       4: }

    Przy korzystaniu z tej kontrolki zauważyłem dodatkowo że każdy handler wywoływany jest dwa razy. Pierwszy z Url’em == “auto:blank” a drugi z tym właściwym, lecz jakoś mi to nie przeszkadzało.

    Podsumowanie

    Chcąc dać użytkownikowi możliwość przeglądania stron www w naszej aplikacji możemy zastosować te trzy kontrolki, lecz jeżeli chcemy mieć dostęp do źródła strony, wiedzieć kiedy nastąpiło żądanie nowej strony pod jaki adres kieruje się użytkownik to zdecydowanie polecam WebBrowser z WinForms.

    Ściągnij przykład

    Tagi: , ,

    Eastgroup.pl na facebooku