SaveFileDialog button events in WPF - wpf

I have a SaveFileDialog in my WPF Project.
If the SaveFileDialog is closed via the red 'x' in the corner, I want the dialog to close and the user to be returned to the main application.
However, if the SaveFileDialog is 'canceled', I want the entire application to close.
The only issue I am having is knowing if the user has pressed the red x or the cancel button. They both evaluate to false in the code below.
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Text file (*.txt)|*.txt";
var dlg = saveFileDialog.ShowDialog();
if (dlg == true)
{
//When the user presses save
File.WriteAllLines(saveFileDialog.FileName, rowList);
ExitApp();
}
else if (dlg == false)
{
//This occurs when red x or cancel is pressed.
}
Is there any way to distinguish between the two in WPF?

The answer is short and simple:
"no"
See Microsoft documentation here

It is not so simple, but you can do it by using hooks and the SetWindowsHookEx method.
First of all we need a class for registering and unregistering our hook:
public class WinHooker
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
private HookProc hookDelegate;
private int hookHandle;
private bool wasClosedButtonPressed;
private static WinHooker instance;
private WinHooker()
{
}
public static WinHooker Instance
{
get
{
if (instance == null)
{
instance = new WinHooker();
}
return instance;
}
}
public bool WasClosedButtonPressed
{
get
{
return wasClosedButtonPressed;
}
}
public void Register()
{
wasClosedButtonPressed = false;
hookDelegate = this.HookProcHandler;
hookHandle = SetWindowsHookEx(5,
hookDelegate,
IntPtr.Zero,
AppDomain.GetCurrentThreadId());
}
public void Unregister()
{
UnhookWindowsHookEx(hookHandle);
hookHandle = 0;
hookDelegate = null;
}
private int HookProcHandler(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
if (nCode == 8 && wParam == 0xF060)
{
wasClosedButtonPressed = true;
}
}
return CallNextHookEx(hookHandle, nCode, wParam, lParam);
}
}
As you can see I used 5 as the first parameter for the SetWindowsHookEx, since it correspond to the WH_CBT value (refer to the SetWindowsHookEx page). Moreover the values in the method HookProcHandler (i.e. nCode == 8 && wParam == 0xF060) can be retrived from here.
Now let's use our class in the code:
SaveFileDialog saveFileDialog = new SaveFileDialog();
WinHooker.Instance.Register();
saveFileDialog.ShowDialog();
WinHooker.Instance.Unregister();
if (WinHooker.Instance.WasClosedButtonPressed)
{
MessageBox.Show("Oh my God! What have you done??");
}
As you can understand WasClosedButtonPressed is set to true just if the user closes the dialog by clicking on the red 'x' in the corner. Otherwise it is false.
I hope it can help you.

Related

UnhookWindowsHookEx produces ERROR_INVALID_HOOK_HANDLE?

