关注表单加载问题

时间:2012-11-14 23:07:35

标签: c# winforms focus

我有一个ActiveX控件(用VB 6.0或C ++编写),我们在C#WinForms程序中用作AxInterop。它非常像一个文本框,但有一些特殊的逻辑等......我们已将它添加到工具栏中。

当表单加载时,我希望键盘焦点位于此控件内部,因此我在其上使用了.Focus.Select方法,但仍然无法获得焦点。

当我从Visual Studio运行时,控件获得焦点。

当我在IDE外部运行时,控件无法获得焦点。

为什么会这样?

以下是它的屏幕截图:

enter image description here

2 个答案:

答案 0 :(得分:1)

您可以使用WindowsApi.SetFocus方法设置焦点 此方法可用于将注意力设置在 an external application 中的特定控件上,因此它应该可以在您的应用程序中使用第三方控件。

这是另一个选项 - 在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 ++

答案 1 :(得分:1)

当您尝试将焦点放在焦点上时,您确定该组件是否可见?

如果您尝试在Form.Load事件处理程序中进行聚焦,请尝试将其移至Form.Shown处理程序,或者Control.Enter

行为上的差异可能会导致时间问题。 看一下on MSDN,了解更多创意在开场表单上发生事件的顺序。