question

MarcelLorenz-8156 avatar image
0 Votes"
MarcelLorenz-8156 asked ·

Bring UWP app window to front and move it

I want to move windows programmatically. It works fine except for all windows belonging to UWP apps. When I try to read out all HWNDs of Microsoft Movies & TV there are 3 possibilities:

  1. The Window is minimized: I can read out 3 HWNDs two of them having bounds of 0,0,0,0 and the 3rd has nonzero bounds but they do not a bit equal with the window size. When I try to ShowWindow all of them, it doesn't work (flag: SW_RESTORE 0x09) no matter if the process is suspended or not, which happens after a small amount of time after minimizing.

  2. The window is visible: The nonzero bounds HWND cannot be read out anymore but when calling SetForegroundWindow the window still gets put in the foreground so the nonzero bounds HWND was not the handle of the visible window.

  3. The window is maximized and in fullscreen: I cannot read out any HWND.

When I try to call SetWindowPos while the window is minimized only the zero bounds HWNDs change their RECT information but when I show the window it's still at the same wrong position. The nonzero bounds HWND doesn't even change the values.

Same for when the window is visible, except for that I cannot read out the nonzero bounds HWND.

So HOW can I show windows of a UWP app and move them to a specified location on one of the possible screens?



dotnet-csharpwindows-uwp
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Castorix31 avatar image
1 Vote"
Castorix31 answered ·

