2010-01-12 20 views
13

Potrzebuję więc proceduralnie generować obraz tła dla siatki, to tylko zajmuje .1sec.WpF zmień rozmiar kompletny

Dzięki temu mogę podłączyć się do zdarzenia SizeChanged, ale gdy zmienisz rozmiar wykresu, będzie on mógł odpalić nawet 30 razy na sekundę, więc wielkość zmiany będzie znacznie mniejsza.

Czy ktokolwiek zna dobry sposób na podłączenie się do zdarzenia zmiany rozmiaru i testowania pogody zmiana rozmiaru jest wykonywana, próbowałem po prostu sprawdzać stan myszy w górę/w dół, ale po uruchomieniu zdarzenia zmiany rozmiaru mysz jest prawie zawsze wyłączona .

+0

Jaka jest natura obrazu? Czy jest to obraz rastrowy czy wektorowy? Powodem jest to, że może istnieć lepsze podejście, w zależności od charakteru tego, co próbujesz zrobić. – codekaizen

+0

Jest to raster i opiera się na nieco skomplikowanej matematyce. Nie jestem do końca obeznany z możliwościami grafiki wektorowej, ale załóżmy, że na razie nie można tego zrobić w xaml. –

+0

@JoelBarsotti: Najlepszym rozwiązaniem jest wywoływanie "GenerateImage()" dwukrotnie w sizechanged eventhandler –

Odpowiedz

21

Podczas zmiany rozmiaru można uruchomić krótkotrwały zegar (powiedzmy 100 ms), po każdym resetowaniu rozmiaru tego zegara, aby zapobiec jego upływowi. Kiedy nastąpi zmiana rozmiaru, licznik czasu upłynie, a następnie można narysować obraz tła.

Przykład:

Timer resizeTimer = new Timer(100) { Enabled = false }; 

public Window1() 
{ 
    InitializeComponent(); 
    resizeTimer.Elapsed += new ElapsedEventHandler(ResizingDone); 
} 

void ResizingDone(object sender, ElapsedEventArgs e) 
{ 
    resizeTimer.Stop(); 
    GenerateImage(); 
} 

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    resizeTimer.Stop(); 
    resizeTimer.Start(); 
} 
+1

to wydaje się trochę jak hack, ale hej hack, który działa, jest o wiele lepszy niż ten nietknięty kod, który się psuje. –

+1

@Joel, domyślam się, że jest to najłatwiejszy sposób, ponieważ zmiana rozmiaru okna jest faktycznie wykonywana przez Window Chrome, który nie jest częścią WPF w rodzimym oknie, więc nie będziesz mieć takich zdarzeń, aby pracować. Alternatywą jest stworzenie własnego okna Chrome, własnego stylu okna bez obramowań, aw swoim stylu trzeba będzie odtworzyć całą ramkę okna i napisać kod zdarzeń myszy. –

+0

Jestem za najłatwiejszy, hack lub nie, jeśli 10 linii kodu, które są prawie takie same i 1000 linii, wezmę 10 linii za każdym razem. –

0

Czy trzeba zobaczyć zmianę rozmiaru obrazu? Możesz obsłużyć zmianę rozmiaru i ponownie renderować obraz po zdarzeniu myszy.

+0

To była moja pierwsza myśl, ale kiedy spróbowałem, nie mogłem wymyślić, jak złapać poprawne zdarzenie mouseup, jestem czymś w rodzaju WPF newb i jestem małpą w kodzie elses. Kod, nad którym pracowałem, jest wstawiany jako element potomny do innego obiektu. Rozumiem, że są to rozgałęzione i tunelowane zdarzenia, co muszę zrobić, to złapać wersję tunelowania.Rozumiem, że te zdarzenia mają zwykle prefiks Podglądu, a nie widziałem go dla przycisku myszy. –

+0

Znalazłem wydarzenie .PreviewMouseLeftButtonUpEvent, ale nie wydaje się, aby uruchomił się po zakończeniu zmiany rozmiaru. –

2

Dla .Net 3.5 i późniejsze Pete Brown describes rozwiązanie z dołączoną właściwością przy użyciu metody Blends System.Windows.Interactivity.dll.

Tam można podłączyć zmianę rozmiaru zdarzenia, aby zatrzymać generowanie obrazu, a zmiana rozmiaru zdarzenia rozpocznie generowanie obrazu dla nowego rozmiaru.

HTH

0

najlepszym rozwiązaniem jest, aby zadzwonić "GenerateImage()" dwukrotnie w sizechanged eventhandler

1

Chciałbym użyć metody Dispatcher.BeginInvoke. Zapewni to, że obraz zostanie wygenerowany tylko wtedy, gdy aplikacja ma czas na jego przetworzenie.

private bool _generateImageReqested = false; 

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    if (!_generateImageReqested) 
    { 
     _generateImageReqested = true; 
     Dispatcher.BeginInvoke(new Action(GenerateImage), DispatcherPriority.ApplicationIdle); 
    } 
} 

private void GenerateImage() 
{ 
    _generateImageReqested = false; 

    // resize your image here 
} 
4

Oto czyste rozwiązanie:

private const int WmExitSizeMove = 0x232; 

private void OnLoaded(object sender, RoutedEventArgs args) 
{ 
    var helper = new WindowInteropHelper(this); 
    if (helper.Handle != null) 
    { 
     var source = HwndSource.FromHwnd(helper.Handle); 
     if (source != null) 
      source.AddHook(HwndMessageHook); 
    } 
} 

private IntPtr HwndMessageHook(IntPtr wnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
{ 
    switch (msg) 
    { 
     case WmExitSizeMove: 
      // DO SOMETHING HERE 
      handled = true; 
      break; 
    } 
    return IntPtr.Zero; 
} 

Powodzenia!