Setting position of a Console Window opened in a WinForms App - c#

I found some source code in this thread posted by Rex Logan here on SO :
link text
... there's also some very interesting code posted in this same thread by Foredecker, but it is incomplete and complex : I'm not up enough on the 'Trace facility to know how to fully implement it ...
I am able to use this Console code Rex (kindly) posted successfully in a WinForms application to log various events, and to push messages onto which are useful in debugging; I can clear it from the application code, also.
What I can't seem to do is to reliably set the screen position of the Console Window when I open the Console Window (in the Main Form load event). I get compile blocking System.ArgumentOutOfRangeException errors if I try to set WindowLeft or WindowTop properties like this :
The window position must be set such
that the current window size fits
within the console's buffer, and the
numbers must not be negative.
Parameter name: left Actual value was
#
I am able, however, to set WindowWidth and WindowHeight properties.
I have tried moving the code that activates the Console various locations including :
in the Program.cs file before the MainForm is 'run
before and after the call to 'InitializeComponent() in the MainForm ctor
in the Form Load event
in the Form Shown event
The Console was activated okay in all these places in the code, but with no change in the seemingly random switching around of where in the upper-left quadrant of the screen it appeared.
Where the Console window opens seems to vary at random (the Main Form is always initialized in the same place on the screen).

