Changing where the .exe window appears when debugging? - c#

First of all I'm not sure if ".exe window" is the proper term. It's the window that pops up when you start the application.
I'm a game programmer, and when I'm debugging, I very rapidly start it up, look at the problem, then close it down again to make minor changes in the code, then start it again etc. I do this like once per minute, so it happens a lot. My problem is that the .exe window always appears at the middle of my main screen (where I'm coding), and I'm running double monitors, and I'd like the game window to appear on my second screen instead of my main screen (obscuring my code).
Can I change where the exe window appears in VS2010? I've looked around everywhere, it feels like. Or is it something that will have to be managed by a 3rd party program? If so, what program?
Edit:
OK, OK, I found the solution. I did a really dumb mistake where I didn't mention that I am using XNA, and not using winforms. Sorry for misleading you guys. Here's how I solved it:
First off I had to include:
using System.Runtime.InteropServices;
Then at the top of my main class I created a tiny class:
public static class User32
{
[DllImport("user32.dll")] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
}
Then in my Initialize function I simply call:
#if DEBUG
User32.MoveWindow(Game.Window.Handle, 2000, 400, 600, 480, true);
#endif
It's a little ugly, but it's only for debugging and only called once, so psh.
Original solution found here: http://social.msdn.microsoft.com/forums/en-US/xnagamestudioexpress/thread/bc9588a9-542f-425b-9025-d69fe2b0b182/

You can set the Form.StartPosition property, or just manually write to the Left and Top properties of the form you want to move.

Option 1: You could set the appropriate properties on the window/form if a debugger is attached.
if (System.Diagnostics.Debugger.IsAttached)
{
// Set the window/form's top/left properties.
}
Option 2: Add a command line switch, use that as startup parameter (Properties->Debug->Commandline arguments), and then set the appropriate properties in the window/form:
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.Args.Any(arg => arg.Equals("/debugmode", StringComparison.OrdinalIgnoreCase))
// Set some value which you check in your main window.
}

Although you are not using winforms, you still change it in Xna by using winforms objects. I know you found a solution but here is how to change it without using interop.
Add a reference to System.Windows.Forms and System.Drawing to the References in the game project.
Resist the temptation to add using statements for these as it can cause ambiguity with some Xna objects (Point, for instance, which in Xna uses floats).
In the Game.Initialize method:
System.Drawing.Point p = new System.Drawing.Point(2000, 400);// or wherever you want
System.Windows.Forms.Control c = Control.FromHandle(this.Window.Handle);
c.Location = p;
the game window will now start at the screen 2000,400 location.

I would just call it the "main application window". Anyway, assuming you're using WinForms, this would put the window in the top left corner of the first screen that isn't your primary screen:
void Form1_Load(object sender, EventArgs e)
{
#if DEBUG
Location = Screen.AllScreens.First(s => !s.Primary).Bounds.Location;
#endif
}
If you've only got two monitors hooked up, it'll work fine. You could also get more creative and center the application window on the other monitor, maximize it, whatever. The #if could be substituted with if (System.Diagnostics.Debugger.IsAttached) as suggested by #Daniel if you wanted. I used the former just to present another alternative.

Related

Force external process to redraw borders after SetWindowPos

I am just trying to see if I can make a program that will sit along the left side of my monitor.
By doing so I am using a BackgroundWorker to loop through all of the users process (ones with a MainWindowTitle) and using SetWindowPos to move and resize them based upon my sidebar.
This all works fine except it causes the border to not draw (I guess that is a way to explain it).
I have attached 2 images and as you can see the borders don't seem to draw (and for Visual Studio it doesn't resize based upon the application BorderStyle)
This is the code I have so far:
foreach (Process p in Process.GetProcesses())
{
if (p.MainWindowTitle == "") continue;
if (p.MainWindowTitle.ToLower().Contains("studio"))
{
IntPtr i = p.MainWindowHandle;
RECT r;
GetWindowRect(i, out r);
if (r.Left <= -1608)
SetWindowPos(i, HWND.Top, Screen.AllScreens[1].Bounds.Left + 200, Screen.AllScreens[1].Bounds.Top, Screen.AllScreens[1].Bounds.Width - 200, Screen.AllScreens[1].Bounds.Height, SetWindowPosFlags.SWP_NOACTIVATE);
}
}
As you can see I am just trying to resize and reposition any (just Visual Studio at the moment) window on my second monitor (to the left of my first using a hackish kind of check :D)
I think you are misinterpreting what you see there: the borders do not draw, because (before you moved them) the windows where MAXIMIZED. Maximized windows typically don't have a border in Windows.
The solution is to first bring them back to normal state, before moving them to the desired coordinate, i.e.
ShowWindow(i, ShowWindowCommands.Normal);
That said, you'll still have to deal with multi-window processes and a myriad of fun little challenges. Enjoy the ride :-).

