5

我有一个捕捉到屏幕边缘的 WPF 应用程序(如果您在屏幕边缘的 20 像素范围内,我只需设置窗口的 .Top 或 .Left),但我最近添加了 WPF SDK 团队提供的一些代码到“窗口镶边的混乱”,虽然它工作得很好(截图),但它导致“快照”意外移动窗口(例如:当它应该直接向下捕捉到底部时它会跳到左边)

我将其范围缩小到他们对 WM_NCCALCSIZE 的处理......这真的很奇怪,因为他们基本上什么都不做,他们只是说他们处理它,然后返回 0。

根据 WM_NCCALCSIZE 的文档,这应该只是导致整个窗口被视为客户端(没有非客户端边缘),但不知何故,这也意味着每当我的 snap-to 代码将窗口向下移动到屏幕底部,它也向左移动了大约 134 像素 ...(移动到其他边缘也有类似的副作用),只要我按住鼠标拖动它,它就会从它应该在的位置来回闪烁。如果我将 WM_NCCALCSIZE 处理注释掉,则 snap-to 会按应有的方式工作(但表单看起来不正确)。

我已经在 WM_NCCALCSIZE 处理程序中尝试了所有我能做的事情,但我无法阻止它向左跳......当然,WM_NCCALCSIZE 只有在窗口大小发生变化时才会被调用,所以我不明白它是如何导致的这首先!

PS如果您想实际查看代码,它已经在 CodePlex 上,在两个文件中,查找_HandleNCCalcSizeOnWindowLocationChanged

4

2 回答 2

6

发生这种情况的原因是处理WM_NCCALCSIZE更改窗口的整体大小......但是如果您正在移动窗口,在WM_MOVEor期间更改您的位置WM_WINDOWPOSCHANGED(对应于 WPFWindowPositionChanged事件)会导致另WM_NCCALCSIZE一条消息......

在期间进行更改WM_NCCALCSIZE(甚至只是断言您处理了消息)会导致另一个调用WM_MOVE... 这使您进入一个循环,其中 positionchanged 消息的“FROM”部分保持不变(使窗口从它开始的位置“跳转”到您在WM_MOVE一遍又一遍地调整它的位置,因为它在之后变回WM_NCCALCSIZE)。

正确的方法

你要做的,就是顺从陈瑞峰,处理WM_WINDOWPOSCHANGING。它发生这些其他消息之前,这样它们就不会相互干扰!

于 2008-11-04T02:09:20.743 回答
0

wParam 似乎总是 TRUE (1) 而 lParam 是一个 NCCALCSIZE_PARAMS ...

目的是完全按照您所说的去做:强制整个窗口成为“客户端”,然后使用 Vista DWM apis 将框架扩展到客户端区域。我只是不明白为什么它向左移动这么远......

如果我跟踪或断点 HandleNCCalcSize 方法,当我调整窗口大小时(当它位于边缘以便触发 snap-to 时),NCCalcSize 被调用两次:一次它应该在的地方,然后离开到左边,它结束的地方向上。

于 2008-10-10T22:48:47.567 回答