you can try something like this.
This code set the position of the Console Window in a Console Application.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication10
{
class Program
{
const int SWP_NOSIZE = 0x0001;
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetConsoleWindow();
private static IntPtr MyConsole = GetConsoleWindow();
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int wFlags);
static void Main(string[] args)
{
int xpos = 300;
int ypos = 300;
SetWindowPos(MyConsole, 0, xpos, ypos, 0, 0, SWP_NOSIZE);
Console.WriteLine("any text");
Console.Read();
}
}
}
This code set the position of the Console Window in a WinForm Application.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication10
{
static class Program
{
const int SWP_NOSIZE = 0x0001;
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int wFlags);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetConsoleWindow();
[STAThread]
static void Main()
{
AllocConsole();
IntPtr MyConsole = GetConsoleWindow();
int xpos = 1024;
int ypos = 0;
SetWindowPos(MyConsole, 0, xpos, ypos, 0, 0, SWP_NOSIZE);
Console.WindowLeft=0;
Console.WriteLine("text in my console");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

Related

How to remove scroll bar from fullscreen Console in C#?

Long story short: I just picked up C# about a week ago. Most of my programming knowledge comes from Java. I want to try my hand at making a text adventure game (yes I know I can used Unity, but I want to make it from scratch) and part of the setup is getting a full screen Console window with no distractions.
I've scavenged about on StackOverflow and so far I've put this together:
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(int handle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleDisplayMode(IntPtr ConsoleOutput, uint Flags, out COORD NewScreenBufferDimensions);
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD(short X, short Y)
{
this.X = X;
this.Y = Y;
}
}
Alongside this bit in the Main method:
IntPtr hConsole = GetStdHandle(-11);
SetConsoleDisplayMode(hConsole, 1, out COORD b1);
Console.ReadLine();
So I've managed to get in full screen successfully, but problem is a scroll bar is still there.
I've done my best to understand exactly how this works and how the scroll bar would be removed. My current understanding is that the Console's screen buffer needs to be changed to match the size of the screen so that the scroll bar can disappear.
From the code I managed to put together, it seems that the buffer is already being played with in order to go full screen. Looks like the 'SetConsoleDisplayMode' method does that.
So my question is, how do I add in the removal of the scroll bar to this code? My mind is saying it has something to do with the 'COORD' struct but honestly I'm totally out of my element here with a new language and new concepts (like structs), any help would be appreciated!
this class is defineatly work for you it full screen automatically the console and remove the scroll bars the clear and black console screen is appers only and you do what ever you want
##
public class SetLayout
{
// Control the console whole setting
public void Set()
{
Console.SetBufferSize(Console.LargestWindowWidth, Console.LargestWindowHeight); // Remove the console both scroll bars
IntPtr hConsole = FullScreen.GetStdHandle(-11); // Get console handle
FullScreen.COORD xy = new FullScreen.COORD(100, 100);
FullScreen.SetConsoleDisplayMode(hConsole, 1, out xy); // Set the console to fullscreen
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); // Set to not show the "Press any key to continue"
Console.CursorVisible = false; // Remove the cursor from the console
}
// Handler Method to remove the "Press any key to continue........."
void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
FullScreen.ShowWindow(FullScreen.ThisConsole,0);
}
}
// Class is setting the console window full screen
internal static class FullScreen
{
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public COORD(short x, short y)
{
this.X = x;
this.Y = y;
}
}
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(int handle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleDisplayMode(IntPtr ConsoleOutput, uint Flags, out COORD NewScreenBufferDimensions);
[DllImport("kernel32.dll", ExactSpelling = true)]
public static extern IntPtr GetConsoleWindow();
public static IntPtr ThisConsole = GetConsoleWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
you just have to write in the main method :
SetLayout s = new SetLayout();
s.Set();
The scrollbar will disapear when your buffer height is equal to your screen height (in Lines). You can test that with a noraml cmd.exe window.
When you make your console fullscreen, Windows will make your Buffer bigger if it was too small and return the new size in the last argument of
SetConsoleDisplayMode. You probably need that size as you progress with your project. So if you make the buffer really small Windows fill "fix" it for you.
In order to change your buffer size you will need to call SetConsoleScreenBufferSize:
BOOL WINAPI SetConsoleScreenBufferSize(
_In_ HANDLE hConsoleOutput,
_In_ COORD dwSize
);
That will look like this (untested):
[DllImport("kernel32.dll")]
private static extern bool SetConsoleScreenBufferSize(int handle, COORD newSize);

Can you get the position of a window that is inside of another application

So I found an example from an answer provided here
There was an answer that gave this example of code to move the Notepad window to the top left corner of the screen. I tried it and it worked fine. I then tried it on a small project I am working on and I couldn't move it.
NOTE: I did change the "Notepad" to the name at the top of the window I wanted to move.
using System;
using System.Runtime.InteropServices; // For the P/Invoke signatures.
public static class PositionWindowDemo
{
// P/Invoke declarations.
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOZORDER = 0x0004;
public static void Main()
{
// Find (the first-in-Z-order) Notepad window.
IntPtr hWnd = FindWindow("Notepad", null);
// If found, position it.
if (hWnd != IntPtr.Zero)
{
// Move the window to (0,0) without changing its size or position
// in the Z order.
SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
}
I will give an example. Consider Visual Studios and how it has the Solution Explorer Window or the Output window, and I can drag them with the mouse and move them or undock them. Would there be a way to have an application that has windows inside of it similar to Visual Studios and get the position of them in a program?
I have seen many answers on here about moving a window or finding the active window etc. However I am not sure if I will be able to access this subWindow that is inside of another application.
Thanks

Moving window with SetWindowPos

I'm trying to move the window of the program I am building inside of unity. I'm getting it's handle via interating through all processes in Process.GetProcesses(). Then, I'm calling SetWindowPos, but nothing happens. Here's my code.
internal static void CheckHandle()
{
Process[] ps = Process.GetProcesses();
foreach (Process p in ps)
{
try
{
if (string.Equals(p.ProcessName, "TestBuild0001"))
{
_correctHandle = true;
_handle = p.Handle;
}
}
catch
{
//no catch, simply exited process
}
}
}
internal static void SetPosition()
{
if (!_correctHandle)
CheckHandle();
if (_correctHandle)
{
NewGUI.SetWarning("Window set!",5,50,900,300,50);
SetWindowPos(_handle, 0, 0, 0, 0, 0, 0x0001);
}
}
NewGUI.SetWarning just displays a label and shows up properly. _correctHandle is a simple bool and SetWindowPos is put in as
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern bool SetWindowPos(IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
I've tried moving quite a few things to get it to work but am out of ideas. Trying to get foregroundwindow brings back a entirely incorrect handle, findwindow for name brings back 0, and quite a few other things don't seem to work. Anyone know what my error could be/
p.Handle is the process' handle, not the window handle. You want p.MainWindowHandle.
It's also possible that the process you're trying to attach to has a hidden message-only main window. To figure that out, you'd need to use a tool like Spy++ to look at the structure of the windows.
If all else fails Spy++ will also give you a window class, which you can use with FindWindowEx to locate the window. (I do the same trick with Sticky Notes windows in this answer)
The GetActiveWindow idea from this thread : Any way to bring Unity3d to the foreground? got me the right window ID, but changing resolutions still caused me issues since unity was setting the window location to halfway between both monitors after my SetWindowPos is called. Here's my solution for other people needing something like this.
void FixedUpdate()
{
if (Handle == IntPtr.Zero)
{
Handle = GetActiveWindow();
uint uP;
GetWindowThreadProcessId(Handle, out uP);
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById((int)uP);
if (string.Equals(p.ProcessName, "Unity"))
AllowReset = false;
else if (string.Equals(p.ProcessName, "TestBuild00001"))
AllowReset = true;
else
Handle = IntPtr.Zero;
}
}
void Update()
{
if (ScreenSet && AllowReset && GuiValidReset)
{
GuiValidReset = false;
ScreenSet = false;
SetPosition();
}
}
void OnGUI()
{
if (ScreenSet && AllowReset && !GuiValidReset)
GuiValidReset = true;
}
internal static void SetPosition()
{
SetWindowPos(Handle, 0, 0, 0, 0, 0, 0x0001);
}
Dll imports of
[DllImport("User32.dll")]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
internal static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
Did update and ongui check to assure that a full redraw of unity would happen before positioning the window, since calling it at the same time a resolution change caused the window to reset to midscreen. ScreenSet is set to true right after my resolution is set.

Pinvoke MoveWindow in C#

I am try to get form2 positioned relative to form1. I've tried many things an nothing seems to work right. I wanted to try:
http://www.pinvoke.net/default.aspx/user32/MoveWindow.html
As a newbie to windows programming especially C# I'm looking at the syntax/example and I find it difficult to know what to put in for the parameters. I did get a different simpler p/invoke to work:
using System.Runtime.InteropServices;
...
public partial class Form1 : Form
{
public Form1()
{ InitializeComponent(); }
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CreateDirectory(string lpPathName,
IntPtr lpSecurityAttributes);
private void Form1_Load(object sender, EventArgs e) { }
private void button1_Click(object sender, EventArgs e)
{ CreateDirectory(#"c:\test4", IntPtr.Zero); }
}
...
I'm taking a guess IntPtr is "saying" I'm pointing at the first node - but only a guess...
The C# signature for MoveWindow:
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
there's comments on this as well on the site. "IntPtr hWnd" - I need to get that associated with Form2 (?) , do I repaint? I'm trying to show I've looked at it and tried to figure it out - I know we are getting it from the system's dll's...the x-y I got but getting it "with" Form2 I'm lost. Help appreciated.
In general you wouldn't need PInvoke for something as simple as this.
As long as you have a reference to form2 from form1 then you can easily do this by listening to the LocationChanged event of form1. When form1 moves then you can move form2 by doing the following:
var location = this.Location;
location.Offset(xoffset, yoffset);
form2.Location = location;
That would normally be enough to make sure form2 is placed somewhere relatively to form1 and that its position is updated when form1 is moved. You may have to set an initial position of form2 if the LocationChanged event is not called when the form is first created.
Something like this should work. Tested too. You can alter this to fit exactly what you wanted to do, which shouldn't be an issue at all.
// Win32 RECT
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
// GetWindowRect gets the win32 RECT by a window handle.
[DllImport("user32.dll", SetLastError=true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
// MoveWindow moves a window or changes its size based on a window handle.
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
// MoveForms moves one form to another using the win api.
void MoveForms(Form fromForm, Form toForm)
{
IntPtr hWnd_from = fromForm.Handle; // fromForm window handle
IntPtr hWnd_to = toForm.Handle; // toForm window handle
RECT rect_from, rect_to; // RECT holders for fromForm and toForm
if (GetWindowRect(hWnd_from, out rect_from) &&
GetWindowRect(hWnd_to, out rect_to)) // if it gets the win32 RECT for both the fromForm and toForm do the following ...
{
int x_to = rect_to.Left; // toForm's X position
int y_to = rect_to.Top; // toForm's Y position
int width_from = rect_from.Right - rect_from.Left; // fromForm's width
int height_from = rect_from.Bottom - rect_from.Top; // fromForm's height
// Moves fromForm to toForm using the x_to, y_to for X/Y and width_from, height_from for W/H.
MoveWindow(hWnd_from, x_to, y_to, width_from, height_from, true);
}
}

Save open application dimensions and positions on Windows to reopen them via configuration file?

Is there a way to open an application to a saved set of dimensions and positions (on Windows) via a script? I'd also like to, of course, save the dimensions and positions of open applications -- the other side of this script. Any suggestions? If a script can't get this done on a Windows machine is there a way with C#/.NET?
You can do this using a User32.dll call to SetWindowPos.
For example:
[DllImport("User32.dll")]
public static extern IntPtr FindWindow(string className, string windowName);
[DllImport("User32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr windowHandle, IntPtr parentWindowHandle, int x, int y, int width, int height, PositionFlags positionFlags);
public static readonly IntPtr HWND_TOP = new IntPtr(0);
[Flags]
public enum PositionFlags : uint
{
ShowWindow = 0x40
}
static void Main(string[] args)
{
var windowHandle = FindWindow(null, "Untitled - Notepad");
SetWindowPos(windowHandle, HWND_TOP, 0, 0, 640, 480, PositionFlags.ShowWindow);
}
This will find the window with the title "Untitled - Notepad", move it to 0, 0, and resize it to 640x480. I have added the bare minimal number of PositionFlags and HWND flags, look at the link I provided if you require more and add them in the same way :)
Oh, and to read the dimensions out, take a look at GetWindowRect. Here's an example of how to use this from c#: Example.
Take a look at Application Settings.

Categories

Resources