Drag opaque Form?

I have the following code to drag the form and make it transparent when its getting dragged. The problem is that it flickers and isn't dragging smooth. I have a picture on the form, not sure if that's what's causing this. How can I make it not flicker. If I remove the opacity then it's getting dragged fast/smooth.
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam,
int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public void Drag(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Opacity = 0.9;
ReleaseCapture();
SendMessage(Handle, 0xA1, 0x2, 0);
this.Opacity = 1;
}
}
private void Body_MouseDown(object sender, MouseEventArgs e)
{
Drag(e);
}
There are a number of properties of the Form and Control class that are "heavy", requiring a great deal of change in the underlying native Windows window. They are the properties that are associated with the style flags that are passed to the native CreateWindowEx() call. The Opacity property, along with the TransparencyKey property are like that, when you change them from the default then the window needs another style flag, WS_EX_LAYERED.
That's a problem, given that this style flag is specified when you create the window. Windows has some support for changing them after the window is created with SetWindowsLongPtr() but that's always been spotty. Particularly so for WS_EX_LAYERED, a lot of stuff happens under the hood when that's turned on. It is implemented by taking advantage of a hardware feature in the video adapter called "layers". A layer is a separate chunk of video memory whose pixels are combined with the main memory. The mixer that supports that provides the opacity effect (multiply) and the transparency key effect (omit).
So changing the Opacity property on the fly, after the window is created is quite difficult. So much so that WPF completely forbids it. But Winforms doesn't, it needed to deal with the limitations of Windows 98. Which also made it difficult to change properties like ShowInTaskbar, RightToLeft, FormBorderStyle. It uses a trick to permit changing these properties, it completely destroys the native window and recreates it, now using the new style flags.
Problem solved, but this does have noticeable side effects. Inevitably, the window you look at disappears and the new window gets created and painted in the same spot. That causes the flicker you complained about. Also, destroying the window causes a lot of internal state to be lost. Winforms does its best to restore that state as well as it can for the new window, but the "I'm currently being moved" state cannot be restored. The modal move loop already terminated.
The workaround for this problem is crude but simple. Set the Opacity property in the Properties window to 99%. And change your code to restore it to 99 instead of 100. Now the style bit never has to be changed so you won't get these artifacts anymore.

set Cursor to desired point c#

Im trying to move my cursor according to my hand point in kinect, I can get the real coordinates I mean I can move an image on screen but I want real cursor to be settled according to my hand coordinates. I tried Console.SetCursor(x,y) but it gives exception I also tried to download windows forms dll but I cant find the version 4.00 . Is there any simple way to set cursor in a desired position? (which is working by the way and as I said Console.SetcursorPosition is not wodking?)
You didn't provide very much information about you app but I suspect that you just need to assign to Cursor.Position from System.Windows.Forms. You may need to add a reference to System.Windows.Forms in order to gain access to this, depending on exactly what type of project you have.
If you want to keep it lightweight and avoid taking a reference to WinForms then you could just pinvoke to SetCursorPos.
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
Just use
Cursor.Position = new Point();
You can find more information's here
Thank you for question and answer.
I found strange and unobvious behavior.
Let you use multi-monitor (two or three monitor) configuration, and use two windows in your application.
One window is active, and you set cursor position for second windows.
And this two windows located on different monitors.
Then, you need call SetCursorPos TWICE!
TWICE, who would have thought?
Firs call move cursor to virtual borderline between monitors.
And only second call move cursor to required position second window!
Example of code (after 6 hours of experiments):
SetForegroundWindow(this.Handle); // set second window active
SendMessage(this.Handle, 0x20, this.Handle, (IntPtr)1); // Send WM_SETCURSOR
SetCursorPos(400, 600);
Thread.Sleep(50);
SetCursorPos(400, 600);

Hosting XNA inside WPF - Weird "Phantom" Window issue

