Using SetParent to dock a window doesn't work on application with uiAccess=true

asked 2020-08-21T07:09:00.64+00:00
Johannes Bergman 41 Reputation points

I'm trying to create a magnification program for accessibility purposes. I want this magnification program to magnify the desktop but also display a docked application that doesn't get magnified.

To achieve this I create a TopMost Form set to Maximized and Transparent. In this form i have a FlowLayoutPanel containing two Panels I've named DockedWindowPanel and MagnificationPanel.

The MagnificationPanel will be hosting the MagnificationWindow and the DockedWindowPanel will host the application I would like to dock. In this example I want to dock Notepad.exe.

private void DockApplication()  
{  
    var dockedProcess = Process.Start("notepad.exe");  
  
    dockedProcess.WaitForInputIdle();  
  
    NativeMethods.SetParent(dockedProcess.MainWindowHandle, DockedWindowPanel.Handle);  
  
     NativeMethods.SetWindowLong(dockedProcess.MainWindowHandle,  
         (int)GWL.GWL_STYLE,  
         NativeMethods.GetWindowLong(dockedProcess.MainWindowHandle, (int)GWL.GWL_STYLE) & (int)~WindowStyles.WS_CAPTION & (int)~WindowStyles.WS_THICKFRAME);  
  
     NativeMethods.SetWindowPos(dockedProcess.MainWindowHandle, IntPtr.Zero, 0, 0, DockedWindowPanel.Width, DockedWindowPanel.Height, (int)SetWindowPosFlags.SWP_NOZORDER | (int)SetWindowPosFlags.SWP_NOACTIVATE);  
}  

and this process goes very smoothly and docks the application correctly.

However, when i set the requestedExecutionLevel to requireAdministrator and uiAccess to true and place the executable in C:\Program Files and sign it, it will not dock correctly anymore. It will instead dock it to the desktop and not my application.

Below is a screenshot taken with UiAccess=false
19360-uiaccessfalse.png

Below is a screnshot with UiAccess=true
19441-uiaccesstrue.png

As you can see, with UiAccess=true, SetParent will not dock onto my application anymore. Is there a workaround or fix for this?

I've added the solution to GitHub.

Thank you for taking your time to read this.

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,314 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
1,887 questions
{count} votes

Accepted answer
  1. answered 2020-09-11T09:13:57.69+00:00
    Rita Han - MSFT 2,141 Reputation points

    Hello @Johannes Bergman ,

    This issue turns out to be related to different z-order instead of "uiAccess=true". The problem occurs on SetParent API when the parent window is set as topmost but the child window is not, so our suggestion is to set the child window as topmost before we can call SetParent().

    In your case, to solve it you can set Notepad's window as topmost at first then call SetParent(), it will work. Code as below:

            IntPtr hWndInsertAfter = new IntPtr(-1); //HWND_TOPMOST (HWND) - 1  
            NativeMethods.SetWindowPos(DockedProcess.MainWindowHandle, hWndInsertAfter, 0, 0, DockedWindowPanel.Width, DockedWindowPanel.Height, 0);  
    
            IntPtr retVal = NativeMethods.SetParent(DockedProcess.MainWindowHandle, DockedWindowPanel.Handle);  
    

    The following snapshot demonstrate the result:

    24079-20200911-2.png

    Thank you!


0 additional answers

Sort by: Most helpful