I had done this test with Calc a long time ago, which still works on my OS (Windows 10, 1909)
(Show Calc window and move it at 100, 100)
(can certainly be simplified...) =>


 public partial class Form1 : Form
 {
     public enum HRESULT : int
     {         
         S_OK = 0,
         S_FALSE = 1,
         E_NOINTERFACE = unchecked((int)0x80004002),
         E_NOTIMPL = unchecked((int)0x80004001),          
         E_FAIL = unchecked((int)0x80004005)          
     }
    
     public const int SW_HIDE = 0;
     public const int SW_SHOWNORMAL = 1;
     public const int SW_NORMAL = 1;
     public const int SW_SHOWMINIMIZED = 2;
     public const int SW_SHOWMAXIMIZED = 3;
     public const int SW_MAXIMIZE = 3;
     public const int SW_SHOWNOACTIVATE = 4;
     public const int SW_SHOW = 5;
     public const int SW_MINIMIZE = 6;
     public const int SW_SHOWMINNOACTIVE = 7;
     public const int SW_SHOWNA = 8;
     public const int SW_RESTORE = 9;
     public const int SW_SHOWDEFAULT = 10;
     public const int SW_FORCEMINIMIZE = 11;
     public const int SW_MAX = 11;
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
     public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
     public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref IntPtr lParam);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
     public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProc lpEnumFunc, ref IntPtr lParam);
    
     public delegate bool EnumWindowsProc(IntPtr hWnd, ref IntPtr lParam);
    
     public const long SYNCHRONIZE = (0x00100000L);
     public const int STANDARD_RIGHTS_REQUIRED = (0x000F0000);
    
     public const int PROCESS_VM_READ = (0x0010);
     public const int PROCESS_VM_WRITE = (0x0020);
     public const int PROCESS_DUP_HANDLE = (0x0040);
     public const int PROCESS_CREATE_PROCESS = (0x0080);
     public const int PROCESS_SET_QUOTA = (0x0100);
     public const int PROCESS_SET_INFORMATION = (0x0200);
     public const int PROCESS_QUERY_INFORMATION = (0x0400);
     public const int PROCESS_SUSPEND_RESUME = (0x0800);
     public const int PROCESS_QUERY_LIMITED_INFORMATION = (0x1000);
     public const int PROCESS_SET_LIMITED_INFORMATION = (0x2000);
     public const long PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF);
    
     [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
    
     [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool QueryFullProcessImageName(IntPtr hProcess, int dwFlags, StringBuilder lpExeName, ref uint lpdwSize);    
    
     [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool CloseHandle(IntPtr hObject);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    
     [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool GetPackageFullName(IntPtr hProcess, ref uint packageFullNameLength, StringBuilder packageFullName);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool IsWindowVisible(IntPtr hWnd);
    
     [StructLayout(LayoutKind.Sequential)]
     public struct RECT
     {
         public int left;
         public int top;
         public int right;
         public int bottom;
     }
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    
     public const int SPI_GETWORKAREA = 0x0030;
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, [In, Out] ref RECT pvParam, uint fWinIni);
    
     [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern HRESULT SHGetPropertyStoreForWindow(IntPtr hwnd, ref Guid iid, [Out(), MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
    
     public struct PROPERTYKEY
     {
         public PROPERTYKEY(Guid InputId, UInt32 InputPid)
         {
             fmtid = InputId;
             pid = InputPid;
         }
         Guid fmtid;
         uint pid;
     };
    
     [StructLayout(LayoutKind.Sequential, Pack = 0)]
     public struct PROPARRAY
     {
         public UInt32 cElems;
         public IntPtr pElems;
     }
    
     [StructLayout(LayoutKind.Explicit, Pack = 1)]
     public struct PROPVARIANT
     {
         [FieldOffset(0)]
         public ushort varType;
         [FieldOffset(2)]
         public ushort wReserved1;
         [FieldOffset(4)]
         public ushort wReserved2;
         [FieldOffset(6)]
         public ushort wReserved3;
    
         [FieldOffset(8)]
         public byte bVal;
         [FieldOffset(8)]
         public sbyte cVal;
         [FieldOffset(8)]
         public ushort uiVal;
         [FieldOffset(8)]
         public short iVal;
         [FieldOffset(8)]
         public UInt32 uintVal;
         [FieldOffset(8)]
         public Int32 intVal;
         [FieldOffset(8)]
         public UInt64 ulVal;
         [FieldOffset(8)]
         public Int64 lVal;
         [FieldOffset(8)]
         public float fltVal;
         [FieldOffset(8)]
         public double dblVal;
         [FieldOffset(8)]
         public short boolVal;
         [FieldOffset(8)]
         public IntPtr pclsidVal; // GUID ID pointer
         [FieldOffset(8)]
         public IntPtr pszVal; // Ansi string pointer
         [FieldOffset(8)]
         public IntPtr pwszVal; // Unicode string pointer
         [FieldOffset(8)]
         public IntPtr punkVal; // punkVal (interface pointer)
         [FieldOffset(8)]
         public PROPARRAY ca;
         [FieldOffset(8)]
         public System.Runtime.InteropServices.ComTypes.FILETIME filetime;        
     }
    
     [ComImport,  Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"),  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
     public interface IPropertyStore
     {
         HRESULT GetCount([Out] out uint propertyCount);
         HRESULT GetAt([In] uint propertyIndex, [Out, MarshalAs(UnmanagedType.Struct)] out PROPERTYKEY key);
         HRESULT GetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [Out, MarshalAs(UnmanagedType.Struct)] out PROPVARIANT pv);
         HRESULT SetValue([In, MarshalAs(UnmanagedType.Struct)] ref PROPERTYKEY key, [In, MarshalAs(UnmanagedType.Struct)] ref PROPVARIANT pv);
         HRESULT Commit();
     }
    
     public static PROPERTYKEY PKEY_AppUserModel_ID = new PROPERTYKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
    
     [DllImport("dwmapi.dll")]
     private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out IntPtr pvAttribute, int cbAttribute);
     [DllImport("dwmapi.dll")]
     private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out  RECT pvAttribute, int cbAttribute);
    
     enum DWMWINDOWATTRIBUTE
     {
         DWMWA_NCRENDERING_ENABLED = 1,
         DWMWA_NCRENDERING_POLICY,
         DWMWA_TRANSITIONS_FORCEDISABLED,
         DWMWA_ALLOW_NCPAINT,
         DWMWA_CAPTION_BUTTON_BOUNDS,
         DWMWA_NONCLIENT_RTL_LAYOUT,
         DWMWA_FORCE_ICONIC_REPRESENTATION,
         DWMWA_FLIP3D_POLICY,
         DWMWA_EXTENDED_FRAME_BOUNDS,
         DWMWA_HAS_ICONIC_BITMAP,
         DWMWA_DISALLOW_PEEK,
         DWMWA_EXCLUDED_FROM_PEEK,
         DWMWA_CLOAK,
         DWMWA_CLOAKED,
         DWMWA_FREEZE_REPRESENTATION,
         DWMWA_LAST
     }
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool SwitchToThisWindow(IntPtr hWnd, Boolean fAltTab);
    
     public const int SWP_NOSIZE = 0x0001;
     public const int SWP_NOMOVE = 0x0002;
     public const int SWP_NOZORDER = 0x0004;
     public const int SWP_NOREDRAW = 0x0008;
     public const int SWP_NOACTIVATE = 0x0010;
     public const int SWP_FRAMECHANGED = 0x0020;  /* The frame changed: send WM_NCCALCSIZE */
     public const int SWP_SHOWWINDOW = 0x0040;
     public const int SWP_HIDEWINDOW = 0x0080;
     public const int SWP_NOCOPYBITS = 0x0100;
     public const int SWP_NOOWNERZORDER = 0x0200;  /* Don't do owner Z ordering */
     public const int SWP_NOSENDCHANGING = 0x0400;  /* Don't send WM_WINDOWPOSCHANGING */
     public const int SWP_DRAWFRAME = SWP_FRAMECHANGED;
     public const int SWP_NOREPOSITION = SWP_NOOWNERZORDER;
     public const int SWP_DEFERERASE = 0x2000;
     public const int SWP_ASYNCWINDOWPOS = 0x4000;
    
     [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    
     public static bool ListWindows(IntPtr hWnd, ref IntPtr lParam)
     {
         ENUMPARAM ep = (ENUMPARAM)Marshal.PtrToStructure(lParam, typeof(ENUMPARAM));
         StringBuilder sbClassName = new StringBuilder(260);
         string sClassName = null;
    
         GetClassName(hWnd, sbClassName, (int)(sbClassName.Capacity));
         sClassName = sbClassName.ToString();
    
         // Minimized : "Windows.UI.Core.CoreWindow" top window
         // Normal : "Windows.UI.Core.CoreWindow" child of "ApplicationFrameWindow"
         if (sClassName == "Windows.UI.Core.CoreWindow")
         {
             int nPID = 0;
             uint nThreadId = GetWindowThreadProcessId(hWnd, out nPID);
             IntPtr hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, nPID);
             string sPackage = string.Empty;
             if (hProcess != IntPtr.Zero)
             {
                 uint nSize = 260;
                 StringBuilder sPackageFullName = new StringBuilder((int)nSize);
                 GetPackageFullName(hProcess, ref nSize, sPackageFullName);
                 if (sPackageFullName.ToString().ToLower().Contains("calculator") && IsWindowVisible(hWnd))
                 {
                     nSize = 260;
                     StringBuilder sProcessImageName = new StringBuilder((int)nSize);
                     QueryFullProcessImageName(hProcess, 0, sProcessImageName, ref nSize);
                     //hWnd = FindWindow("ApplicationFrameWindow", "Calculatrice");
                     //ep.hWnd = hWnd;
                     ep.sExeName = sProcessImageName.ToString();
                     ep.nPID = nPID;
                     ep.nState = 1;
                     Marshal.StructureToPtr(ep, lParam, false);
                     if (ep.hWnd != IntPtr.Zero)
                     {
                         CloseHandle(hProcess);
                         return false;
                     }
                 }
                 CloseHandle(hProcess);
             }
         }
    
         if (sClassName == "ApplicationFrameWindow")
         {
             // get real hWnd 
             IPropertyStore pPropertyStore;
             Guid guid = new Guid("{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}");                
             HRESULT hr = SHGetPropertyStoreForWindow(hWnd, ref guid, out pPropertyStore);
             //if (hr != HRESULT.S_OK)
             //    throw Marshal.GetExceptionForHR((int)hr);
             if (hr == HRESULT.S_OK)
             {
                 PROPVARIANT propVar = new PROPVARIANT();
                 hr = pPropertyStore.GetValue(ref PKEY_AppUserModel_ID, out propVar);
                 string sAUMID = Marshal.PtrToStringUni(propVar.pwszVal);
                 if (sAUMID != null && sAUMID.ToLower().Contains("calculator"))
                 { 
                     RECT rect, rectWorkArea = new RECT();
                     GetWindowRect(hWnd, out rect);
                     IntPtr pRectWorkArea = IntPtr.Zero;
                     bool bRet = SystemParametersInfo(SPI_GETWORKAREA, 0, ref rectWorkArea, 0);                       
                     // maximized : out of SPI_GETWORKAREA   
                     if (rect.left < rectWorkArea.left && rect.top < rectWorkArea.top && rect.right > rectWorkArea.right && rect.bottom > rectWorkArea.bottom)
                         ep.nState = 2;
                     ep.hWnd = hWnd;
                     Marshal.StructureToPtr(ep, lParam, false);
                 }
                 Marshal.ReleaseComObject(pPropertyStore);
             }
    
             IntPtr hWndFind = FindWindowEx(hWnd, IntPtr.Zero, "Windows.UI.Core.CoreWindow", null);               
             if (hWndFind != IntPtr.Zero)
             {
                 int nPID = 0;
                 uint nThreadId = GetWindowThreadProcessId(hWndFind, out nPID);
                 IntPtr hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, nPID);
                 string sPackage = string.Empty;
                 if (hProcess != IntPtr.Zero)
                 {
                     uint nSize = 260;
                     StringBuilder sPackageFullName = new StringBuilder((int)nSize);
                     GetPackageFullName(hProcess, ref nSize, sPackageFullName);
                     if (sPackageFullName.ToString().ToLower().Contains("calculator") && IsWindowVisible(hWnd))
                     {
                         nSize = 260;
                         StringBuilder sProcessImageName = new StringBuilder((int)nSize);
                         QueryFullProcessImageName(hProcess, 0, sProcessImageName, ref nSize);
                         ep.hWnd = hWnd;
                         ep.sExeName = sProcessImageName.ToString();
                         ep.nPID = nPID;
                         Marshal.StructureToPtr(ep, lParam, false);
                         CloseHandle(hProcess);
                         return false;
                     }
                     CloseHandle(hProcess);
                 }
             }
         }
         return true;
     }
     public Form1()
     {
         InitializeComponent();
     }
    
     private System.Windows.Forms.Button button1;
    
     private void Form1_Load(object sender, EventArgs e)
     {
         this.button1 = new System.Windows.Forms.Button();
    
         this.button1.Location = new System.Drawing.Point(105, 110);
         this.button1.Name = "button1";
         this.button1.Size = new System.Drawing.Size(75, 23);
         this.button1.TabIndex = 0;
         this.button1.Text = "Find Calc";
         this.button1.UseVisualStyleBackColor = true;
         this.button1.Click += new System.EventHandler(this.button1_Click);
    
         this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.ClientSize = new System.Drawing.Size(284, 261);
    
         this.Controls.Add(this.button1);
         CenterToScreen();
     }
    
     private void button1_Click(object sender, EventArgs e)
     {
         EnumWindowsProc Callback = new EnumWindowsProc(ListWindows);
         ENUMPARAM ep = new ENUMPARAM();
         IntPtr plParam = Marshal.AllocHGlobal(Marshal.SizeOf(ep));
         Marshal.StructureToPtr(ep, plParam, false);
         EnumWindows(Callback, ref plParam);
         ENUMPARAM epret = (ENUMPARAM)Marshal.PtrToStructure(plParam, typeof(ENUMPARAM));
         Marshal.FreeHGlobal(plParam);
         if (epret.hWnd != IntPtr.Zero)
         {
             // State can also be got with UI Automation and WindowVisualState
             //string sState = (epret.nState == 1) ? "\n(state = minimized)" : "";
             string sState = string.Empty;
             switch (epret.nState)
             {
                 case 0:
                     sState = "Normal";
                     break;
                 case 1:
                     sState = "Minimized";
                     break;
                 case 2:
                     sState = "Maximized";
                     break;                  
             }
             MessageBox.Show(string.Format("Window handle = 0x{0}\nPID = {1}\nExecutable = {2}\nState = {3}", epret.hWnd.ToString("X"), epret.nPID, epret.sExeName, sState), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);               
         }
         else
             MessageBox.Show("Calc not found", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    
         ShowWindow(epret.hWnd, SW_SHOWNORMAL);
         SetWindowPos(epret.hWnd, new IntPtr(-1), 100, 100, 0, 0, SWP_NOSIZE);
     }
    
     [StructLayoutAttribute(LayoutKind.Sequential)]
     private struct ENUMPARAM
     {
         public IntPtr hWnd;
         public int nPID;
         public string sExeName;
         public int nState;
     }
 }


· 10 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

OMG it works. I had to change the contains from "calculator" to "zunevideo" and it worked. Thank you so much. There are only two little problems left.

  1. It doesn't work when the window is maximized and in fullscreen. Is there a reason for that?

  2. The window is always in the foreground until I close and reopen Edit: Okay I just added SWP_NOZORDER.

0 Votes 0 ·
Castorix31 avatar image Castorix31 MarcelLorenz-8156 ·

Right, I forgot SWP_NOZORDER

For a FullScreen UWP app, I just did some tests with Microsoft Windows Photos : the code must be updated.
When Photos is FullScreen, I get : (I added a Sleep and GetForegroundWindow to test quickly with the right window...)
sClassName = "ApplicationFrameWindow"
sProcessImageName = "C:\Windows\System32\ApplicationFrameHost.exe"
sAUMID = "Microsoft.Windows.Photos_8wekyb3d8bbwe!App"
and I added a test with DwmGetWindowAttribute :
DWMWA_EXTENDED_FRAME_BOUNDS = screen size (1920 * 1080 on my OS)
DWMWA_CAPTION_BUTTON_BOUNDS = 0
DWMWA_CLOAKED = DWM_CLOAKED_SHELL

 public const int DWM_CLOAKED_APP = 0x00000001;
 public const int DWM_CLOAKED_SHELL = 0x00000002;
 public const int DWM_CLOAKED_INHERITED = 0x00000004;


     [DllImport("User32.dll", SetLastError = true)]
     public static extern IntPtr GetForegroundWindow();



1 Vote 1 ·

Okay, I already accepted the answer but there is still one problem. I cannot enumerate fullscreen windows. So I could do GetForegroundWindow but the window has to be visible and focused. But when not, or when the window is in fullscreen mode and then minimized I cannot read it out.

0 Votes 0 ·
Show more comments
RoyLi-MSFT avatar image
0 Votes"
RoyLi-MSFT answered ·

Hello,

Welcome to Microsoft Q&A!

HOW can I show windows of a UWP app and move them to a specified location on one of the possible screens?

Currently, there is no API that could bring UWP windows to the foreground when it is not in the foreground and move the app's position.



Thank you.


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.