How to hide game form's close button? - c#

It's somewhat easy to find a way to do this in a winforms application, but in XNA I can't make the code snippets work as intended. I also don't want to disable the system buttons at all, I still need maximize and minimize buttons.
How do I disable the close button (x) on XNA game form without disabling the other buttons?

Define this in your code
[DllImport("user32.dll")]
static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
internal const UInt32 SC_CLOSE = 0xF060;
internal const UInt32 MF_ENABLED = 0x00000000;
internal const UInt32 MF_GRAYED = 0x00000001;
internal const UInt32 MF_DISABLED = 0x00000002;
internal const uint MF_BYCOMMAND = 0x00000000;
Then use this function to disable or enable the close button
public void EnableOrDisableCloseButton(bool Enabled)
{
IntPtr hSystemMenu = GetSystemMenu(this.Window.Handle, false);
EnableMenuItem(hSystemMenu, SC_CLOSE, (uint)(MF_ENABLED | (Enabled ? MF_ENABLED : MF_GRAYED)));
}

Related

Add screen modes in settings

I've created UI options menu for graphics and screen. The thing is that I was able to add obly a boolean value for fullScreen mode. I need to add a dropdown with 3 modes: fullscreen, windowed, and windowed with no frame (stretched to the entire screen size). How do I get the third mode?
Check out this sample code. It uses the user32.dll library, though, so you most likely need to reference it in your project.
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Diagnostics;
using UnityEngine;
public class WindowMod : MonoBehaviour
{
public Rect screenPosition;
[DllImport("user32.dll")]
static extern IntPtr SetWindowLong (IntPtr hwnd,int _nIndex ,int dwNewLong);
[DllImport("user32.dll")]
static extern bool SetWindowPos (IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow ();
// not used rigth now
//const uint SWP_NOMOVE = 0x2;
//const uint SWP_NOSIZE = 1;
//const uint SWP_NOZORDER = 0x4;
//const uint SWP_HIDEWINDOW = 0x0080;
const uint SWP_SHOWWINDOW = 0x0040;
const int GWL_STYLE = -16;
const int WS_BORDER = 1;
void Start ()
{
SetWindowLong(GetForegroundWindow (), GWL_STYLE, WS_BORDER);
bool result = SetWindowPos (GetForegroundWindow (), 0,(int)screenPosition.x,(int)screenPosition.y, (int)screenPosition.width,(int) screenPosition.height, SWP_SHOWWINDOW);
}
With this method your best bet would be to:
Create an enum for all options, for example public enum WindowMode { FullScreen, Borderless, Window }
Create a manager class with a method that takes the enum as an argument: public void SetWindowMode(WindowMode wm // or int) {...}
Wire it up so that the method is called whenever an item is selected from the ComboBox on the Options menu with the UUI's EventSystem thingy
That's pretty much it.

C# Console Disable Resize

How to achieve programmatically that the console window is not resizable.
I don't want user to change the console window size with their mouse.
See the answer in this post on MSDN. It requires p-invoking:
private const int MF_BYCOMMAND = 0x00000000;
public const int SC_CLOSE = 0xF060;
public const int SC_MINIMIZE = 0xF020;
public const int SC_MAXIMIZE = 0xF030;
public const int SC_SIZE = 0xF000;//resize
[DllImport("user32.dll")]
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetConsoleWindow();
static void Main(string[] args)
{
IntPtr handle = GetConsoleWindow();
IntPtr sysMenu = GetSystemMenu(handle, false);
if (handle != IntPtr.Zero)
{
DeleteMenu(sysMenu, SC_CLOSE, MF_BYCOMMAND);
DeleteMenu(sysMenu, SC_MINIMIZE, MF_BYCOMMAND);
DeleteMenu(sysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(sysMenu, SC_SIZE, MF_BYCOMMAND);//resize
}
Console.Read();
}
Note that this does not prevent Windows window snapping (e.g. dragging window to edge of screen, Win+Left and Win+Right)
Since you're trying to disable resizing, I'm guessing you won't want scrollbars either. For that, see this answer to Remove space left after console scrollbars in C# (leftover after matching Console.SetWindowSize and SetBufferSize; also requires p-invoking to "fix").
I'm not sure you can avoid that kind of action.
But you may try to use WindowHeight, WindowWidth, LargestWindowHeight and LargestWindowWidth.
See this:
https://msdn.microsoft.com/pt-br/library/system.console(v=vs.110).aspx

How to bring a form already shown up to the very foreground and focus it?

How to programmatically (assuming we've got a reference to it as a variable) bring a form already shown up to the very foreground and focus it in a C# WinForms application?
You can use SetForegroundWindow. Good example here: C# Force Form Focus.
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
Usage:
SetForegroundWindow(form.Handle);
You should use the BringToFront() method
The answers here didn't quite do it for me. Using BringToFront wouldn't actually bring it to the front if the form was not focused and using Form.Activate just makes the form flash if it doesn't have focus. I wrote this little helper and it works flawlessly (I can't take total credit, found this somewhere on the web for WPF and converted it):
public static class FormHelper
{
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
public static void BringToFront(Form form)
{
var currentForegroundWindow = GetForegroundWindow();
var thisWindowThreadId = GetWindowThreadProcessId(form.Handle, IntPtr.Zero);
var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);
SetWindowPos(form.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);
form.Show();
form.Activate();
}
}
All you have to do is call FormHelper.BringToFront passing in the form you want to be shown.
Form.Show();
or
Form.ShowDialog();
What's different? First show new form but all other will be activity. Second solution make that only this new form will be activity.
Have you tried Form.Show() and/or Form.BringToFront() ?

How to hide/show a Process using c#?

While executing my program, I want to hide/minimize Microsoft Speech Recognition Application:
alt text http://img143.imageshack.us/img143/9380/minimize.png
and at the end I want to show/maximize using c#!
This process is not started by me so I can't give control the process startInfo.
I've tried to use user32.dll methods such as:
ShowWindow
AnimatedWindows
AnimatedWindows
SetForegroundWindow
SetWindowPos
With all of them I have the same problem.
I can hide the windows (althought I have to call one of the methods two times with SW_HIDE option), but when I call the method with a SW_SHOW flag, it simply doesn't shows..
How can I maximize/show after hiding the process?
Thanks in advance!
Here is some pieces of the code, now implemented to use SetWindowPlacement:
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPlacement(IntPtr hWnd,
[In] ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll")]
public static extern Boolean ShowWindowAsync(IntPtr hWnd, Int32 nCmdShow);
[DllImport("user32.dll")]
public static extern Boolean SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
[DllImport("user32.dll")]
public static extern Boolean AnimateWindow(IntPtr hWnd, uint dwTime, uint dwFlags);
[DllImport("dwmapi.dll")]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, uint dwAttribute, IntPtr pvAttribute, IntPtr lol);
//Definitions For Different Window Placement Constants
const UInt32 SW_HIDE = 0;
const UInt32 SW_SHOWNORMAL = 1;
const UInt32 SW_NORMAL = 1;
const UInt32 SW_SHOWMINIMIZED = 2;
const UInt32 SW_SHOWMAXIMIZED = 3;
const UInt32 SW_MAXIMIZE = 3;
const UInt32 SW_SHOWNOACTIVATE = 4;
const UInt32 SW_SHOW = 5;
const UInt32 SW_MINIMIZE = 6;
const UInt32 SW_SHOWMINNOACTIVE = 7;
const UInt32 SW_SHOWNA = 8;
const UInt32 SW_RESTORE = 9;
public sealed class AnimateWindowFlags
{
public const int AW_HOR_POSITIVE = 0x00000001;
public const int AW_HOR_NEGATIVE = 0x00000002;
public const int AW_VER_POSITIVE = 0x00000004;
public const int AW_VER_NEGATIVE = 0x00000008;
public const int AW_CENTER = 0x00000010;
public const int AW_HIDE = 0x00010000;
public const int AW_ACTIVATE = 0x00020000;
public const int AW_SLIDE = 0x00040000;
public const int AW_BLEND = 0x00080000;
}
public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
//this works
param = new WINDOWPLACEMENT();
param.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
param.showCmd = (int)SW_HIDE;
lol = SetWindowPlacement(theprocess.MainWindowHandle, ref param);
// this doesn't work
WINDOWPLACEMENT param = new WINDOWPLACEMENT();
param.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
param.showCmd = SW_SHOW;
lol = GetWindowPlacement(theprocess.MainWindowHandle, ref param);
NOTE:
Does the SAPI API has a command to minimize this minimize and maximize this window?
As Tomas said, you should try to use the SW_HIDE and SW_SHOW messages.
You do that by knowing the Speech Recognition winwow name and then using something like this:
HWND hc = FindWindow("processname","Windowtitle");
ShowWindow(hc,SW_HIDE);
The whole SetForegroundWindow/ShowWindow set of functions only work when stars align! :) It's usually a matter of calling functions in the right order. Sorry can't help specifically but this might provide some ideas
http://markribau.org/blog/2005/12/29/why-dont-focus-and-setforegroundwindow-work/
Is the procoess still runing if you send it the SW_HIDE message? The application is certainly not using the standard style of GUI, so it may react to the message by closing itself.
If that's the case, you could try other tricks, such as moving the window to some invisible location (e.g. -1000, -1000), which should be also possible using the SetWindowPlacement method that you already imported.

Why are Maximize/Minimize events causing the Close Button to be re-enabled after disabling it?

I have used P/Invoke to call GetSystemMenu and EnableMenuItem (win32api) to disable the close functionality. However, after minimizing or maximizing my Windows Forms application the button is re-enabled.
Obviously minimizing or maximizing is causing the behavior, but how? I'm not sure where to look to prevent this behavior.
Should I be preventing the maximize and minimize behavior or is there something particularly wrong with the way in which I P/Invoked the calls? Once the application (main form) has loaded, I call the static method from a button click.
class PInvoke
{
// P/Invoke signatures
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
// SysCommand (WM_SYSCOMMAND) constant
internal const UInt32 SC_CLOSE = 0xF060;
// Constants used with Add/Check/EnableMenuItem
internal const UInt32 MF_BYCOMMAND = 0x00000000;
internal const UInt32 MF_ENABLED = 0x00000000;
internal const UInt32 MF_GRAYED = 0x00000001;
internal const UInt32 MF_DISABLED = 0x00000002;
/// <summary>
/// Sets the state of the Close (X) button and the System Menu close functionality.
/// </summary>
/// <param name="window">Window or Form</param>
/// <param name="bEnabled">Enabled state</param>
public static void EnableCloseButton(IWin32Window window, bool bEnabled)
{
IntPtr hSystemMenu = GetSystemMenu(window.Handle, false);
EnableMenuItem(hSystemMenu, SC_CLOSE, MF_BYCOMMAND | (bEnabled ? MF_ENABLED : MF_GRAYED));
}
}
Each window has a window class, which defines styles for all windows of that class. You can use CS_NOCLOSE class style to remove the close button for windows of that class. See here and here for details how to set this class flag.
If this doesn't give you what you want, I wouldn't disable minimize/maximize for sake of usability, but you could listen for minimize/maximimize events and re-run the code to disable the close button. Finally, it is possible to handle the close event, and simply not close. Then you know your window will definitely not be closed, even if the close button does inadvertently become enabled.
The accepted answer does propose a possible workaround to the problem (and one that I've used many times), but it simply doesn't answer the question that was originally asked:
How/why does maximizing or minimizing the form cause the close button to be re-enabled after it was disabled using the GetSystemMenu and EnableMenuItem API functions?
I arrived at this question during the course of a completely fruitless Google search after discovering this seemingly unexplainable behavior for myself. Not finding an answer that actually explained the behavior,I was forced to resort to some digging of my own.
For reference, note that the exact same code as shown in the original question works fine in a native Win32 application. The re-enabling of the Close menu item seems limited to WinForms applications.
Studying the source code for the System.Windows.Forms.Form class uncovers an interesting implementation detail: The .NET Framework designers apparently decided to adjust the form's system menu each time that the form's WindowState changes, which includes maximize and minimize events sent by the system.
Specifically, there are two methods by the name AdjustSystemMenu that are responsible for altering the system menu in response to the these events (and messing up any customization that you may have done yourself). If you're interested in examining the code (which I have abstained from posting here for the benefit of those involved with projects such as Mono), grab a free copy of .NET Reflector.
I'm not entirely sure why this decision was made, but at least I have my explanation now.
I had the same requirement. After trying several ways to disable the close menu option and then deleting and trying to recreate it (correctly), I found this hack from Microsoft http://support.microsoft.com/kb/184686 .
Works like a charm. It's still a hack, but it works.
Here's my (loose) C# conversion of the VB original
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int GetMenuItemCount(IntPtr hMenu);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool DrawMenuBar(IntPtr hWnd);
public static void EnableCloseButton(Form frm, bool enabled) {
IntPtr hMenu;
int n;
hMenu = GetSystemMenu(frm.Handle, false);
if (hMenu != IntPtr.Zero) {
n = GetMenuItemCount(hMenu);
if (n > 0) {
if (enabled) {
EnableClose(frm);
}
else {
DisableClose(frm);
}
SendMessage(frm.Handle, WM_NCACTIVATE, (IntPtr)1, (IntPtr)0);
DrawMenuBar(frm.Handle);
Application.DoEvents();
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MENUITEMINFO {
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public int wID;
public int hSubMenu;
public int hbmpChecked;
public int hbmpUnchecked;
public int dwItemData;
public string dwTypeData;
public uint cch;
// public int hbmpItem;
}
internal const UInt32 SC_CLOSE = 0xF060;
//SetMenuItemInfo fMask constants.
const UInt32 MIIM_STATE = 0x1;
const UInt32 MIIM_ID = 0x2;
//'SetMenuItemInfo fState constants.
const UInt32 MFS_ENABLED = 0x0;
const UInt32 MFS_GRAYED = 0x3;
const UInt32 MFS_CHECKED = 0x8;
internal const int MFS_DEFAULT = 0x1000;
[DllImport("user32.dll")]
static extern bool SetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, [In] ref MENUITEMINFO lpmii);
[DllImport("user32.dll")]
static extern bool GetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, ref MENUITEMINFO lpmii);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private const UInt32 WM_NCACTIVATE = 0x0086;
private static void DisableClose(Form frm) {
IntPtr hMenu;
int n;
hMenu = GetSystemMenu(frm.Handle, false);
if (hMenu != IntPtr.Zero) {
MENUITEMINFO mif = new MENUITEMINFO();
mif.cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO));
mif.fMask = MIIM_ID | MIIM_STATE;
mif.fType = 0;
mif.dwTypeData = null;
bool a = GetMenuItemInfo(hMenu, (int)SC_CLOSE, false, ref mif);
mif.fState = MFS_GRAYED;
SetMenuItemInfo(hMenu, (int)SC_CLOSE, false, ref mif);
SendMessage(frm.Handle, WM_NCACTIVATE, (IntPtr)1, (IntPtr)0);
mif.wID = -10;
mif.fState = MFS_GRAYED;
SetMenuItemInfo(hMenu, (int)SC_CLOSE, false, ref mif);
}
}
private static void EnableClose(Form frm) {
IntPtr hMenu;
int n;
hMenu = GetSystemMenu(frm.Handle, false);
if (hMenu != IntPtr.Zero) {
MENUITEMINFO mif = new MENUITEMINFO();
mif.cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO));
mif.fMask = MIIM_ID | MIIM_STATE;
mif.fType = 0;
mif.dwTypeData = null;
bool a = GetMenuItemInfo(hMenu, -10, false, ref mif);
mif.wID = (int)SC_CLOSE;
SetMenuItemInfo(hMenu, -10, false, ref mif);
SendMessage(frm.Handle, WM_NCACTIVATE, (IntPtr)1, (IntPtr)0);
mif.fState = MFS_ENABLED;
SetMenuItemInfo(hMenu, (int)SC_CLOSE, false, ref mif);
SendMessage(frm.Handle, WM_NCACTIVATE, (IntPtr)1, (IntPtr)0);
}
}

Categories