我有一個WPF自定義的虛擬鍵盤應用程式。我需要將此 WPF 應用程式作為獨立主機托管,并且用戶應該能夠使用它為任何視窗應用程式輸入值。
如何獲取當前聚焦的應用程式視窗?例如:notepad、notepad 或任何其他接受輸入的視窗應用程式。
我試過下面的代碼來獲取當前的活動視窗,但它回傳 WPF 虛擬鍵盤應用程式本身,因為它也處于活動狀態
var window = System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(w => w.IsActive);
下面的代碼作業正常,但這windowname需要param設定foregroundwindow
public partial class MainWindow : Window{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
private void button1_Click(object sender, RoutedEventArgs e){
SetForegroundWindow(FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad"));
}
}
uj5u.com熱心網友回復:
要獲取當前活動視窗句柄,您可以使用user32.dll 中的GetForegroundWindow。
在 C# 中,它應該看起來像
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
或者,如果您的應用程式視窗將成為活動視窗,您可以使用GetWindow
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
enum GetWindow_Cmd : uint {
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
因此,您可以將自己的視窗句柄作為第一個引數和GW_HWNDNEXT第二個引數傳遞。結果,您將獲得當前視窗下方的視窗句柄。
編輯
正如 IInspectable 所提到的,上述內容在 WPF 應用程式中不起作用。
但是您可以嘗試使用EnumWindows使用以下內容:
// Get own hWnd
WindowInteropHelper windowHwnd = new(this);
IntPtr ownHwnd = windowHwnd.Handle;
// Find target hWnd
IntPtr targetHWnd = IntPtr.Zero;
NativeMethods.EnumWindows((hWnd, lParam) =>
{
if (hWnd == ownHwnd) { return true; } // Ignore own window
if (!NativeMethods.IsWindowVisible(hWnd)) { return true; } // Ignore hidden windows
if (GetClassName(hWnd).Equals("Shell_TrayWnd", StringComparison.OrdinalIgnoreCase)) { return true; } // Ignore taskbar window
if (string.IsNullOrEmpty(GetWindowTitle(hWnd))) { return true; } // Ignore windows without a title
targetHWnd = hWnd; // Found target hWnd
return false; // Stop iterating
}, IntPtr.Zero);
// Used functions
private string GetWindowTitle(IntPtr hWnd)
{
int textLength = NativeMethods.GetWindowTextLength(hWnd);
StringBuilder sb = new(textLength 1);
NativeMethods.GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
private string GetClassName(IntPtr hWnd)
{
StringBuilder sb = new(256);
NativeMethods.GetClassName(hWnd, sb, sb.Capacity);
return sb.ToString().Trim();
}
internal static class NativeMethods
{
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
internal delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
}
編輯 2
為確保創建 WPF hWnd,您可以使用WindowInteropHelper.EnsureHandle()方法而不是Handle屬性。如果尚未顯示 WPF 視窗,這一點很重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/474446.html
上一篇:即使呼叫了DeleteEnhMetaFile(),CopyEnhMetaFile()之后的檔案訪問System.IO.Exception
