【问题标题】:SetWindowPos/MoveWindow persist issueSetWindowPos/MoveWindow 仍然存在问题
【发布时间】:2011-02-04 02:45:40
【问题描述】:

我正在使用SetWindowPosMoveWindow 调整窗口大小和居中。它工作正常,但在 Windows Media Player 或控制面板等多个窗口上,当您关闭窗口并再次打开它时,不会反映新的调整大小/移动。当我手动调整大小时,更改会在我下次打开窗口时反映出来。即使我打电话给UpdateWindow,这些变化也不会反映出来。我需要发送窗口以保存更改吗? RedrawWindow 有帮助吗?谢谢?

【问题讨论】:

  • 问题是那些 API 显式设置了窗口大小(我不确定目标应用程序甚至接收到一个事件 - 但我可能是错的),所以在内部没有设置窗口大小当窗口未最小化时被应用程序“记住”。我不知道如何解决这个问题,但我会研究一下 SendMessage API 之类的东西。
  • 有趣的是,当我以编程方式调整大小时,我手动将鼠标悬停在窗口边缘,直到获得调整大小的鼠标光标,然后我只需向下和向上单击(而不是单击和拖动),然后关闭窗口,以编程方式设置的新大小被保存。不知何故,我需要向窗口发送一些消息,与手动调整大小时发送的消息相同。
  • 您是否尝试过 Spy++ 来查看执行此操作时会触发什么事件?
  • 当你使用SetWindowPos函数时,目标窗口实际上会收到一个带有更新参数的WM_WINDOWPOSCHANGING message。这就是它首先移动的原因。您可以使用 Spy++ 看到这一点。但这仍然不能解决您的问题;详情见我的回答。

标签: c# .net windows winapi window-position


【解决方案1】:

您应该使用 GetWindowPlacementSetWindowPlacement 函数来检索和更改窗口的恢复、最小化和最大化位置。这可确保应用程序正确保存窗口大小,以便在下次启动时恢复它们。

由于您使用的是 C#,因此您需要从 Windows API 中 P/Invoke 这些函数:

const int SW_HIDE = 0;
const int SW_SHOWNORMAL = 1;
const int SW_SHOWMINIMIZED = 2;
const int SW_SHOWMAXIMIZED = 3;

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

[StructLayout(LayoutKind.Sequential)]
struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

[StructLayout(LayoutKind.Sequential)]
struct WINDOWPLACEMENT
{
    public int length;
    public int flags;
    public int showCmd;
    public Point ptMinPosition;
    public Point ptMaxPosition;
    public RECT rcNormalPosition;
}

【讨论】:

  • 非常感谢您的意见,我明天会试试这个,并将更新您的结果。非常感谢。
  • @user577240:当然,没问题。我意识到这是一个非常丑陋的代码混乱,但问题是窗口必须为每个可能的位置(最小化、正常和最大化)保留不同的大小信息。这应该做你想要的。如果您需要从 C# 调用它的帮助,请告诉我。
  • NativeMethods.WINDOWPLACEMENT 放置 = 新 NativeMethods.WINDOWPLACEMENT(); Placement.length = Marshal.SizeOf(placement); NativeMethods.GetWindowPlacement(hwnd, outplacement); Placement.rcNormalPosition.bottom = 宽度; Placement.rcNormalPosition.right = 高度;放置.rcNormalPosition.left = x;放置.rcNormalPosition.top = y; NativeMethods.SetWindowPlacement(hwnd, 参考位置);
  • 好的,我找到了解决方案,谢谢。我按照你的建议去了 Spy++ 并开始监视我手动移动的窗口,我发现 WM_ENTERSIZEMOVE 和 WM_EXITSIZEMOVE 总是被调用。所以我只是用 WM_ENTER... 和 WM_EXIT 做了两次 SendMessage,媒体播放器和控制面板的大小保持不变。非常感谢您的帮助科迪。
猜你喜欢
  • 2011-01-08
  • 2010-11-14
  • 2014-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 2021-10-14
相关资源
最近更新 更多