There seemed to be quite a lot of interest in my previous post on non-rectangular spash screen and I also received a lot of requests to post code to move around such a window.
The magic to this is to use a thumb and then use the dragdelta event. The code would look something like this:
void
b_Click(object sender, RoutedEventArgs e){
HwndSourceParameters sParams = new HwndSourceParameters("Layered window", 200, 200); sParams.UsesPerPixelOpacity =
true; _source =
new HwndSource(sParams); _source.Disposed +=
new EventHandler(_source_Disposed); Thumb t = new Thumb(); t.Height = 200;
t.Width = 200;
t.DragDelta += MoveImage;
Image vista = new Image(); vista.Margin =
new Thickness(0); BitmapImage bi = new BitmapImage(); bi.BeginInit();
bi.UriSource =
new Uri(@"pack://siteoforigin:,,,/vista.jpg"); bi.EndInit();
vista.Source = bi;
FrameworkElementFactory fe = new FrameworkElementFactory(typeof(Image), "Image"); fe.SetValue(
Image.SourceProperty, bi);
ControlTemplate ct = new ControlTemplate(typeof(Thumb)); ct.VisualTree = fe;
t.Template = ct;
Canvas body = new Canvas();
body.Width = 200d;
body.Height = 200d;
body.Children.Add(t);
_source.RootVisual = body;
}
void _source_Disposed(object sender, EventArgs e)
{
Dispatcher.InvokeShutdown();
}
private void MoveImage(object s, DragDeltaEventArgs e)
{
top += (int)e.HorizontalChange;
left += (int)e.VerticalChange;
SetWindowPos(_source.Handle, IntPtr.Zero, top, left, 200, 200, 0);
}
private int top = 0, left = 0;
HwndSource _source;
[DllImport("User32.dll", SetLastError = true)]
internal static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int Flags);
The final result consists of an image which you can move around since we make use of a thumb.(below you see two images of vista - bear in mind that the code above can create multiple images but the moving around would work only with the latest window created because we only track the latest :) )
The dragdelta handler calculates the drag and repositions the window. We change the template of the so that the entire window/image acts as a Thumb and consequently, wherever you drag on the image the entire image moves. The simpler thing to do would be to create a simple thumb but then the window can be moved only when you drag the thumb. This would be the common usage since most of the times an app can be moved only on dragging certain parts of the app.
One thing to note is that I have used a disposed handler. (not really useful if Hwndsource is being created from an existing window) This is necessary if you create an HwndSource from the MainApp (OnStartUp). Why? Because if the hwndsource is closed the app still continues to exist the reason being that Application is a Framework concept while Application is a Core concept. The other way to do this is to add a hook to the HwndSource and then listen to the WM_CLOSE msg and then call the dispatcher. This would be lengthier but is the more appropriate way to do it considering coding style. ;)
btw I have now started using Expression Interactive Designer and it does make things a lot simpler. So hopefully will find time to create something on it and then have it posted. EID for the Feb CTP will be released this month. Let your imagination loose!!!...
文章来源:
http://blogs.msdn.com/llobo/archive/2006/03/04/543762.aspx