I'm trying to host an XNA game inside a WPF window using the Windows Forms host control. I've got a weird problem that a "Phantom" window is created when I run the game. It is created exactly at the first call to game's Update method exits.
Here is the Update code, the default one from a new XNA project:
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
The window is created after I step from the last curly brace at the very bottom. (yes, weird to have it NOT in base.Update but the after the } after it.)
I have a Windows Forms host as I've said, with the code below:
The relevant XAML is here (I've obviously got the Forms namespace etc. set up so no need to paste here):
<WindowsFormsHost Margin="12" Name="windowsFormsHost1">
<forms:Panel x:Name="p"></forms:Panel>
</WindowsFormsHost>
and in codebehind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Viewer v = new Viewer(p.Handle);
v.Run();
}
where the Viewer is my Game class (from XNA), with:
public Viewer(IntPtr handle)
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
panelHandle = handle;
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
}
void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{
e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = panelHandle;
}
This technique is from a blog post I've found a few days ago (I can't find it again now, it is EXACTLY the same way -- with the exception that the post was old and doesn't have the issue I'm having).
The problem is that, I build and run, but along with my "normal" window, there is a phantom window created. In my main window, XNA renders correctly. But the phantom window (the Window title is my assembly's name), doesn't have anything in it, is not resizable, cursor doesn't render inside it, and it acts like the main window in the sense that when I minimize this window, my main window stops rendering the XNA content until I un-minimize that phantom window. My program doesn't quit until I close BOTH windows. (If I close the phantom only, my main window, as you guess, stops rendering my XNA content). I tried iterating over my application windows, with 'App.Current.Windows', and all I've got is my main window listed there, that's why I'm calling that semi-responsive window the "phantom" window. It is not visible in my object model in WPF.
When I wrote "XNA WPF phantom window", the first I've got was this: WPF: How to determine the origin of a phantom window?
So I went and tried the Snoop. But Snoop probably also relies on the Windows iteration, and it also doesn't see any extra window there. I use the crosshair-drag feature (you drag the cursor around the screen and Snoop tells which process and window it belongs to), and Snoop tells that the Phantom Window is actually my MainWindow. But my MainWindow is ALSO the same window, according to Snoop. So this phantom is somewhat closely related (or maybe a "child"?) of my MainWindow instance, but I need a way to close it (or at least, hide it).
Any ideas?
The two good ways of embedding XNA in WPF that I know of are in this post (one is described in the post itself, the other is described in the first link in the post):
http://blogs.msdn.com/b/nicgrave/archive/2011/03/25/wpf-hosting-for-xna-game-studio-4-0.aspx
Both have code samples and I've used the WriteableBitmap version before with good results. (I was creating a development tool that didn't need to show anything larger than 384x384 so FPS was acceptable; if you need high FPS with a large back buffer (e.g. 800x600, 720p, etc.) you'll definitely want to use the HwndHost method).
I'd recommend trying whichever one of those two best fits your needs. When you try to use the window XNA creates, XNA's WinForms window expects to be a top level window. I've tried messing around with solutions such as what you've posted in the past but have never gotten beyond the phantom window issue.
I wrote this and finished it just now, maybe this can help you. I wrote it for the express purpose of XNA <-> WPF Compatibility; that is, having XNA be able to render inside a specific Control on WPF. Give it a shot:
https://xnaml.codeplex.com/
Besides being just a workaround, I think we are stuck with this being the best until something new comes in..
After further investigation, I've found out that the phantom window is the "window handle" of the Game instance, and it is required for the game to keep running. It could be accessed as the game's window handle, and creating (actually getting reference to an existing) a form from it. The game also prevented the input mechanisms of the objects such as WPF TextBox, and I got a very inconvenient (but works for me now) workaround by deriving the TextBox class and overriding the OnKeyDown manually (it caught the even but weirdly wasn't putting in text input.) and raising a TextInput event manually. A bit hacky, but works. And with the form, I can just set the opacity to zero and move it somewhere not in the middle, and it will stay there.
But my solution is just a hacky workaround and Mike's solution is definitely better, so if you are reading this and just about to start off a new project like these, follow his answer.

Programaticly Move Mouse in VMWare C#

I'm writing a toy application that plays with the mouse cursor, and I'm trying to move it programmticly. Using either Cursor.Position = ... or Win32 interop calls work fine on a normal machine, but I'm having difficulties getting it to work under VMWare.
Does anyone have any suggestions?
EDIT
To clarify:
I've got a small windows forms application I've made running inside the VM, it has one button on it, when clicked it is supposed to move the mouse cursor inside the VM. I've used both the Cursor.Position method and the approach that Wolf5 has suggested.
Try this instead:
[DllImport("user32", SetLastError = true)]
private static extern int SetCursorPos(int x, int y);
public static void SetMousePos(Point p) {
SetMousePos(p.X, p.Y);
}
public static void SetMousePos(int x, int y) {
SetCursorPos(x, y);
}
Of course you will have to make sure VMWARE has focus in the first place since it cannot set the mouse position of your mouse outside VMWARE.
Don't focus the VM with your real mouse. Or uninstall the VMWare mouse driver so the VM doesn't get the focus unless you click inside it.
I have resolved the issue.
In a desperate attempt to try anything i finally gave up and un-installed the mouse driver from the VM. After a reboot, my toy application works.
The device was listed as a VMWare Pointing device, after the reboot it's coming up as an "unknown device", but the mouse still works. Albeit I a little on the nippy side.

Categories

Resources