2014-05-14 22:04:47 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2014-07-27 15:22:30 +00:00
|
|
|
|
using System.ComponentModel;
|
2014-07-28 02:31:51 +00:00
|
|
|
|
using System.Drawing;
|
2014-05-14 22:04:47 +00:00
|
|
|
|
using System.Linq;
|
2014-07-27 15:22:30 +00:00
|
|
|
|
using System.Runtime.InteropServices;
|
2014-05-14 22:04:47 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
2014-07-03 17:29:01 +00:00
|
|
|
|
using BizHawk.Common.ReflectionExtensions;
|
2014-07-27 15:22:30 +00:00
|
|
|
|
|
|
|
|
|
namespace BizHawk.Client.EmuHawk.WinFormExtensions
|
2014-05-14 22:04:47 +00:00
|
|
|
|
{
|
|
|
|
|
public static class ControlExtensions
|
|
|
|
|
{
|
|
|
|
|
public static void PopulateFromEnum<T>(this ComboBox box, object enumVal)
|
|
|
|
|
where T : struct, IConvertible
|
|
|
|
|
{
|
|
|
|
|
if (!typeof(T).IsEnum)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("T must be an enumerated type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
box.Items.Clear();
|
|
|
|
|
box.Items.AddRange(
|
2014-07-03 17:41:55 +00:00
|
|
|
|
typeof(T).GetEnumDescriptions()
|
2014-05-14 22:04:47 +00:00
|
|
|
|
.ToArray());
|
2014-07-03 17:01:10 +00:00
|
|
|
|
box.SelectedItem = enumVal.GetDescription();
|
2014-05-14 22:04:47 +00:00
|
|
|
|
}
|
2014-07-27 15:22:30 +00:00
|
|
|
|
|
|
|
|
|
// extension method to make Control.Invoke easier to use
|
2015-01-04 18:22:17 +00:00
|
|
|
|
public static object Invoke(this Control control, Action action)
|
2014-07-27 15:22:30 +00:00
|
|
|
|
{
|
2015-01-04 18:22:17 +00:00
|
|
|
|
return control.Invoke(action);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// extension method to make Control.BeginInvoke easier to use
|
|
|
|
|
public static IAsyncResult BeginInvoke(this Control control, Action action)
|
|
|
|
|
{
|
|
|
|
|
return control.BeginInvoke(action);
|
2014-07-27 15:22:30 +00:00
|
|
|
|
}
|
2014-07-28 02:10:31 +00:00
|
|
|
|
|
2019-10-15 00:56:35 +00:00
|
|
|
|
public static ToolStripMenuItem ToColumnsMenu(this InputRoll inputRoll, Action changeCallback)
|
2019-10-15 00:11:07 +00:00
|
|
|
|
{
|
|
|
|
|
var menu = new ToolStripMenuItem
|
|
|
|
|
{
|
|
|
|
|
Name = "GeneratedColumnsSubMenu",
|
|
|
|
|
Text = "Columns"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var columns = inputRoll.AllColumns;
|
|
|
|
|
|
|
|
|
|
foreach (var column in columns)
|
|
|
|
|
{
|
|
|
|
|
var menuItem = new ToolStripMenuItem
|
|
|
|
|
{
|
2019-10-18 23:56:21 +00:00
|
|
|
|
Name = column.Name,
|
2019-10-15 00:11:07 +00:00
|
|
|
|
Text = $"{column.Text} ({column.Name})",
|
|
|
|
|
Checked = column.Visible,
|
|
|
|
|
CheckOnClick = true,
|
|
|
|
|
Tag = column.Name
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menuItem.CheckedChanged += (o, ev) =>
|
|
|
|
|
{
|
|
|
|
|
var sender = (ToolStripMenuItem)o;
|
|
|
|
|
columns.Find(c => c.Name == (string)sender.Tag).Visible = sender.Checked;
|
|
|
|
|
columns.ColumnsChanged();
|
2019-10-15 00:56:35 +00:00
|
|
|
|
changeCallback();
|
2019-10-15 00:11:07 +00:00
|
|
|
|
inputRoll.Refresh();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.DropDownItems.Add(menuItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-28 02:31:51 +00:00
|
|
|
|
public static Point ChildPointToScreen(this Control control, Control child)
|
|
|
|
|
{
|
|
|
|
|
return control.PointToScreen(new Point(child.Location.X, child.Location.Y));
|
|
|
|
|
}
|
2014-07-28 03:01:57 +00:00
|
|
|
|
|
2019-10-26 21:04:27 +00:00
|
|
|
|
public static Color Add(this Color color, int val)
|
|
|
|
|
{
|
|
|
|
|
var col = color.ToArgb();
|
|
|
|
|
col += val;
|
|
|
|
|
return Color.FromArgb(col);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-28 03:01:57 +00:00
|
|
|
|
#region Enumerable to Enumerable<T>
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2019-05-29 10:58:01 +00:00
|
|
|
|
/// Converts the outdated IEnumerable Controls property to an <see cref="IEnumerable{T}"/> like .NET should have done a long time ago
|
2014-07-28 03:01:57 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
public static IEnumerable<Control> Controls(this Control control)
|
|
|
|
|
{
|
|
|
|
|
return control.Controls
|
|
|
|
|
.OfType<Control>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static IEnumerable<TabPage> TabPages(this TabControl tabControl)
|
|
|
|
|
{
|
|
|
|
|
return tabControl.TabPages.Cast<TabPage>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2014-07-27 15:22:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class FormExtensions
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles EmuHawk specific issues before showing a modal dialog
|
|
|
|
|
/// </summary>
|
2017-01-19 20:24:41 +00:00
|
|
|
|
public static DialogResult ShowHawkDialog(this Form form, IWin32Window owner = null, Point position = default(Point))
|
2014-07-27 15:22:30 +00:00
|
|
|
|
{
|
|
|
|
|
GlobalWin.Sound.StopSound();
|
2017-01-19 20:24:41 +00:00
|
|
|
|
if (position != default(Point))
|
|
|
|
|
{
|
|
|
|
|
form.StartPosition = FormStartPosition.Manual;
|
|
|
|
|
form.Location = position;
|
|
|
|
|
}
|
2019-11-03 18:46:39 +00:00
|
|
|
|
var result = (owner == null ? form.ShowDialog(new Form { TopMost = true }) : form.ShowDialog(owner));
|
2014-07-27 15:22:30 +00:00
|
|
|
|
GlobalWin.Sound.StartSound();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles EmuHawk specific issues before showing a modal dialog
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static DialogResult ShowHawkDialog(this CommonDialog form)
|
|
|
|
|
{
|
|
|
|
|
GlobalWin.Sound.StopSound();
|
2019-11-02 04:29:09 +00:00
|
|
|
|
using var tempForm = new Form() { TopMost = true };
|
2017-07-17 14:56:55 +00:00
|
|
|
|
var result = form.ShowDialog(tempForm);
|
2014-07-27 15:22:30 +00:00
|
|
|
|
GlobalWin.Sound.StartSound();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class ListViewExtensions
|
|
|
|
|
{
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
|
|
public struct HDITEM
|
|
|
|
|
{
|
|
|
|
|
public Mask mask;
|
|
|
|
|
public int cxy;
|
|
|
|
|
[MarshalAs(UnmanagedType.LPTStr)]
|
|
|
|
|
public string pszText;
|
|
|
|
|
public IntPtr hbm;
|
|
|
|
|
public int cchTextMax;
|
|
|
|
|
public Format fmt;
|
|
|
|
|
public IntPtr lParam;
|
|
|
|
|
// _WIN32_IE >= 0x0300
|
|
|
|
|
public int iImage;
|
|
|
|
|
public int iOrder;
|
|
|
|
|
// _WIN32_IE >= 0x0500
|
|
|
|
|
public uint type;
|
|
|
|
|
public IntPtr pvFilter;
|
|
|
|
|
// _WIN32_WINNT >= 0x0600
|
|
|
|
|
public uint state;
|
|
|
|
|
|
|
|
|
|
[Flags]
|
|
|
|
|
public enum Mask
|
|
|
|
|
{
|
|
|
|
|
Format = 0x4, // HDI_FORMAT
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
[Flags]
|
|
|
|
|
public enum Format
|
|
|
|
|
{
|
|
|
|
|
SortDown = 0x200, // HDF_SORTDOWN
|
|
|
|
|
SortUp = 0x400, // HDF_SORTUP
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public const int LVM_FIRST = 0x1000;
|
|
|
|
|
public const int LVM_GETHEADER = LVM_FIRST + 31;
|
|
|
|
|
|
|
|
|
|
public const int HDM_FIRST = 0x1200;
|
|
|
|
|
public const int HDM_GETITEM = HDM_FIRST + 11;
|
|
|
|
|
public const int HDM_SETITEM = HDM_FIRST + 12;
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
|
|
|
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
|
|
|
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Dumps the contents of the ListView into a tab separated list of lines
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static string CopyItemsAsText(this ListView listViewControl)
|
|
|
|
|
{
|
|
|
|
|
var indexes = listViewControl.SelectedIndices;
|
|
|
|
|
if (indexes.Count <= 0)
|
|
|
|
|
{
|
2017-05-10 11:45:23 +00:00
|
|
|
|
return "";
|
2014-07-27 15:22:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
// walk over each selected item and subitem within it to generate a string from it
|
|
|
|
|
foreach (int index in indexes)
|
|
|
|
|
{
|
|
|
|
|
foreach (ListViewItem.ListViewSubItem item in listViewControl.Items[index].SubItems)
|
|
|
|
|
{
|
2019-10-26 21:01:21 +00:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(item.Text))
|
2014-07-27 15:22:30 +00:00
|
|
|
|
{
|
|
|
|
|
sb.Append(item.Text).Append('\t');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove the last tab
|
|
|
|
|
sb.Remove(sb.Length - 1, 1);
|
|
|
|
|
|
|
|
|
|
sb.Append("\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove last newline
|
|
|
|
|
sb.Length -= 2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void SetSortIcon(this ListView listViewControl, int columnIndex, SortOrder order)
|
|
|
|
|
{
|
|
|
|
|
IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
|
|
|
|
|
for (int columnNumber = 0; columnNumber <= listViewControl.Columns.Count - 1; columnNumber++)
|
|
|
|
|
{
|
|
|
|
|
var columnPtr = new IntPtr(columnNumber);
|
|
|
|
|
var item = new HDITEM
|
|
|
|
|
{
|
|
|
|
|
mask = HDITEM.Mask.Format
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
throw new Win32Exception();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (order != SortOrder.None && columnNumber == columnIndex)
|
|
|
|
|
{
|
|
|
|
|
switch (order)
|
|
|
|
|
{
|
|
|
|
|
case SortOrder.Ascending:
|
|
|
|
|
item.fmt &= ~HDITEM.Format.SortDown;
|
|
|
|
|
item.fmt |= HDITEM.Format.SortUp;
|
|
|
|
|
break;
|
|
|
|
|
case SortOrder.Descending:
|
|
|
|
|
item.fmt &= ~HDITEM.Format.SortUp;
|
|
|
|
|
item.fmt |= HDITEM.Format.SortDown;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
throw new Win32Exception();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-14 22:04:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|