15

So I need to procedurally generate a background image for a grid, it only takes .1sec.

So I can wire into the SizeChanged event, but then when you resize the chart, it goes and fires the event maybe 30 times a second, so the resize event lags out signifigantly.

Does anybody know a good way to wire into the resize event and test weather the use is done resizing, I tried simply checking for the mouse up/down state, but when the resize event fires the mouse is pretty much always down.

3
  • What is the nature of the image? Is it a raster or a vector image? The reason is that there could be a better approach, depending on the nature of what you are trying to do.
    – codekaizen
    Commented Jan 12, 2010 at 5:05
  • It's raster and is based on some somewhat complicated math. I'm not entirely familiar with capabilities of vector art, but lets assume it can't be done in xaml for now. Commented Jan 12, 2010 at 5:35
  • @JoelBarsotti : Best solution is to call "GenerateImage()" twice in the sizechanged eventhandler Commented Jun 4, 2012 at 20:24

6 Answers 6

25

On resize, you could start a short lived timer (say 100 mSec), on each resize reset that timer to prevent it from elapsing. When the last resize happens, the timer will elapse, and you can draw your background image then.

Example:

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();
}
3
  • 1
    this seems a bit like a hack, but hey a hack that works is much better that pristine code that breaks. Commented Jan 12, 2010 at 6:41
  • 1
    @Joel, I guess this is the only easiest way, because window resizing is actually done by Window Chrome which is not part of WPF in native window, so you will not get any such mouse up events to work with. Alternative is to create your own Window Chrome, your own style of window without borders and in your style you will need to recreate entire window frame and write the code of mouse events.
    – Akash Kava
    Commented Jan 12, 2010 at 7:07
  • I'm all for easiest, hack or not if 10 lines of code that are almost the same and 1000 lines, I'll take the 10 lines every time. Commented Jan 12, 2010 at 23:43
7

Here is the clean solution:

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;
}

Good luck!

2

For .Net 3.5 and later Pete Brown describes a solution with an attached Property using Blends System.Windows.Interactivity.dll.

There you could wire the Resizing event to stop generating your image and in Resized event start to generate the image for the new size.

HTH

1

I would use the Dispatcher.BeginInvoke method. This will ensure that your image is only generated when the application has time to process it.

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
}
0

Do you need to see the image resizing? You could handle the resize and re-render the image on mouse up event.

2
  • That was my first thought, but when I tried it I couldn't figure out how to catch the correct mouseup event, I'm sort of a WPF newb and I'm monkey about in someone elses code. The code I was working on is inserted as a child element inside another object. What I understand is that there are bubbling and tunneling routed events, what I need to do is catch the tunneling version. My understanding is that those events are typically have a Preview prefix, and I didn't see one for mouseleftbuttonup. Commented Jan 12, 2010 at 6:37
  • well I found the .PreviewMouseLeftButtonUpEvent event, but it doesn't seem to fire when I'm done resizing. Commented Jan 12, 2010 at 6:39
0

Best solution is to call "GenerateImage()" twice in the sizechanged eventhandler

Not the answer you're looking for? Browse other questions tagged or ask your own question.