我尝试从工作线程调用2个Win32 API函数:
-
SetforeGroundindow
-
FlashWindowEx
这两个Win32函数都需要hWnd作为参数。我尝试了两种不同的方法来获得有效的hWnd:
-
HwndSource=(HwndSource)HwndSource。FromVisual(窗口);
IntPtr hWnd=源。手柄
-
WindowInteropHelper WindowInteropHelper=新的WindowInteropHelper(窗口);
IntPtr hwnd=windowInteropHelper。手柄
从工作线程调用时,我收到:
System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'
在里面net Core、WPF、作为“Dispatcher”属性的窗口,但Dispatcher没有CheckAccess或VerifyAccess。
所以我有几个问题:
-
我想要使用的2 Win32 Api不需要从主窗口线程调用。有没有办法让hWnd直接给他们打电话而不用进行线程检查?
-
为什么调度器上没有CheckAccess或VerifyAccess,以及在中是什么替代了这两个选项。net核心WPF(与.net framework WPF的区别)?
-
我获取hWnd的两种方法有什么区别?最好的方法是什么?
-
做我想做的事最好的方法是什么?
作为参考,这是我的代码。注释显示异常发生的位置:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
namespace UnmanagedCore.WindowEx
{
public static class WindowExtension
{
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static bool SetForegroundWindow(this Window window)
{
// WindowInteropHelper windowInteropHelper = new WindowInteropHelper(window);
// IntPtr hwnd = windowInteropHelper.Handle;
HwndSource source = (HwndSource)HwndSource.FromVisual(window); // System.InvalidOperationException
IntPtr hWnd = source.Handle;
return SetForegroundWindow(hWnd);
}
public static T RunSafeWindowAction<T>(this Window window, Func<T> func)
{
// Missing code here ... waiting answer from StackOverflow to write proper code
return func();
}
[StructLayout(LayoutKind.Sequential)]
public struct FLASHWINFO
{
public UInt32 cbSize;
public IntPtr hwnd;
public UInt32 dwFlags;
public UInt32 uCount;
public UInt32 dwTimeout;
}
public enum FlashWindow : uint
{
/// <summary>
/// Stop flashing. The system restores the window to its original state.
/// </summary>
FLASHW_STOP = 0,
/// <summary>
/// Flash the window caption
/// </summary>
FLASHW_CAPTION = 1,
/// <summary>
/// Flash the taskbar button.
/// </summary>
FLASHW_TRAY = 2,
/// <summary>
/// Flash both the window caption and taskbar button.
/// This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
/// </summary>
FLASHW_ALL = 3,
/// <summary>
/// Flash continuously, until the FLASHW_STOP flag is set.
/// </summary>
FLASHW_TIMER = 4,
/// <summary>
/// Flash continuously until the window comes to the foreground.
/// </summary>
FLASHW_TIMERNOFG = 12
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
/// <summary>
/// Flashes a window
/// </summary>
/// <param name="hWnd">The handle to the window to flash</param>
/// <returns>whether or not the window needed flashing</returns>
public static bool FlashWindowEx(IntPtr hWnd)
{
FLASHWINFO fInfo = new FLASHWINFO();
fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
fInfo.hwnd = hWnd;
fInfo.dwFlags = (int)FlashWindow.FLASHW_ALL;
fInfo.uCount = UInt32.MaxValue;
fInfo.dwTimeout = 0;
return FlashWindowEx(ref fInfo);
}
/// Minor adjust to the code above
/// <summary>
/// Flashes a window until the window comes to the foreground
/// Receives the form that will flash
/// </summary>
/// <param name="hWnd">The handle to the window to flash</param>
/// <returns>whether or not the window needed flashing</returns>
public static bool FlashWindowEx(this Window window)
{
HwndSource source = (HwndSource)HwndSource.FromVisual(window);
IntPtr hWnd = source.Handle;
FLASHWINFO fInfo = new FLASHWINFO();
fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
fInfo.hwnd = hWnd;
fInfo.dwFlags = (int)(FlashWindow.FLASHW_ALL | FlashWindow.FLASHW_TIMERNOFG);
fInfo.uCount = UInt32.MaxValue;
fInfo.dwTimeout = 0;
return FlashWindowEx(ref fInfo);
}
}
}