【问题标题】:How do I force my app to come to the front and take focus?我如何强制我的应用程序出现在前面并集中注意力?
【发布时间】:2010-10-15 20:35:27
【问题描述】:

我正在开发一个应用程序,该应用程序恰好是我也在开发的安装程序的引导程序。该应用程序进行了几次 MSI 调用以获取我需要的信息,以便将作为我的应用程序主窗口的向导组合在一起,这会导致在收集信息时打开一个进度窗口,然后在完成后消失。然后设置并启动向导。我的问题是向导(从 CPropertySheet 派生)不想在没有我添加一些调用的情况下出现在最前面并成为活动应用程序。

我已经在我的 OnInitDialog() 方法中使用以下代码解决了将其置于最前面的问题:

SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // force window to top
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // lose the topmost status that the previous line gave us

我的问题是我还没有弄清楚如何让窗口自动激活(即,让自己成为拥有焦点的窗口)。 SetFocus() 在这种情况下不起作用。我需要一些东西来强制窗口到 Z 顺序的顶部并激活它,最好是在尽可能少的调用中。

我的猜测是 MSI 调用在开始时打开的进度窗口导致主窗口出错,但我无法阻止该窗口出现。此外,隐藏它是没有意义的,因为它可以让用户在主窗口到达之前知道发生了什么。

【问题讨论】:

    标签: c++ windows mfc propertysheet dialogbasedapp


    【解决方案1】:

    安德鲁并不完全正确。 Windows 确实会尽力阻止您窃取焦点,但可以使用以下方法。

    1. 附加到当前具有焦点的窗口线程。
    2. 让您的窗口成为焦点。
    3. 从线程中分离。

    代码会是这样的:

    DWORD dwCurrentThread = GetCurrentThreadId();
    DWORD dwFGThread      = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
    
    
    AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);
    
    // Possible actions you may wan to bring the window into focus.
    SetForegroundWindow(hwnd);
    SetCapture(hwnd);
    SetFocus(hwnd);
    SetActiveWindow(hwnd);
    EnableWindow(hwnd, TRUE);
    
    AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);
    

    您可能需要也可能不需要以管理权限运行您的程序才能使其正常工作,但我已经亲自使用过这段代码,它已经完成了工作。

    【讨论】:

    • 这在 Windows 10 1703(创作者更新)中不起作用
    【解决方案2】:

    你不能窃取焦点。期间。

    请参阅这篇旧新事物文章:

    https://blogs.msdn.microsoft.com/oldnewthing/20090220-00/?p=19083

    【讨论】:

    • 谢谢,我一直在寻找这篇文章作为这个问题的答案。请阅读此内容的每个人,将其内化并修复试图窃取前台激活的病毒模因。但我的应用程序很特别!您的应用程序对用户怀有敌意。不要这样做!
    • 我同意,尽管这很可能适用于作者,但他(或其他人)可能有充分的理由需要此功能(仅限封闭系统、私人或家用计算机)。提出使用建议,但不要隐藏信息。
    • 我希望微软能够——总有一天——最终一劳永逸地解决所有的焦点窃取问题。做焦点窃取的程序员应该被派往西伯利亚。裸体。
    • 听起来它完全适用于您的情况。您有流程 A 启动流程 B,并且您希望流程 B 获得关注。正如文章所解释的,解决方案是进程 A 必须给予进程 B 焦点 - 进程 B 不能自己获得焦点。
    • 对于以下内容:RobH 的情况正是您不应该窃取焦点的原因。如果我启动一个启动某个进程的应用程序,您可以打赌我在等待它加载时正在输入一封电子邮件。现在你的焦点窃取应用程序很可能会在我按下回车键的同时询问是否可以做某事......只是不要这样做。
    【解决方案3】:

    ShowWindow(youwindow,SW_SHOWNORMAL) 不工作吗? -不要

    【讨论】:

    • 没试过,但我猜它并不比BringWindowToTop()有效。 (请参阅我对 Mitch Wheat 回复的评论。)
    【解决方案4】:

    您会发现,BringWindowToTop 或 SetForegroundWindow 必须满足一些要求,然后才能将窗口实际强制置于所有其他窗口(应用程序)的前面。如果不满足这些条件,Windows 只会在任务栏中闪烁应用程序的图标。 This 文章提出了一种解决方法,但正如 1800 INFORMATION 指出的那样,不建议这样做。我想你只需要接受它。

    【讨论】:

    【解决方案5】:

    应用“窃取”焦点是有充分理由的。我的应用程序是一个加载许多驱动程序 DLL 的服务器。另一个连接到服务器的应用程序有一个按钮,该按钮向服务器发送消息以显示其中一个 DLL(由服务器拥有,而不是客户端应用程序拥有)中的详细信息,以方便使用。不幸的是,这个弹出的打开窗口通常隐藏在多个窗口下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 2013-05-10
      • 1970-01-01
      • 2022-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      相关资源
      最近更新 更多