Position a small console window to the bottom left of the screen?

15,624

Solution 1

You can use Console.WindowTop and Console.WindowWidth of the System.Console class to set the location of the console window.

Here is an example on MSDN

The BufferHeight and BufferWidth property gets/sets the number of rows and columns to be displayed.

WindowHeight and WindowWidth properties must always be less than BufferHeight and BufferWidth respectively.

WindowLeft must be less than BufferWidth - WindowWidth and WindowTop must be less than BufferHeight - WindowHeight.

WindowLeft and WindowTop are relative to the buffer.

To move the actual console window, this article has a good example.

I have used some of your code and code from the CodeProject sample. You can set window location and size both in a single function. No need to set Console.WindowHeight and Console.WindowWidth again. This is how my class looks:

class Program
{
    const int SWP_NOZORDER = 0x4;
    const int SWP_NOACTIVATE = 0x10;

    [DllImport("kernel32")]
    static extern IntPtr GetConsoleWindow();


    [DllImport("user32")]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
        int x, int y, int cx, int cy, int flags);

    static void Main(string[] args)
    {
        Console.WindowWidth = 50;
        Console.WindowHeight = 3;
        Console.BufferWidth = 50;
        Console.BufferHeight = 3;
        Console.BackgroundColor = ConsoleColor.Black;
        Console.ForegroundColor = ConsoleColor.DarkMagenta;

        var screen = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
        var width = screen.Width;
        var height = screen.Height;

        SetWindowPosition(100, height - 300, 500, 100);
        Console.Title = "My Title";
        Console.WriteLine("");
        Console.Write(" Press any key to close this window ...");

        Console.ReadKey();
    }


    /// <summary>
    /// Sets the console window location and size in pixels
    /// </summary>
    public static void SetWindowPosition(int x, int y, int width, int height)
    {
        SetWindowPos(Handle, IntPtr.Zero, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
    }

    public static IntPtr Handle
    {
        get
        {
            //Initialize();
            return GetConsoleWindow();
        }
    }

}

Solution 2

Note: Despite their names, setting Console.WindowLeft and Console.WindowTop of the System.Console class does not change the window's position on screen.
Instead, they position the visible part of the window relative to the (potentially larger) window buffer - you cannot use type System.Console to change the position of console windows on the screen - you need to use the Windows API for that.


The following is code for a complete console application that positions its own window in the lower left corner of the screen, respecting the location of the taskbar.

Note:

  • It should work with multi-monitor setups - positioning the window on the specific monitor (display, screen) it is (mostly) being displayed on - but I haven't personally verified it.

  • Only Windows API functions are used via P/Invoke declarations, avoiding the need for referencing the WinForms assembly (System.Windows.Forms), which is not normally needed in console applications.

    • You'll see that a good portion of the code is devoted to P/Invoke signatures (declaration) for interfacing with the native Windows APIs; these were gratefully adapted from pinvoke.net

    • The actual code in the Main() method is short by comparison.

  • If you compile the code below from a console-application project in Visual Studio and run the resulting executable from a cmd.exe console window (Command Prompt), that console window should shift to the lower left corner of the (containing screen).

    • To verify the functionality while running from Visual Studio, place a breakpoint at the closing } and, when execution pauses, Alt-Tab to the console window to verify its position.

using System;
using System.Runtime.InteropServices; // To enable P/Invoke signatures.

public static class PositionConsoleWindowDemo
{

    // P/Invoke declarations.

    [DllImport("kernel32.dll")]
    static extern IntPtr GetConsoleWindow();

    [DllImport("user32.dll")]
    static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

    const int MONITOR_DEFAULTTOPRIMARY = 1;

    [DllImport("user32.dll")]
    static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    [StructLayout(LayoutKind.Sequential)]
    struct MONITORINFO
    {
        public uint cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
        public static MONITORINFO Default
        {
            get { var inst= new MONITORINFO(); inst.cbSize = (uint)Marshal.SizeOf(inst); return inst; }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    struct RECT
    {
        public int Left, Top, Right, Bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct POINT
    {
        public int x, y;
    }

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

    const uint SW_RESTORE= 9;

    [StructLayout(LayoutKind.Sequential)]
    struct WINDOWPLACEMENT
    {
        public uint Length;
        public uint Flags;
        public uint ShowCmd;
        public POINT MinPosition;
        public POINT MaxPosition;
        public RECT NormalPosition;
        public static WINDOWPLACEMENT Default
        {
            get
            {
                var instance = new WINDOWPLACEMENT();
                instance.Length = (uint) Marshal.SizeOf(instance);
                return instance;
            }
        }
    }

    public static void Main()
    {
        // Get this console window's hWnd (window handle).
        IntPtr hWnd = GetConsoleWindow();

        // Get information about the monitor (display) that the window is (mostly) displayed on.
        // The .rcWork field contains the monitor's work area, i.e., the usable space excluding
        // the taskbar (and "application desktop toolbars" - see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx)
        var mi = MONITORINFO.Default;
        GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);

        // Get information about this window's current placement.
        var wp = WINDOWPLACEMENT.Default;
        GetWindowPlacement(hWnd, ref wp);

        // Calculate the window's new position: lower left corner.
        // !! Inexplicably, on W10, work-area coordinates (0,0) appear to be (7,7) pixels 
        // !! away from the true edge of the screen / taskbar.
        int fudgeOffset = 7;
        wp.NormalPosition = new RECT() {
            Left = -fudgeOffset,
            Top = mi.rcWork.Bottom - (wp.NormalPosition.Bottom - wp.NormalPosition.Top),
            Right = (wp.NormalPosition.Right - wp.NormalPosition.Left),
            Bottom = fudgeOffset + mi.rcWork.Bottom
        };

        // Place the window at the new position.
        SetWindowPlacement(hWnd, ref wp);

    }

}
Share:
15,624
J. Scott Elblein
Author by

J. Scott Elblein

GeekDrop.com | GD Facebook Page | GD Twitter Page

Updated on June 06, 2022

Comments

  • J. Scott Elblein
    J. Scott Elblein almost 2 years

    As the title says, I want to position it to the bottom left corner of the screen. Here's the code I have so far:

        Console.WindowWidth = 50
        Console.WindowHeight = 3
        Console.BufferWidth = 50
        Console.BufferHeight = 3
        Console.BackgroundColor = ConsoleColor.Black
        Console.ForegroundColor = ConsoleColor.DarkMagenta
        Console.Title = "My Title"
        Console.WriteLine("")
        Console.Write(" Press any key to close this window ...")
    
        Console.ReadKey()