Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?
If you are experiencing any issues with your desktop wallpaper or taskbar buttons
please download and install the latest DisplayFusion beta version before contacting support.

User Image
RickyMoose
14 discussion posts
Hi,

Just an annoyance but when you press Windows key+H and the voice typing pops up, does anyone have a good method to make DF move it to another window to get it out of the way?

Nothing I have tried so far has worked. :(

Thanks.
• Attachment: 0001.jpg [2,992 bytes]
0001.jpg
0001.jpg
• Attachment: 0002.jpg [57,922 bytes]
0002.jpg
0002.jpg
10 days ago (modified 10 days ago)  • #1
Keith Lammers (BFS)'s profile on WallpaperFusion.com
DisplayFusion can't seem to detect this window at all, I believe because it runs in the svchost.exe system process. I will add this to our open issues list and if we're able to make it work in a future version, we'll be sure to let you know.

Thanks!
10 days ago  • #2
User Image
JLJTGR
140 discussion posts
To me, this is a "Windows.UI.Core.CoreWindow" class window in "TextInputHost.exe: DictationControl" thread. Unfortunately the window always exists so you cannot trigger off it being created. Further, it has the WS_EX_NOACTIVATE flag so it cannot pull focus when it appears.

I almost think it would be easier to keylog Windows+H to detect when you're trying to get it to show up and manipulate it then. I don't think DisplayFusion can read Windows+H without registering exclusive use and causing a conflict. If you could figure out a valid trigger(like interval seconds), you'd still have to write a fairly custom Scripted Function to figure out the correct window handle and manipulate it with BFS helper methods.
5 days ago  • #3
User Image
RickyMoose
14 discussion posts
Hi,

I was experimenting with copilot to see if I could come up with a way to do this within Display Fusion.

If I open up the DF Scripted Function editor window with this code and click the Run function button then it will reposition the window exactly where I want it.

While this function "Technically" works, it has to be manually triggered I cannot come up with a way to trigger this when the window appears, so effectively this is just some proof of concept code.

Perhaps someone could make a viable Display Fusion solution out of this one day.

Also since I am not a programmer I do not really understand this code and why it works at all.... :(


Code

```csharp
using System;
using System.Drawing;
using System.Runtime.InteropServices;

public static class DisplayFusionFunction
{
    // ============================================================
    // TARGET WINDOW IDENTIFICATION
    // ============================================================

    private const string ExpectedClass =
        "ApplicationFrameWindow";

    private const uint ExpectedStyle =
        0x940B0000;

    private const uint ExpectedExStyle =
        0x08200008;

    private const int ExpectedW = 160;
    private const int ExpectedH = 102;

    private const int SizeTol = 10;

    // ============================================================
    // MONITOR IDs
    // ============================================================

    private const uint PrimaryMonitorID = 1;
    private const uint SecondaryMonitorID = 2;

    // ============================================================
    // REFERENCE POSITION ON PRIMARY MONITOR
    //
    // We know from the previous test that Windows can successfully
    // put this window at 1651,0 using SetWindowPos().
    //
    // We use that position as the reference position and then
    // calculate the equivalent position on Monitor 2.
    // ============================================================

    private const int ReferenceX = 1651;
    private const int ReferenceY = 0;

    // ============================================================
    // SetWindowPos FLAGS
    // ============================================================

    private const uint SWP_NOSIZE = 0x0001;
    private const uint SWP_NOZORDER = 0x0004;
    private const uint SWP_NOACTIVATE = 0x0010;

    // ============================================================
    // MAIN FUNCTION
    // ============================================================

    public static void Run(IntPtr windowHandle)
    {
        // --------------------------------------------------------
        // Find the unique target window.
        //
        // We intentionally ignore windowHandle during this
        // manual test.
        // --------------------------------------------------------

        IntPtr target =
            FindTargetWindow();

        if (target == IntPtr.Zero)
            return;

        // ========================================================
        // STEP 1
        //
        // Get the actual bounds of Monitor 1.
        // ========================================================

        Rectangle primary =
            BFS.Monitor.GetMonitorBoundsByID(
                PrimaryMonitorID);

        if (primary == Rectangle.Empty)
            return;

        // ========================================================
        // STEP 2
        //
        // Get the actual bounds of Monitor 2.
        // ========================================================

        Rectangle secondary =
            BFS.Monitor.GetMonitorBoundsByID(
                SecondaryMonitorID);

        if (secondary == Rectangle.Empty)
            return;

        // ========================================================
        // STEP 3
        //
        // Calculate the absolute virtual-desktop coordinate for
        // the reference position on Monitor 1.
        // ========================================================

        int primaryX =
            primary.X + ReferenceX;

        int primaryY =
            primary.Y + ReferenceY;

        // ========================================================
        // STEP 4
        //
        // Put the window at the known-good reference position
        // on Monitor 1.
        //
        // This uses Windows SetWindowPos(), NOT the DisplayFusion
        // SetLocation() function.
        // ========================================================

        if (!SetWindowPosition(
            target,
            primaryX,
            primaryY))
        {
            return;
        }

        // Allow Windows to complete the move.
        BFS.General.ThreadWait(250);

        // ========================================================
        // STEP 5
        //
        // Calculate the equivalent position on Monitor 2.
        //
        // Example:
        //
        // Monitor 2 X = -1920
        // Reference X = 1651
        //
        // Final X = -269
        // ========================================================

        int secondaryX =
            secondary.X + ReferenceX;

        int secondaryY =
            secondary.Y + ReferenceY;

        // ========================================================
        // STEP 6
        //
        // Move directly to the calculated Monitor 2 coordinate.
        //
        // NO MoveToMonitor()
        // NO BFS.Window.SetLocation()
        //
        // Just Windows SetWindowPos().
        // ========================================================

        if (!SetWindowPosition(
            target,
            secondaryX,
            secondaryY))
        {
            return;
        }

        BFS.General.ThreadWait(250);
    }

    // ============================================================
    // DIRECT WINDOWS POSITIONING
    // ============================================================

    private static bool SetWindowPosition(
        IntPtr hWnd,
        int x,
        int y)
    {
        return SetWindowPosNative(
            hWnd,
            IntPtr.Zero,
            x,
            y,
            0,
            0,
            SWP_NOSIZE |
            SWP_NOZORDER |
            SWP_NOACTIVATE);
    }

    // ============================================================
    // FIND TARGET WINDOW
    // ============================================================

    private static IntPtr FindTargetWindow()
    {
        IntPtr[] handles =
            BFS.Window.GetVisibleWindowHandles();

        for (int i = 0; i < handles.Length; i++)
        {
            IntPtr hWnd =
                handles[i];

            if (IsTargetWindow(hWnd))
                return hWnd;
        }

        return IntPtr.Zero;
    }

    // ============================================================
    // VERIFY TARGET WINDOW
    // ============================================================

    private static bool IsTargetWindow(
        IntPtr hWnd)
    {
        if (hWnd == IntPtr.Zero)
            return false;

        if (!BFS.Window.IsVisible(hWnd))
            return false;

        // --------------------------------------------------------
        // Window class
        // --------------------------------------------------------

        string cls =
            BFS.Window.GetClass(hWnd) ?? "";

        if (!cls.Equals(
            ExpectedClass,
            StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        // --------------------------------------------------------
        // Window style
        // --------------------------------------------------------

        uint style =
            GetWindowStyleRaw(hWnd);

        if (style != ExpectedStyle)
            return false;

        // --------------------------------------------------------
        // Extended style
        // --------------------------------------------------------

        uint exStyle =
            GetWindowExStyleRaw(hWnd);

        if (exStyle != ExpectedExStyle)
            return false;

        // --------------------------------------------------------
        // Window size
        // --------------------------------------------------------

        Rectangle bounds =
            BFS.Window.GetBounds(hWnd);

        if (Math.Abs(
            bounds.Width - ExpectedW) > SizeTol)
        {
            return false;
        }

        if (Math.Abs(
            bounds.Height - ExpectedH) > SizeTol)
        {
            return false;
        }

        return true;
    }

    // ============================================================
    // WINDOWS USER32 SetWindowPos
    //
    // IMPORTANT:
    //
    // The C# method is named SetWindowPosNative, but the actual
    // Windows API entry point is "SetWindowPos".
    //
    // This explicit EntryPoint declaration fixes the error from
    // the previous version.
    // ============================================================

    [DllImport(
        "user32.dll",
        EntryPoint = "SetWindowPos",
        SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetWindowPosNative(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int X,
        int Y,
        int cx,
        int cy,
        uint uFlags);

    // ============================================================
    // WINDOW STYLE FUNCTIONS
    // ============================================================

    private const int GWL_STYLE = -16;
    private const int GWL_EXSTYLE = -20;

    private static uint GetWindowStyleRaw(
        IntPtr hWnd)
    {
        return unchecked(
            (uint)GetWindowLongPtrCompat(
                hWnd,
                GWL_STYLE).ToInt64());
    }

    private static uint GetWindowExStyleRaw(
        IntPtr hWnd)
    {
        return unchecked(
            (uint)GetWindowLongPtrCompat(
                hWnd,
                GWL_EXSTYLE).ToInt64());
    }

    // ============================================================
    // 32/64-BIT COMPATIBILITY
    // ============================================================

    private static IntPtr GetWindowLongPtrCompat(
        IntPtr hWnd,
        int nIndex)
    {
        if (IntPtr.Size == 8)
        {
            return GetWindowLongPtrW(
                hWnd,
                nIndex);
        }

        return new IntPtr(
            GetWindowLongW(
                hWnd,
                nIndex));
    }

    [DllImport(
        "user32.dll",
        EntryPoint = "GetWindowLongPtrW",
        SetLastError = true)]
    private static extern IntPtr GetWindowLongPtrW(
        IntPtr hWnd,
        int nIndex);

    [DllImport(
        "user32.dll",
        EntryPoint = "GetWindowLongW",
        SetLastError = true)]
    private static extern int GetWindowLongW(
        IntPtr hWnd,
        int nIndex);
}
```

The important change is:

```csharp
[DllImport(
    "user32.dll",
    EntryPoint = "SetWindowPos",
    SetLastError = true)]
```

Previously, Windows was looking for an API function literally called `SetWindowPosNative`, which doesn't exist.

### What this version should do

It will now perform exactly the experiment we want:

**Monitor 1:**

```text
X = 1651
Y = 0
```

then calculate the equivalent position on Monitor 2 from its actual monitor bounds and directly call Windows:

```text
SetWindowPos(...)
```

There is **no `MoveToMonitor()`** in this version.

This is a useful test because we already know the direct Windows positioning call successfully moved your window to `1651,0`. Now we're applying that same mechanism to the calculated coordinates of the second monitor.


Using the spy tool in AutoIt, I see this info about the window in question:

Code

>>>> Window <<<<
Title:    
Class:    ApplicationFrameWindow
Position:    613, 357
Size:    160, 102
Style:    0x940B0000
ExStyle:    0x08200008
Handle:    0x0000000000020514

>>>> Control <<<<
Class:    Windows.UI.Core.CoreWindow
Instance:    0
ClassnameNN:    Windows.UI.Core.CoreWindow0
Name:    
Advanced (Class):    [CLASS:Windows.UI.Core.CoreWindow; INSTANCE:0]
ID:    
Text:    Windows Input Experience
Position:    0, 0
Size:    160, 102
ControlClick Coords:    17, 18
Style:    0x54000000
ExStyle:    0x08280008
Handle:    0x0000000000030512

>>>> Mouse <<<<
Position:    630, 375
Cursor ID:    0
Color:    0xF1F1F1

>>>> StatusBar <<<<

>>>> ToolsBar <<<<

>>>> Visible Text <<<<

>>>> Hidden Text <<<<
4 days ago  • #4
Subscribe to this discussion topic using RSS
Was this helpful?  Login to Vote(-)  Login to Vote(-)