-1

I have a WPF application that opens a new process (Notepad.exe) using the Process.Start() method. I wrote code that prevents the user from moving the Notepad window where the Top property of the window cannot be less that 130 pixels. I used info from this SO question where I eventually used the following code to manage this movement

Here is the windows event delegate that I defined when the target window is moved:

    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);
            
        }
    }

This code works fine, it keeps that window within the boundaries, but there is an annoying issue: While the window is being dragged above the 130 pixel mark (when Top becomes less than 130), the window flickers back and forth between where I am dragging it, and where it is being stopped.

How can I remove this flickering?

Ray
  • 4,679
  • 10
  • 46
  • 92
  • You can't. It is annoying on all 4 sides, just a lot more noticeable on the top thanks to the title bar. A true fix requires code injection to subclass the window and intercept WM_MOVING and WM_SIZING, C# is not the proper tool for that. Not that any language is an ideal tool for such hackorama :) – Hans Passant Dec 21 '20 at 23:01
  • "How can I remove this flickering?" The short answer is that you probably can't (reasonably). The flickering is happening because the window is being moved to the new location, then you're catching it and moving it back where it was,and being drawn twice in quick succession like that leads to flickering. So just don't do that. Notepad.exe is basically just a Windows edit control with a bare minimum of wrapping anyway, so don't use it. Just create your own window containing an edit control. There you can handle `WM_NCCALCSIZE` to assure the position/size of the window without flickering. – Jerry Coffin Dec 21 '20 at 23:03

1 Answers1

1

When you drag a window, WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED will be sent to the window procedure, and then redraw the changes. If this window procedure is created by you, then you can handle these two messages and limit left and top to 0 and 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;
}

If This is not your window procedure, you need SetWindowSubclass, but you cannot subclass a window across threads, you also need to use code injection.

So, for the notepad window, you cannot simply solve this issue, As the comment said, you can simply integrate an edit control into your own window. Then process the window message like the code above.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30