mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Fix for #434 - SysTray SafeHandle
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
#pragma warning disable 169
|
||||
|
||||
namespace mRemoteNG.App
|
||||
@@ -42,11 +45,17 @@ namespace mRemoteNG.App
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, System.Text.StringBuilder lParam);
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, string lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SendMessage([In] IntPtr hWnd, [In] uint msg, [Out] StringBuilder wParam, [In] IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
|
||||
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
@@ -76,6 +85,10 @@ namespace mRemoteNG.App
|
||||
|
||||
[DllImport("user32", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
|
||||
|
||||
[DllImport("kernel32", SetLastError = true)]
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
internal static extern bool CloseHandle(IntPtr handle);
|
||||
#endregion
|
||||
|
||||
#region Structures
|
||||
@@ -286,7 +299,10 @@ namespace mRemoteNG.App
|
||||
public const int WA_ACTIVE = 0x1;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Sent to both the window being activated and the window being deactivated.
|
||||
/// If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the
|
||||
/// top-level window being deactivated, then to the window procedure of the top-level window being activated. If the
|
||||
/// windows use different input queues, the message is sent asynchronously, so the window is activated immediately.
|
||||
/// </summary>
|
||||
public const int WA_CLICKACTIVE = 0x2;
|
||||
#endregion
|
||||
@@ -455,6 +471,12 @@ namespace mRemoteNG.App
|
||||
public const int VK_C = 0x67;
|
||||
#endregion
|
||||
|
||||
#region EM
|
||||
public const uint ECM_FIRST = 0x1500;
|
||||
public const uint EM_SETCUEBANNER = ECM_FIRST + 1;
|
||||
public const uint EM_GETCUEBANNER = ECM_FIRST + 2;
|
||||
#endregion
|
||||
|
||||
#region LB
|
||||
public const int LB_ERR = -1;
|
||||
public const int LB_SELECTSTRING = 0x18C;
|
||||
|
||||
@@ -1,54 +1,92 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using mRemoteNG.App;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
// ReSharper disable MemberCanBeMadeStatic.Global
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public class SystemMenu
|
||||
{
|
||||
public sealed class SystemMenu : SafeHandleZeroOrMinusOneIsInvalid, IDisposable
|
||||
{
|
||||
[Flags]
|
||||
public enum Flags
|
||||
{
|
||||
MF_STRING = App.NativeMethods.MF_STRING,
|
||||
MF_SEPARATOR = App.NativeMethods.MF_SEPARATOR,
|
||||
MF_BYCOMMAND = App.NativeMethods.MF_BYCOMMAND,
|
||||
MF_BYPOSITION = App.NativeMethods.MF_BYPOSITION,
|
||||
MF_POPUP = App.NativeMethods.MF_POPUP,
|
||||
WM_SYSCOMMAND = App.NativeMethods.WM_SYSCOMMAND
|
||||
MF_STRING = NativeMethods.MF_STRING,
|
||||
MF_SEPARATOR = NativeMethods.MF_SEPARATOR,
|
||||
MF_BYCOMMAND = NativeMethods.MF_BYCOMMAND,
|
||||
MF_BYPOSITION = NativeMethods.MF_BYPOSITION,
|
||||
MF_POPUP = NativeMethods.MF_POPUP,
|
||||
WM_SYSCOMMAND = NativeMethods.WM_SYSCOMMAND
|
||||
}
|
||||
|
||||
public IntPtr SystemMenuHandle;
|
||||
public IntPtr FormHandle;
|
||||
|
||||
public SystemMenu(IntPtr Handle)
|
||||
|
||||
private bool disposed;
|
||||
internal IntPtr SystemMenuHandle;
|
||||
private readonly IntPtr FormHandle;
|
||||
|
||||
public SystemMenu(IntPtr Handle) :base(true)
|
||||
{
|
||||
FormHandle = Handle;
|
||||
SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, false);
|
||||
}
|
||||
SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, false);
|
||||
SetHandle(SystemMenuHandle);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
SystemMenuHandle = App.NativeMethods.GetSystemMenu(FormHandle, true);
|
||||
SystemMenuHandle = NativeMethods.GetSystemMenu(FormHandle, true);
|
||||
}
|
||||
|
||||
public void AppendMenuItem(IntPtr ParentMenu, Flags Flags, IntPtr ID, string Text)
|
||||
{
|
||||
App.NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
|
||||
NativeMethods.AppendMenu(ParentMenu, (int)Flags, ID, Text);
|
||||
}
|
||||
|
||||
public IntPtr CreatePopupMenuItem()
|
||||
{
|
||||
return App.NativeMethods.CreatePopupMenu();
|
||||
return NativeMethods.CreatePopupMenu();
|
||||
}
|
||||
|
||||
public bool InsertMenuItem(IntPtr SysMenu, int Position, Flags Flags, IntPtr SubMenu, string Text)
|
||||
{
|
||||
return App.NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
|
||||
return NativeMethods.InsertMenu(SysMenu, Position, (int)Flags, SubMenu, Text);
|
||||
}
|
||||
|
||||
public IntPtr SetBitmap(IntPtr Menu, int Position, Flags Flags, Bitmap Bitmap)
|
||||
{
|
||||
return new IntPtr(Convert.ToInt32(App.NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
|
||||
return new IntPtr(Convert.ToInt32(NativeMethods.SetMenuItemBitmaps(Menu, Position, (int)Flags, Bitmap.GetHbitmap(), Bitmap.GetHbitmap())));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.CloseHandle(SystemMenuHandle);
|
||||
}
|
||||
|
||||
|
||||
/* If we don't have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms182329.aspx (CA2216: Disposable types should declare finalizer)
|
||||
* If we DO have the finalizer, then we get this warning: https://msdn.microsoft.com/library/ms244737.aspx (CA1063: Implement IDisposable correctly)
|
||||
*
|
||||
* Since the handle is likely going to be in use for the entierty of the process, the finalizer isn't very important since when we're calling it
|
||||
* the process is likely exiting. Leaks would be moot once it exits. CA2216 is the lesser of 2 evils as far as I can tell. Suppress.
|
||||
~SystemMenu()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
*/
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2216:DisposableTypesShouldDeclareFinalizer")]
|
||||
public new void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed) return;
|
||||
if (!disposing) return;
|
||||
|
||||
ReleaseHandle();
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user