【问题标题】:C++: A Lingering 'ghost' window appears..?C ++:出现一个挥之不去的“幽灵”窗口..?
【发布时间】:2012-11-15 04:56:55
【问题描述】:

我的程序 - 除其他外 - 更改了控制台窗口的外观(主要是窗口大小和边框)。
现在在 我的 计算机上,目前一切正常,但是当我在 VirtualBox不同 计算机上运行应用程序时,我得到以下内容:

图像左上角的窗口实际上并不是一个窗口。这是一个窗口的图像,您无法单击。 (鼠标点击通过)
您可以通过在桌面上拉伸选择矩形来摆脱它,或者突出显示(例如)它下方的按钮。此外,您可以在其上移动一个窗口,使其完全消失。

图片右下角的黑色矩形是我的控制台窗口,显示正确。

我的问题是,如何用 C++ 去除“幽灵”窗口?
我试着用谷歌搜索了一下,但我能找到的只是ChangeDisplaySettings(0, 0);,它在我的电脑上什么也没做(可能是因为我的电脑上什至没有这个问题),在 VirtualBox 中,它首先出现使控制台窗口全屏显示,然后恢复原样。 (第一次运行应用程序时屏幕会闪烁)
虽然它确实删除了幽灵窗口,但我不希望屏幕像那样闪烁,所以这不是我要找的。​​p>

编辑:
由于我无法真正弄清楚与此问题相关的代码是什么,因此我将转储几乎所有与在我的程序中更改窗口本身有关的代码。

CSBIEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
GetConsoleScreenBufferInfoEx(hCon, &CSBIEx);
CSBIEx.dwSize.X = 49;
CSBIEx.dwSize.Y = 21;
SetConsoleScreenBufferInfoEx(hCon, &CSBIEx);
srWnd.Bottom = 20;
srWnd.Left = 0;
srWnd.Right = 48;
srWnd.Top = 0;
SetConsoleWindowInfo(hCon, TRUE, &srWnd);
GetClientRect(hWnd, &rClnt);
rClnt.top += 1;
rClnt.bottom -= 2;
rClnt.right -= 1;
SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP);
exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
exStyle &= ~WS_EX_CLIENTEDGE;
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle);
BringWindowToTop(hWnd);
SetWindowPos(hWnd, HWND_TOPMOST, ((rScr.right / 2) - rClnt.right / 2) - 1, (rScr.bottom / 2) - rClnt.bottom / 2, 0, 0, SWP_FRAMECHANGED | SWP_DRAWFRAME | SWP_NOSIZE);
SetWindowRgn(hWnd, CreateRectRgnIndirect(&rClnt), 1);
ShowWindow(hWnd, SW_SHOWNORMAL);
//ChangeDisplaySettings(0, 0);

第二次编辑:
我不知道它是否有任何帮助,但我注意到如果我使用 ChangeDisplaySettings(NULL, 0); 而不是 ChangeDisplaySettings(0, 0); 它不会做任何事情。考虑到 NULL#defined 0..
这很奇怪 如果没有人能弄清楚任何事情,我可能会最终使用ChangeDisplaySettings(0, 0);

【问题讨论】:

  • 你能做一个short, self contained and correct example 给我们看吗?不看任何代码很难猜出问题所在。
  • 这是在其所有者背后更改 Windows 设置的缺点。由于窗口进程不知道您做了什么,因此无法正确绘制或清除事物。
  • @JoachimPileborg 提供任何相关代码对我来说真的很困难,因为我实际上无法在自己的计算机上复制它,但我会尽我所能添加一些代码。请稍等。
  • 一般提示:不要清除错误代码,调用函数并检查是否有错误代码。而是检查函数的返回值。如果您阅读GetLastError 的文档,则说明某些函数也会在成功时设置“错误”代码。
  • 我一直发现 SetWindowPos 可能会在屏幕上偶尔留下垃圾,除非使用 SWP_NOCOPYBITS 标志。 (不过,我不能说这在这种情况下是否有用。我只用它来移动没有非客户区的子窗口。)

标签: c++ windows winapi user-interface console


【解决方案1】:
InvalidateRect(NULL, NULL, TRUE);

是我一直在寻找的东西。

【讨论】:

    【解决方案2】:

    您是否在计算机上运行“Aero”主题?如果是这样,请切换到经典主题。 Betcha,您将看到问题本身。我认为您的应用程序没有正确处理 WM_PAINT 消息。 Aero 主题发送的 WM_PAINT 消息要少得多。操作系统使用它保存的位图进行绘画。

    编辑:尝试使用新维度调用这些:

    BOOL WINAPI SetConsoleDisplayMode(
        _In_       HANDLE hConsoleOutput,
        _In_       DWORD dwFlags,
        _Out_opt_  PCOORD lpNewScreenBufferDimensions
    );
    

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033%28v=vs.85%29.aspx

    BOOL WINAPI SetConsoleWindowInfo(
      _In_  HANDLE hConsoleOutput,
      _In_  BOOL bAbsolute,
      _In_  const SMALL_RECT *lpConsoleWindow
    );
    

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms686125%28v=vs.85%29.aspx

    您也可以尝试使用 DispatchMessage 向自己发送 WM_PAINT 消息。

    【讨论】:

    • 你说的很对,关闭 Aero 后我的电脑也能看到 bug。问题是它是一个控制台应用程序,所以我无法处理 WM_PAINT 消息(或任何消息)。我该怎么办?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    相关资源
    最近更新 更多