[C#.NET] Set Window Position + Eject CD Drive

Soldato
Joined
12 Jun 2005
Posts
5,361
Hi there,

Looking to be able to set the position of a third party app on the users screen and possibly minimize it. I am guessing you need API calls for this, but I don't know which ones to use or how to implement them.

Also looking to be able to eject an optical drive (cd drive) - but again don't know how to do this.

Any help would be appreciated? If posting code for API calls, I haven't really used them before, so a little explanation about the parameters would be nice.

Thanks.
 
You'll need to use the SetWindowPos Win32 function to set another window's position.

The code should look something like this:
Code:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

The parameters:
  • hWnd: the handle to the window you want to resize. Since your target window is from a third party app, you'll have to use more API calls to obtain this handle, but which ones to use will depend on how you actually identify the window.
  • hWndInsertAfter: the window that the resized window should be placed above after being resized. You can give special values here as well to send it to the back, or to the front, for example.
  • X, Y: the new position of the top-left corner of the window.
  • cx, cy: the new width and height of the window.
  • uFlags: some options you can set for resizing.

The extern keyword tells the compiler that the method should be imported from an external library; the DllImport attribute tells it where to find this method.

You'll probably want to use HWND_NOTOPMOST for hWndInsertAfter. This has an equivalent IntPtr value of -2, so you'd do something like this:

Code:
IntPtr HWND_NOTOPMOST = new IntPtr(-2);
SetWindowPos(targetWindowHandle, HWND_NOTOPMOST, x, y, width, height, flags);

You can find more detail on the flags and other stuff on MSDN and pinvoke.net
 
Also looking to be able to eject an optical drive (cd drive) - but again don't know how to do this.

You can do this via the Media Control Interface API, so building on what Inquisitor said you'll need to p/invoke a Win32 function from an external library, in this case the mciSendString function.

First import the method (parameters described via the link above):

Code:
[DllImport("winmm.dll", EntryPoint = "mciSendStringA")]
public static extern void mciSendStringA(string lpstrCommand, string lpstrReturnString, Int32 uReturnLength, IntPtr hwndCallback);

Then invoke as follows (E being the drive letter of the optical drive in this example):

Code:
mciSendStringA("open cdaudio!E: alias driveX", string.Empty, 0, IntPtr.Zero);
mciSendStringA("set driveX door open wait", string.Empty, 0, IntPtr.Zero);
mciSendStringA("close driveX", string.Empty, 0, IntPtr.Zero);
 
Cheers guys - both worked perfectly, but I did find that if I set the position of an application to off screen, for some reason it killed it, but i have found a work around.


=========

How do I kill a c#.net application without it running any more code in the initializing function of a form:

Code:
        public MainForm()
        {
            InitializeComponent();

            // I want to kill it here.
        }
 
Process.GetCurrentProcess().Kill() would certainly do the trick, but might be considered a bit "heavy-handed". If the form in question is your main application form, can you determine whether you want to abort from within the Main() method of your app before the form is constructed i.e. before the call to Application.Run(new MainForm()) ?
 
As voodooflux said, you should really allow the process to end naturally, by reaching the end of the Main method. If you need to make a decision on application startup that affects whether or not the application will even continue to run, you're best off doing this in Main before any forms are displayed.
 
If the form in question is your main application form, can you determine whether you want to abort from within the Main() method of your app before the form is constructed i.e. before the call to Application.Run(new MainForm()) ?

Exactly what I needed.

Thank again guys!


=====

I am trying to be able to put in some code for unhandled errors, should i just add logic for the following events (which i know how to do), but will that cover everything?:

Code:
Application.ThreadException
AppDomain.CurrentDomain.UnhandledException

...because it doesn't seem to when i put the logic in the form, but it doesn't seem to track some of the errors, like NullException...etc...
 
Last edited:
Back
Top Bottom