This is a duplicate of a question I posted at Windows Dev Center. Still awaiting replies, so I thought I would try it here. My apologies if the formatting goes awry.
This is currently being written and debugged using Windows 7 Professional, SP1.
The application is located at the top of the desktop, and the working area is appropriately resized via a hook into the SystemParametersInfo function. The MenuStrip appears as it should, with the exception that any dropdown from the MenuStrip shows as detached from the MenuStrip itself (as if it is being drawn on the new working area, as opposed to the form containing the MenuStrip). For example:
Application TopLevel: true
Application Height: 150
Application Location: 0,0 on Desktop (prior to working area's resize)
MenuStrip Height: 25
MenuStrip Location: 0,0 inside Parent Form
MenuStrip DropDown Location: x,2 (where x is a valid and acceptable value) this is being drawn on the resized working area (i.e. beneath the form)
I have attempted correcting this with a custom Renderer to no present avail. I tried to override WndProc (as follows) so as to see what exactly was occurring, but that resulted in a stackoverflow halfway through drawing the application.
protected override void WndProc(ref Message m)
{
if (mainForm.Visible)
{
MessageBox.Show("ID: " + m.Msg.ToString() + "\n" + m.ToString());
}
base.WndProc(ref m);
}
I suspect I've run this into the ground by now, but if you require any further explanation, just let me know. Just hoping someone can point me in the appropriate direction as to where I should look.
Hopefully this will answer the question regarding why I used SystemParametersInfo:
#region TEMPORARY FIX TO ACHIEVE APPBAR
public RECT normalWorkingRECT = new RECT();
public RECT newWorkingRECT = new RECT();
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
};
[DllImport("user32.dll", EntryPoint="SystemParametersInfo")]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT pvParam, uint fWinIni);
//call after scale is set
private void setAppBar()
{
//make the parent = the desktop
if (!this.GetTopLevel())
{
this.SetTopLevel(true);
}
this.Width = SystemInformation.PrimaryMonitorSize.Width;
//set old Working Area
SystemParametersInfo(0x0030, 0, ref normalWorkingRECT, 0);
//change work area based on size of main form
newWorkingRECT.left = normalWorkingRECT.left;
newWorkingRECT.top = normalWorkingRECT.top + this.DesktopBounds.Height + 4;
newWorkingRECT.right = normalWorkingRECT.right;
newWorkingRECT.bottom = normalWorkingRECT.bottom;
SystemParametersInfo(0x002F, 0, ref newWorkingRECT, 0x0002);
}
//called on close
private void unsetAppBar()
{
//get current work area to compare
RECT testRECT = new RECT();
SystemParametersInfo(0x0030, 0, ref testRECT, 0);
//if no change, resize to normal working rect
if (newWorkingRECT.top == testRECT.top &&
newWorkingRECT.bottom == testRECT.bottom &&
newWorkingRECT.left == testRECT.left &&
newWorkingRECT.right == testRECT.right)
{
SystemParametersInfo(0x002F, 0, ref normalWorkingRECT, 0x0002);
}
//if there is a change, resize to current working rect - this.height
else
{
testRECT.top -= this.DesktopBounds.Height + 4;
SystemParametersInfo(0x002F, 0, ref testRECT, 0x0002);
}
}
#endregion
EDIT: Added image as requested and code to show reason for SystemParametersInfo.
Related
I have an application with at least 2 separate windows.
The secondary window is too far from the PC to use the mouse, so I have a method that temporarily brings that specific window to the current main display, changes are done, then the window is sent back.
This worked well under Windows 10, however under Windows 11, the window seems to disappear and is nowhere to be seen during the initial call. It can however be sent back (from wherever it was hiding) to the secondary monitor.
Here is some code to position the window (normal MoveWindow):
// Position is assigned in the constructor of the second window
public System.Drawing.Rectangle Position { get; set; }
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
MoveW();
}
public void MoveW()
{
WindowInteropHelper wih = new(this);
IntPtr hWnd = wih.Handle;
if (!Position.IsEmpty)
{
_ = MoveWindow(hWnd, Position.Left, Position.Top, Position.Width, Position.Height, false);
}
}
and here is how I am bringing the window to the current display (work perfect Win10):
// Getting the coordinates of the MainWindow
var screen = System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(App.Current.MainWindow).Handle);
System.Drawing.Rectangle rect = screen.WorkingArea;
// Simply passing them to second window needing to be moved
if (!rect.IsEmpty)
{
var wih = new WindowInteropHelper(this);
IntPtr hWnd = wih.Handle;
MoveWindow(hWnd, rect.Left, rect.Top, rect.Width, rect.Height, false);
}
Here is the link for MoveWindow
I have created a small GitHub project to illustrate the issue. If you have 2 screens and win10 and 11, get it from here.
Any suggestions?
As far as I noticed, on Windows 11, WindowState.Maximized seems to prevent the window from being shown after its location is changed by MoveWindow function.
So the workround is returing to WindowState.Normal before calling MoveWindow. It would be something like below.
WindowState state = this.WindowState;
try
{
this.WindowState = WindowState.Normal;
MoveWindow(hWnd, rect.Left, rect.Top, rect.Width, rect.Height, false);
}
finally
{
this.WindowState = state;
}
I am a beginner at coding and I want to create an application that says the width, height, and position of the window.
The problem is that I don't know how to GET the position of the window.
I searched the internet but couldn't find the answer to my question.
Here is the code I have:
using System;
namespace WindowSizeChecker
{
class Program
{
const bool alwaysTrue = true;
static void Main(string[] args)
{
while (alwaysTrue == true)
{
Console.Write("Set your console window to your prefered size and position. Then press Enter");
Console.ReadLine();
screenSizeAndPosition();
Console.WriteLine("\n\nPress enter to repeat\n\n");
Console.ReadLine();
}
}
public static void screenSizeAndPosition()
{
int consoleWidth = Console.WindowWidth;
int consoleHeight = Console.WindowHeight;
string consoleWidthString = consoleWidth.ToString();
string consoleHeightString = consoleHeight.ToString();
Console.WriteLine("\nThe width of the window is: {0}\nAnd the height of the window is: {1}", consoleWidthString, consoleHeightString);
int largestWindowWidth = Console.LargestWindowWidth;
int largestWindowHeight = Console.LargestWindowHeight;
string largestWindowWidthString = largestWindowWidth.ToString();
string largestWindowHeightString = largestWindowHeight.ToString();
Console.WriteLine("\nThe largest width of the window is: {0}\nAnd the largest height of the window is: {1}", largestWindowWidthString, largestWindowHeightString);
}
}
}
Here is the program running:
enter image description here
I am a beginner at coding and I want to create an application that says the width, height, and position of the window. The problem is that I don't know how to GET the position of the window. I searched the internet but couldn't find the answer to my question.
The information is out there, but I admit, it's not necessarily presented in the easiest to understand manner, especially for a beginner.
IMHO, two of the most relevant Stack Overflow questions you probably should read are these:
Position a small console window to the bottom left of the screen?
DwmGetWindowAttribute returns 0 with PInvoke
They aren't really duplicates of your question, and for a beginner it's probably hard to see how they answer it. But they do in fact contain almost all of the information you would need.
There are a couple of things you need to understand, besides the "how":
The Console properties you're looking at now are not pixel dimensions, but rather are in terms of character columns and rows. That is, how many characters can fit across the window in a single row, and how many rows of those characters can fit vertically.
When it comes to pixels, there are actually (at least) two different ways to look at the window size: raw screen coordinates, and "DPI-adjusted". The latter is IMHO a misnomer, because it's not taking into account any actual screen resolution (i.e. "dots per inch"), but rather the scaling factor that is set for your desktop. It's considered "DPI-adjusted" because setting the scaling factor is the Windows mechanism for attempting to keep the visual presentation of a program consistent across displays of different resolution.
As you already have seen, you can get the character-oriented dimensions straight from the .NET Console class. But to get the pixel information, you need to use .NET's native interop support to call the Windows API directly. Here are some helper classes I put together, based on available documentation and Stack Overflow posts, to do that for your scenario:
[StructLayout(LayoutKind.Sequential)]
struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public int Width => Right - Left;
public int Height => Bottom - Top;
}
class NativeConsole
{
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
}
class Winuser
{
[DllImport(#"user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
public static Rect GetWindowRect(IntPtr handle)
{
if (!GetWindowRect(handle, out Rect rect))
{
throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
}
return rect;
}
}
class DwmApi
{
private const int DWMWA_EXTENDED_FRAME_BOUNDS = 9;
[DllImport(#"dwmapi.dll")]
private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);
public static Rect GetExtendedFrameBounds(IntPtr hwnd)
{
int hresult = DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, out Rect rect, Marshal.SizeOf(typeof(Rect)));
if (hresult != 0)
{
throw Marshal.GetExceptionForHR(hresult);
}
return rect;
}
}
You could, of course, lump all of the above together in a single class, but I prefer to keep things organized. The above groups the various parts of the API into the same organization used in the native Win32 API itself.
With those pieces in hand, now we can put together a program similar to the one you have above, except that it will display the window position (which is what you want), along with the width and height as well (since those come for free from the native API anyway).
That looks like this:
using static System.Console;
class Program
{
static void Main(string[] args)
{
Clear();
string prompt = "Set your console window to your preferred size and position. Press X to exit";
while (true)
{
if (KeyAvailable && ReadKey(intercept: true).Key == ConsoleKey.X)
{
break;
}
ScreenSizeAndPosition(prompt);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.25));
}
}
static void ScreenSizeAndPosition(string prompt)
{
string format = $"{{0, {-WindowWidth}}}";
SetCursorPosition(0, 0);
Write(format, prompt);
Write(format, $"Window is {WindowWidth} columns wide and {WindowHeight} rows high");
Write(format, $"The largest window that can fit on the screen is {LargestWindowWidth} columns wide and {LargestWindowHeight} rows high");
IntPtr consoleHwnd = NativeConsole.GetConsoleWindow();
Rect winuserRect = Winuser.GetWindowRect(consoleHwnd),
dwmRect = DwmApi.GetExtendedFrameBounds(consoleHwnd);
Write(format, $"DPI-adjusted screen values: location is {{{winuserRect.Left}, {winuserRect.Top}}}, window is {winuserRect.Width} pixels wide, {winuserRect.Height} pixels high");
Write(format, $"Desktop Window Manager values: location is {{{dwmRect.Left}, {dwmRect.Top}}}, window is {dwmRect.Width} pixels wide, {dwmRect.Height} pixels high");
for (int i = 0; i < WindowHeight - 5; i++)
{
Write(format, "");
}
}
}
I did change your basic logic in the program a bit, so that it just checks every quarter second rather than waiting for the user to press a key, displaying whatever the current values are as the user changes the window size and position.
For more details on the Windows functions used above, you should read the documentation:
GetConsoleWindow()
GetWindowRect()
DwmGetWindowAttribute()
There are some additional subtleties in the ways that GetWindowRect() and DwmGetWindowAttribute() work, so it's worth checking out the docs so that you understand better what they are returning in terms of the window dimensional values.
You should call a Win32 API DwmGetWindowAttribute via PInovke to the current window position. Refer to the document and see how to use it.
Ok, consider this image.
I develop an IE extension in c# and I would :
- the distance in red, between top of screen and top of `visible webpage`
- the distance in red between left of screen and left of `visible webpage`
- the width/heigth of the visible webpage
Of course considering that i have the whole screen size. If i have red and black I can calculate green.
What the point ?
I have thousand screen coordinates (X,Y), i have to calcul the coordinate relative to the webpage.
Example :
Considering
Screen size : 1200 * 800
Webpage size : 400*300
Red distance between left screen border and left webpage border : 200
Red distance between top screen border and top webpage border : 300
So my coordinates screen => relative webpage becomes :
( 100, 100 ) => OUTSIDE WEBPAGE( ignored )
( 1100, 650 ) => OUTSIDE WEBPAGE ( ignored )
( 200, 300 ) => ( 0,0 )
( 250, 400 ) => ( 50, 100 )
Actually i have this code, this is inherited from AddinExpress.IE.ADXIEModule, thetoolbarObj is the toolbar that I added to InternetExplorer. So i can use pointToScreen on it and i'm not far of what I need, but the left corner of the toolbar is not what I need, I need the leftcorner of the webpage.
public void getUtilsDimension()
{
Rectangle resolution = Screen.PrimaryScreen.Bounds;
Int32 screenWidth = resolution.Width;
Int32 screenHeight = resolution.Height;
AddinExpress.IE.ADXIEToolBarItem toolbarItem = this.ToolBars[0];
AddinExpress.IE.ADXIEToolbar toolbarObj = toolbarItem.ToolBarObj;
Point leftCornerWebPage = toolbarObj.PointToScreen(new Point(0, 0));
Int32 toolbarHeight = toolbarObj.Height;
Int32 toolbarWidth = toolbarObj.Width;
Debug.WriteLine("Largeur écran : " + screenWidth);
Debug.WriteLine("Hauteur écran : " + screenHeight);
Debug.WriteLine("LeftCornerX : " + leftCornerWebPage.X);
Debug.WriteLine("LeftCornerY : " + leftCornerWebPage.Y);
Debug.WriteLine("toolbarHeight : " + toolbarHeight);
Debug.WriteLine("toolbarWidth : " + toolbarWidth);
}
This is what I get actually, the screen is 1600*900, pointToScreen return the coordinates of the red cross ( 484,158 ). But I need the coordinates of the blue cross, as the width and heigh of visible webpage. I know I can get that with $(window) in Jquery, but i don't know how with c#.
I can access at the HTLMDocument (typeof mshtml.HTMLDocument) with this.HTMLDocument, unfortunately pointToScreen is not available on HTMLDocument object.
Edit : It s chrome on the first screenshot but of course that should be IE
Update 08/12
OK I have the width and height of the visible webpage ( black line on my screen shot )
The only missing thing is the coordinates of blue cross on my screenshot 2
var heightVisibleWebPage = HTMLDocument.documentElement.offsetHeight;
var widthVisibleWebPage = HTMLDocument.documentElement.offsetWidth;
For the bounty, I need the exact coordinates of the blue cross. No matter how. It should work no matter the Internet explorer version, favorites/tool/command/state bar displayed or not.
Update 08/12 HTMLDocument
HTMLDocument is from AddinExpress, it's not a System.Windows.Forms.HtmlDocument
public mshtml.HTMLDocument HTMLDocument
{
get
{
return (this.HTMLDocumentObj as mshtml.HTMLDocument);
}
}
His parent HTMLDocument.parentWindows is a IHTMLWindow2 object
HTMLDocumentObj is a member of
public class ADXIEModule : Component, IRemoteModule2, IRemoteModule, IObjectWithSite, IWin32Window
{
...
//
// Résumé :
// Gets the automation object (a COM object) of the active document, if any.
//
// Notes :
// When the active document is an HTML page, this property provides access to
// the contents of the HTML Document Object Model (DOM). Specifically, it returns
// an HTMLDocument object reference. The HTMLDocument object is functionally
// equivalent to the HTML document object used in HTML page script. It supports
// all the properties and methods necessary to access the entire contents of
// the active HTML document.
// The HTMLDocument object can be used through the IHTMLDocument interface,
// the IHTMLDocument2 interface, and the IHTMLDocument3 interface.
// When other document types are active, such as a Microsoft Word document,
// this property returns the document automation object of that document. For
// Word documents, this is the Document object.
[Browsable(false)]
public object HTMLDocumentObj { get; }
...
}
Explain when -1 for the community please ;)
These are the steps:
Find Internet Explorer window handle with EnumWindows() api. Class name is IEFrame
Iterate through all child windows with EnumChildWindows() api. Class name is Internet Explorer_Server
Find x, y coordinate with GetWindowRect() api
Code:
[DllImport("user32.dll")]
public static extern int EnumWindows(EnumWindowsCallback lpEnumFunc, int lParam);
[DllImport("user32.dll")]
public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsCallback lpEnumFunc, int lParam);
public delegate bool EnumWindowsCallback(IntPtr hwnd, int lParam);
[DllImport("user32.dll")]
public static extern void GetClassName(IntPtr hwnd, StringBuilder s, int nMaxCount);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
private IntPtr ieHandle, ieChildHandle;
private void GetWindows()
{
EnumWindows(Callback, 0);
}
private bool Callback(IntPtr hwnd, int lParam)
{
StringBuilder className = new StringBuilder(256);
GetClassName(hwnd, className, className.Capacity);
if (className.ToString().Equals("IEFrame"))
{
ieHandle = hwnd;
return false;
}
return true; //continue enumeration
}
private void GetChildWindows()
{
if (ieHandle != IntPtr.Zero)
{
EnumChildWindows(ieHandle, CallbackChild, 0);
}
}
private bool CallbackChild(IntPtr hwnd, int lParam)
{
StringBuilder className = new StringBuilder(256);
GetClassName(hwnd, className, className.Capacity);
if (className.ToString().Equals("Internet Explorer_Server"))
{
ieChildHandle = hwnd;
return false;
}
return true; //continue enumeration
}
To get the coordinates:
GetWindows();
GetChildWindows();
if (ieChildHandle != IntPtr.Zero)
{
RECT rect;
if (GetWindowRect(ieChildHandle, out rect))
{
//rect.Left, rect.Top
}
}
ieChildHandle = IntPtr.Zero;
ieHandle = IntPtr.Zero;
Tested with IE 6, 9 and 11
Get a handle on the current tab:
foreach (InternetExplorer ie in new ShellWindows())
{
// Find
// Current
// Tab
//currentTab.left // left edge in pixels
}
You may need to drill down into parent objects using ".parent" to add all the the offsets needed until you get the total offset of the browser tab.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa752084(v=vs.85).aspx#properties
I have a Form that has a combobox on it.
The combobox is set DropDownList. These drop down items are a descriptive form of an object. This means they can get quite long. The position of the combobox on the screen means when the drop down list is displayed it doesn't all fit on the screen. Some of it is chopped off by the right edge of the screen.
I can't move the combobox.
Is their some way I can move the drop down list part of the control. Perhaps centre it under the control ?
Update
I've attached a screenshot. You can see the form here -
When entering transactions the user fills in the form and clicks Save. A number of the transactions that will be entered for any client though will be recurring transactions. These can be saved to the favourites. The drop down box lists the currently saved favourites and when one is selected the program automatically fills in the transaction fields.
Screenshot 2 showing the whole program and the combobox list running out of space.
I realise from the screenshot I could move the form but I like to keep the forms for entering transactions centered on the screen.
I may have to look at other options for the interface.
Thanks,
maybe you should create your own comboBox, as shown here:
http://msdn.microsoft.com/en-us/library/ms996411
Sorry for late posting :-). Yes You can do that. But you need to create a custom ComboBox and override the WndProc method of base ComboBox;
Its like this;
System.Runtime.InteropServices
private const int SWP_NOSIZE = 0x1;
private const int WM_CTLCOLORLISTBOX = 0x0134;
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int
X, int Y, int cx, int cy, uint uFlags);
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CTLCOLORLISTBOX)
{
// Make sure we are inbounds of the screen
int left = this.PointToScreen(new Point(0, 0)).X;
//Only do this if the dropdown is going off right edge of screen
if (this.DropDownWidth > Screen.PrimaryScreen.WorkingArea.Width - left)
{
// Get the current combo position and size
Rectangle comboRect = this.RectangleToScreen(this.ClientRectangle);
int dropHeight = 0;
int topOfDropDown = 0;
int leftOfDropDown = 0;
//Calculate dropped list height
for (int i = 0; (i < this.Items.Count && i < this.MaxDropDownItems); i++)
{
dropHeight += this.ItemHeight;
}
//Set top position of the dropped list if
//it goes off the bottom of the screen
if (dropHeight > Screen.PrimaryScreen.WorkingArea.Height -
this.PointToScreen(new Point(0, 0)).Y)
{
topOfDropDown = comboRect.Top - dropHeight - 2;
}
else
{
topOfDropDown = comboRect.Bottom;
}
//Calculate shifted left position
leftOfDropDown = comboRect.Left - (this.DropDownWidth -
(Screen.PrimaryScreen.WorkingArea.Width - left));
//when using the SWP_NOSIZE flag, cx and cy params are ignored
SetWindowPos(m.LParam,
IntPtr.Zero,
leftOfDropDown,
topOfDropDown,
0,
0,
SWP_NOSIZE);
}
}
base.WndProc(ref m);
}
The code is obtain from a MSDN article Building a Better ComboBox
Did you try setting in the designer
Combobox.Anchor = Left | Right
Try setting the DropdownWidth of the combo.
Simple, i want to move a windows pressing ALT+MOUSE, like linux os (ALT+drag).
It's possible to pass a win32 api (move api) to the windows interested clicking on it?
I have a windows services that hook key pressed (ALT button in specific).
When ALT key is pressed and a mouse down event is verified, i want to move window clicking anywhere, not only on the title bar!
Currently i move my form windows in this way:
using System.Runtime.InteropServices;
[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, int wParam, int lParam );
[DllImportAttribute( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
public static extern bool ReleaseCapture();
private void Form1_MouseDown( object sender, MouseEventArgs e )
{
ReleaseCapture();
SendMessage( this.Handle, 0xa1, 0x2, 0 );
}
How can I get windows handle of the specific windows by clicking and after call SendMessage() on it?
It's possible?
You can do this by trapping the WM_NCHITTEST message that Windows sends to see what area of the window got clicked. You can fool it by returning HTCAPTION and it will dutifully perform the mouse actions you'd normally get when clicking the caption of a window. Including moving the window. Paste this code into your form:
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
// Trap WM_NCHITTEST when the ALT key is down
if (m.Msg == 0x84 && (Control.ModifierKeys == Keys.Alt)) {
// Translate HTCLIENT to HTCAPTION
if (m.Result == (IntPtr)1) m.Result = (IntPtr)2;
}
}
I worked this out my self, came up with something interesting of my own calculations, worked perfectly for me, for any window (any active foreground window). Kinda long, but really easy to understand if you follow along the comments, hope it helps :)
The way it works, is that you press a certain registered key-combo, like Ctrl+Alt+M
and the mouse will stick in the center of an active window, you move the mouse, the windows follows it, press the SAME combo again, to release, no need for mouse clicks or anything.
public void MoveWindow_AfterMouse()
{
// 1- get a handle to the foreground window (or any window that you want to move).
// 2- set the mouse pos to the window's center.
// 3- let the window move with the mouse in a loop, such that:
// win(x) = mouse(x) - win(width)/2
// win(y) = mouse(y) - win(height)/2
// This is because the origin (point of rendering) of the window, is at its top-left corner and NOT its center!
// 1-
IntPtr hWnd = WinAPIs.GetForegroundWindow();
// 2- Then:
// first we need to get the x, y to the center of the window.
// to do this, we have to know the width/height of the window.
// to do this, we could use GetWindowRect which will give us the coords of the bottom right and upper left corners of the window,
// with some math, we could deduce the width/height of the window.
// after we do that, we simply set the x, y coords of the mouse to that center.
RECT wndRect = new RECT();
WinAPIs.GetWindowRect(hWnd, out wndRect);
int wndWidth = wndRect.right - wndRect.left;
int wndHeight = wndRect.bottom - wndRect.top; // cuz the more you go down, the more y value increases.
Point wndCenter = new Point(wndWidth / 2, wndHeight / 2); // this is the center of the window relative to itself.
WinAPIs.ClientToScreen(hWnd, out wndCenter); // this will make its center relative to the screen coords.
WinAPIs.SetCursorPos(wndCenter.X, wndCenter.Y);
// 3- Moving :)))
while (true)
{
Point cursorPos = new Point();
WinAPIs.GetCursorPos(out cursorPos);
int xOffset = cursorPos.X - wndWidth / 2;
int yOffset = cursorPos.Y - wndHeight / 2;
WinAPIs.MoveWindow(hWnd, xOffset, yOffset, wndWidth, wndHeight, true);
Thread.Sleep(25);
}
}
And now:
int moveCommandToggle = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312)
{
int keyID = m.WParam.ToInt32();
if(keyID == some_key_combo_you_registered_for_the_moving)
{
if (moveCommandToggle++ % 2 == 0)
{
mover = new Thread(() => MoveWindow_AfterMouse());
mover.Start();
}
else mover.Abort();
}
}
}
If you're wondering about RECT:
public struct RECT
{
public int left; // xCoor of upper left corner.
public int top; // yCoor of upper left corner.
public int right; // xCoor of lower right corner.
public int bottom; // yCoor of lower right corner.
};
WinAPIs was just a static class that I did my DllImports in.