【问题标题】:Starting a windows-application with focus启动具有焦点的 Windows 应用程序
【发布时间】:2012-06-13 05:17:01
【问题描述】:

我正在用 Visual C++ 编写一个没有 MVC 的小型 Windows 应用程序。它真的很小,它只包含一个文本字段、一个确定按钮和一个取消按钮。

当用户开始打印时,应用程序由后台进程启动。打开应用程序时没有获得焦点,甚至不可见。

对于用户来说,应用程序直接处于焦点是很重要的,因此他们可以通过尽可能多的点击来使用它。

我尝试了很多方法来使应用程序成为焦点:

SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(hWnd);
ShowWindow(hWnd, SW_RESTORE);
SetFocus(hWnd);

我什至在计时器中重复了这个调用。这一切都行不通。现在我在 MSDN 上找到了一些注释:

系统限制哪些进程可以设置前台窗口。一个 只有满足以下条件之一时,进程才能设置前台窗口 条件为真:

The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.

有人知道解决方法吗?

【问题讨论】:

    标签: winapi visual-c++


    【解决方案1】:

    没有解决方法。这种新的 Windows 行为的全部意义在于防止应用程序自行将自己带到前台并造成麻烦。在您的情况下,我建议使用通知图标并在必要时显示气球消息而不是窗口。但是,即使在这种情况下,您的通知图标也可能被用户隐藏,并且没有解决方法,原因与上述相同。

    【讨论】:

    • 很不满意。如果我的应用程序没有直接弹出,我会遇到真正的用户接受问题。是否有任何 Windows 选项或任何东西可以防止这种行为或允许我的应用程序弹出?最后的手段是模拟点击任务列表,但这真的是我最不想做的事情
    • 不,没有这个选项,否则所有程序都会自己设置这个选项。请参阅blogs.msdn.com/b/oldnewthing/archive/2009/02/26/9445006.aspx 和相关帖子,了解有关此“军备竞赛”的讨论。您将不得不使用通知区域或重新考虑您的 UI。你的用例到底是什么?您的兼容性要求是什么?
    • 应用程序“中断”并弹出的一个问题是它们最终可能会无意中“窃取输入”。过去我曾多次在某些文本编辑器中输入内容,出现一些随机弹出对话框,我在输入时按了空格键,然后对话框消失了,因为空格键最终触发了一些确定或取消按钮 - 在我有机会阅读对话框之前!像这样的问题正是 SetForegroundWindow 以这种方式被“禁用”的原因 - 以及为什么要引入通知气球。
    【解决方案2】:

    现在,这是来自 Java 开发人员而不是 Visual C++ 开发人员,但是您可以将 frame/window/whatever-its-call-in-visual-c 设置为始终位于顶部吗?在 Java 中,如果你有一个JFrame,比如myJFrame,你可以调用myJFrame.setAlwaysOnTop(true),它会保持在所有其他窗口的顶部。这似乎是解决您的问题的一个简单解决方法,但是如果它在屏幕上阻止了用户的某些内容,则用户可能不希望这样做。

    【讨论】:

    • 这行不通,因为窗口一开始就没有显示出来。
    • 哦,我的错。我误解了。我以为它出现了,就在所有其他窗口的下方。
    【解决方案3】:

    http://www.thescarms.com/vbasic/alttab.aspx 似乎可以完成这项工作

    void forceToFront(HWND hWnd) {
    HWND foregroundWindow = GetForegroundWindow();
    
    if (foregroundWindow == hWnd) {
        // Window is already Foreground-window
        return;
    }
    
    if (SetForegroundWindow(hWnd)) {
        // could set window to foreground without any tricks
        return;
    }
    
    // attach thread of foreground-window to this window
    DWORD foregroundThread = GetWindowThreadProcessId(foregroundWindow, NULL);
    DWORD myThread = GetWindowThreadProcessId(hWnd, NULL);
    AttachThreadInput(foregroundThread, myThread, true);
    SetForegroundWindow(hWnd);
    AttachThreadInput(foregroundThread, myThread, false);
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多