I'm trying to implement a background application in WPF that does some things only when right-clicking the top of the screen, so I tried hooking WH_MOUSE_LL, which works great. The problem is unhooking the callback when exiting the application, which works perfectly fine in C, but gives me ERROR_INVALID_HOOK_HANDLE in C# even though the hook handle passed to UnhookWindowsHookEx is exactly the same handle I got from SetWindowsHookEx (examples below).
EDIT: I just created a bare bones C# console application registering the same hook and instantly unregistering it and it works fine too, so I think WPF might cause the problems.
Here is the C# code that does not work, problem is in the destructor:
using System;
using System.Runtime.InteropServices;
public class LowLevelMouseHook {
#region Win32 API
private const int WH_MOUSE_LL = 14;
private const ulong WM_RBUTTONDOWN = 0x0204;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate long LowLevelMouseProc (int nCode, UIntPtr wParam, IntPtr lParam);
private struct POINT {
long x;
long y;
}
private struct MSLLHOOKSTRUCT {
POINT pt;
int mouseData;
int flags;
int time;
UIntPtr dwExtraInfo;
}
[DllImport("User32.dll", EntryPoint = "CallNextHookEx", SetLastError = true)]
private static extern long CallNextHookEx (IntPtr hHook, int nCode, UIntPtr wParam, IntPtr lParam);
[DllImport("Kernel32.dll", EntryPoint = "GetLastError", SetLastError = true)]
private static extern uint GetLastError ();
[DllImport("Kernel32.dll", EntryPoint = "LoadLibraryW", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr LoadLibrary (string lpFileName);
[DllImport("User32.dll", EntryPoint = "SetWindowsHookExW", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx (int idHook, Delegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("User32.dll", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
private static extern byte UnhookWindowsHookEx (IntPtr hHook);
#endregion
// There shall only be one instance of this class
private static LowLevelMouseHook instance = null;
private IntPtr hHook;
private LowLevelMouseProc hProc; // If I don't store the delegate, I get some CallbackOnCollectedDelegate exception
private LowLevelMouseHook () {
this.hProc = new LowLevelMouseProc(MouseProc);
this.hHook = SetWindowsHookEx(WH_MOUSE_LL, this.hProc, LoadLibrary("User32.dll"), 0);
}
~LowLevelMouseHook () {
//
// PROBLEM:
// UnhookWindowsHookEx always returns 0 and GetLastError returns ERROR_INVALID_HOOK_HANDLE (1404)
// even though this.hHook is still the same value SetWindowsHookEx returned.
//
if (UnhookWindowsHookEx(this.hHook) == 0)
System.Windows.Forms.MessageBox.Show($"Error {GetLastError()} unhooking WH_MOUSE_LL", "UnhookWindowsHookEx Error");
LowLevelMouseHook.instance = null;
}
// Create new LowLevelMouseHook instance.
// This is called during the Startup-Event of Application.
public static void Init () {
LowLevelMouseHook.instance = new LowLevelMouseHook();
}
private static long MouseProc (int nCode, UIntPtr wParam, IntPtr lParam) {
if ((ulong)wParam == WM_RBUTTONDOWN) {
; // Things to do; that works fine
}
return CallNextHookEx(LowLevelMouseHook.instance.hHook, nCode, wParam, lParam);
}
}
Here is the C code that works perfectly fine:
#include <stdio.h>
#include <Windows.h>
FILE *file;
HHOOK hHook;
LRESULT CALLBACK LowLevelMouseProc_Test (int nCode, WPARAM wParam, LPARAM lParam) {
PMSLLHOOKSTRUCT pHookStruct = (PMSLLHOOKSTRUCT)lParam;
fprintf(file, "MouseProc_Test(nCode = %i, wParam = %lu, lParam->pt = (%i, %i))\n", nCode, wParam, pHookStruct->pt.x, pHookStruct->pt.y);
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
VOID CALLBACK TimerProc_Test (HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
PostQuitMessage(0);
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nShow) {
fopen_s(&file, "wm_mouse_ll.txt", "w");
hHook = SetWindowsHookExW(WH_MOUSE_LL, LowLevelMouseProc_Test, LoadLibrary("User32.dll"), 0);
if (hHook != 0) {
fprintf(file, "SetWindowsHookExW Success (hHook = 0x%p)\n", hHook);
SetTimer(NULL, 0, 5000, TimerProc_Test);
MSG msg = {0};
while (GetMessageW(&msg, NULL, 0, 0) != 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (UnhookWindowsHookEx(hHook) != 0)
fputs("UnhookWindowsHookEx Success\n", file);
else
fprintf(file, "UnhookWindowsHookEx Error %u\n", GetLastError());
} else {
fprintf(file, "SetWindowsHookExW Error %u\n", GetLastError());
}
fclose(file);
return 0;
}
Ok, I simply restructured LowLevelMouseHook a little bit and added a custom Main() method that looks like the one below. UnhookWindowsHookEx now succeeds.
public static class EntryPoint {
public static void Main () {
LowLevelMouseHook.Begin() // Here SetWindowsHookEx is called
App.Main() // Original entrypoint
LowLevelMouseHook.End() // Here UnhookWindowsHookEx is called
}
}

How to capture MouseUp event outside the WPF window?

The subject is all in the title. Sorry if it's a duplicate, I really couldn't find anything on SO.
Well, many thanks to Anatoliy Nikolaev for steering me in the right direction! That article helped me much and this answer was useful to make code from the article work. This is what I have now:
internal static class MouseHook
{
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
private static int _mouseHookHandle;
private static HookProc _mouseDelegate;
private static event MouseUpEventHandler MouseUp;
public static event MouseUpEventHandler OnMouseUp
{
add
{
Subscribe();
MouseUp += value;
}
remove
{
MouseUp -= value;
Unsubscribe();
}
}
private static void Unsubscribe()
{
if (_mouseHookHandle != 0)
{
int result = UnhookWindowsHookEx(_mouseHookHandle);
_mouseHookHandle = 0;
_mouseDelegate = null;
if (result == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
private static void Subscribe()
{
if (_mouseHookHandle == 0)
{
_mouseDelegate = MouseHookProc;
_mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL,
_mouseDelegate,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
0);
if (_mouseHookHandle == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (wParam == WM_LBUTTONUP)
{
if (MouseUp != null)
{
MouseUp.Invoke(null, new Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y));
}
}
}
return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONUP = 0x0202;
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
}
public delegate void MouseUpEventHandler(object sender, Point p);
And using it is pretty simple:
MouseHook.OnMouseUp += MouseHookMouseUp;

WPF Listview does not scroll (with mouse wheel) when Application not in focus

I have a WPF app (written in C#) which has a Listview control which scrolls perfectly with the mouse wheel when the app is in focus.
However when the app is not in focus, even when the mouse pointer is over the app & list view area, the Listview does not scroll. I continue to see mousehover related effects on the app but no mousewheel event is received. This is inline with how most of the other apps work on my desktop however some of them (like Facebook messenger) support scrolling without focus which i would like to mimic in my WPF app.
I have searched MSDN forums and Stackoverflow and seen multiple solutions for Windows Forms however they were questions asked over 5 years ago and i was wondering if someone has managed to do it relatively easily on .net 4.5 and can point me to possible solutions.
---Edit---
I was able to progress to some extent on this thanks to this thread C# ListView mouse wheel scroll without focus
Here is how my the function that receives the mousewheel looks
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
Console.WriteLine((short)((hookStruct.mouseData)>>16));
MouseWheelEventArgs myArgs = new MouseWheelEventArgs(System.Windows.Input.Mouse.PrimaryDevice, (int)hookStruct.time, (short)((hookStruct.mouseData)>>16));
myMainFrame.SidePanelControl.ScrollTheListView(myArgs);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
As you can see i am initializing a MouseWheelEventArgs instance and have the time, delta and the mouse device attributes.
How do i go about passing this mousewheel event to my listview scrollviewer?
Managed to get this working. Here is my class.
All one needs to do to use the class is
Initialize InterceptMouse passing it the app/listview/etc pointer
Start intercepting the mouse when the app is not in focus but the corresponding mouseenter event has occured.
As long as the event is mousewheel the scrollviewer of the listview will be sent the mouseWheel event.
Stop intercepting the mouse when the app gets activated or mouseleave is called.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Forms;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Forms.Integration;
namespace myApp.HelperClasses
{
public class InterceptMouse
{
public static System.Windows.Controls.ListView myListview;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public InterceptMouse(System.Windows.Controls.ListView myListviewParam)
{
myListview = myListviewParam;
}
public static void StartIntercepting()
{
_hookID = SetHook(_proc);
}
public static void StopIntercepting()
{
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
//Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y + "," + hookStruct.mouseData);
var delta = (short)((hookStruct.mouseData) >> 16);
var mouse = InputManager.Current.PrimaryMouseDevice;
var args = new MouseWheelEventArgs(mouse, Environment.TickCount, delta);
args.RoutedEvent = WindowsFormsHost.MouseWheelEvent;
Decorator border = VisualTreeHelper.GetChild(myListview, 0) as Decorator;
// Get scrollviewer
ScrollViewer scrollViewer = border.Child as ScrollViewer;
scrollViewer.RaiseEvent(args);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}

When minimized into the system tray, a WPF Window does not respond to message from PostMessage from the other instance when

I am working on a task to restore and maximize a window from system tray when the second instance of the same application starts.
When the 2nd instance starts and fail to grab the mutex. It calls the following code to signal the first instance to show itself:
public static void ShowFirstInstance()
{
WinApi.PostMessage(
(IntPtr)WinApi.HWND_BROADCAST,
WM_SHOWFIRSTINSTANCE,
IntPtr.Zero,
IntPtr.Zero);
}
The message is registered using the following:
public static readonly int WM_SHOWFIRSTINSTANCE =
WinApi.RegisterWindowMessage("WM_SHOWFIRSTINSTANCE|{0}", 250);
I have following in the code behind of the window to catch the message and show the window:
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == SingleInstance.WM_SHOWFIRSTINSTANCE)
{
WinApi.ShowToFront(hwnd);
}
return IntPtr.Zero;
}
When I test it out. Whenever the first instance hide in the system tray, the message never caught. Do I miss anything?
Thanks,
Here's how I've done this in the past:
App.xaml.cs:
private static readonly Mutex Mutex = new Mutex(true, "{" + YourGuidHere + "}");
//return true if other instance is open, allowing for UI cleanup/suspension while shutdown() is completed
private bool EnforceSingleInstance()
{
//try...catch provides safety for if the other instance is closed during Mutex wait
try
{
if (!Mutex.WaitOne(TimeSpan.Zero, true))
{
var currentProcess = Process.GetCurrentProcess();
var runningProcess =
Process.GetProcesses().Where(
p =>
p.Id != currentProcess.Id &&
p.ProcessName.Equals(currentProcess.ProcessName, StringComparison.Ordinal)).FirstOrDefault();
if (runningProcess != null)
{
WindowFunctions.RestoreWindow(runningProcess.MainWindowHandle);
Shutdown();
return true;
}
}
Mutex.ReleaseMutex();
}
catch (AbandonedMutexException ex)
{
//do nothing, other instance was closed so we may continue
}
return false;
}
WindowFunctions:
//for enum values, see http://www.pinvoke.net/default.aspx/Enums.WindowsMessages
public enum WM : uint
{
...
SYSCOMMAND = 0x0112,
...
}
//for message explanation, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx
private const int SC_RESTORE = 0xF120;
public static void RestoreWindow(IntPtr hWnd)
{
if (hWnd.Equals(0))
return;
SendMessage(hWnd,
(uint)WM.SYSCOMMAND,
SC_RESTORE,
0);
}
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,
uint msg,
uint wParam,
uint lParam);

How can I prevent focus stealing, but still get focus when returning to my app using Alt+Tab?

Following MS guidelines, my WPF application's App constructor includes the following code for proper focus behavior:
HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
Keyboard.DefaultRestoreFocusMode = RestoreFocusMode.None;
As explained in this article, these settings prevent focus stealing.
However, setting DefaultRestoreFocusMode to None has a bad side effect. When using Alt+Tab to leave a WPF application and then return to it, the WPF application doesn't get focus. However, if I don't set DefaultRestoreFocusMode to none, it does get focus as expected. Is there a way to prevent focus stealing but have focus still set when returning to a WPF application via Alt+Tab?
-Craig
I prevent my wpf window from getting focus by doing the below and i can still activate it by using ALT-TAB or clicking on it's taskbar item.
Here you change the window styles on your window so that it has no activate.
var yourWindow = new YourWindowType();
//set the windowstyle to noactivate so the window doesn't get focus
yourWindow.SourceInitialized += (s, e) =>
{
var interopHelper = new WindowInteropHelper(yourWindow);
int exStyle = User32.GetWindowLong(interopHelper.Handle, (int)WindowLongFlags.GWL_EXSTYLE);
User32.SetWindowLong(interopHelper.Handle, (int)WindowLongFlags.GWL_EXSTYLE, exStyle | (int)WindowStylesEx.WS_EX_NOACTIVATE);
//If you have trouble typing into your form's textboxes then do this
ElementHost.EnableModelessKeyboardInterop(yourWindow);
};
This is something i added as an extra precaution, plus it lets you drag your window around if it is borderless:
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
//don't activate the window when you click on it.
case WindowMessage.WM_MOUSEACTIVATE:
handled = true;
return (IntPtr)MouseActivate.MA_NOACTIVATE;
//For Borderless Windows: occurs while dragging. it reports new position before it has been finalized.
//otherwise you wont see the window moving while you're dragging it
case WindowMessage.WM_MOVING:
RECT rect = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT));
User32.SetWindowPos(new WindowInteropHelper(this).Handle, Hwnd.HWND_TOPMOST,
rect.Left, rect.Top, rect.Width, rect.Height,
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOSIZE);
break;
}
return IntPtr.Zero;
}
These add a hook so that WndProc is actually called in WPF:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if (source == null) return;
source.AddHook(WndProc);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if (source == null) return;
source.RemoveHook(WndProc);
}
Just an FYI.. this still works even though you don't get focus:
private void WpfPillForm_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
Here's the Win32 API declarations so you don't have to look them up:
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
public int left, top, right, bottom;
}
public static class MouseActivate
{
public const int MA_ACTIVATE = 1;
public const int MA_ACTIVATEANDEAT = 2;
public const int MA_NOACTIVATE = 3;
public const int MA_NOACTIVATEANDEAT = 4;
}
public enum WindowLongFlags : int
{
GWL_EXSTYLE = -20,
GWLP_HINSTANCE = -6,
GWLP_HWNDPARENT = -8,
GWL_ID = -12,
GWL_STYLE = -16,
GWL_USERDATA = -21,
GWL_WNDPROC = -4,
DWLP_USER = 0x8,
DWLP_MSGRESULT = 0x0,
DWLP_DLGPROC = 0x4
}
public const int WM_MOVING = 0x0216;
public const uint WS_EX_NOACTIVATE = 0x08000000,
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowLong(IntPtr hwnd, int index);

Resources