C# Console Disable Resize - c#

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

Related

Make a DLL loaded with LoadLibrary show its windows in foreground

I developed an add-on for SAP Business One, as a C# Windows Forms application.
In this add-on, using LoadLibraryEx, I load a native unmanaged DLL (correct me if I'm wrong) written in C++.
The add-on calls a method of the DLL, in this way:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
//...
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
This method opens a window with which the user interacts.
Everything working fine, except that such window starts minimized in the task bar, while I need it to appear in the forground as the active window. How can I acieve this?
Finally I found this hack: launching a parallel thread that looks for the window that will be opened by the DLL and bring it to the foreground with Windows API functions:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
[DllImport("User32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
private const int ALT = 0xA4;
private const int EXTENDEDKEY = 0x1;
private const int KEYUP = 0x2;
private const int SW_RESTORE = 9;
//...
//launch a parallel thread that looks for library window
//and brings it to the foreground
ThreadPool.QueueUserWorkItem(delegate {
bool windowFound = false;
int attempts = 0;
while (!windowFound && attempts < 10)
{
attempts++;
//check frequently
Thread.Sleep(200);
//look for the window using its class name
IntPtr handle = FindWindow("DllWindowClassName", null);
//check it is a running process
if (handle != IntPtr.Zero)
{
bool success = false;
//if window is minimized to icon
if (IsIconic(handle))
{
//then show it
success = ShowWindow(handle, SW_RESTORE);
}
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
else
{
//in case of failure, try this hack
//simulate a key press and release (hack for SetForegroundWindow to work)
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
}
}
}
}, null);
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
You can discover window class name using FindWindow, passing window title, and then with GetClassName. Class name is more reliable than the title, which can change with the language and in the time.

ShowWindow is unable to show or minimize Task Manager

I need to show Task Manager app programatically, maximize it and minimize it as any other window but there is a problem and it simply doesn't respond to ShowWindow(int hWnd, int nCmdShow).
I am pretty sure I use the correct handle because I enumerated all of the windows with EnumWindows(PCallBack callback, int lParam) and the only window that didn't respond was the task manager window with title process.MainWindowTitle = "Task Manager", I even manually found its handle using spy++ but it still doesn't respond to SW_SHOWNORMAL or any other nCmdShow parameter. I tried running apps as administrator to see if it has something to do with the issue but they kept behaving like normal when proper handle was given to ShowWindow function;
private delegate bool PCallBack(int hWnd, int lParam);
private static void ShowWindows()
{
EnumWindows(new PCallBack(FindWindows), 0);
}
private bool FindWindows(int handle, int lparam)
{
Console.WriteLine("showing");
ShowWindow(handle, (int)SW.SHOWMINIMIZED);
ShowWindow(handle, (int)SW.SHOWNORMAL);
Thread.Sleep(3000);
return true;
}
static void Main(string[] args)
{
ShowWindows();
}
This code literally shows every window EnumWindows can find even if they are not visible and task manager was never shown which proved to me that the problem has nothing to do with wrong handle.
This is how I find it by the way.
// the correct handle of Task Manager window
var handle = (int)Process.GetProcessesByName("taskmgr").FirstOrDefault().MainWindowHandle;
Basically this is my problem. Need help.
it simply doesn't respond to ShowWindow(int hWnd, int nCmdShow).
I tested on Windows 10 and this works for me :
Manifest file with level="requireAdministrator"
Test :
IntPtr hWndTarget = FindWindow("TaskManagerWindow", null);
bool bRet = ShowWindow(hWndTarget, SW_SHOWMINIMIZED);
with declarations :
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public const int SW_HIDE = 0;
public const int SW_SHOWNORMAL = 1;
public const int SW_SHOWMINIMIZED = 2;
public const int SW_SHOWMAXIMIZED = 3;

How to check whether application is running fullscreen mode on any screen?

I'd like to check, if any screen hosts application in fullscreen mode. I have solution only for one screen which is code copied from here: [WPF] [C#] How-to : Detect if another application is running in full screen mode. This solution is based on
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
which gathers only active window handle. The problem is, I have two screens. I've searched many sites but none of them answers my question. It is not about capturing screenshot, which is simple and doesn't rely on P/Invoke.
Is this possible?
No ready-to-use solution here, but let's see..
Get list of all displayed windows and check positions and sizes of those windows - possible, lots of tools does it, many articles on that, I'll skip this one. Then, you can call MonitorFromWindow for each or some windows and compare window dimensions&position against monitor info. If windowpos ~= 0,0 and windowsize ~= monitorresolution you could assume that this window is in fullscreen mode.
On the other hand, if already having a list of all HWNDs, then why not just Query the window for its placement and check the WINDOWPLACEMENT.showCmd for SW_MAXIMIZE/SW_SHOWMAXIMIZED flags. That won't tell you which monitor is it, but should tell you at least if the window is maximized and if it's enough for you..
I don't know how fast/slow would it be to do it like that, but, yes, it seems possible.
You could use EnumWindows in conjunction with Screen.FromHandle. And maybe GetWindowRect() for calculations.
Something like (pseudo-code!):
//------------------------------
//this sample code is taken from http://pinvoke.net/default.aspx/user32/EnumWindows.html
public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);
public static ArrayList GetWindows()
{
ArrayList windowHandles = new ArrayList();
EnumedWindow callBackPtr = GetWindowHandle;
EnumWindows(callBackPtr, windowHandles);
return windowHandles;
}
private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
{
windowHandles.Add(windowHandle);
return true;
}
//------------------------------
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, [In,Out] ref Rect rect);
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
static void Main() {
foreach(IntPtr handle in GetWindows())
{
Screen scr = Screen.FromHandle(handle);
if(IsFullscreen(handle, scr))
{
// the window is fullscreen...
}
}
}
private bool IsFullscreen(IntPtr wndHandle, Screen screen)
{
Rect r = new Rect();
GetWindowRect(wndHandle, ref r);
return new Rectangle(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top)
.Contains(screen.Bounds);
}
I wrote piece of code which is working:
namespace EnumWnd
{
using System;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct MonitorInfoEx
{
public int cbSize;
public Rect rcMonitor;
public Rect rcWork;
public UInt32 dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szDeviceName;
}
internal class Program
{
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("User32")]
public static extern IntPtr MonitorFromWindow(IntPtr hWnd, int dwFlags);
[DllImport("user32", EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto,
SetLastError = true)]
internal static extern bool GetMonitorInfoEx(IntPtr hMonitor, ref MonitorInfoEx lpmi);
protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
const int MONITOR_DEFAULTTOPRIMARY = 1;
var mi = new MonitorInfoEx();
mi.cbSize = Marshal.SizeOf(mi);
GetMonitorInfoEx(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);
Rect appBounds;
GetWindowRect(hWnd, out appBounds);
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
var sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
if (sb.Length > 20)
{
sb.Remove(20, sb.Length - 20);
}
int windowHeight = appBounds.Right - appBounds.Left;
int windowWidth = appBounds.Bottom - appBounds.Top;
int monitorHeight = mi.rcMonitor.Right - mi.rcMonitor.Left;
int monitorWidth = mi.rcMonitor.Bottom - mi.rcMonitor.Top;
bool fullScreen = (windowHeight == monitorHeight) && (windowWidth == monitorWidth);
sb.AppendFormat(" Wnd:({0} | {1}) Mtr:({2} | {3} | Name: {4}) - {5}", windowWidth, windowHeight, monitorWidth, monitorHeight, mi.szDeviceName, fullScreen);
Console.WriteLine(sb.ToString());
}
return true;
}
private static void Main()
{
while (true)
{
EnumWindows(EnumTheWindows, IntPtr.Zero);
Console.ReadKey();
Console.Clear();
}
}
protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
}
}
Thanks for #SamAxe and #quetzalcoatl for providing me useful tips.

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() ?

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