我有一个 ActiveX 控件(可能是用 VB 6.0 或 C++ 编写的),我们在 C# WinForms 程序中用作 AxInterop。它非常像一个文本框,但有一些特殊的逻辑等......我们已经将它添加到工具栏。
当表单加载时,我希望键盘焦点位于此控件内,因此我在其上使用了.Focus
和.Select
方法,但它仍然没有获得焦点。
当我从 Visual Studio 运行时,控件获得焦点。
当我在 IDE 之外运行时,控件没有获得焦点。
为什么是这样?
这是它的屏幕截图:
您可以使用WindowsApi.SetFocus方法来设置焦点。
此方法可用于将焦点设置在外部应用程序中的特定控件上,因此它应该在您的应用程序中的第 3 方控件上工作。
这是另一个选项 - 一个工作代码块,用于在 winforms 中为外部应用程序中的控件设置焦点:
[DllImport("user32.dll")]
static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThread();
[DllImport("user32.dll")]
static extern bool AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll")]
static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, string lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, string className);
[DllImport("user32.dll")]
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder pszType, uint cchType);
void SetFocus(IntPtr hwndTarget, string childClassName)
{
// hwndTarget is the other app's main window
// ...
IntPtr targetThreadID = GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id
IntPtr myThreadID = GetCurrentThread(); // calling thread id, our thread id
bool lRet = AttachThreadInput(myThreadID, targetThreadID, true); // attach current thread id to target window
// if it's not already in the foreground...
lRet = BringWindowToTop(hwndTarget);
SetForegroundWindow(hwndTarget);
// Enumerate and find target to set focus on
EnumChildWindows(hwndTarget, OnChildWindow, childClassName);
}
List<object> windowHandles = new List<object>();
static bool OnChildWindow(IntPtr handle, string className)
{
// Find class of current handle
StringBuilder pszType = new StringBuilder();
pszType.Capacity = 255;
RealGetWindowClass(handle, pszType, (UInt32)pszType.Capacity);
string s = pszType.ToString();
// Remove (potentially) unneeded parts of class
if (s.Length > className.Length)
{
s = s.Substring(0, className.Length);
}
// Set focus on correct control
if (s == className)
{
SetFocus(handle);
}
return true;
}
private void Form1_Load(object sender, EventArgs e)
{
InitializeComponent();
SetFocus(this.Handle, "<ClassName from Spy++>");
}
如果您不知道该文本框的类名,您可以使用spy++
当您尝试赋予它焦点时,您确定该组件是可见的吗?
如果您尝试在Form.Load
事件处理程序中进行聚焦,请尝试将其移至Form.Shown
处理程序,或者也许Control.Enter
.
行为上的差异可能归结为时间问题。在 MSDN 上查看打开表单上事件发生的顺序以获得更多想法。