问题描述
我有一个 WPF 应用程序,它使用 Process.Start() 方法打开一个新进程 (Notepad.exe)。我编写了防止用户移动记事本窗口的代码,其中窗口的 Top 属性不能小于 130 像素。我使用了来自此 SO question 的信息,最终使用以下代码来管理此运动
这是我在移动目标窗口时定义的windows事件委托:
protected void TargetMoved(IntPtr hWinEventHook,Hook.SWEH_Events eventType,IntPtr hWnd,Hook.SWEH_ObjectId idobject,long idChild,uint dwEventThread,uint dwmsEventTime)
{
if (hWnd == targethWnd &&
eventType == Hook.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE &&
idobject == (Hook.SWEH_ObjectId)Hook.SWEH_CHILDID_SELF)
{
rect = Hook.GetwindowRect(hWnd);
int x = rect.Left;
int y = rect.Top;
int width = rect.Right - rect.Left;
int height = rect.Bottom - rect.Top;
if (rect.Left <= 0)
x = 0;
if (rect.Top <= 130)
y = 130;
UnsafeNativeMethods.MoveWindow(targethWnd,x,y,width,height,true);
}
}
这段代码工作正常,它使窗口保持在边界内,但有一个恼人的问题:当窗口被拖动到 130 像素标记上方时(当 Top 小于 130 时),窗口在它们之间来回闪烁我拖动它的位置,以及它停止的位置。
如何消除这种闪烁?
解决方法
当你拖动一个窗口时,WM_WINDOWPOSCHANGING
和WM_WINDOWPOSCHANGED
会被发送到窗口过程,然后重新绘制更改。如果这个窗口过程是你自己创建的,那么你就可以处理这两条消息,把left和top限制为0和130。
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS* pos = (PWINDOWPOS)lParam;
if (pos->x <= 0)
pos->x = 0;
if (pos->y <= 130)
pos->y = 130;
return 0;
}
如果这不是你的窗口过程,你需要SetWindowSubclass
,但是你不能跨线程子类化一个窗口,你还需要使用代码注入。
所以,对于记事本窗口,你不能简单地解决这个问题, 正如评论所说,您可以简单地将编辑控件集成到您自己的窗口中。然后像上面的代码一样处理窗口消息。