Merge branch 'master' into MoreUnixMonoCompatWork

This doesn't compile because of Input.cs, didn't know what to do. Also search for Merge TODO for some commenting things that probably need to be deleted
# Conflicts:
#	BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
#	BizHawk.Client.EmuHawk/CustomControls/InputRoll.Drawing.cs
#	BizHawk.Client.EmuHawk/CustomControls/InputRoll/InputRoll.cs
#	BizHawk.Client.EmuHawk/Program.cs
#	BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs
#	BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
#	BizHawk.Client.EmuHawk/tools/ToolHelpers.cs
#	BizHawk.Client.EmuHawk/tools/ToolManager.cs
#	BizHawk.Client.EmuHawk/tools/TraceLogger.Designer.cs
#	BizHawk.Client.EmuHawk/tools/TraceLogger.cs
#	BizHawk.Client.EmuHawk/tools/Watch/RamSearch.Designer.cs
#	BizHawk.Client.EmuHawk/tools/Watch/RamSearch.cs
#	BizHawk.Common/BizInvoke/DynamicLibraryImportResolver.cs
This commit is contained in:
adelikat 2019-10-31 17:01:19 -05:00
commit 6c7653e158
350 changed files with 14099 additions and 18578 deletions

View File

@ -2,3 +2,12 @@ root = true
[*]
indent_style = tab
[*.cs]
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_indent_switch_labels = true
csharp_indent_case_contents = true
csharp_indent_labels = one_less_than_current

File diff suppressed because it is too large Load Diff

View File

@ -555,8 +555,8 @@ A5359E35839B40C414EAE498CA633B28176629AA G Olympic Hockey 98 (Japan) N64 Glide_
7592F4C16B8E040539B5DCC201FAB2965A5E8C8D G Onegai Monsters (Japan) N64
133F17162B2734286F9E94F64ACB1538B11506B2 G Operation WinBack (Europe) (En,Fr,De,Es,It) N64
B8F29E8EFCF51EE9A6A16E2A1E60442B4F304950 G Pachinko 365 Nichi (Japan) N64
2111D39265A317414D359E35A7D971C4DFA5F9E1 G Paper Mario (Europe) (En,Fr,De,Es) N64 Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=2
3837F44CDA784B466C9A2D99DF70D77C322B97A0 G Paper Mario (USA) N64 RiceFrameBufferOption=3;RiceRenderToTextureOption=3;RiceScreenUpdateSettingHack=4;Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=2
2111D39265A317414D359E35A7D971C4DFA5F9E1 G Paper Mario (Europe) (En,Fr,De,Es) N64 Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=1
3837F44CDA784B466C9A2D99DF70D77C322B97A0 G Paper Mario (USA) N64 RiceFrameBufferOption=3;RiceRenderToTextureOption=3;RiceScreenUpdateSettingHack=4;Glide_enable_hacks_for_game=15;Glide_fb_hires_buf_clear=false;Glide_fb_optimize_texrect=false;Glide_swapmode=2;Glide_fb_smart=true;Glide_fb_read_alpha=true;Glide64mk2_enable_hacks_for_game=20;Glide64mk2_hires_buf_clear=false;Glide64mk2_optimize_texrect=false;Glide64mk2_filtering=1;Glide64mk2_swapmode=2;Glide64mk2_fb_smart=true;Glide64mk2_fb_read_alpha=true;Jabo_Clear_Frame=1;GLideN64_CopyColorToRDRAM=1
7DB4808042B9651B47592E814AC4C125B51D4D2F G Paperboy (Europe) N64
B043C47B9758FA6BB289CA7DBA2068BDA6CAFA3A G Paperboy (USA) N64
9887A0E4BFE3C5E85E31638853574069F6C41CD3 G Parlor! Pro 64 - Pachinko Jikki Simulation Game (Japan) N64 Glide_force_microcheck=true;Glide64mk2_force_microcheck=true;Glide64mk2_filtering=1

View File

@ -305,7 +305,6 @@ sha1:17473C223453D2D80FCB9DCFA317947287DC5C52 Xing He Zhan Shi (China) (Unl) NE
sha1:B1C74236FD17FAB4AB9AA6AB28E38864C66D6255 Pocahontus (UNL) NES board=MAPPER182;PRG=256;CHR=256;WRAM=8;PAD_H=1
sha1:5FA23F88432006DCF6874EA36E9E7DA8934427BE Super Donkey Kong (Unl) NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1
sha1:8A7DAB8B78DA1C5EA159BA9EEC00FF97742245F1 B Super Donkey Kong (Unl) [b1] NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1
sha1:8A7DAB8B78DA1C5EA159BA9EEC00FF97742245F1 O Super Donkey Kong (Unl) [o1] NES board=MAPPER182;PRG=128;CHR=128;WRAM=8;PAD_H=1
;wrong vram info
sha1:32D71DD6C5A8D78A918FE1B9D6D6C4A570D9652D Oeka Kids Anpanman no Hiragana Daisuki (J) NES board=MAPPER096;VRAM=32

View File

@ -33,7 +33,9 @@
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NoWarn>1591</NoWarn><!-- don't bug us with "Missing XML comment [...]" until we have and enforce .stylecop.json i.e. when we care -->
<LangVersion>8.0</LangVersion>
<NoWarn>1591</NoWarn>
<!-- don't bug us with "Missing XML comment [...]" until we have and enforce .stylecop.json i.e. when we care -->
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>

View File

@ -117,6 +117,9 @@ namespace BizHawk.Client.ApiHawk
case "GB4x":
return CoreSystem.GB3x;
case "MAME":
return CoreSystem.MAME;
case "VB":
case "NGP":
case "DNGP":

View File

@ -134,54 +134,54 @@ namespace SevenZip
/// <param name="format">Archive format</param>
public static void LoadLibrary(object user, Enum format)
{
lock (_syncRoot)
{
if (_inArchives == null
#if COMPRESS
|| _outArchives == null
#endif
)
lock (_syncRoot)
{
Init();
}
if (_inArchives == null
#if COMPRESS
|| _outArchives == null
#endif
)
{
Init();
}
#if !WINCE && !MONO
if (_modulePtr == IntPtr.Zero)
{
//zero 29-oct-2012 - this check isnt useful since LoadLibrary can pretty much check for the same thing. and it wrecks our dll relocation scheme
//if (!File.Exists(_libraryFileName))
//{
// throw new SevenZipLibraryException("DLL file does not exist.");
//}
if ((_modulePtr = libLoader.LoadPlatformSpecific(_libraryFileName)) == IntPtr.Zero)
if (_modulePtr == IntPtr.Zero)
{
//try a different directory
string alternateFilename = Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName),"dll"),"7z.dll");
if ((_modulePtr = libLoader.LoadPlatformSpecific(alternateFilename)) == IntPtr.Zero)
throw new SevenZipLibraryException("failed to load library.");
}
if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
{
libLoader.FreePlatformSpecific(_modulePtr);
throw new SevenZipLibraryException("library is invalid.");
}
}
#endif
if (format is InArchiveFormat)
{
InitUserInFormat(user, (InArchiveFormat) format);
return;
}
#if COMPRESS
if (format is OutArchiveFormat)
{
InitUserOutFormat(user, (OutArchiveFormat) format);
return;
}
#endif
throw new ArgumentException(
"Enum " + format + " is not a valid archive format attribute!");
}
//zero 29-oct-2012 - this check isnt useful since LoadOrNull can pretty much check for the same thing. and it wrecks our dll relocation scheme
//if (!File.Exists(_libraryFileName))
//{
// throw new SevenZipLibraryException("DLL file does not exist.");
//}
var newPtr = libLoader.LoadOrNull(_libraryFileName);
if (!newPtr.HasValue)
{
//try a different directory
newPtr = libLoader.LoadOrNull(Path.Combine(Path.Combine(Path.GetDirectoryName(_libraryFileName), "dll"), "7z.dll"));
if (!newPtr.HasValue) throw new SevenZipLibraryException("failed to load library.");
}
_modulePtr = newPtr.Value;
if (libLoader.GetProcAddr(_modulePtr, "GetHandlerProperty") == IntPtr.Zero)
{
libLoader.FreeByPtr(_modulePtr);
throw new SevenZipLibraryException("library is invalid.");
}
}
#endif
if (format is InArchiveFormat)
{
InitUserInFormat(user, (InArchiveFormat) format);
return;
}
#if COMPRESS
if (format is OutArchiveFormat)
{
InitUserOutFormat(user, (OutArchiveFormat) format);
return;
}
#endif
throw new ArgumentException("Enum " + format + " is not a valid archive format attribute!");
}
}
/*/// <summary>
@ -435,7 +435,7 @@ namespace SevenZip
if (_totalUsers == 0)
{
#if !WINCE && !MONO
libLoader.FreePlatformSpecific(_modulePtr);
libLoader.FreeByPtr(_modulePtr);
#endif
_modulePtr = IntPtr.Zero;

View File

@ -34,8 +34,9 @@
ZXSpectrum,
AmstradCPC,
GGL,
ChannelF,
GB3x,
GB4x
GB4x,
ChannelF,
MAME
}
}

View File

@ -13,6 +13,7 @@
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<LangVersion>8.0</LangVersion>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
@ -127,6 +128,7 @@
<Compile Include="config\ConfigPersistAttribute.cs" />
<Compile Include="config\ConfigService.cs" />
<Compile Include="config\PathEntry.cs" />
<Compile Include="config\RestoreDefaultsAttribute.cs" />
<Compile Include="config\ToolDialogSettings.cs" />
<Compile Include="ControllerBinding.cs" />
<Compile Include="CoreFileProvider.cs" />

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>

View File

@ -36,6 +36,7 @@ namespace BizHawk.Client.Common
public const string OpenRom = "OpenRom";
public const string Libretro = "Libretro";
public const string LibretroNoGame = "LibretroNoGame";
public const string MAME = "MAME";
}
@ -55,12 +56,33 @@ namespace BizHawk.Client.Common
string type = text.Substring(0, idx);
string token = text.Substring(idx + 1);
IOpenAdvanced ioa;
if (type == OpenAdvancedTypes.OpenRom) ioa = new OpenAdvanced_OpenRom();
else if (type == OpenAdvancedTypes.Libretro) ioa = new OpenAdvanced_Libretro();
else if (type == OpenAdvancedTypes.LibretroNoGame) ioa = new OpenAdvanced_LibretroNoGame();
else ioa = null;
if (ioa == null)
throw new InvalidOperationException($"{nameof(IOpenAdvanced)} deserialization error");
if (type == OpenAdvancedTypes.OpenRom)
{
ioa = new OpenAdvanced_OpenRom();
}
else if (type == OpenAdvancedTypes.Libretro)
{
ioa = new OpenAdvanced_Libretro();
}
else if (type == OpenAdvancedTypes.LibretroNoGame)
{
ioa = new OpenAdvanced_LibretroNoGame();
}
else if (type == OpenAdvancedTypes.MAME)
{
ioa = new OpenAdvanced_MAME();
}
else
{
ioa = null;
}
if (ioa == null)
{
throw new InvalidOperationException($"{nameof(IOpenAdvanced)} deserialization error");
}
ioa.Deserialize(token);
return ioa;
}
@ -161,4 +183,26 @@ namespace BizHawk.Client.Common
tw.Write(Path);
}
}
public class OpenAdvanced_MAME : IOpenAdvanced
{
public OpenAdvanced_MAME()
{ }
public string Path;
public string TypeName { get { return "MAME"; } }
public string DisplayName { get { return Path; } }
public string SimplePath { get { return Path; } }
public void Deserialize(string str)
{
Path = str;
}
public void Serialize(TextWriter tw)
{
tw.Write(Path);
}
}
}

View File

@ -89,17 +89,7 @@ namespace BizHawk.Client.Common
{
if (!Frozen)
{
var removed = false;
foreach (var recent in recentlist.ToList())
{
if (string.Compare(newFile, recent, StringComparison.CurrentCultureIgnoreCase) == 0)
{
recentlist.Remove(newFile); // intentionally keeps iterating after this to remove duplicate instances, though those should never exist in the first place
removed = true;
}
}
return removed;
return recentlist.RemoveAll(recent => string.Compare(newFile, recent, StringComparison.CurrentCultureIgnoreCase) == 0) != 0; // none removed => return false
}
return false;

View File

@ -24,6 +24,7 @@ using BizHawk.Emulation.Cores.Sega.Saturn;
using BizHawk.Emulation.Cores.Sony.PSP;
using BizHawk.Emulation.Cores.Sony.PSX;
using BizHawk.Emulation.Cores.Computers.SinclairSpectrum;
using BizHawk.Emulation.Cores.Arcades.MAME;
using BizHawk.Emulation.DiscSystem;
using GPGX64 = BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
@ -171,7 +172,7 @@ namespace BizHawk.Client.Common
return false;
}
public bool AsLibretro { get; set; }
public AdvancedRomLoaderType AdvancedLoader { get; set; }
private bool HandleArchiveBinding(HawkFile file)
{
@ -268,8 +269,13 @@ namespace BizHawk.Client.Common
// only try mounting a file if a filename was given
if (!string.IsNullOrEmpty(path))
{
// lets not use this unless we need to
// file.NonArchiveExtensions = romExtensions;
// MAME uses these extensions for arcade ROMs, but also accepts all sorts of variations of archives, folders, and files. if we let archive loader handle this, it won't know where to stop, since it'd require MAME's ROM database (which contains ROM names and blob hashes) to look things up, and even then it might be confused by archive/folder structure
// so assume the user provides the proper ROM directly, and handle possible errors later
if (AdvancedLoader == AdvancedRomLoaderType.MAMELaunchGame)
{
file.NonArchiveExtensions = new[] { ".zip", ".7z" };
}
file.Open(path);
// if the provided file doesnt even exist, give up!
@ -289,7 +295,7 @@ namespace BizHawk.Client.Common
{
string ext = null;
if (AsLibretro)
if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchGame)
{
string codePathPart = Path.GetFileNameWithoutExtension(nextComm.LaunchLibretroCore);
@ -1152,6 +1158,9 @@ namespace BizHawk.Client.Common
nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings<Octoshock>(), GetCoreSyncSettings<Octoshock>());
nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
break;
case "Arcade":
nextEmulator = new MAME(nextComm, file.Directory, file.CanonicalName);
break;
case "GEN":
if (Global.Config.CoreForcingViaGameDB && game.ForcedCore?.ToLower() == "pico")
{

View File

@ -97,12 +97,6 @@ namespace BizHawk.Client.Common
return _redo[slot];
}
public void Clear()
{
ClearRedoList();
Update();
}
public void SwapBackupSavestate(string path)
{
// Takes the .state and .bak files and swaps them

View File

@ -223,6 +223,11 @@ namespace BizHawk.Client.Common
/// </summary>
public static SystemInfo ChannelF { get; } = new SystemInfo("Channel F", CoreSystem.ChannelF, 2);
/// <summary>
/// Gets the <see cref="SystemInfo"/> instance for MAME
/// </summary>
public static SystemInfo MAME { get; } = new SystemInfo("MAME", CoreSystem.MAME, 4);
#endregion Get SystemInfo
/// <summary>

View File

@ -96,13 +96,8 @@ namespace BizHawk.Client.Common
}
}
List<Binding> entriesToRemove = (from entry in Bindings let binding = DefaultValues.FirstOrDefault(b => b.DisplayName == entry.DisplayName) where binding == null select entry).ToList();
// Remove entries that no longer exist in defaults
foreach (Binding entry in entriesToRemove)
{
Bindings.Remove(entry);
}
Bindings.RemoveAll(entry => DefaultValues.All(b => b.DisplayName != entry.DisplayName));
}
private static List<Binding> _defaultValues;

View File

@ -104,6 +104,8 @@ namespace BizHawk.Client.Common
public int MainHeight = -1;
public bool RunInBackground = true;
public bool AcceptBackgroundInput = false;
public bool AcceptBackgroundInputControllerOnly = false;
public bool HandleAlternateKeyboardLayouts = false;
public bool SingleInstanceMode = false;
public bool AllowUD_LR = false;
public bool ForbidUD_LR = false;

View File

@ -119,7 +119,7 @@ namespace BizHawk.Client.Common
}
// Add missing displaynames
var missingDisplayPaths = Paths.Where(p => p.SystemDisplayName == null).ToList();
var missingDisplayPaths = Paths.Where(p => p.SystemDisplayName == null);
foreach (PathEntry path in missingDisplayPaths)
{
path.SystemDisplayName = DefaultValues.First(p => p.System == path.System).SystemDisplayName;

View File

@ -0,0 +1,12 @@
using System;
namespace BizHawk.Client.Common
{
/// <summary>
/// Defines a method to be called when a tool dialog's Restore Defaults method is called
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class RestoreDefaultsAttribute : Attribute
{
}
}

View File

@ -50,78 +50,66 @@ namespace BizHawk.Client.Common
public void CallSaveStateEvent(string name)
{
var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateSave").ToList();
if (lfs.Any())
var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateSave");
try
{
try
foreach (var lf in lfs)
{
foreach (var lf in lfs)
{
lf.Call(name);
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onsavestate\nError message: {e.Message}");
lf.Call(name);
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onsavestate\nError message: {e.Message}");
}
}
public void CallLoadStateEvent(string name)
{
var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateLoad").ToList();
if (lfs.Any())
var lfs = _luaFunctions.Where(l => l.Event == "OnSavestateLoad");
try
{
try
foreach (var lf in lfs)
{
foreach (var lf in lfs)
{
lf.Call(name);
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onloadstate\nError message: {e.Message}");
lf.Call(name);
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onloadstate\nError message: {e.Message}");
}
}
public void CallFrameBeforeEvent()
{
var lfs = _luaFunctions.Where(l => l.Event == "OnFrameStart").ToList();
if (lfs.Any())
var lfs = _luaFunctions.Where(l => l.Event == "OnFrameStart");
try
{
try
foreach (var lf in lfs)
{
foreach (var lf in lfs)
{
lf.Call();
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onframestart\nError message: {e.Message}");
lf.Call();
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onframestart\nError message: {e.Message}");
}
}
public void CallFrameAfterEvent()
{
var lfs = _luaFunctions.Where(l => l.Event == "OnFrameEnd").ToList();
if (lfs.Any())
var lfs = _luaFunctions.Where(l => l.Event == "OnFrameEnd");
try
{
try
foreach (var lf in lfs)
{
foreach (var lf in lfs)
{
lf.Call();
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onframeend\nError message: {e.Message}");
lf.Call();
}
}
catch (Exception e)
{
Log($"error running function attached by lua function event.onframeend\nError message: {e.Message}");
}
}
private bool N64CoreTypeDynarec()

View File

@ -48,6 +48,11 @@
public void Stop()
{
if (Thread == null)
{
return;
}
State = RunState.Disabled;
//if(NLua.Lua.WhichLua == "NLua")
Thread.GetTable("keepalives")[Thread] = null;

View File

@ -140,11 +140,19 @@ namespace BizHawk.Client.Common
var sb = new StringBuilder();
foreach (var file in this)
{
sb
.Append(file.Enabled ? "1" : "0")
.Append(' ')
.Append(PathManager.MakeRelativeTo(PathManager.MakeAbsolutePath(file.Path, ""), Path.GetDirectoryName(path)))
.AppendLine();
if (file.IsSeparator)
{
sb.AppendLine("---");
}
else
{
sb
.Append(file.Enabled ? "1" : "0")
.Append(' ')
.Append(PathManager.MakeRelativeTo(PathManager.MakeAbsolutePath(file.Path, "")
, Path.GetDirectoryName(path)))
.AppendLine();
}
}
sw.Write(sb.ToString());

View File

@ -160,7 +160,7 @@ namespace BizHawk.Client.Common
{
var def = Global.Emulator.ControllerDefinition;
var trimmed = mnemonic.Replace("|", "");
var buttons = Definition.ControlsOrdered.SelectMany(c => c).ToList();
var buttons = Definition.ControlsOrdered.SelectMany(c => c);
var iterator = 0;
foreach (var key in buttons)

View File

@ -338,7 +338,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
if (Global.Emulator is SMS && (Global.Emulator as SMS).IsSG1000)
{
movie.HeaderEntries.Add("IsSGMode", "1");
}
}
if (Global.Emulator is SMS && (Global.Emulator as SMS).IsGameGear)
{

View File

@ -68,14 +68,8 @@ namespace BizHawk.Client.Common
public class ImportResult
{
public ImportResult()
{
Warnings = new List<string>();
Errors = new List<string>();
}
public IList<string> Warnings { get; private set; }
public IList<string> Errors { get; }
public IList<string> Warnings { get; } = new List<string>();
public IList<string> Errors { get; } = new List<string>();
public Bk2Movie Movie { get; set; }
}
@ -88,6 +82,6 @@ namespace BizHawk.Client.Common
Extension = extension;
}
public string Extension { get; private set; }
public string Extension { get; }
}
}

View File

@ -42,23 +42,16 @@ namespace BizHawk.Client.Common
public static void ProcessMovieImport(string fn, Action<string> conversionErrorCallback, Action<string> messageCallback)
{
var d = PathManager.MakeAbsolutePath(Global.Config.PathEntries.MoviesPathFragment, null);
string errorMsg;
string warningMsg;
var m = ImportFile(fn, out errorMsg, out warningMsg);
var m = ImportFile(fn, out var errorMsg, out var warningMsg);
if (!string.IsNullOrWhiteSpace(errorMsg))
{
conversionErrorCallback(errorMsg);
}
if (!string.IsNullOrWhiteSpace(warningMsg))
{
messageCallback(warningMsg);
}
else
{
messageCallback($"{Path.GetFileName(fn)} imported as {m.Filename}");
}
messageCallback(!string.IsNullOrWhiteSpace(warningMsg)
? warningMsg
: $"{Path.GetFileName(fn)} imported as {m.Filename}");
if (!Directory.Exists(d))
{
@ -67,7 +60,7 @@ namespace BizHawk.Client.Common
}
// Attempt to import another type of movie file into a movie object.
public static Bk2Movie ImportFile(string path, out string errorMsg, out string warningMsg)
public static IMovie ImportFile(string path, out string errorMsg, out string warningMsg)
{
errorMsg = "";
warningMsg = "";
@ -118,25 +111,15 @@ namespace BizHawk.Client.Common
private static IEnumerable<Type> ImportersForExtension(string ext)
{
var info = typeof(MovieImport).Module;
var importers = from t in info.GetTypes()
where typeof(IMovieImport).IsAssignableFrom(t)
&& TypeImportsExtension(t, ext)
select t;
return importers;
return typeof(MovieImport).Module
.GetTypes()
.Where(t => typeof(IMovieImport).IsAssignableFrom(t));
}
private static bool TypeImportsExtension(Type t, string ext)
{
var attrs = (ImportExtensionAttribute[])t.GetCustomAttributes(typeof(ImportExtensionAttribute), inherit: false);
if (attrs.Any(a => a.Extension.ToUpper() == ext.ToUpper()))
{
return true;
}
return false;
return attrs.Any(a => a.Extension.ToUpper() == ext.ToUpper());
}
private static BkmMovie LegacyImportFile(string ext, string path, out string errorMsg, out string warningMsg)
@ -252,9 +235,12 @@ namespace BizHawk.Client.Common
private static IController EmptyLmsvFrame(string line)
{
var emptyController = new SimpleController { Definition = new ControllerDefinition { Name = "SNES Controller" } };
emptyController["Reset"] = false;
emptyController["Power"] = false;
var emptyController = new SimpleController
{
Definition = new ControllerDefinition { Name = "SNES Controller" }
, ["Reset"] = false
, ["Power"] = false
};
string[] buttons = { "B", "Y", "Select", "Start", "Up", "Down", "Left", "Right", "A", "X", "L", "R" };
string[] sections = line.Split('|');
@ -263,9 +249,9 @@ namespace BizHawk.Client.Common
int player = section - 1; // We start with 1
string prefix = $"P{player} "; // "P1"
for (int button = 0; button < buttons.Length; button++)
foreach (var b in buttons)
{
emptyController[prefix + buttons[button]] = false;
emptyController[prefix + b] = false;
}
}

View File

@ -222,7 +222,7 @@ namespace BizHawk.Client.Common
public void RemoveRange(IEnumerable<Cheat> cheats)
{
foreach (var cheat in cheats.ToList())
foreach (var cheat in cheats.ToList()) // enumerate passed IEnumerable because it may depend on the value of _cheatList
{
_cheatList.Remove(cheat);
}
@ -232,12 +232,7 @@ namespace BizHawk.Client.Common
public void RemoveRange(IEnumerable<Watch> watches)
{
var removeList = _cheatList.Where(cheat => watches.Any(w => w == cheat)).ToList();
foreach (var cheat in removeList)
{
_cheatList.Remove(cheat);
}
_cheatList.RemoveAll(cheat => watches.Any(w => w == cheat));
Changes = true;
}
@ -389,7 +384,9 @@ namespace BizHawk.Client.Common
}
else
{
// Set to hex for saving
// Set to hex for saving
var temp_cheat_type = cheat.Type;
cheat.SetType(DisplayType.Hex);
sb
@ -404,6 +401,9 @@ namespace BizHawk.Client.Common
.Append((cheat.BigEndian ?? false) ? '1' : '0').Append('\t')
.Append(cheat.ComparisonType).Append('\t')
.AppendLine();
cheat.SetType(temp_cheat_type);
}
}

View File

@ -341,8 +341,7 @@ namespace BizHawk.Client.Common
}
var addresses = watches.Select(w => w.Address);
var removeList = _watchList.Where(w => addresses.Contains(w.Address)).ToList();
_watchList = _watchList.Except(removeList).ToList();
_watchList.RemoveAll(w => addresses.Contains(w.Address));
}
public void RemoveRange(IEnumerable<int> indices)

View File

@ -388,15 +388,8 @@ namespace BizHawk.Client.Common
/// <returns><see cref="Watch"/> at the specified index</returns>
public Watch this[int index]
{
get
{
return _watchList[index];
}
set
{
_watchList[index] = value;
}
get => _watchList[index];
set => _watchList[index] = value;
}
#endregion IList<Watch>
@ -607,14 +600,7 @@ namespace BizHawk.Client.Common
CurrentFileName = path;
}
if (!append)
{
Changes = false;
}
else
{
Changes = true;
}
Changes = append;
return true;
}

View File

@ -39,6 +39,7 @@
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="CSharp-SQLite">

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>

View File

@ -188,11 +188,11 @@ namespace BizHawk.Client.DBMan
// process dump info flags and other info contained in []
if (nameString.Contains("[") && nameString.Contains("]"))
{
List<string> e = nameString.ToString().Split('[', ']').ToList();
// remove first entry (this is the bit before the [] entries start
e.RemoveAt(0);
// remove empty entries
e = e.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
var e = nameString.Split('[', ']')
.Skip(1) // remove first entry (this is the bit before the [] entries start)
.Where(s => !string.IsNullOrWhiteSpace(s)) // remove empty entries
.Distinct()
.ToList();
if (e.Count > 0)
{

View File

@ -206,11 +206,11 @@ namespace BizHawk.Client.DBMan
// process dump info flags and other info contained in []
if (nameString.Contains("[") && nameString.Contains("]"))
{
List<string> e = nameString.ToString().Split('[', ']').ToList();
// remove first entry (this is the bit before the [] entries start
e.RemoveAt(0);
// remove empty entries
e = e.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
var e = nameString.Split('[', ']')
.Skip(1) // remove first entry (this is the bit before the [] entries start)
.Where(s => !string.IsNullOrWhiteSpace(s)) // remove empty entries
.Distinct()
.ToList();
if (e.Count > 0)
{

View File

@ -32,6 +32,7 @@
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<NoWin32Manifest>true</NoWin32Manifest>

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>

View File

@ -23,15 +23,12 @@ namespace BizHawk.Client.EmuHawk
.Where(t => typeof(IExternalApi).IsAssignableFrom(t))
.Where(t => t.IsSealed)
.Where(t => ServiceInjector.IsAvailable(serviceProvider, t))
.ToList();
apis.AddRange(
Assembly
.GetAssembly(typeof(ApiContainer))
.GetTypes()
.Where(t => typeof(IExternalApi).IsAssignableFrom(t))
.Where(t => t.IsSealed)
.Where(t => ServiceInjector.IsAvailable(serviceProvider, t)));
.Concat(Assembly
.GetAssembly(typeof(ApiContainer))
.GetTypes()
.Where(t => typeof(IExternalApi).IsAssignableFrom(t))
.Where(t => t.IsSealed)
.Where(t => ServiceInjector.IsAvailable(serviceProvider, t)));
foreach (var api in apis)
{

View File

@ -48,8 +48,7 @@ namespace BizHawk.Client.EmuHawk
.Select(t => t.GetCustomAttributes(false).OfType<CoreAttribute>().FirstOrDefault())
.Where(a => a != null)
.Where(a => a.Released)
.OrderByDescending(a => a.CoreName.ToLower())
.ToList();
.OrderByDescending(a => a.CoreName.ToLower());
foreach (var core in cores)
{

View File

@ -38,6 +38,7 @@
<BootstrapperEnabled>true</BootstrapperEnabled>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<NoWin32Manifest>true</NoWin32Manifest>
@ -84,7 +85,7 @@
<HintPath>..\output\dll\nlua\NLua.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OpenTK, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\References\OpenTK.dll</HintPath>
</Reference>
@ -566,6 +567,8 @@
<Compile Include="CoreFeatureAnalysis.Designer.cs">
<DependentUpon>CoreFeatureAnalysis.cs</DependentUpon>
</Compile>
<Compile Include="CustomControls\ControlRenderer\GdiPlusRenderer.cs" />
<Compile Include="CustomControls\ControlRenderer\IControlRenderer.cs" />
<Compile Include="CustomControls\ExceptionBox.cs">
<SubType>Form</SubType>
</Compile>
@ -575,7 +578,7 @@
<Compile Include="CustomControls\FolderBrowserDialogEx.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\GDIRenderer.cs" />
<Compile Include="CustomControls\ControlRenderer\GDIRenderer.cs" />
<Compile Include="CustomControls\HexTextBox.cs">
<SubType>Component</SubType>
</Compile>
@ -585,21 +588,17 @@
<Compile Include="CustomControls\InputConfigBase.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="CustomControls\InputRoll.cs">
<Compile Include="CustomControls\InputRoll\Cell.cs" />
<Compile Include="CustomControls\InputRoll\ColumnType.cs" />
<Compile Include="CustomControls\InputRoll\InputRoll.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\InputRoll.Drawing.cs">
<DependentUpon>InputRoll.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\InputRoll.Drawing.GDI.cs">
<DependentUpon>InputRoll.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\InputRoll.Drawing.GDIP.cs">
<Compile Include="CustomControls\InputRoll\InputRoll.Drawing.cs">
<DependentUpon>InputRoll.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\InputRoll\RollColumn.cs" />
<Compile Include="CustomControls\InputRoll\RollColumns.cs" />
<Compile Include="CustomControls\MenuButton.cs">
<SubType>Component</SubType>
</Compile>
@ -612,30 +611,6 @@
<Compile Include="CustomControls\MsgBox.designer.cs">
<DependentUpon>MsgBox.cs</DependentUpon>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.API.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.Classes.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.Drawing.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.EventHandlers.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.Helpers.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.Properties.cs">
<DependentUpon>PlatformAgnosticVirtualListView.cs</DependentUpon>
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\PrereqsAlert.cs">
<SubType>Form</SubType>
</Compile>
@ -660,9 +635,6 @@
<Compile Include="CustomControls\SmartTextBoxControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\TasListView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\TextDebugView.cs">
<SubType>Component</SubType>
</Compile>
@ -672,7 +644,6 @@
<Compile Include="CustomControls\ViewportPanel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CustomControls\VirtualListView.cs" />
<Compile Include="CustomControls\Win32.cs" />
<Compile Include="DisplayManager\DisplayManager.cs" />
<Compile Include="DisplayManager\DisplaySurface.cs" />
@ -685,9 +656,11 @@
<Compile Include="DisplayManager\RenderTargetFrugalizer.cs" />
<Compile Include="DisplayManager\SwappableDisplaySurfaceSet.cs" />
<Compile Include="DisplayManager\TextureFrugalizer.cs" />
<Compile Include="EmuHawkUtil.cs" />
<Compile Include="Extensions\ControlExtensions.cs" />
<Compile Include="Extensions\CoreExtensions.cs" />
<Compile Include="Extensions\ToolExtensions.cs" />
<Compile Include="FileFilterEntry.cs" />
<Compile Include="FileLoader.cs">
<SubType>Form</SubType>
</Compile>
@ -704,6 +677,7 @@
<Compile Include="Input\GamePad.cs" />
<Compile Include="Input\GamePad360.cs" />
<Compile Include="Input\Input.cs" />
<Compile Include="Input\KeyboardMapping.cs" />
<Compile Include="Input\OTK_Gamepad.cs" />
<Compile Include="Input\OTK_Keyboard.cs" />
<Compile Include="IControlMainform.cs" />
@ -779,9 +753,6 @@
<Compile Include="OpenAdvancedChooser.Designer.cs">
<DependentUpon>OpenAdvancedChooser.cs</DependentUpon>
</Compile>
<Compile Include="CustomControls\PlatformAgnosticVirtualListView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="PlatformChooser.cs">
<SubType>Form</SubType>
</Compile>
@ -814,12 +785,6 @@
<Compile Include="Sound\Utilities\SoundOutputProvider.cs" />
<Compile Include="Throttle.cs" />
<Compile Include="ToolAttribute.cs" />
<Compile Include="tools\AutoHawk.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="tools\AutoHawk.Designer.cs">
<DependentUpon>AutoHawk.cs</DependentUpon>
</Compile>
<Compile Include="tools\BasicBot\BasicBot.cs">
<SubType>Form</SubType>
</Compile>
@ -1553,9 +1518,6 @@
<EmbeddedResource Include="CustomControls\QuickProgressPopup.resx">
<DependentUpon>QuickProgressPopup.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="CustomControls\TasListView.resx">
<DependentUpon>TasListView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
@ -1584,9 +1546,6 @@
<EmbeddedResource Include="RomStatusPicker.resx">
<DependentUpon>RomStatusPicker.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="tools\AutoHawk.resx">
<DependentUpon>AutoHawk.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="tools\BasicBot\BasicBot.resx">
<DependentUpon>BasicBot.cs</DependentUpon>
</EmbeddedResource>
@ -1899,6 +1858,7 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="app.manifest" />
<None Include="images\FindHS.png" />
</ItemGroup>
<ItemGroup>
@ -1926,6 +1886,8 @@
<None Include="config\ControllerImages\GENController.png" />
</ItemGroup>
<ItemGroup>
<None Include="images\StopButton.png" />
<None Include="images\mame.png" />
<None Include="Resources\MoveTop.png" />
<None Include="Resources\MoveBottom.png" />
<None Include="Resources\MoveTop.bmp" />
@ -2255,6 +2217,7 @@
<None Include="images\ESE.png" />
<None Include="images\ControllerImages\NGPController.png" />
<Content Include="config\ControllerImages\ZXSpectrumKeyboards.png" />
<None Include="images\ControllerImages\ArcadeController.jpg" />
<Content Include="images\logo.ico" />
<None Include="images\Paste.png" />
<None Include="images\reboot.png" />

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp60</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>

View File

@ -0,0 +1,505 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
namespace BizHawk.Client.EmuHawk.CustomControls
{
/// <summary>
/// Wrapper for GDI rendering functions
/// This class is not thread-safe as GDI functions should be called from the UI thread
/// </summary>
public sealed class GdiRenderer : IControlRenderer
{
// Cache of all the Fonts used, rather than create them again and again
private readonly Dictionary<Font, FontCacheEntry> _fontsCache = new Dictionary<Font, FontCacheEntry>();
private class FontCacheEntry
{
public IntPtr HFont;
public IntPtr RotatedHFont;
}
// Cache of all the brushes used, rather than create them again and again
private readonly Dictionary<Color, IntPtr> _brushCache = new Dictionary<Color, IntPtr>();
private Graphics _g;
private IntPtr _hdc;
private IntPtr _currentBrush = IntPtr.Zero;
#region Construct and Destroy
public void Dispose()
{
foreach (var brush in _brushCache)
{
if (brush.Value != IntPtr.Zero)
{
DeleteObject(brush.Value);
}
}
foreach (var fc in _fontsCache)
{
DeleteObject(fc.Value.HFont);
DeleteObject(fc.Value.RotatedHFont);
}
System.Diagnostics.Debug.Assert(_hdc == IntPtr.Zero, "Disposed a GDIRenderer while it held an HDC");
System.Diagnostics.Debug.Assert(_g == null, "Disposed a GDIRenderer while it held a Graphics");
}
#endregion
#region Api
public void DrawBitmap(Bitmap bitmap, Point point)
{
IntPtr hBmp = bitmap.GetHbitmap();
var bitHdc = CreateCompatibleDC(CurrentHdc);
IntPtr old = SelectObject(bitHdc, hBmp);
AlphaBlend(CurrentHdc, point.X, point.Y, bitmap.Width, bitmap.Height, bitHdc, 0, 0, bitmap.Width, bitmap.Height, new BLENDFUNCTION(AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA));
SelectObject(bitHdc, old);
DeleteDC(bitHdc);
DeleteObject(hBmp);
}
public IDisposable LockGraphics(Graphics g, int width, int height)
{
_g = g;
_hdc = g.GetHdc();
SetBkMode(_hdc, BkModes.TRANSPARENT);
var l = new GdiGraphicsLock(this);
StartOffScreenBitmap(width, height);
return l;
}
public Size MeasureString(string str, Font font)
{
SetFont(font);
var size = new Size();
GetTextExtentPoint32(CurrentHdc, str, str.Length, ref size);
return size;
}
public void DrawString(string str, Point point)
{
TextOut(CurrentHdc, point.X, point.Y, str, str.Length);
}
public static IntPtr CreateNormalHFont(Font font, int width)
{
var logFont = new LOGFONT();
font.ToLogFont(logFont);
logFont.lfWidth = width;
logFont.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS;
var ret = CreateFontIndirect(logFont);
return ret;
}
//this returns an IntPtr font because .net's Font class will erase the relevant properties when using its Font.FromLogFont()
//note that whether this is rotated clockwise or CCW might affect how you have to position the text (right-aligned sometimes?, up or down by the height of the font?)
public static IntPtr CreateRotatedHFont(Font font, bool cw)
{
LOGFONT logF = new LOGFONT();
font.ToLogFont(logF);
logF.lfEscapement = cw ? 2700 : 900;
logF.lfOrientation = logF.lfEscapement;
logF.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS;
var ret = CreateFontIndirect(logF);
return ret;
}
// TODO: this should go away and be abstracted internally
public static void DestroyHFont(IntPtr hFont)
{
DeleteObject(hFont);
}
public void PrepDrawString(Font font, Color color, bool rotate = false)
{
var fontEntry = GetCachedHFont(font);
SetGraphicsMode(CurrentHdc, 2); // shouldn't be necessary.. cant hurt
SelectObject(CurrentHdc, rotate ? fontEntry.RotatedHFont : fontEntry.HFont);
SetTextColor(color);
}
// Set the text color of the device context
private void SetTextColor(Color color)
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
SetTextColor(CurrentHdc, rgb);
}
public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
{
Rectangle(CurrentHdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
}
public void SetBrush(Color color)
{
if (_brushCache.ContainsKey(color))
{
_currentBrush = _brushCache[color];
}
else
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
var newBrush = CreateSolidBrush(rgb);
_brushCache.Add(color, newBrush);
_currentBrush = newBrush;
}
}
public void FillRectangle(int x, int y, int w, int h)
{
var r = new GDIRect(new Rectangle(x, y, w, h));
FillRect(CurrentHdc, ref r, _currentBrush);
}
public void SetSolidPen(Color color)
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
SelectObject(CurrentHdc, GetStockObject((int)PaintObjects.DC_PEN));
SetDCPenColor(CurrentHdc, rgb);
}
public void Line(int x1, int y1, int x2, int y2)
{
MoveToEx(CurrentHdc, x1, y1, IntPtr.Zero);
LineTo(CurrentHdc, x2, y2);
}
private IntPtr CurrentHdc => _bitHdc != IntPtr.Zero ? _bitHdc : _hdc;
private IntPtr _bitMap = IntPtr.Zero;
private IntPtr _bitHdc = IntPtr.Zero;
private int _bitW;
private int _bitH;
private void StartOffScreenBitmap(int width, int height)
{
_bitW = width;
_bitH = height;
_bitHdc = CreateCompatibleDC(_hdc);
_bitMap = CreateCompatibleBitmap(_hdc, width, height);
SelectObject(_bitHdc, _bitMap);
SetBkMode(_bitHdc, BkModes.TRANSPARENT);
}
private void EndOffScreenBitmap()
{
_bitW = 0;
_bitH = 0;
DeleteObject(_bitMap);
DeleteObject(_bitHdc);
_bitHdc = IntPtr.Zero;
_bitMap = IntPtr.Zero;
}
private void CopyToScreen()
{
BitBlt(_hdc, 0, 0, _bitW, _bitH, _bitHdc, 0, 0, 0x00CC0020);
}
#endregion
#region Helpers
// Set a resource (e.g. a font) for the current device context.
private void SetFont(Font font)
{
var blah = GetCachedHFont(font);
SelectObject(CurrentHdc, blah.HFont);
}
private FontCacheEntry GetCachedHFont(Font font)
{
FontCacheEntry fontEntry;
var result = _fontsCache.TryGetValue(font, out fontEntry);
if (!result)
{
// Hack! The 6 is hardcoded to make tastudio look like taseditor, because taseditor is so perfect and wonderful
fontEntry = new FontCacheEntry
{
HFont = CreateNormalHFont(font, 6),
RotatedHFont = CreateRotatedHFont(font, true)
};
_fontsCache.Add(font, fontEntry);
}
return fontEntry;
}
#endregion
#region Imports
// ReSharper disable IdentifierTypo
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateFontIndirect(
[In, MarshalAs(UnmanagedType.LPStruct)]LOGFONT lplf
);
[DllImport("gdi32.dll")]
private static extern int Rectangle(IntPtr hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("user32.dll")]
private static extern int FillRect(IntPtr hdc, [In] ref GDIRect lprc, IntPtr hbr);
[DllImport("gdi32.dll")]
private static extern int SetBkMode(IntPtr hdc, BkModes mode);
[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiObj);
[DllImport("gdi32.dll")]
private static extern int SetTextColor(IntPtr hdc, int color);
[DllImport("gdi32.dll", EntryPoint = "GetTextExtentPoint32W")]
private static extern int GetTextExtentPoint32(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Size size);
[DllImport("gdi32.dll", EntryPoint = "TextOutW")]
private static extern bool TextOut(IntPtr hdc, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string str, int len);
[DllImport("gdi32.dll")]
public static extern int SetGraphicsMode(IntPtr hdc, int iMode);
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateSolidBrush(int color);
[DllImport("gdi32.dll")]
private static extern IntPtr MoveToEx(IntPtr hdc, int x, int y, IntPtr point);
[DllImport("gdi32.dll")]
private static extern IntPtr LineTo(IntPtr hdc, int nXEnd, int nYEnd);
[DllImport("gdi32.dll")]
private static extern IntPtr GetStockObject(int fnObject);
[DllImport("gdi32.dll")]
private static extern IntPtr SetDCPenColor(IntPtr hdc, int crColor);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
public static extern bool DeleteDC([In] IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll", EntryPoint = "GdiAlphaBlend")]
static extern bool AlphaBlend(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction);
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedMember.Local
// ReSharper disable NotAccessedField.Local
// ReSharper disable ArrangeTypeMemberModifiers
public enum FontPrecision : byte
{
OUT_DEFAULT_PRECIS = 0,
OUT_STRING_PRECIS = 1,
OUT_CHARACTER_PRECIS = 2,
OUT_STROKE_PRECIS = 3,
OUT_TT_PRECIS = 4,
OUT_DEVICE_PRECIS = 5,
OUT_RASTER_PRECIS = 6,
OUT_TT_ONLY_PRECIS = 7,
OUT_OUTLINE_PRECIS = 8,
OUT_SCREEN_OUTLINE_PRECIS = 9,
OUT_PS_ONLY_PRECIS = 10,
}
// It is important for this to be the right declaration
// See more here http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2004-04/0319.html
// If it's wrong (I had a wrong one from pinvoke.net) then ToLogFont will fail mysteriously
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
class LOGFONT
{
public int lfHeight = 0;
public int lfWidth = 0;
public int lfEscapement = 0;
public int lfOrientation = 0;
public int lfWeight = 0;
public byte lfItalic = 0;
public byte lfUnderline = 0;
public byte lfStrikeOut = 0;
public byte lfCharSet = 0;
public byte lfOutPrecision = 0;
public byte lfClipPrecision = 0;
public byte lfQuality = 0;
public byte lfPitchAndFamily = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName = null;
}
/// <summary>
/// The graphics mode that can be set by SetGraphicsMode.
/// </summary>
public enum GraphicsMode : int
{
/// <summary>
/// Sets the graphics mode that is compatible with 16-bit Windows. This is the default mode. If
/// this value is specified, the application can only modify the world-to-device transform by
/// calling functions that set window and viewport extents and origins, but not by using
/// SetWorldTransform or ModifyWorldTransform; calls to those functions will fail.
/// Examples of functions that set window and viewport extents and origins are SetViewportExtEx
/// and SetWindowExtEx.
/// </summary>
GM_COMPATIBLE = 1,
/// <summary>
/// Sets the advanced graphics mode that allows world transformations. This value must be
/// specified if the application will set or modify the world transformation for the specified
/// device context. In this mode all graphics, including text output, fully conform to the
/// world-to-device transformation specified in the device context.
/// </summary>
GM_ADVANCED = 2,
}
/// <summary>
/// The XFORM structure specifies a world-space to page-space transformation.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XFORM
{
public float eM11;
public float eM12;
public float eM21;
public float eM22;
public float eDx;
public float eDy;
public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy)
{
this.eM11 = eM11;
this.eM12 = eM12;
this.eM21 = eM21;
this.eM22 = eM22;
this.eDx = eDx;
this.eDy = eDy;
}
/// <summary>
/// Allows implicit conversion to a managed transformation matrix.
/// </summary>
public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf)
{
return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy);
}
/// <summary>
/// Allows implicit conversion from a managed transformation matrix.
/// </summary>
public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m)
{
float[] elems = m.Elements;
return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct BLENDFUNCTION
{
byte BlendOp;
byte BlendFlags;
byte SourceConstantAlpha;
byte AlphaFormat;
public BLENDFUNCTION(byte op, byte flags, byte alpha, byte format)
{
BlendOp = op;
BlendFlags = flags;
SourceConstantAlpha = alpha;
AlphaFormat = format;
}
}
const byte AC_SRC_OVER = 0x00;
const byte AC_SRC_ALPHA = 0x01;
#endregion
#region Classes, Structs, and Enums
private class GdiGraphicsLock : IDisposable
{
private readonly GdiRenderer _gdi;
public GdiGraphicsLock(GdiRenderer gdi)
{
_gdi = gdi;
}
public void Dispose()
{
_gdi.CopyToScreen();
_gdi.EndOffScreenBitmap();
_gdi._g.ReleaseHdc(_gdi._hdc);
_gdi._hdc = IntPtr.Zero;
_gdi._g = null;
}
}
private struct GDIRect
{
private int left;
private int top;
private int right;
private int bottom;
public GDIRect(Rectangle r)
{
left = r.Left;
top = r.Top;
bottom = r.Bottom;
right = r.Right;
}
}
private enum PaintObjects
{
WHITE_BRUSH = 0,
LTGRAY_BRUSH = 1,
GRAY_BRUSH = 2,
DKGRAY_BRUSH = 3,
BLACK_BRUSH = 4,
NULL_BRUSH = 5,
WHITE_PEN = 6,
BLACK_PEN = 7,
NULL_PEN = 8,
OEM_FIXED_FONT = 10,
ANSI_FIXED_FONT = 11,
ANSI_VAR_FONT = 12,
SYSTEM_FONT = 13,
DEVICE_DEFAULT_FONT = 14,
DEFAULT_PALETTE = 15,
SYSTEM_FIXED_FONT = 16,
DC_BRUSH = 18,
DC_PEN = 19,
}
private enum BkModes : int
{
TRANSPARENT = 1,
OPAQUE = 2
}
#endregion
}
}

View File

@ -0,0 +1,108 @@
using System;
using System.Drawing;
namespace BizHawk.Client.EmuHawk.CustomControls
{
public class GdiPlusRenderer : IControlRenderer
{
private Graphics _graphics;
private readonly Pen _currentPen = new Pen(Color.Black);
private readonly SolidBrush _currentBrush = new SolidBrush(Color.Black);
private readonly SolidBrush _currentStringBrush = new SolidBrush(Color.Black);
private readonly Font _defaultFont = new Font("Arial", 8, FontStyle.Bold);
private Font _currentFont;
private bool _rotateString;
public GdiPlusRenderer()
{
_currentFont = _defaultFont;
}
private class GdiPlusGraphicsLock : IDisposable
{
public void Dispose()
{
// Nothing to do
// Other drawing methods need a way to dispose on demand, hence the need for
// this dummy class
}
}
public void Dispose()
{
_currentPen.Dispose();
_currentBrush.Dispose();
_currentStringBrush.Dispose();
_defaultFont.Dispose();
}
public void DrawBitmap(Bitmap bitmap, Point point)
{
_graphics.DrawImage(bitmap, point);
}
public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
{
_graphics.DrawRectangle(
_currentPen,
new Rectangle(nLeftRect, nTopRect, nRightRect - nLeftRect, nBottomRect - nTopRect));
}
public void DrawString(string str, Point point)
{
if (_rotateString)
{
_graphics.TranslateTransform(point.X, point.Y);
_graphics.RotateTransform(90);
_graphics.DrawString(str, _currentFont, _currentStringBrush, Point.Empty);
_graphics.ResetTransform();
}
else
{
_graphics.DrawString(str, _currentFont, _currentStringBrush, point);
}
}
public void FillRectangle(int x, int y, int w, int h)
{
_graphics.FillRectangle(
_currentBrush,
new Rectangle(x, y, w, h));
}
public void Line(int x1, int y1, int x2, int y2)
{
_graphics.DrawLine(_currentPen, x1, y1, x2, y2);
}
public IDisposable LockGraphics(Graphics g, int width, int height)
{
_graphics = g;
return new GdiPlusGraphicsLock();
}
public Size MeasureString(string str, Font font)
{
var size = _graphics.MeasureString(str, font);
return new Size((int)(size.Width + 0.5), (int)(size.Height + 0.5));
}
public void PrepDrawString(Font font, Color color, bool rotate = false)
{
_currentFont = font;
_currentStringBrush.Color = color;
_rotateString = rotate;
}
public void SetBrush(Color color)
{
_currentBrush.Color = color;
}
public void SetSolidPen(Color color)
{
_currentPen.Color = color;
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Drawing;
namespace BizHawk.Client.EmuHawk.CustomControls
{
public interface IControlRenderer : IDisposable
{
/// <summary>
/// Required to use before calling drawing methods
/// </summary>
IDisposable LockGraphics(Graphics g, int width, int height);
/// <summary>
/// Measure the width and height of string <paramref name="str"/> when drawn
/// using the given font <paramref name="font"/>
/// </summary>
Size MeasureString(string str, Font font);
void SetBrush(Color color);
void SetSolidPen(Color color);
void PrepDrawString(Font font, Color color, bool rotate = false);
/// <summary>
/// Draw the given string using the given font and foreground color at given location
/// </summary>
void DrawString(string str, Point point);
void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
void FillRectangle(int x, int y, int w, int h);
/// <summary>
/// Draw a bitmap object at the given position
/// </summary>
void DrawBitmap(Bitmap bitmap, Point point);
void Line(int x1, int y1, int x2, int y2);
}
}

View File

@ -1,769 +0,0 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
namespace BizHawk.Client.EmuHawk.CustomControls
{
/// <summary>
/// Wrapper for GDI rendering functions
/// This class is not thread-safe as GDI functions should be called from the UI thread
/// </summary>
public sealed class GDIRenderer : IDisposable
{
/// <summary>
/// used for <see cref="MeasureString(string, System.Drawing.Font, float, out int, out int)"/> calculation.
/// </summary>
private static readonly int[] CharFit = new int[1];
/// <summary>
/// used for <see cref="MeasureString(string, System.Drawing.Font,float, out int, out int)"/> calculation
/// </summary>
private static readonly int[] CharFitWidth = new int[1000];
/// <summary>
/// Cache of all the HFONTs used, rather than create them again and again
/// </summary>
private readonly Dictionary<Font, FontCacheEntry> FontsCache = new Dictionary<Font, FontCacheEntry>();
class FontCacheEntry
{
public IntPtr HFont;
}
/// <summary>
/// Cache of all the brushes used, rather than create them again and again
/// </summary>
private readonly Dictionary<Color, IntPtr> BrushCache = new Dictionary<Color, IntPtr>();
private Graphics _g;
private IntPtr _hdc;
private IntPtr _currentBrush = IntPtr.Zero;
#region Construct and Destroy
public GDIRenderer()
{
//zero 04-16-2016 : this can't be legal, theres no HDC yet
//SetBkMode(_hdc, BkModes.OPAQUE);
}
public void Dispose()
{
foreach (var brush in BrushCache)
{
if (brush.Value != IntPtr.Zero)
{
DeleteObject(brush.Value);
}
}
foreach (var fc in FontsCache)
DeleteObject(fc.Value.HFont);
EndOffScreenBitmap();
System.Diagnostics.Debug.Assert(_hdc == IntPtr.Zero, "Disposed a GDIRenderer while it held an HDC");
System.Diagnostics.Debug.Assert(_g == null, "Disposed a GDIRenderer while it held a Graphics");
}
#endregion
#region Api
/// <summary>
/// Draw a bitmap object at the given position
/// </summary>
public void DrawBitmap(Bitmap bitmap, Point point, bool blend = false)
{
IntPtr hbmp = bitmap.GetHbitmap();
var bitHDC = CreateCompatibleDC(CurrentHDC);
IntPtr old = SelectObject(bitHDC, hbmp);
if (blend)
{
AlphaBlend(CurrentHDC, point.X, point.Y, bitmap.Width, bitmap.Height, bitHDC, 0, 0, bitmap.Width, bitmap.Height, new BLENDFUNCTION(AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA));
}
else
{
BitBlt(CurrentHDC, point.X, point.Y, bitmap.Width, bitmap.Height, bitHDC, 0, 0, 0xCC0020);
}
SelectObject(bitHDC, old);
DeleteDC(bitHDC);
DeleteObject(hbmp);
}
/// <summary>
/// Required to use before calling drawing methods
/// </summary>
public GdiGraphicsLock LockGraphics(Graphics g)
{
_g = g;
_hdc = g.GetHdc();
SetBkMode(_hdc, BkModes.TRANSPARENT);
return new GdiGraphicsLock(this);
}
/// <summary>
/// Measure the width and height of string <paramref name="str"/> when drawn on device context HDC
/// using the given font <paramref name="font"/>
/// </summary>
public Size MeasureString(string str, Font font)
{
SetFont(font);
var size = new Size();
GetTextExtentPoint32(CurrentHDC, str, str.Length, ref size);
return size;
}
/// <summary>
/// Measure the width and height of string <paramref name="str"/> when drawn on device context HDC
/// using the given font <paramref name="font"/>
/// Restrict the width of the string and get the number of characters able to fit in the restriction and
/// the width those characters take
/// </summary>
/// <param name="maxWidth">the max width to render the string in</param>
/// <param name="charFit">the number of characters that will fit under <see cref="maxWidth"/> restriction</param>
public Size MeasureString(string str, Font font, float maxWidth, out int charFit, out int charFitWidth)
{
SetFont(font);
var size = new Size();
GetTextExtentExPoint(CurrentHDC, str, str.Length, (int)Math.Round(maxWidth), CharFit, CharFitWidth, ref size);
charFit = CharFit[0];
charFitWidth = charFit > 0 ? CharFitWidth[charFit - 1] : 0;
return size;
}
public void DrawString(string str, Point point)
{
TextOut(CurrentHDC, point.X, point.Y, str, str.Length);
}
public static IntPtr CreateNormalHFont(Font font, int width)
{
LOGFONT logf = new LOGFONT();
font.ToLogFont(logf);
logf.lfWidth = width;
logf.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS;
var ret = CreateFontIndirect(logf);
return ret;
}
//this returns an IntPtr HFONT because .net's Font class will erase the relevant properties when using its Font.FromLogFont()
//note that whether this is rotated clockwise or CCW might affect how you have to position the text (right-aligned sometimes?, up or down by the height of the font?)
public static IntPtr CreateRotatedHFont(Font font, bool CW)
{
LOGFONT logf = new LOGFONT();
font.ToLogFont(logf);
logf.lfEscapement = CW ? 2700 : 900;
logf.lfOrientation = logf.lfEscapement;
logf.lfOutPrecision = (byte)FontPrecision.OUT_TT_ONLY_PRECIS;
//this doesnt work! .net erases the relevant propreties.. it seems?
//return Font.FromLogFont(logf);
var ret = CreateFontIndirect(logf);
return ret;
}
public static void DestroyHFont(IntPtr hfont)
{
DeleteObject(hfont);
}
public void PrepDrawString(IntPtr hfont, Color color)
{
SetGraphicsMode(CurrentHDC, 2); //shouldnt be necessary.. cant hurt
SelectObject(CurrentHDC, hfont);
SetTextColor(color);
}
public void PrepDrawString(Font font, Color color)
{
SetFont(font);
SetTextColor(color);
}
/// <summary>
/// Draw the given string using the given font and foreground color at given location
/// See [http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx][15]
/// </summary>
public void DrawString(string str, Font font, Color color, Rectangle rect, TextFormatFlags flags)
{
SetFont(font);
SetTextColor(color);
var rect2 = new Rect(rect);
DrawText(CurrentHDC, str, str.Length, ref rect2, (uint)flags);
}
/// <summary>
/// Set the text color of the device context
/// </summary>
public void SetTextColor(Color color)
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
SetTextColor(CurrentHDC, rgb);
}
public void SetBackgroundColor(Color color)
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
SetBkColor(CurrentHDC, rgb);
}
public void DrawRectangle(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect)
{
Rectangle(CurrentHDC, nLeftRect, nTopRect, nRightRect, nBottomRect);
}
public void SetBrush(Color color)
{
if (BrushCache.ContainsKey(color))
{
_currentBrush = BrushCache[color];
}
else
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
var newBrush = CreateSolidBrush(rgb);
BrushCache.Add(color, newBrush);
_currentBrush = newBrush;
}
}
public void FillRectangle(int x, int y, int w, int h)
{
var r = new GDIRect(new Rectangle(x, y, w, h));
FillRect(CurrentHDC, ref r, _currentBrush);
}
public void SetPenPosition(int x, int y)
{
MoveToEx(CurrentHDC, x, y, IntPtr.Zero);
}
public void SetSolidPen(Color color)
{
int rgb = (color.B & 0xFF) << 16 | (color.G & 0xFF) << 8 | color.R;
SelectObject(CurrentHDC, GetStockObject((int)PaintObjects.DC_PEN));
SetDCPenColor(CurrentHDC, rgb);
}
public void Line(int x1, int y1, int x2, int y2)
{
MoveToEx(CurrentHDC, x1, y1, IntPtr.Zero);
LineTo(CurrentHDC, x2, y2);
}
private IntPtr CurrentHDC
{
get { return _bitHDC != IntPtr.Zero ? _bitHDC : _hdc; }
}
private IntPtr _bitMap = IntPtr.Zero;
private IntPtr _bitHDC = IntPtr.Zero;
private int _bitW;
private int _bitH;
public void StartOffScreenBitmap(int width, int height)
{
_bitW = width;
_bitH = height;
_bitHDC = CreateCompatibleDC(_hdc);
_bitMap = CreateCompatibleBitmap(_hdc, width, height);
SelectObject(_bitHDC, _bitMap);
SetBkMode(_bitHDC, BkModes.TRANSPARENT);
}
public void EndOffScreenBitmap()
{
_bitW = 0;
_bitH = 0;
DeleteObject(_bitMap);
DeleteObject(_bitHDC);
_bitHDC = IntPtr.Zero;
_bitMap = IntPtr.Zero;
}
public void CopyToScreen()
{
BitBlt(_hdc, 0, 0, _bitW, _bitH, _bitHDC, 0, 0, 0x00CC0020);
}
#endregion
#region Helpers
/// <summary>
/// Set a resource (e.g. a font) for the specified device context.
/// </summary>
private void SetFont(Font font)
{
SelectObject(CurrentHDC, GetCachedHFont(font));
}
private IntPtr GetCachedHFont(Font font)
{
//the original code struck me as bad. attempting to ID fonts by picking a subset of their fields is not gonna work.
//don't call this.Font in InputRoll.cs, it is probably slow.
//consider Fonts to be a jealously guarded resource (they need to be disposed, after all) and manage them carefully.
//this cache maintains the HFONTs only.
FontCacheEntry ce;
if (!FontsCache.TryGetValue(font, out ce))
{
FontsCache[font] = ce = new FontCacheEntry();
ce.HFont = font.ToHfont();
}
return ce.HFont;
}
#endregion
#region Imports
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr BeginPaint(IntPtr hWnd, ref IntPtr lpPaint);
[DllImport("user32.dll")]
private static extern IntPtr EndPaint(IntPtr hWnd, IntPtr lpPaint);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateFontIndirect(
[In, MarshalAs(UnmanagedType.LPStruct)]LOGFONT lplf
);
[DllImport("gdi32.dll")]
private static extern int Rectangle(IntPtr hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("user32.dll")]
private static extern int FillRect(IntPtr hdc, [In] ref GDIRect lprc, IntPtr hbr);
[DllImport("gdi32.dll")]
private static extern int SetBkMode(IntPtr hdc, BkModes mode);
[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiObj);
[DllImport("gdi32.dll")]
private static extern int SetTextColor(IntPtr hdc, int color);
[DllImport("gdi32.dll")]
private static extern int SetBkColor(IntPtr hdc, int color);
[DllImport("gdi32.dll", EntryPoint = "GetTextExtentPoint32W")]
private static extern int GetTextExtentPoint32(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Size size);
[DllImport("gdi32.dll", EntryPoint = "GetTextExtentExPointW")]
private static extern bool GetTextExtentExPoint(IntPtr hDc, [MarshalAs(UnmanagedType.LPWStr)]string str, int nLength, int nMaxExtent, int[] lpnFit, int[] alpDx, ref Size size);
[DllImport("gdi32.dll", EntryPoint = "TextOutW")]
private static extern bool TextOut(IntPtr hdc, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string str, int len);
[DllImport("gdi32.dll")]
public static extern int SetGraphicsMode(IntPtr hdc, int iMode);
[DllImport("user32.dll", EntryPoint = "DrawTextW")]
private static extern int DrawText(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string str, int len, ref Rect rect, uint uFormat);
[DllImport("gdi32.dll", EntryPoint = "ExtTextOutW")]
private static extern bool ExtTextOut(IntPtr hdc, int X, int Y, uint fuOptions, uint cbCount, [In] IntPtr lpDx);
[DllImport("gdi32.dll")]
static extern bool SetWorldTransform(IntPtr hdc, [In] ref XFORM lpXform);
[DllImport("gdi32.dll")]
private static extern int SelectClipRgn(IntPtr hdc, IntPtr hrgn);
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateSolidBrush(int color);
[DllImport("gdi32.dll")]
private static extern IntPtr CreatePen(int fnPenStyle, int nWidth, int color);
[DllImport("gdi32.dll")]
private static extern IntPtr MoveToEx(IntPtr hdc, int x, int y, IntPtr point);
[DllImport("gdi32.dll")]
private static extern IntPtr LineTo(IntPtr hdc, int nXEnd, int nYEnd);
[DllImport("gdi32.dll")]
private static extern IntPtr GetStockObject(int fnObject);
[DllImport("gdi32.dll")]
private static extern IntPtr SetDCPenColor(IntPtr hdc, int crColor);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
public static extern bool DeleteDC([In] IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll", EntryPoint = "GdiAlphaBlend")]
static extern bool AlphaBlend(IntPtr hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, BLENDFUNCTION blendFunction);
public enum FontWeight : int
{
FW_DONTCARE = 0,
FW_THIN = 100,
FW_EXTRALIGHT = 200,
FW_LIGHT = 300,
FW_NORMAL = 400,
FW_MEDIUM = 500,
FW_SEMIBOLD = 600,
FW_BOLD = 700,
FW_EXTRABOLD = 800,
FW_HEAVY = 900,
}
public enum FontCharSet : byte
{
ANSI_CHARSET = 0,
DEFAULT_CHARSET = 1,
SYMBOL_CHARSET = 2,
SHIFTJIS_CHARSET = 128,
HANGEUL_CHARSET = 129,
HANGUL_CHARSET = 129,
GB2312_CHARSET = 134,
CHINESEBIG5_CHARSET = 136,
OEM_CHARSET = 255,
JOHAB_CHARSET = 130,
HEBREW_CHARSET = 177,
ARABIC_CHARSET = 178,
GREEK_CHARSET = 161,
TURKISH_CHARSET = 162,
VIETNAMESE_CHARSET = 163,
THAI_CHARSET = 222,
EASTEUROPE_CHARSET = 238,
RUSSIAN_CHARSET = 204,
MAC_CHARSET = 77,
BALTIC_CHARSET = 186,
}
public enum FontPrecision : byte
{
OUT_DEFAULT_PRECIS = 0,
OUT_STRING_PRECIS = 1,
OUT_CHARACTER_PRECIS = 2,
OUT_STROKE_PRECIS = 3,
OUT_TT_PRECIS = 4,
OUT_DEVICE_PRECIS = 5,
OUT_RASTER_PRECIS = 6,
OUT_TT_ONLY_PRECIS = 7,
OUT_OUTLINE_PRECIS = 8,
OUT_SCREEN_OUTLINE_PRECIS = 9,
OUT_PS_ONLY_PRECIS = 10,
}
public enum FontClipPrecision : byte
{
CLIP_DEFAULT_PRECIS = 0,
CLIP_CHARACTER_PRECIS = 1,
CLIP_STROKE_PRECIS = 2,
CLIP_MASK = 0xf,
CLIP_LH_ANGLES = (1 << 4),
CLIP_TT_ALWAYS = (2 << 4),
CLIP_DFA_DISABLE = (4 << 4),
CLIP_EMBEDDED = (8 << 4),
}
public enum FontQuality : byte
{
DEFAULT_QUALITY = 0,
DRAFT_QUALITY = 1,
PROOF_QUALITY = 2,
NONANTIALIASED_QUALITY = 3,
ANTIALIASED_QUALITY = 4,
CLEARTYPE_QUALITY = 5,
CLEARTYPE_NATURAL_QUALITY = 6,
}
[Flags]
public enum FontPitchAndFamily : byte
{
DEFAULT_PITCH = 0,
FIXED_PITCH = 1,
VARIABLE_PITCH = 2,
FF_DONTCARE = (0 << 4),
FF_ROMAN = (1 << 4),
FF_SWISS = (2 << 4),
FF_MODERN = (3 << 4),
FF_SCRIPT = (4 << 4),
FF_DECORATIVE = (5 << 4),
}
//it is important for this to be the right declaration
//see more here http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2004-04/0319.html
//if it's wrong (I had a wrong one from pinvoke.net) then ToLogFont will fail mysteriously
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
class LOGFONT
{
public int lfHeight = 0;
public int lfWidth = 0;
public int lfEscapement = 0;
public int lfOrientation = 0;
public int lfWeight = 0;
public byte lfItalic = 0;
public byte lfUnderline = 0;
public byte lfStrikeOut = 0;
public byte lfCharSet = 0;
public byte lfOutPrecision = 0;
public byte lfClipPrecision = 0;
public byte lfQuality = 0;
public byte lfPitchAndFamily = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string lfFaceName = null;
}
/// <summary>
/// The graphics mode that can be set by SetGraphicsMode.
/// </summary>
public enum GraphicsMode : int
{
/// <summary>
/// Sets the graphics mode that is compatible with 16-bit Windows. This is the default mode. If
/// this value is specified, the application can only modify the world-to-device transform by
/// calling functions that set window and viewport extents and origins, but not by using
/// SetWorldTransform or ModifyWorldTransform; calls to those functions will fail.
/// Examples of functions that set window and viewport extents and origins are SetViewportExtEx
/// and SetWindowExtEx.
/// </summary>
GM_COMPATIBLE = 1,
/// <summary>
/// Sets the advanced graphics mode that allows world transformations. This value must be
/// specified if the application will set or modify the world transformation for the specified
/// device context. In this mode all graphics, including text output, fully conform to the
/// world-to-device transformation specified in the device context.
/// </summary>
GM_ADVANCED = 2,
}
/// <summary>
/// The XFORM structure specifies a world-space to page-space transformation.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct XFORM
{
public float eM11;
public float eM12;
public float eM21;
public float eM22;
public float eDx;
public float eDy;
public XFORM(float eM11, float eM12, float eM21, float eM22, float eDx, float eDy)
{
this.eM11 = eM11;
this.eM12 = eM12;
this.eM21 = eM21;
this.eM22 = eM22;
this.eDx = eDx;
this.eDy = eDy;
}
/// <summary>
/// Allows implicit converstion to a managed transformation matrix.
/// </summary>
public static implicit operator System.Drawing.Drawing2D.Matrix(XFORM xf)
{
return new System.Drawing.Drawing2D.Matrix(xf.eM11, xf.eM12, xf.eM21, xf.eM22, xf.eDx, xf.eDy);
}
/// <summary>
/// Allows implicit converstion from a managed transformation matrix.
/// </summary>
public static implicit operator XFORM(System.Drawing.Drawing2D.Matrix m)
{
float[] elems = m.Elements;
return new XFORM(elems[0], elems[1], elems[2], elems[3], elems[4], elems[5]);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct BLENDFUNCTION
{
byte BlendOp;
byte BlendFlags;
byte SourceConstantAlpha;
byte AlphaFormat;
public BLENDFUNCTION(byte op, byte flags, byte alpha, byte format)
{
BlendOp = op;
BlendFlags = flags;
SourceConstantAlpha = alpha;
AlphaFormat = format;
}
}
const byte AC_SRC_OVER = 0x00;
const byte AC_SRC_ALPHA = 0x01;
[DllImport("gdi32.dll")]
static extern int SetBitmapBits(IntPtr hbmp, uint cBytes, byte[] lpBits);
#endregion
#region Classes, Structs, and Enums
public class GdiGraphicsLock : IDisposable
{
private readonly GDIRenderer Gdi;
public GdiGraphicsLock(GDIRenderer gdi)
{
this.Gdi = gdi;
}
public void Dispose()
{
Gdi._g.ReleaseHdc(Gdi._hdc);
Gdi._hdc = IntPtr.Zero;
Gdi._g = null;
}
}
private struct Rect
{
private int _left;
private int _top;
private int _right;
private int _bottom;
public Rect(Rectangle r)
{
_left = r.Left;
_top = r.Top;
_bottom = r.Bottom;
_right = r.Right;
}
}
private struct GDIRect
{
private int left;
private int top;
private int right;
private int bottom;
public GDIRect(Rectangle r)
{
left = r.Left;
top = r.Top;
bottom = r.Bottom;
right = r.Right;
}
}
private struct GDIPoint
{
private int x;
private int y;
private GDIPoint(int x, int y)
{
this.x = x;
this.y = y;
}
}
[Flags]
public enum ETOOptions : uint
{
CLIPPED = 0x4,
GLYPH_INDEX = 0x10,
IGNORELANGUAGE = 0x1000,
NUMERICSLATIN = 0x800,
NUMERICSLOCAL = 0x400,
OPAQUE = 0x2,
PDY = 0x2000,
RTLREADING = 0x800,
}
/// <summary>
/// See [http://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx][15]
/// </summary>
[Flags]
public enum TextFormatFlags : uint
{
Default = 0x00000000,
Center = 0x00000001,
Right = 0x00000002,
VCenter = 0x00000004,
Bottom = 0x00000008,
WordBreak = 0x00000010,
SingleLine = 0x00000020,
ExpandTabs = 0x00000040,
TabStop = 0x00000080,
NoClip = 0x00000100,
ExternalLeading = 0x00000200,
CalcRect = 0x00000400,
NoPrefix = 0x00000800,
Internal = 0x00001000,
EditControl = 0x00002000,
PathEllipsis = 0x00004000,
EndEllipsis = 0x00008000,
ModifyString = 0x00010000,
RtlReading = 0x00020000,
WordEllipsis = 0x00040000,
NoFullWidthCharBreak = 0x00080000,
HidePrefix = 0x00100000,
ProfixOnly = 0x00200000,
}
[Flags]
public enum PenStyles
{
PS_SOLID = 0x00000000
// TODO
}
public enum PaintObjects
{
WHITE_BRUSH = 0,
LTGRAY_BRUSH = 1,
GRAY_BRUSH = 2,
DKGRAY_BRUSH = 3,
BLACK_BRUSH = 4,
NULL_BRUSH = 5,
WHITE_PEN = 6,
BLACK_PEN = 7,
NULL_PEN = 8,
OEM_FIXED_FONT = 10,
ANSI_FIXED_FONT = 11,
ANSI_VAR_FONT = 12,
SYSTEM_FONT = 13,
DEVICE_DEFAULT_FONT = 14,
DEFAULT_PALETTE = 15,
SYSTEM_FIXED_FONT = 16,
DC_BRUSH = 18,
DC_PEN = 19,
}
public enum BkModes : int
{
TRANSPARENT = 1,
OPAQUE = 2
}
#endregion
}
}

View File

@ -12,7 +12,7 @@ namespace BizHawk.Client.EmuHawk
{
public class HexView : Control
{
private readonly GDIRenderer Gdi;
//private readonly IControlRenderer _renderer;
private readonly Font NormalFont;
private Size _charSize;
@ -27,18 +27,18 @@ namespace BizHawk.Client.EmuHawk
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Opaque, true);
Gdi = new GDIRenderer();
//_renderer = new GdiRenderer();
using (var g = CreateGraphics())
using (var LCK = Gdi.LockGraphics(g))
{
_charSize = Gdi.MeasureString("A", NormalFont); // TODO make this a property so changing it updates other values.
}
//using (var g = CreateGraphics())
//using (var LCK = _renderer.LockGraphics(g))
//{
// _charSize = _renderer.MeasureString("A", NormalFont); // TODO make this a property so changing it updates other values.
//}
}
protected override void Dispose(bool disposing)
{
Gdi.Dispose();
//_renderer.Dispose();
NormalFont.Dispose();
@ -49,21 +49,21 @@ namespace BizHawk.Client.EmuHawk
protected override void OnPaint(PaintEventArgs e)
{
using (var LCK = Gdi.LockGraphics(e.Graphics))
{
Gdi.StartOffScreenBitmap(Width, Height);
//using (var lck = _renderer.LockGraphics(e.Graphics))
//{
// _renderer.StartOffScreenBitmap(Width, Height);
// White Background
Gdi.SetBrush(Color.White);
Gdi.SetSolidPen(Color.White);
Gdi.FillRectangle(0, 0, Width, Height);
// // White Background
// _renderer.SetBrush(Color.White);
// _renderer.SetSolidPen(Color.White);
// _renderer.FillRectangle(0, 0, Width, Height);
Gdi.DrawString("Hello World", new Point(10, 10));
// _renderer.DrawString("Hello World", new Point(10, 10));
Gdi.CopyToScreen();
Gdi.EndOffScreenBitmap();
}
// _renderer.CopyToScreen();
// _renderer.EndOffScreenBitmap();
//}
}
#endregion

View File

@ -0,0 +1,96 @@
using System.Collections.Generic;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Represents a single cell of the <seealso cref="InputRoll"/>
/// </summary>
public class Cell
{
public RollColumn Column { get; internal set; }
public int? RowIndex { get; internal set; }
public string CurrentText { get; internal set; }
public Cell() { }
public Cell(Cell cell)
{
Column = cell.Column;
RowIndex = cell.RowIndex;
}
public bool IsDataCell => Column != null && RowIndex.HasValue;
public override bool Equals(object obj)
{
var cell = obj as Cell;
if (cell != null)
{
return Column == cell.Column && RowIndex == cell.RowIndex;
}
return false;
}
public override int GetHashCode()
{
return Column.GetHashCode() + RowIndex.GetHashCode();
}
public static bool operator ==(Cell a, Cell b)
{
if (ReferenceEquals(a, null))
{
return ReferenceEquals(b, null);
}
return a.Equals(b);
}
public static bool operator !=(Cell a, Cell b)
{
return !(a == b);
}
}
internal class SortCell : IComparer<Cell>
{
int IComparer<Cell>.Compare(Cell c1, Cell c2)
{
if (c1 == null && c2 == null)
{
return 0;
}
if (c2 == null)
{
return 1;
}
if (c1 == null)
{
return -1;
}
if (c1.RowIndex.HasValue)
{
if (c2.RowIndex.HasValue)
{
int row = c1.RowIndex.Value.CompareTo(c2.RowIndex.Value);
return row == 0
? c1.Column.Name.CompareTo(c2.Column.Name)
: row;
}
return 1;
}
if (c2.RowIndex.HasValue)
{
return -1;
}
return c1.Column.Name.CompareTo(c2.Column.Name);
}
}
}

View File

@ -0,0 +1,10 @@
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Specifies the type of column of a <see cref="RollColumn"/>
/// </summary>
public enum ColumnType
{
Boolean, Float, Text, Image
}
}

View File

@ -0,0 +1,697 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using BizHawk.Client.EmuHawk.WinFormExtensions;
namespace BizHawk.Client.EmuHawk
{
public partial class InputRoll
{
protected override void OnPaint(PaintEventArgs e)
{
using (_renderer.LockGraphics(e.Graphics, Width, Height))
{
// White Background
_renderer.SetBrush(Color.White);
_renderer.SetSolidPen(Color.White);
_renderer.FillRectangle(0, 0, Width, Height);
// Lag frame calculations
SetLagFramesArray();
var visibleColumns = _columns.VisibleColumns.ToList();
CalculateHorizontalColumnPositions(visibleColumns);
if (visibleColumns.Any())
{
DrawColumnBg(visibleColumns);
DrawColumnText(visibleColumns);
}
// Background
DrawBg(visibleColumns);
// Foreground
DrawData(visibleColumns);
DrawColumnDrag(visibleColumns);
DrawCellDrag(visibleColumns);
}
}
private void DrawString(string text, int? width, Point point)
{
if (string.IsNullOrWhiteSpace(text))
{
return;
}
if (width.HasValue)
{
var max = (width.Value - CellWidthPadding) / _charSize.Width;
if (text.Length >= max)
{
text = text.Substring(0, max);
}
}
_renderer.DrawString(text, point);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Do nothing, and this should never be called
}
private void CalculateHorizontalColumnPositions(List<RollColumn> visibleColumns)
{
if (!HorizontalOrientation)
{
_horizontalColumnHeights = null;
_horizontalColumnTops = null;
return;
}
_horizontalColumnHeights = new int[visibleColumns.Count];
_horizontalColumnTops = new int[visibleColumns.Count];
int top = 0;
int startRow = FirstVisibleRow;
for (int j = 0; j < visibleColumns.Count; j++)
{
RollColumn col = visibleColumns[j];
int height = CellHeight;
if (col.Rotatable && col.RotatedHeight != null)
{
height = Math.Max(height, col.RotatedHeight.Value);
}
else if (col.Rotatable)
{
string text;
int strOffsetX = 0;
int strOffsetY = 0;
QueryItemText(startRow, col, out text, ref strOffsetX, ref strOffsetY);
int textWidth = _renderer.MeasureString(text, _font).Width;
height = Math.Max(height, textWidth + (CellWidthPadding * 2));
}
_horizontalColumnHeights[j] = height;
_horizontalColumnTops[j] = top;
top += height;
}
}
private void DrawColumnDrag(List<RollColumn> visibleColumns)
{
if (_columnDown?.Width != null && _columnDownMoved && _currentX.HasValue && _currentY.HasValue && IsHoveringOnColumnCell)
{
int columnWidth = _columnDown.Width.Value;
int columnHeight = CellHeight;
if (HorizontalOrientation)
{
int columnIndex = visibleColumns.IndexOf(_columnDown);
columnWidth = ColumnWidth;
columnHeight = GetHColHeight(columnIndex);
}
int x1 = _currentX.Value - (columnWidth / 2);
int y1 = _currentY.Value - (columnHeight / 2);
int x2 = x1 + columnWidth;
int y2 = y1 + columnHeight;
int textOffsetY = CellHeightPadding;
if (HorizontalOrientation)
{
int textHeight = _renderer.MeasureString(_columnDown.Text, _font).Height;
textOffsetY = (columnHeight - textHeight) / 2;
}
_renderer.SetSolidPen(_backColor);
_renderer.DrawRectangle(x1, y1, x2, y2);
_renderer.PrepDrawString(_font, _foreColor);
_renderer.DrawString(_columnDown.Text, new Point(x1 + CellWidthPadding, y1 + textOffsetY));
}
}
private void DrawCellDrag(List<RollColumn> visibleColumns)
{
if (_draggingCell != null && _draggingCell.RowIndex.HasValue && _draggingCell.Column.Width.HasValue
&& _currentX.HasValue && _currentY.HasValue)
{
var text = "";
int offsetX = 0;
int offsetY = 0;
QueryItemText?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, out text, ref offsetX, ref offsetY);
Color bgColor = _backColor;
QueryItemBkColor?.Invoke(_draggingCell.RowIndex.Value, _draggingCell.Column, ref bgColor);
int columnHeight = CellHeight;
if (HorizontalOrientation)
{
int columnIndex = visibleColumns.IndexOf(_draggingCell.Column);
columnHeight = GetHColHeight(columnIndex);
}
int x1 = _currentX.Value - (_draggingCell.Column.Width.Value / 2);
int y1 = _currentY.Value - (columnHeight / 2);
int x2 = x1 + _draggingCell.Column.Width.Value;
int y2 = y1 + columnHeight;
_renderer.SetBrush(bgColor);
_renderer.FillRectangle(x1, y1, x2 - x1, y2 - y1);
_renderer.PrepDrawString(_font, _foreColor);
_renderer.DrawString(text, new Point(x1 + CellWidthPadding + offsetX, y1 + CellHeightPadding + offsetY));
}
}
private void DrawColumnText(List<RollColumn> visibleColumns)
{
if (HorizontalOrientation)
{
int y = -_vBar.Value;
_renderer.PrepDrawString(_font, _foreColor);
for(int j = 0; j < visibleColumns.Count; j++)
{
var column = visibleColumns[j];
var columnHeight = GetHColHeight(j);
var textHeight = _renderer.MeasureString(column.Text, _font).Height;
var point = new Point(CellWidthPadding, y + ((columnHeight - textHeight) / 2));
if (IsHoveringOnColumnCell && column == CurrentCell.Column)
{
_renderer.PrepDrawString(_font, SystemColors.HighlightText);
DrawString(column.Text, column.Width, point);
_renderer.PrepDrawString(_font, _foreColor);
}
else
{
DrawString(column.Text, column.Width, point);
}
y += columnHeight;
}
}
else
{
_renderer.PrepDrawString(_font, _foreColor);
foreach (var column in visibleColumns)
{
var point = new Point(column.Left.Value + 2 * CellWidthPadding - _hBar.Value, CellHeightPadding); // TODO: fix this CellPadding issue (2 * CellPadding vs just CellPadding)
if (IsHoveringOnColumnCell && column == CurrentCell.Column)
{
_renderer.PrepDrawString(_font, SystemColors.HighlightText);
DrawString(column.Text, column.Width, point);
_renderer.PrepDrawString(_font, _foreColor);
}
else
{
DrawString(column.Text, column.Width, point);
}
}
}
}
private void DrawData(List<RollColumn> visibleColumns)
{
// Prevent exceptions with small TAStudio windows
if (visibleColumns.Count == 0)
{
return;
}
if (QueryItemText != null)
{
if (HorizontalOrientation)
{
int startRow = FirstVisibleRow;
int range = Math.Min(LastVisibleRow, RowCount - 1) - startRow + 1;
_renderer.PrepDrawString(_font, _foreColor);
int lastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= lastVisible; j++)
{
RollColumn col = visibleColumns[j];
int colHeight = GetHColHeight(j);
for (int i = 0, f = 0; f < range; i++, f++)
{
f += _lagFrames[i];
int baseX = RowsToPixels(i) + (col.Rotatable ? CellWidth : 0);
int baseY = GetHColTop(j) - _vBar.Value;
if (!col.Rotatable)
{
Bitmap image = null;
int bitmapOffsetX = 0;
int bitmapOffsetY = 0;
QueryItemIcon?.Invoke(f + startRow, col, ref image, ref bitmapOffsetX, ref bitmapOffsetY);
if (image != null)
{
int x = baseX + CellWidthPadding + bitmapOffsetX;
int y = baseY + CellHeightPadding + bitmapOffsetY;
_renderer.DrawBitmap(image, new Point(x, y));
}
}
string text;
int strOffsetX = 0;
int strOffsetY = 0;
QueryItemText(f + startRow, col, out text, ref strOffsetX, ref strOffsetY);
int textWidth = _renderer.MeasureString(text, _font).Width;
if (col.Rotatable)
{
// Center Text
int textX = Math.Max(((colHeight - textWidth) / 2), CellWidthPadding) + strOffsetX;
int textY = CellWidthPadding + strOffsetY;
var point = new Point(baseX - textY, baseY + textX);
_renderer.PrepDrawString(_font, _foreColor, rotate: true);
DrawString(text, null, point);
_renderer.PrepDrawString(_font, _foreColor, rotate: false);
}
else
{
// Center Text
int textX = Math.Max(((CellWidth - textWidth) / 2), CellWidthPadding) + strOffsetX;
int textY = CellHeightPadding + strOffsetY;
var point = new Point(baseX + textX, baseY + textY);
DrawString(text, ColumnWidth, point);
}
}
}
}
else
{
int startRow = FirstVisibleRow;
int range = Math.Min(LastVisibleRow, RowCount - 1) - startRow + 1;
_renderer.PrepDrawString(_font, _foreColor);
int xPadding = CellWidthPadding + 1 - _hBar.Value;
for (int i = 0, f = 0; f < range; i++, f++) // Vertical
{
f += _lagFrames[i];
int lastVisible = LastVisibleColumnIndex;
for (int j = FirstVisibleColumn; j <= lastVisible; j++) // Horizontal
{
RollColumn col = visibleColumns[j];
string text;
int strOffsetX = 0;
int strOffsetY = 0;
Point point = new Point(col.Left.Value + xPadding, RowsToPixels(i) + CellHeightPadding);
Bitmap image = null;
int bitmapOffsetX = 0;
int bitmapOffsetY = 0;
QueryItemIcon?.Invoke(f + startRow, visibleColumns[j], ref image, ref bitmapOffsetX, ref bitmapOffsetY);
if (image != null)
{
_renderer.DrawBitmap(image, new Point(point.X + bitmapOffsetX, point.Y + bitmapOffsetY + CellHeightPadding));
}
QueryItemText(f + startRow, visibleColumns[j], out text, ref strOffsetX, ref strOffsetY);
bool rePrep = false;
if (_selectedItems.Contains(new Cell { Column = visibleColumns[j], RowIndex = f + startRow }))
{
_renderer.PrepDrawString(_font, SystemColors.HighlightText);
rePrep = true;
}
DrawString(text, col.Width, new Point(point.X + strOffsetX, point.Y + strOffsetY));
if (rePrep)
{
_renderer.PrepDrawString(_font, _foreColor);
}
}
}
}
}
}
private void DrawColumnBg(List<RollColumn> visibleColumns)
{
_renderer.SetBrush(SystemColors.ControlLight);
_renderer.SetSolidPen(Color.Black);
if (HorizontalOrientation)
{
_renderer.FillRectangle(0, 0, ColumnWidth + 1, DrawHeight + 1);
int y = -_vBar.Value;
for (int j = 0; j < visibleColumns.Count; j++)
{
_renderer.Line(1, y, ColumnWidth, y);
y += GetHColHeight(j);
}
if (visibleColumns.Any())
{
_renderer.Line(1, y, ColumnWidth, y);
}
_renderer.Line(0, 0, 0, y + 1);
_renderer.Line(ColumnWidth, 0, ColumnWidth, y + 1);
}
else
{
int bottomEdge = RowsToPixels(0);
// Gray column box and black line underneath
_renderer.FillRectangle(0, 0, Width + 1, bottomEdge + 1);
_renderer.Line(0, 0, TotalColWidth.Value + 1, 0);
_renderer.Line(0, bottomEdge, TotalColWidth.Value + 1, bottomEdge);
// Vertical black separators
foreach (var column in visibleColumns)
{
int pos = column.Left.Value - _hBar.Value;
_renderer.Line(pos, 0, pos, bottomEdge);
}
// Draw right most line
if (visibleColumns.Any())
{
int right = TotalColWidth.Value - _hBar.Value;
_renderer.Line(right, 0, right, bottomEdge);
}
}
// Emphasis
foreach (var column in visibleColumns.Where(c => c.Emphasis))
{
_renderer.SetBrush(SystemColors.ActiveBorder);
if (HorizontalOrientation)
{
int columnIndex = visibleColumns.IndexOf(column);
_renderer.FillRectangle(1, GetHColTop(columnIndex) + 1, ColumnWidth - 1, GetHColHeight(columnIndex) - 1);
}
else
{
_renderer.FillRectangle(column.Left.Value + 1 - _hBar.Value, 1, column.Width.Value - 1, ColumnHeight - 1);
}
}
// If the user is hovering over a column
if (IsHoveringOnColumnCell)
{
if (HorizontalOrientation)
{
for (int i = 0; i < visibleColumns.Count; i++)
{
if (visibleColumns[i] != CurrentCell.Column)
{
continue;
}
int top = GetHColTop(i) - _vBar.Value;
int height = GetHColHeight(i);
_renderer.SetBrush(CurrentCell.Column.Emphasis
? SystemColors.Highlight.Add(0x00222222)
: SystemColors.Highlight);
_renderer.FillRectangle(1, top + 1, ColumnWidth - 1, height - 1);
}
}
else
{
// TODO multiple selected columns
foreach (var column in visibleColumns)
{
if (column == CurrentCell.Column)
{
// Left of column is to the right of the viewable area or right of column is to the left of the viewable area
if (column.Left.Value - _hBar.Value > Width || column.Right.Value - _hBar.Value < 0)
{
continue;
}
int left = column.Left.Value - _hBar.Value;
int width = column.Right.Value - _hBar.Value - left;
_renderer.SetBrush(CurrentCell.Column.Emphasis
? SystemColors.Highlight.Add(0x00550000)
: SystemColors.Highlight);
_renderer.FillRectangle(left + 1, 1, width - 1, ColumnHeight - 1);
}
}
}
}
}
// TODO refactor this and DoBackGroundCallback functions.
/// <summary>
/// Draw Gridlines and background colors using QueryItemBkColor.
/// </summary>
private void DrawBg(List<RollColumn> visibleColumns)
{
if (UseCustomBackground && QueryItemBkColor != null)
{
DoBackGroundCallback(visibleColumns);
}
if (GridLines)
{
_renderer.SetSolidPen(SystemColors.ControlLight);
if (HorizontalOrientation)
{
// Columns
for (int i = 1; i < VisibleRows + 1; i++)
{
int x = RowsToPixels(i);
_renderer.Line(x, 1, x, DrawHeight);
}
// Rows
for (int i = 0; i < visibleColumns.Count + 1; i++)
{
int y = GetHColTop(i) - _vBar.Value;
_renderer.Line(RowsToPixels(0) + 1, y, DrawWidth, y);
}
}
else
{
// Columns
int y = ColumnHeight + 1;
foreach (var column in visibleColumns)
{
int x = (column.Left ?? 0) - _hBar.Value;
_renderer.Line(x, y, x, Height - 1);
}
if (visibleColumns.Any())
{
int x = (TotalColWidth ?? 0) - _hBar.Value;
_renderer.Line(x, y, x, Height - 1);
}
// Rows
for (int i = 1; i < VisibleRows + 1; i++)
{
_renderer.Line(0, RowsToPixels(i), Width + 1, RowsToPixels(i));
}
}
}
if (_selectedItems.Any())
{
DoSelectionBG(visibleColumns);
}
}
private void DoSelectionBG(List<RollColumn> visibleColumns)
{
Color rowColor = Color.White;
int lastVisibleRow = LastVisibleRow;
int lastRow = -1;
foreach (Cell cell in _selectedItems)
{
if (cell.RowIndex > lastVisibleRow || cell.RowIndex < FirstVisibleRow || !VisibleColumns.Contains(cell.Column))
{
continue;
}
Cell relativeCell = new Cell
{
RowIndex = cell.RowIndex - FirstVisibleRow,
Column = cell.Column,
};
relativeCell.RowIndex -= CountLagFramesAbsolute(relativeCell.RowIndex.Value);
if (QueryRowBkColor != null && lastRow != cell.RowIndex.Value)
{
QueryRowBkColor(cell.RowIndex.Value, ref rowColor);
lastRow = cell.RowIndex.Value;
}
Color cellColor = rowColor;
QueryItemBkColor?.Invoke(cell.RowIndex.Value, cell.Column, ref cellColor);
// Alpha layering for cell before selection
float alpha = (float)cellColor.A / 255;
if (cellColor.A != 255 && cellColor.A != 0)
{
cellColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - cellColor.R) * alpha),
rowColor.G - (int)((rowColor.G - cellColor.G) * alpha),
rowColor.B - (int)((rowColor.B - cellColor.B) * alpha));
}
// Alpha layering for selection
alpha = 0.33f;
cellColor = Color.FromArgb(cellColor.R - (int)((cellColor.R - SystemColors.Highlight.R) * alpha),
cellColor.G - (int)((cellColor.G - SystemColors.Highlight.G) * alpha),
cellColor.B - (int)((cellColor.B - SystemColors.Highlight.B) * alpha));
DrawCellBG(cellColor, relativeCell, visibleColumns);
}
}
/// <summary>
/// Given a cell with RowIndex in between 0 and VisibleRows, it draws the background color specified. Do not call with absolute row indices.
/// </summary>
private void DrawCellBG(Color color, Cell cell, List<RollColumn> visibleColumns)
{
int x, y, w, h;
if (HorizontalOrientation)
{
x = RowsToPixels(cell.RowIndex.Value) + 1;
if (x < ColumnWidth)
{
return;
}
int columnIndex = visibleColumns.IndexOf(cell.Column);
w = CellWidth - 1;
y = GetHColTop(columnIndex) - _vBar.Value + 1; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't
h = GetHColHeight(columnIndex) - 1;
}
else
{
y = RowsToPixels(cell.RowIndex.Value) + 1; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't
if (y < ColumnHeight)
{
return;
}
x = cell.Column.Left.Value - _hBar.Value + 1;
w = cell.Column.Width.Value - 1;
h = CellHeight - 1;
}
// Don't draw if off screen.
if (x > DrawWidth || y > DrawHeight)
{
return;
}
_renderer.SetBrush(color);
_renderer.FillRectangle(x, y, w, h);
}
/// <summary>
/// Calls QueryItemBkColor callback for all visible cells and fills in the background of those cells.
/// </summary>
private void DoBackGroundCallback(List<RollColumn> visibleColumns)
{
int startIndex = FirstVisibleRow;
int range = Math.Min(LastVisibleRow, RowCount - 1) - startIndex + 1;
int lastVisibleColumn = LastVisibleColumnIndex;
int firstVisibleColumn = FirstVisibleColumn;
// Prevent exceptions with small TAStudio windows
if (firstVisibleColumn < 0)
{
return;
}
if (HorizontalOrientation)
{
for (int i = 0, f = 0; f < range; i++, f++)
{
f += _lagFrames[i];
Color rowColor = Color.White;
QueryRowBkColor?.Invoke(f + startIndex, ref rowColor);
for (int j = firstVisibleColumn; j <= lastVisibleColumn; j++)
{
Color itemColor = Color.White;
QueryItemBkColor?.Invoke(f + startIndex, visibleColumns[j], ref itemColor);
if (itemColor == Color.White)
{
itemColor = rowColor;
}
else if (itemColor.A != 255 && itemColor.A != 0)
{
float alpha = (float)itemColor.A / 255;
itemColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - itemColor.R) * alpha),
rowColor.G - (int)((rowColor.G - itemColor.G) * alpha),
rowColor.B - (int)((rowColor.B - itemColor.B) * alpha));
}
if (itemColor != Color.White) // An easy optimization, don't draw unless the user specified something other than the default
{
var cell = new Cell
{
Column = visibleColumns[j],
RowIndex = i
};
DrawCellBG(itemColor, cell, visibleColumns);
}
}
}
}
else
{
for (int i = 0, f = 0; f < range; i++, f++) // Vertical
{
f += _lagFrames[i];
Color rowColor = Color.White;
QueryRowBkColor?.Invoke(f + startIndex, ref rowColor);
for (int j = FirstVisibleColumn; j <= lastVisibleColumn; j++) // Horizontal
{
Color itemColor = Color.White;
QueryItemBkColor?.Invoke(f + startIndex, visibleColumns[j], ref itemColor);
if (itemColor == Color.White)
{
itemColor = rowColor;
}
else if (itemColor.A != 255 && itemColor.A != 0)
{
float alpha = (float)itemColor.A / 255;
itemColor = Color.FromArgb(rowColor.R - (int)((rowColor.R - itemColor.R) * alpha),
rowColor.G - (int)((rowColor.G - itemColor.G) * alpha),
rowColor.B - (int)((rowColor.B - itemColor.B) * alpha));
}
if (itemColor != Color.White) // An easy optimization, don't draw unless the user specified something other than the default
{
var cell = new Cell
{
Column = visibleColumns[j],
RowIndex = i
};
DrawCellBG(itemColor, cell, visibleColumns);
}
}
}
}
}
}
}

View File

@ -0,0 +1,31 @@
using System;
namespace BizHawk.Client.EmuHawk
{
public class RollColumn
{
public string Group { get; set; }
public int? Width { get; set; }
public int? Left { get; set; }
public int? Right { get; set; }
public string Name { get; set; }
public string Text { get; set; }
public ColumnType Type { get; set; }
public bool Visible { get; set; } = true;
/// <summary>
/// Column will be drawn with an emphasized look, if true
/// </summary>
public bool Emphasis { get; set; }
/// <summary>
/// Column header text will be drawn rotated, if true
/// </summary>
public bool Rotatable { get; set; }
/// <summary>
/// If drawn rotated, specifies the desired height, or null to auto-size
/// </summary>
public int? RotatedHeight { get; set; }
}
}

View File

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Client.EmuHawk
{
public class RollColumns : List<RollColumn>
{
public RollColumn this[string name] => this.SingleOrDefault(column => column.Name == name);
public IEnumerable<RollColumn> VisibleColumns => this.Where(c => c.Visible);
public Action ChangedCallback { get; set; }
// TODO: this shouldn't be exposed. But in order to not expose it, each RollColumn must have a change callback, and all property changes must call it, it is quicker and easier to just call this when needed
public void ColumnsChanged()
{
int pos = 0;
foreach (var col in VisibleColumns)
{
col.Left = pos;
pos += col.Width ?? 0;
col.Right = pos;
}
ChangedCallback?.Invoke();
}
public new void Add(RollColumn column)
{
if (this.Any(c => c.Name == column.Name))
{
// The designer sucks, doing nothing for now
return;
//throw new InvalidOperationException("A column with this name already exists.");
}
base.Add(column);
ColumnsChanged();
}
public new void AddRange(IEnumerable<RollColumn> collection)
{
var items = collection.ToList();
foreach (var column in items)
{
if (this.Any(c => c.Name == column.Name))
{
// The designer sucks, doing nothing for now
return;
throw new InvalidOperationException("A column with this name already exists.");
}
}
base.AddRange(items);
ColumnsChanged();
}
public new void Insert(int index, RollColumn column)
{
if (this.Any(c => c.Name == column.Name))
{
// The designer sucks, doing nothing for now
return;
throw new InvalidOperationException("A column with this name already exists.");
}
base.Insert(index, column);
ColumnsChanged();
}
public new void InsertRange(int index, IEnumerable<RollColumn> collection)
{
var items = collection.ToList();
foreach (var column in items)
{
if (this.Any(c => c.Name == column.Name))
{
throw new InvalidOperationException("A column with this name already exists.");
}
}
base.InsertRange(index, items);
ColumnsChanged();
}
public new bool Remove(RollColumn column)
{
var result = base.Remove(column);
ColumnsChanged();
return result;
}
public new int RemoveAll(Predicate<RollColumn> match)
{
var result = base.RemoveAll(match);
ColumnsChanged();
return result;
}
public new void RemoveAt(int index)
{
base.RemoveAt(index);
ColumnsChanged();
}
public new void RemoveRange(int index, int count)
{
base.RemoveRange(index, count);
ColumnsChanged();
}
public new void Clear()
{
base.Clear();
ColumnsChanged();
}
public IEnumerable<string> Groups => this
.Select(x => x.Group)
.Distinct();
}
}

View File

@ -47,6 +47,7 @@ namespace BizHawk.Client.EmuHawk.CustomControls
{
InitializeComponent();
this.ControlBox = false; // Do not set in designer (causes problems with auto scaling)
this.messageLbl.Text = message;
this.Text = title;
this.m_sysIcon = icon;
@ -58,7 +59,7 @@ namespace BizHawk.Client.EmuHawk.CustomControls
public void SetMessageToAutoSize()
{
this.messageLbl.AutoSize = true;
this.messageLbl.MaximumSize = new Size(this.MaximumSize.Width - this.m_sysIcon.Width - 25, this.MaximumSize.Height);
this.messageLbl.MaximumSize = new Size(this.MaximumSize.Width - this.m_sysIcon.Width - UIHelper.ScaleX(25), this.MaximumSize.Height);
}
/// <summary>
@ -220,11 +221,11 @@ namespace BizHawk.Client.EmuHawk.CustomControls
}
const int FORM_Y_MARGIN = 10;
const int FORM_X_MARGIN = 16;
const int BUTTON_SPACE = 5;
const int CHECKBOX_SPACE = 15;
const int TEXT_Y_MARGIN = 30;
private static readonly int FORM_Y_MARGIN = UIHelper.ScaleY(10);
private static readonly int FORM_X_MARGIN = UIHelper.ScaleX(16);
private static readonly int BUTTON_SPACE = UIHelper.ScaleX(5);
private static readonly int CHECKBOX_SPACE = UIHelper.ScaleX(15);
private static readonly int TEXT_Y_MARGIN = UIHelper.ScaleY(30);
/// <summary>
/// Auto fits the dialog box to fit the text and the buttons.

View File

@ -105,7 +105,6 @@
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btn1;
this.ClientSize = new System.Drawing.Size(485, 149);
this.ControlBox = false;
this.Controls.Add(this.btn3);
this.Controls.Add(this.chkBx);
this.Controls.Add(this.btn1);

View File

@ -1,181 +0,0 @@
using System;
using System.Linq;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk
{
public class TasListView : VirtualListView
{
public class Cell
{
public int? RowIndex;
public string Column;
// Convenience hack
public override string ToString()
{
return string.IsNullOrEmpty(Column) ? "?" : $"{Column} - {(RowIndex.HasValue ? RowIndex.ToString() : "?")}";
}
}
public bool RightButtonHeld { get; set; }
public int? LastSelectedIndex
{
get
{
if (SelectedIndices.Count > 0)
{
return SelectedIndices
.OfType<int>()
.OrderBy(x => x)
.Last();
}
return null;
}
}
private Cell _currentPointedCell = new Cell();
public Cell CurrentCell
{
get { return _currentPointedCell; }
}
private Cell _lastPointedCell = new Cell();
public Cell LastCell
{
get { return _lastPointedCell; }
}
public bool InputPaintingMode { get; set; }
public bool IsPaintDown { get; private set; }
/// <summary>
/// Calculates the column name and row number that the point (x, y) lies in.
/// </summary>
/// <param name="x">X coordinate</param>
/// <param name="y">Y coordinate</param>
private void CalculatePointedCell(int x, int y)
{
int? newRow;
string newColumn = "";
var accumulator = 0;
foreach (ColumnHeader column in Columns)
{
accumulator += column.Width;
if (accumulator < x)
{
continue;
}
newColumn = column.Name;
break;
}
var rowHeight = this.LineHeight;// 5 (in VirtualListView) and 6 work here for me, but are they always dependable, how can I get the padding?
var headerHeight = rowHeight + 6;
newRow = ((y - headerHeight) / rowHeight) + this.VScrollPos;
if (newRow >= ItemCount)
{
newRow = null;
}
if (newColumn != CurrentCell.Column || newRow != CurrentCell.RowIndex)
{
LastCell.Column = CurrentCell.Column;
LastCell.RowIndex = CurrentCell.RowIndex;
CurrentCell.Column = newColumn;
CurrentCell.RowIndex = newRow;
CellChanged(LastCell, CurrentCell);
}
}
public class CellEventArgs
{
public CellEventArgs(Cell oldCell, Cell newCell)
{
OldCell = oldCell;
NewCell = newCell;
}
public Cell OldCell { get; private set; }
public Cell NewCell { get; private set; }
}
public delegate void CellChangeEventHandler(object sender, CellEventArgs e);
public event CellChangeEventHandler PointedCellChanged;
private void CellChanged(Cell oldCell, Cell newCell)
{
if (PointedCellChanged != null)
{
PointedCellChanged(this, new CellEventArgs(oldCell, newCell));
}
}
protected override void OnMouseLeave(EventArgs e)
{
_currentPointedCell.Column = "";
_currentPointedCell.RowIndex = null;
IsPaintDown = false;
base.OnMouseLeave(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
CalculatePointedCell(e.X, e.Y);
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && InputPaintingMode)
{
IsPaintDown = true;
}
if (e.Button == MouseButtons.Right)
{
RightButtonHeld = true;
}
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
IsPaintDown = false;
RightButtonHeld = false;
base.OnMouseUp(e);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (RightButtonHeld)
{
DoRightMouseScroll(this, e);
}
else
{
base.OnMouseWheel(e);
}
}
public delegate void RightMouseScrollEventHandler(object sender, MouseEventArgs e);
public event RightMouseScrollEventHandler RightMouseScrolled;
private void DoRightMouseScroll(object sender, MouseEventArgs e)
{
if (RightMouseScrolled != null)
{
RightMouseScrolled(sender, e);
}
}
}
}

View File

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="RightClickMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@ -1,854 +0,0 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk
{
#region win32interop
[StructLayout(LayoutKind.Sequential)]
internal struct LvDispInfo
{
public NmHdr Hdr;
public LvItem Item;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NmHdr
{
public IntPtr HwndFrom;
public IntPtr IdFrom;
public int Code;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NmItemActivate
{
public NmHdr Hdr;
public int Item;
public int SubItem;
public uint NewState;
public uint OldState;
public uint uChanged;
public POINT Action;
public uint lParam;
public uint KeyFlags;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int Top;
public int Left;
public int Bottom;
public int Right;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NmCustomDrawInfo
{
public NmHdr Hdr;
public uint dwDrawStage;
public IntPtr Hdc;
public RECT Rect;
public IntPtr dwItemSpec;
public uint ItemState;
private int _pad64bits;
public IntPtr lItemlParam;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NmLvCustomDraw
{
public NmCustomDrawInfo Nmcd;
public int ClearText;
public int ClearTextBackground;
public int SubItem;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct LvItem
{
public uint Mask;
public int Item;
public int SubItem;
public uint State;
public uint StateMask;
public IntPtr PszText;
public int cchTextMax;
public int Image;
public IntPtr lParam;
public int Indent;
}
[FlagsAttribute]
internal enum CustomDrawReturnFlags
{
CDRF_DODEFAULT = 0x00000000,
CDRF_NEWFONT = 0x00000002,
CDRF_SKIPDEFAULT = 0x00000004,
CDRF_NOTIFYPOSTPAINT = 0x00000010,
CDRF_NOTIFYITEMDRAW = 0x00000020,
CDRF_NOTIFYSUBITEMDRAW = 0x00000020,
CDRF_NOTIFYPOSTERASE = 0x00000040,
}
[FlagsAttribute]
internal enum CustomDrawDrawStageFlags
{
CDDS_PREPAINT = 0x00000001,
CDDS_POSTPAINT = 0x00000002,
CDDS_PREERASE = 0x00000003,
CDDS_POSTERASE = 0x00000004,
// the 0x000010000 bit means it's individual item specific
CDDS_ITEM = 0x00010000,
CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT),
CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT),
CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE),
CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE),
CDDS_SUBITEM = 0x00020000,
CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT),
CDDS_SUBITEMPOSTPAINT = (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT),
CDDS_SUBITEMPREERASE = (CDDS_SUBITEM | CDDS_ITEMPREERASE),
CDDS_SUBITEMPOSTERASE = (CDDS_SUBITEM | CDDS_ITEMPOSTERASE),
}
[FlagsAttribute]
internal enum LvHitTestFlags
{
LVHT_NOWHERE = 0x0001,
LVHT_ONITEMICON = 0x0002,
LVHT_ONITEMLABEL = 0x0004,
LVHT_ONITEMSTATEICON = 0x0008,
LVHT_ONITEM = (LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON),
LVHT_ABOVE = 0x0008,
LVHT_BELOW = 0x0010,
LVHT_TORIGHT = 0x0020,
LVHT_TOLEFT = 0x0040
}
[StructLayout(LayoutKind.Sequential)]
internal struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
internal class LvHitTestInfo
{
public POINT Point;
public uint Flags;
public int Item;
public int SubItem;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NMLISTVIEW
{
public NmHdr hdr;
public int iItem;
public int iSubItem;
public uint uNewState;
public uint uOldState;
public uint uChanged;
public POINT ptAction;
public IntPtr lParam;
}
internal enum ListViewItemMask : short
{
LVIF_TEXT = 0x0001,
LVIF_IMAGE = 0x0002,
LVIF_PARAM = 0x0004,
LVIF_STATE = 0x0008,
LVIF_INDENT = 0x0010,
LVIF_NORECOMPUTE = 0x0800,
LVIF_GROUPID = 0x0100,
LVIF_COLUMNS = 0x0200
}
internal enum LvNi
{
ALL = 0x0000,
FOCUSED = 0x0001,
SELECTED = 0x0002,
CUT = 0x0004,
DROPHILITED = 0x0008,
ABOVE = 0x0100,
BELOW = 0x0200,
TOLEFT = 0x0400,
TORIGHT = 0x0800
}
internal enum ListViewMessages
{
LVM_FIRST = 0x1000,
LVM_GETITEMCOUNT = (LVM_FIRST + 4),
LVM_SETCALLBACKMASK = (LVM_FIRST + 11),
LVM_GETNEXTITEM = (LVM_FIRST + 12),
LVM_HITTEST = (LVM_FIRST + 18),
LVM_ENSUREVISIBLE = (LVM_FIRST + 19),
LVM_SETITEMSTATE = (LVM_FIRST + 43),
LVM_GETITEMSTATE = (LVM_FIRST + 44),
LVM_SETITEMCOUNT = (LVM_FIRST + 47),
LVM_GETSUBITEMRECT = (LVM_FIRST + 56)
}
internal enum ListViewStyles : short
{
LVS_OWNERDATA = 0x1000,
LVS_SORTASCENDING = 0x0010,
LVS_SORTDESCENDING = 0x0020,
LVS_SHAREIMAGELISTS = 0x0040,
LVS_NOLABELWRAP = 0x0080,
LVS_AUTOARRANGE = 0x0100
}
internal enum ListViewStylesICF : uint
{
LVSICF_NOINVALIDATEALL = 0x00000001,
LVSICF_NOSCROLL = 0x00000002
}
internal enum WindowsMessage : uint
{
WM_ERASEBKGND = 0x0014,
WM_SCROLL = 0x115,
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_LBUTTONDBLCLK = 0x0203,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_RBUTTONDBLCLK = 0x0206,
WM_SETFOCUS = 0x0007,
WM_NOTIFY = 0x004E,
WM_USER = 0x0400,
WM_REFLECT = WM_USER + 0x1c00
}
internal enum Notices
{
NM_FIRST = 0,
NM_CUSTOMDRAW = NM_FIRST - 12,
NM_CLICK = NM_FIRST - 2,
NM_DBLCLICK = NM_FIRST - 3,
}
internal enum ListViewNotices
{
LVN_FIRST = (0 - 100),
LVN_LAST = (0 - 199),
LVN_BEGINDRAG = LVN_FIRST - 9,
LVN_BEGINRDRAG = LVN_FIRST - 11,
LVN_GETDISPINFOA = LVN_FIRST - 50,
LVN_GETDISPINFOW = LVN_FIRST - 77,
LVN_SETDISPINFOA = LVN_FIRST - 51,
LVN_SETDISPINFOW = LVN_FIRST - 78,
LVN_ODCACHEHINT = LVN_FIRST - 13,
LVN_ODFINDITEMW = LVN_FIRST - 79
}
[Flags]
internal enum ListViewCallBackMask : uint
{
LVIS_FOCUSED = 0x0001,
LVIS_SELECTED = 0x0002,
LVIS_CUT = 0x0004,
LVIS_DROPHILITED = 0x0008,
LVIS_GLOW = 0x0010,
LVIS_ACTIVATING = 0x0020,
LVIS_OVERLAYMASK = 0x0F00,
LVIS_STATEIMAGEMASK = 0xF000,
}
#endregion
#region VirtualListView Delegates
/// <summary>
/// Retrieve the background color for a Listview cell (item and subitem).
/// </summary>
/// <param name="item">Listview item (row).</param>
/// <param name="subItem">Listview subitem (column).</param>
/// <param name="color">Background color to use</param>
public delegate void QueryItemBkColorHandler(int item, int subItem, ref Color color);
/// <summary>
/// Retrieve the text for a Listview cell (item and subitem).
/// </summary>
/// <param name="item">Listview item (row).</param>
/// <param name="subItem">Listview subitem (column).</param>
/// <param name="text">Text to display.</param>
public delegate void QueryItemTextHandler(int item, int subItem, out string text);
/// <summary>
/// Retrieve the image index for a Listview item.
/// </summary>
/// <param name="item">Listview item (row).</param>
/// <param name="subItem">Listview subitem (column) - should always be zero.</param>
/// <param name="imageIndex">Index of associated ImageList.</param>
public delegate void QueryItemImageHandler(int item, int subItem, out int imageIndex);
/// <summary>
/// Retrieve the indent for a Listview item. The indent is always width of an image.
/// For example, 1 indents the Listview item one image width.
/// </summary>
/// <param name="item">Listview item (row).</param>
/// <param name="itemIndent">The amount to indent the Listview item.</param>
public delegate void QueryItemIndentHandler(int item, out int itemIndent);
public delegate void QueryItemHandler(int idx, out ListViewItem item);
#endregion
/// <summary>
/// VirtualListView is a virtual Listview which allows for a large number of items(rows)
/// to be displayed. The virtual Listview contains very little actual information -
/// mainly item selection and focus information.
/// </summary>
public class VirtualListView : ListView
{
// store the item count to prevent the call to SendMessage(LVM_GETITEMCOUNT)
private int _itemCount;
#region Display query callbacks
/// <summary>
/// Fire the QueryItemBkColor event which requests the background color for the passed Listview cell
/// </summary>
public event QueryItemBkColorHandler QueryItemBkColor;
/// <summary>
/// Fire the QueryItemText event which requests the text for the passed Listview cell.
/// </summary>
[Category("Data")]
public event QueryItemTextHandler QueryItemText;
/// <summary>
/// Fire the QueryItemImage event which requests the ImageIndex for the passed Listview item.
/// </summary>
[Category("Data")]
public event QueryItemImageHandler QueryItemImage;
/// <summary>
/// Fire the QueryItemIndent event which requests the indent for the passed Listview item.
/// </summary>
[Category("Data")]
public event QueryItemIndentHandler QueryItemIndent;
[Category("Data")]
public event QueryItemHandler QueryItem;
#endregion
#region Properties
/// <summary>
/// Gets or sets the sets the virtual number of items to be displayed.
/// </summary>
[Category("Behavior")]
public int ItemCount
{
get
{
return _itemCount;
}
set
{
_itemCount = value;
// If the virtual item count is set before the handle is created
// then the image lists don't get loaded properly
if (!IsHandleCreated)
{
return;
}
SetVirtualItemCount();
}
}
/// <summary>
/// Gets or sets how list items are to be displayed.
/// Hide the ListView.View property.
/// Virtual Listviews only allow Details or List.
/// </summary>
public new View View
{
get
{
return base.View;
}
set
{
if (value == View.LargeIcon ||
value == View.SmallIcon)
{
throw new ArgumentException($"Icon views are invalid for virtual {nameof(ListView)}s", nameof(View));
}
base.View = value;
}
}
/// <summary>
/// Gets the required creation parameters when the control handle is created.
/// Use LVS_OWNERDATA to set this as a virtual Listview.
/// </summary>
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
// LVS_OWNERDATA style must be set when the control is created
cp.Style |= (int)ListViewStyles.LVS_OWNERDATA;
return cp;
}
}
#endregion
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int LineHeight { get; private set; }
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int NumberOfVisibleRows
{
get
{
return Height / LineHeight;
}
}
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="VirtualListView"/> class.
/// Create a new instance of this control.
/// </summary>
public VirtualListView()
{
// virtual listviews must be Details or List view with no sorting
View = View.Details;
Sorting = SortOrder.None;
UseCustomBackground = true;
ptrlvhti = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LvHitTestInfo)));
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
LineHeight = this.Font.Height + 5;
}
~VirtualListView()
{
Marshal.FreeHGlobal(ptrlvhti);
}
#endregion
#region Methods
/// <summary>
/// Set the state of the passed Listview item's index.
/// </summary>
/// <param name="index">Listview item's index.</param>
/// <param name="selected">Select the passed item?</param>
public void SelectItem(int index, bool selected)
{
var ptrItem = IntPtr.Zero;
try
{
// Determine whether selecting or unselecting.
uint select = selected ? (uint)ListViewCallBackMask.LVIS_SELECTED : 0;
// Fill in the LVITEM structure with state fields.
var stateItem = new LvItem
{
Mask = (uint)ListViewItemMask.LVIF_STATE,
Item = index,
SubItem = 0,
State = @select,
StateMask = (uint)ListViewCallBackMask.LVIS_SELECTED
};
// Copy the structure to unmanaged memory.
ptrItem = Marshal.AllocHGlobal(Marshal.SizeOf(stateItem.GetType()));
Marshal.StructureToPtr(stateItem, ptrItem, true);
// Send the message to the control window.
Win32.SendMessage(
this.Handle,
(int)ListViewMessages.LVM_SETITEMSTATE,
(IntPtr)index,
ptrItem);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine($"VirtualListView.SetItemState error={ex.Message}");
// TODO: should this eat any exceptions?
throw;
}
finally
{
// Always release the unmanaged memory.
if (ptrItem != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptrItem);
}
}
}
private void SetVirtualItemCount()
{
Win32.SendMessage(
this.Handle,
(int)ListViewMessages.LVM_SETITEMCOUNT,
(IntPtr)this._itemCount,
IntPtr.Zero);
}
protected void OnDispInfoNotice(ref Message m, bool useAnsi)
{
var info = (LvDispInfo)m.GetLParam(typeof(LvDispInfo));
if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_TEXT) > 0)
{
if (QueryItemText != null)
{
string lvtext;
QueryItemText(info.Item.Item, info.Item.SubItem, out lvtext);
if (lvtext != null)
{
try
{
int maxIndex = Math.Min(info.Item.cchTextMax - 1, lvtext.Length);
var data = new char[maxIndex + 1];
lvtext.CopyTo(0, data, 0, lvtext.Length);
data[maxIndex] = '\0';
Marshal.Copy(data, 0, info.Item.PszText, data.Length);
}
catch (Exception e)
{
Debug.WriteLine($"Failed to copy text name from client: {e}", $"{nameof(VirtualListView)}.{nameof(OnDispInfoNotice)}");
}
}
}
}
if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_IMAGE) > 0)
{
int imageIndex = 0;
if (QueryItemImage != null)
{
QueryItemImage(info.Item.Item, info.Item.SubItem, out imageIndex);
}
info.Item.Image = imageIndex;
Marshal.StructureToPtr(info, m.LParam, false);
}
if ((info.Item.Mask & (uint)ListViewItemMask.LVIF_INDENT) > 0)
{
int itemIndent = 0;
if (QueryItemIndent != null)
{
QueryItemIndent(info.Item.Item, out itemIndent);
}
info.Item.Indent = itemIndent;
Marshal.StructureToPtr(info, m.LParam, false);
}
m.Result = new IntPtr(0);
}
protected void OnCustomDrawNotice(ref Message m)
{
var cd = (NmLvCustomDraw)m.GetLParam(typeof(NmLvCustomDraw));
switch (cd.Nmcd.dwDrawStage)
{
case (int)CustomDrawDrawStageFlags.CDDS_ITEMPREPAINT:
case (int)CustomDrawDrawStageFlags.CDDS_PREPAINT:
m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_NOTIFYSUBITEMDRAW);
break;
case (int)CustomDrawDrawStageFlags.CDDS_SUBITEMPREPAINT:
if (QueryItemBkColor != null)
{
var color = Color.FromArgb(cd.ClearTextBackground & 0xFF, (cd.ClearTextBackground >> 8) & 0xFF, (cd.ClearTextBackground >> 16) & 0xFF);
QueryItemBkColor(cd.Nmcd.dwItemSpec.ToInt32(), cd.SubItem, ref color);
cd.ClearTextBackground = (color.B << 16) | (color.G << 8) | color.R;
Marshal.StructureToPtr(cd, m.LParam, false);
}
m.Result = new IntPtr((int)CustomDrawReturnFlags.CDRF_DODEFAULT);
break;
}
}
/// <summary>
/// Event to be fired whenever the control scrolls
/// </summary>
public event ScrollEventHandler Scroll;
protected virtual void OnScroll(ScrollEventArgs e)
{
var handler = this.Scroll;
if (handler != null)
{
handler(this, e);
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, Orientation nBar);
/// <summary>
/// Gets the Vertical Scroll position of the control.
/// </summary>
public int VScrollPos
{
get { return GetScrollPos(this.Handle, Orientation.Vertical); }
}
protected override void WndProc(ref Message m)
{
var messageProcessed = false;
switch (m.Msg)
{
case (int)WindowsMessage.WM_REFLECT + (int)WindowsMessage.WM_NOTIFY:
var nm1 = (NmHdr)m.GetLParam(typeof(NmHdr));
switch (nm1.Code)
{
case (int)Notices.NM_CUSTOMDRAW:
OnCustomDrawNotice(ref m);
messageProcessed = true;
if (QueryItemBkColor == null || !UseCustomBackground)
{
m.Result = (IntPtr)0;
}
break;
case (int)ListViewNotices.LVN_GETDISPINFOW:
OnDispInfoNotice(ref m, false);
messageProcessed = true;
break;
case (int)ListViewNotices.LVN_BEGINDRAG:
OnBeginItemDrag(MouseButtons.Left, ref m);
messageProcessed = true;
break;
case (int)ListViewNotices.LVN_BEGINRDRAG:
OnBeginItemDrag(MouseButtons.Right, ref m);
messageProcessed = true;
break;
}
break;
case (int)WindowsMessage.WM_SCROLL:
// http://stackoverflow.com/questions/1851620/handling-scroll-event-on-listview-in-c-sharp
OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), m.WParam.ToInt32()));
break;
case (int)WindowsMessage.WM_ERASEBKGND:
if (BlazingFast)
{
messageProcessed = true;
m.Result = new IntPtr(1);
}
break;
}
if (!messageProcessed)
{
try
{
base.WndProc(ref m);
}
catch (Exception ex)
{
Trace.WriteLine($"Message {m} caused an exception: {ex.Message}");
}
}
}
public bool BlazingFast { get; set; }
public bool UseCustomBackground { get; set; }
protected ListViewItem GetItem(int idx)
{
ListViewItem item = null;
if (QueryItem != null)
{
QueryItem(idx, out item);
}
if (item == null)
{
throw new ArgumentException($"cannot find item {idx} via {nameof(QueryItem)} event");
}
return item;
}
protected void OnBeginItemDrag(MouseButtons mouseButton, ref Message m)
{
var info = (NMLISTVIEW)m.GetLParam(typeof(NMLISTVIEW));
ListViewItem item = null;
if (QueryItem != null)
{
QueryItem(info.iItem, out item);
}
OnItemDrag(new ItemDragEventArgs(mouseButton, item));
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
// ensure the value for ItemCount is sent to the control properly if the user set it
// before the handle was created
SetVirtualItemCount();
}
protected override void OnHandleDestroyed(EventArgs e)
{
// the ListView OnHandleDestroyed accesses the Items list for all selected items
ItemCount = 0;
base.OnHandleDestroyed(e);
}
#endregion
LvHitTestInfo lvhti = new LvHitTestInfo();
IntPtr ptrlvhti;
int selection = -1;
public int hitTest(int x, int y)
{
lvhti.Point.X = x;
lvhti.Point.Y = y;
Marshal.StructureToPtr(lvhti, ptrlvhti, true);
int z = (int)Win32.SendMessage(this.Handle, (int)ListViewMessages.LVM_HITTEST, (IntPtr)0, ptrlvhti);
Marshal.PtrToStructure(ptrlvhti, lvhti);
return z;
}
public void ensureVisible(int index)
{
Win32.SendMessage(Handle, (int)ListViewMessages.LVM_ENSUREVISIBLE, (IntPtr)index, (IntPtr)1);
}
public void ensureVisible()
{
ensureVisible(selectedItem);
}
public void setSelection(int index)
{
clearSelection();
selection = index;
SelectItem(selection, true);
}
public int selectedItem
{
get
{
if (SelectedIndices.Count == 0)
{
return -1;
}
else
{
return SelectedIndices[0];
}
}
set
{
setSelection(value);
}
}
public void clearSelection()
{
if (selection != -1)
{
SelectItem(selection, false);
}
selection = -1;
}
// Informs user that a select all event is in place, can be used in change events to wait until this is false
public bool SelectAllInProgress { get; set; }
public void SelectAll()
{
this.BeginUpdate();
SelectAllInProgress = true;
for (var i = 0; i < _itemCount; i++)
{
if (i == _itemCount - 1)
{
SelectAllInProgress = false;
}
this.SelectItem(i, true);
}
this.EndUpdate();
}
public void DeselectAll()
{
this.BeginUpdate();
SelectAllInProgress = true;
for (var i = 0; i < _itemCount; i++)
{
if (i == _itemCount - 1)
{
SelectAllInProgress = false;
}
this.SelectItem(i, false);
}
this.EndUpdate();
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.A && e.Control && !e.Alt && !e.Shift) // Select All
{
SelectAll();
}
base.OnKeyDown(e);
}
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.CustomControls;
using BizHawk.Emulation.Common;
using Cores = BizHawk.Emulation.Cores;
namespace BizHawk.Client.EmuHawk
{
public static class EmuHawkUtil
{
public static bool EnsureCoreIsAccurate(IEmulator emulator)
{
static bool PromptToSwitchCore(string currentCore, string recommendedCore, Action disableCurrentCore)
{
using var box = new MsgBox(
$"While the {currentCore} core is faster, it is not nearly as accurate as {recommendedCore}.{Environment.NewLine}It is recommended that you switch to the {recommendedCore} core for movie recording.{Environment.NewLine}Switch to {recommendedCore}?",
"Accuracy Warning",
MessageBoxIcon.Warning);
box.SetButtons(
new[] { "Switch", "Continue" },
new[] { DialogResult.Yes, DialogResult.Cancel });
box.MaximumSize = UIHelper.Scale(new Size(575, 175));
box.SetMessageToAutoSize();
var result = box.ShowDialog();
if (result != DialogResult.Yes)
{
return false;
}
disableCurrentCore();
GlobalWin.MainForm.RebootCore();
return true;
}
if (emulator is Cores.Nintendo.SNES9X.Snes9x)
{
return PromptToSwitchCore("Snes9x", "bsnes", () => Global.Config.SNES_InSnes9x = false);
}
if (emulator is Cores.Consoles.Nintendo.QuickNES.QuickNES)
{
return PromptToSwitchCore("QuickNes", "NesHawk", () => Global.Config.NES_InQuickNES = false);
}
return true;
}
}
}

View File

@ -7,10 +7,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using BizHawk.Common;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk.WinFormExtensions
{
@ -43,44 +40,7 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions
return control.BeginInvoke(action);
}
public static void AddColumn(this ListView listView, string columnName, bool enabled, int columnWidth)
{
if (enabled)
{
if (listView.Columns[columnName] == null)
{
var column = new ColumnHeader
{
Name = columnName,
Text = columnName.Replace("Column", ""),
Width = columnWidth,
};
listView.Columns.Add(column);
}
}
}
public static void AddColumn(this ListView listView, ToolDialogSettings.Column column)
{
if (column.Visible)
{
if (listView.Columns[column.Name] == null)
{
var lsstViewColumn = new ColumnHeader
{
Name = column.Name,
Text = column.Name.Replace("Column", ""),
Width = column.Width,
DisplayIndex = column.Index
};
listView.Columns.Add(lsstViewColumn);
}
}
}
public static ToolStripMenuItem GenerateColumnsMenu(this ToolDialogSettings.ColumnList list, Action changeCallback)
public static ToolStripMenuItem ToColumnsMenu(this InputRoll inputRoll, Action changeCallback)
{
var menu = new ToolStripMenuItem
{
@ -88,33 +48,31 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions
Text = "Columns"
};
var dummyList = list;
var columns = inputRoll.AllColumns;
foreach (var column in dummyList)
foreach (var column in columns)
{
var menuItem = new ToolStripMenuItem
{
Name = column.Name,
Text = column.Name.Replace("Column", "")
Text = $"{column.Text} ({column.Name})",
Checked = column.Visible,
CheckOnClick = true,
Tag = column.Name
};
menuItem.Click += (o, ev) =>
menuItem.CheckedChanged += (o, ev) =>
{
dummyList[menuItem.Name].Visible ^= true;
var sender = (ToolStripMenuItem)o;
columns.Find(c => c.Name == (string)sender.Tag).Visible = sender.Checked;
columns.ColumnsChanged();
changeCallback();
inputRoll.Refresh();
};
menu.DropDownItems.Add(menuItem);
}
menu.DropDownOpened += (o, e) =>
{
foreach (var column in dummyList)
{
(menu.DropDownItems[column.Name] as ToolStripMenuItem).Checked = column.Visible;
}
};
return menu;
}
@ -123,6 +81,13 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions
return control.PointToScreen(new Point(child.Location.X, child.Location.Y));
}
public static Color Add(this Color color, int val)
{
var col = color.ToArgb();
col += val;
return Color.FromArgb(col);
}
#region Enumerable to Enumerable<T>
/// <summary>
@ -139,16 +104,6 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions
return tabControl.TabPages.Cast<TabPage>();
}
public static IEnumerable<int> SelectedIndices(this ListView listView)
{
return listView.SelectedIndices.Cast<int>();
}
public static IEnumerable<ColumnHeader> ColumnHeaders(this ListView listView)
{
return listView.Columns.OfType<ColumnHeader>();
}
#endregion
}
@ -251,7 +206,7 @@ namespace BizHawk.Client.EmuHawk.WinFormExtensions
{
foreach (ListViewItem.ListViewSubItem item in listViewControl.Items[index].SubItems)
{
if (!String.IsNullOrWhiteSpace(item.Text))
if (!string.IsNullOrWhiteSpace(item.Text))
{
sb.Append(item.Text).Append('\t');
}

View File

@ -11,6 +11,7 @@ using BizHawk.Emulation.Cores.Nintendo.SNES9X;
using BizHawk.Emulation.Cores.Sega.Saturn;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
using BizHawk.Emulation.Cores.Sony.PSP;
using BizHawk.Emulation.Cores.Arcades.MAME;
using BizHawk.Client.Common;
@ -51,6 +52,10 @@ namespace BizHawk.Client.EmuHawk.CoreExtensions
{
return Properties.Resources.snes9x;
}
else if (core is MAME)
{
return Properties.Resources.mame;
}
else
{
return null;

View File

@ -50,7 +50,7 @@ namespace BizHawk.Client.EmuHawk.ToolExtensions
}
//TODO - do TSMI and TSDD need disposing? yuck
var item = new ToolStripMenuItem { Text = caption };
var item = new ToolStripMenuItem { Text = caption.Replace("&", "&&") };
items.Add(item);
item.Click += (o, ev) =>

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Client.EmuHawk
{
public class FileFilterEntry
{
public string Description { get; }
public string[] Filters { get; }
public string[] DeveloperFilters { get; }
public FileFilterEntry(string description, string filters, string developerFilters = null)
{
Description = description;
Filters = filters?.Split(';') ?? Array.Empty<string>();
DeveloperFilters = developerFilters?.Split(';') ?? Array.Empty<string>();
}
public IEnumerable<string> EffectiveFilters
{
get
{
IEnumerable<string> effectiveFilters = Filters;
if (VersionInfo.DeveloperBuild)
{
effectiveFilters = effectiveFilters.Concat(DeveloperFilters);
}
return effectiveFilters;
}
}
}
}

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using BizHawk.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Emulation.Cores.PCEngine;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
@ -40,31 +39,8 @@ namespace BizHawk.Client.EmuHawk
}
}
// This is the list from MainForm->RomFilter()'s non-developer build. It needs to be kept up-to-date when new cores are added.
// adelikat: This is annoying and bad. Maybe we could generate RomFilter from this property?
private string[] KnownRomExtensions
{
get
{
if (VersionInfo.DeveloperBuild)
{
return new[]
{
".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC",
".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML",
".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".EXE", ".PRG", ".D64", ".G64", ".CRT", ".TAP", ".32X", ".MDS", ".TZX",
".PZX", ".CSW", ".WAV", ".CDT"
};
}
return new[]
{
".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC",
".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML",
".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".PRG", ".D64", ".G64", ".CRT", ".TAP", ".32X", ".MDS", ".TZX", ".PZX", ".CSW", ".WAV"
};
}
}
private IEnumerable<string> KnownRomExtensions =>
RomFilterEntries.SelectMany(f => f.EffectiveFilters.Where(s => s.StartsWith("*.", StringComparison.Ordinal)).Select(s => s.Substring(1).ToUpperInvariant()));
private readonly string[] _nonArchive = { ".ISO", ".CUE", ".CCD" };
@ -173,7 +149,7 @@ namespace BizHawk.Client.EmuHawk
{
foreach (string file in fileList)
{
var ext = Path.GetExtension(file).ToUpper() ?? "";
var ext = Path.GetExtension(file).ToUpperInvariant() ?? "";
FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive);
switch (ext)

View File

@ -3,8 +3,6 @@ using System.Linq;
using System.Collections.Generic;
using System.Threading;
using SlimDX.DirectInput;
using BizHawk.Common;
using BizHawk.Client.Common;
@ -70,6 +68,13 @@ namespace BizHawk.Client.EmuHawk
Pad = 4
}
public enum AllowInput
{
None = 0,
All = 1,
OnlyController = 2
}
/// <summary>
/// If your form needs this kind of input focus, be sure to say so.
/// Really, this only makes sense for mouse, but I've started building it out for other things
@ -196,71 +201,53 @@ namespace BizHawk.Client.EmuHawk
{
public LogicalButton LogicalButton;
public InputEventType EventType;
public InputFocus Source;
public override string ToString()
{
return $"{EventType.ToString()}:{LogicalButton.ToString()}";
}
}
private readonly WorkingDictionary<string, object> ModifierState = new WorkingDictionary<string, object>();
private readonly Dictionary<string, LogicalButton> ModifierState = new Dictionary<string, LogicalButton>();
private readonly WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>();
private readonly WorkingDictionary<string, bool> UnpressState = new WorkingDictionary<string, bool>();
private readonly HashSet<string> IgnoreKeys = new HashSet<string>(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" });
private readonly WorkingDictionary<string, float> FloatValues = new WorkingDictionary<string, float>();
private readonly WorkingDictionary<string, float> FloatDeltas = new WorkingDictionary<string, float>();
private bool trackdeltas = false;
private bool IgnoreEventsNextPoll = false;
void HandleButton(string button, bool newState)
void HandleButton(string button, bool newState, InputFocus source)
{
bool isModifier = IgnoreKeys.Contains(button);
if (EnableIgnoreModifiers && isModifier) return;
if (LastState[button] && newState) return;
if (!LastState[button] && !newState) return;
ModifierKey currentModifier = ButtonToModifierKey(button);
if (EnableIgnoreModifiers && currentModifier != ModifierKey.None) return;
if (LastState[button] == newState) return;
//apply
//NOTE: this is not quite right. if someone held leftshift+rightshift it would be broken. seems unlikely, though.
if (button == "LeftShift")
if (currentModifier != ModifierKey.None)
{
_Modifiers &= ~ModifierKey.Shift;
if (newState)
_Modifiers |= ModifierKey.Shift;
_Modifiers |= currentModifier;
else
_Modifiers &= ~currentModifier;
}
if (button == "RightShift") { _Modifiers &= ~ModifierKey.Shift; if (newState) _Modifiers |= ModifierKey.Shift; }
if (button == "LeftControl") { _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; }
if (button == "RightControl") { _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; }
if (button == "LeftAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; }
if (button == "RightAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; }
if (UnpressState.ContainsKey(button))
{
if (newState) return;
Console.WriteLine($"Removing Unpress {button} with {nameof(newState)} {newState}");
UnpressState.Remove(button);
LastState[button] = false;
return;
}
//dont generate events for things like Ctrl+LeftControl
ModifierKey mods = _Modifiers;
if (button == "LeftShift") mods &= ~ModifierKey.Shift;
if (button == "RightShift") mods &= ~ModifierKey.Shift;
if (button == "LeftControl") mods &= ~ModifierKey.Control;
if (button == "RightControl") mods &= ~ModifierKey.Control;
if (button == "LeftAlt") mods &= ~ModifierKey.Alt;
if (button == "RightAlt") mods &= ~ModifierKey.Alt;
if (currentModifier != ModifierKey.None)
mods &= ~currentModifier;
var ie = new InputEvent
{
EventType = newState ? InputEventType.Press : InputEventType.Release,
LogicalButton = new LogicalButton(button, mods)
LogicalButton = new LogicalButton(button, mods),
Source = source
};
LastState[button] = newState;
//track the pressed events with modifiers that we send so that we can send corresponding unpresses with modifiers
//this is an interesting idea, which we may need later, but not yet.
//for example, you may see this series of events: press:ctrl+c, release:ctrl, release:c
//but you might would rather have press:ctr+c, release:ctrl+c
//but you might would rather have press:ctrl+c, release:ctrl+c
//this code relates the releases to the original presses.
//UPDATE - this is necessary for the frame advance key, which has a special meaning when it gets stuck down
//so, i am adding it as of 11-sep-2011
@ -270,32 +257,53 @@ namespace BizHawk.Client.EmuHawk
}
else
{
if (ModifierState[button] != null)
LogicalButton buttonModifierState;
if (ModifierState.TryGetValue(button, out buttonModifierState))
{
LogicalButton alreadyReleased = ie.LogicalButton;
var ieModified = new InputEvent
{
LogicalButton = (LogicalButton)ModifierState[button],
EventType = InputEventType.Release
};
if (ieModified.LogicalButton != alreadyReleased)
_NewEvents.Add(ieModified);
if (buttonModifierState != ie.LogicalButton && !IgnoreEventsNextPoll)
{
_NewEvents.Add(
new InputEvent
{
LogicalButton = buttonModifierState,
EventType = InputEventType.Release,
Source = source
});
}
ModifierState.Remove(button);
}
ModifierState[button] = null;
}
_NewEvents.Add(ie);
if (!IgnoreEventsNextPoll)
{
_NewEvents.Add(ie);
}
}
ModifierKey _Modifiers;
private static ModifierKey ButtonToModifierKey(string button)
{
switch (button)
{
case "LeftShift": return ModifierKey.Shift;
case "RightShift": return ModifierKey.Shift;
case "LeftControl": return ModifierKey.Control;
case "RightControl": return ModifierKey.Control;
case "LeftAlt": return ModifierKey.Alt;
case "RightAlt": return ModifierKey.Alt;
}
return ModifierKey.None;
}
private ModifierKey _Modifiers;
private readonly List<InputEvent> _NewEvents = new List<InputEvent>();
//do we need this?
public void ClearEvents()
{
lock (this)
{
InputEvents.Clear();
// To "clear" anything currently in the input device buffers
IgnoreEventsNextPoll = true;
}
}
@ -351,7 +359,7 @@ namespace BizHawk.Client.EmuHawk
//analyze keys
foreach (var ke in keyEvents)
HandleButton(ke.Key.ToString(), ke.Pressed);
HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard);
lock (FloatValues)
{
@ -378,7 +386,7 @@ namespace BizHawk.Client.EmuHawk
{
string xname = $"X{pad.PlayerNumber} ";
for (int b = 0; b < pad.NumButtons; b++)
HandleButton(xname + pad.ButtonName(b), pad.Pressed(b));
HandleButton(xname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad);
foreach (var sv in pad.GetFloats())
{
string n = xname + sv.Item1;
@ -394,7 +402,7 @@ namespace BizHawk.Client.EmuHawk
{
string jname = $"J{pad.PlayerNumber} ";
for (int b = 0; b < pad.NumButtons; b++)
HandleButton(jname + pad.ButtonName(b), pad.Pressed(b));
HandleButton(jname + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad);
foreach (var sv in pad.GetFloats())
{
string n = jname + sv.Item1;
@ -423,11 +431,11 @@ namespace BizHawk.Client.EmuHawk
FloatValues["WMouse Y"] = P.Y;
var B = System.Windows.Forms.Control.MouseButtons;
HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0);
HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0);
HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0);
HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0);
HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0);
HandleButton("WMouse L", (B & System.Windows.Forms.MouseButtons.Left) != 0, InputFocus.Mouse);
HandleButton("WMouse C", (B & System.Windows.Forms.MouseButtons.Middle) != 0, InputFocus.Mouse);
HandleButton("WMouse R", (B & System.Windows.Forms.MouseButtons.Right) != 0, InputFocus.Mouse);
HandleButton("WMouse 1", (B & System.Windows.Forms.MouseButtons.XButton1) != 0, InputFocus.Mouse);
HandleButton("WMouse 2", (B & System.Windows.Forms.MouseButtons.XButton2) != 0, InputFocus.Mouse);
}
else
{
@ -439,22 +447,26 @@ namespace BizHawk.Client.EmuHawk
//HandleButton("WMouse 1", false);
//HandleButton("WMouse 2", false);
}
}
//WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING.
bool swallow = !GlobalWin.MainForm.AllowInput(false);
foreach (var ie in _NewEvents)
if (_NewEvents.Count != 0)
{
//events are swallowed in some cases:
if (ie.LogicalButton.Alt && !GlobalWin.MainForm.AllowInput(true))
{ }
else if (ie.EventType == InputEventType.Press && swallow)
{ }
else
//WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING.
AllowInput allowInput = GlobalWin.MainForm.AllowInput(false);
foreach (var ie in _NewEvents)
{
//events are swallowed in some cases:
if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie))
continue;
if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie))
continue;
EnqueueEvent(ie);
}
}
IgnoreEventsNextPoll = false;
} //lock(this)
//arbitrary selection of polling frequency:
@ -462,6 +474,11 @@ namespace BizHawk.Client.EmuHawk
}
}
private static bool ShouldSwallow(AllowInput allowInput, InputEvent inputEvent)
{
return allowInput == AllowInput.None || (allowInput == AllowInput.OnlyController && inputEvent.Source != InputFocus.Pad);
}
public void StartListeningForFloatEvents()
{
lock (FloatValues)
@ -500,42 +517,39 @@ namespace BizHawk.Client.EmuHawk
}
//returns the next Press event, if available. should be useful
public string GetNextBindEvent()
public string GetNextBindEvent(ref InputEvent lastPress)
{
//this whole process is intimately involved with the data structures, which can conflict with the input thread.
lock (this)
{
if (InputEvents.Count == 0) return null;
if (!GlobalWin.MainForm.AllowInput(false)) return null;
AllowInput allowInput = GlobalWin.MainForm.AllowInput(false);
//we only listen to releases for input binding, because we need to distinguish releases of pure modifierkeys from modified keys
//wait for the first release after a press to complete input binding, because we need to distinguish pure modifierkeys from modified keys
//if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl
//if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl
//so its the first unpress we need to listen for
//but in the 2nd example the unpresses will be swapped if ctrl is released first, so we'll take the last press before the release
while (InputEvents.Count != 0)
{
var ie = DequeueEvent();
InputEvent ie = DequeueEvent();
//as a special perk, we'll accept escape immediately
if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape")
goto ACCEPT;
if (ShouldSwallow(allowInput, ie)) continue;
if (ie.EventType == InputEventType.Press) continue;
if (ie.EventType == InputEventType.Press)
{
lastPress = ie;
//don't allow presses to directly complete binding except escape which we'll accept as a special perk
if (ie.LogicalButton.Button != "Escape")
continue;
}
else if (lastPress == null) continue;
ACCEPT:
Console.WriteLine("Bind Event: {0} ", ie);
foreach (var kvp in LastState)
if (kvp.Value)
{
Console.WriteLine($"Unpressing {kvp.Key}");
UnpressState[kvp.Key] = true;
}
Console.WriteLine("Bind Event: {0} ", lastPress);
InputEvents.Clear();
return ie.LogicalButton.ToString();
return lastPress.LogicalButton.ToString();
}
return null;
@ -545,16 +559,6 @@ namespace BizHawk.Client.EmuHawk
//controls whether modifier keys will be ignored as key press events
//this should be used by hotkey binders, but we may want modifier key events
//to get triggered in the main form
public bool EnableIgnoreModifiers = false;
//sets a key as unpressed for the binding system
public void BindUnpress(System.Windows.Forms.Keys key)
{
//only validated for Return
string keystr = key.ToString();
UnpressState[keystr] = true;
LastState[keystr] = true;
}
public volatile bool EnableIgnoreModifiers = false;
}
}

View File

@ -60,9 +60,9 @@ namespace BizHawk.Client.EmuHawk
foreach (var e in events)
{
foreach (var k in e.PressedKeys)
_eventList.Add(new KeyEvent { Key = k, Pressed = true });
_eventList.Add(new KeyEvent { Key = KeyboardMapping.Handle(k), Pressed = true });
foreach (var k in e.ReleasedKeys)
_eventList.Add(new KeyEvent { Key = k, Pressed = false });
_eventList.Add(new KeyEvent { Key = KeyboardMapping.Handle(k), Pressed = false });
}
}

View File

@ -0,0 +1,416 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using BizHawk.Client.Common;
using SlimDX.DirectInput;
namespace BizHawk.Client.EmuHawk
{
internal static class KeyboardMapping
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
private const uint MAPVK_VSC_TO_VK_EX = 0x03;
public static Key Handle(Key key)
{
if (!Global.Config.HandleAlternateKeyboardLayouts) return key;
ScanCode inputScanCode = SlimDXScanCodeMap[(int)key];
Keys virtualKey = (Keys)MapVirtualKey((uint)inputScanCode, MAPVK_VSC_TO_VK_EX);
ScanCode standardScanCode = GetStandardScanCode(virtualKey);
if (standardScanCode == 0)
standardScanCode = inputScanCode;
return ScanCodeToSlimDXKey[standardScanCode];
}
private static ScanCode GetStandardScanCode(Keys virtualKey)
{
switch (virtualKey)
{
case Keys.Escape: return ScanCode.Escape;
case Keys.D1: return ScanCode.D1;
case Keys.D2: return ScanCode.D2;
case Keys.D3: return ScanCode.D3;
case Keys.D4: return ScanCode.D4;
case Keys.D5: return ScanCode.D5;
case Keys.D6: return ScanCode.D6;
case Keys.D7: return ScanCode.D7;
case Keys.D8: return ScanCode.D8;
case Keys.D9: return ScanCode.D9;
case Keys.D0: return ScanCode.D0;
case Keys.OemMinus: return ScanCode.Minus;
case Keys.Oemplus: return ScanCode.Equals;
case Keys.Back: return ScanCode.Back;
case Keys.Tab: return ScanCode.Tab;
case Keys.Q: return ScanCode.Q;
case Keys.W: return ScanCode.W;
case Keys.E: return ScanCode.E;
case Keys.R: return ScanCode.R;
case Keys.T: return ScanCode.T;
case Keys.Y: return ScanCode.Y;
case Keys.U: return ScanCode.U;
case Keys.I: return ScanCode.I;
case Keys.O: return ScanCode.O;
case Keys.P: return ScanCode.P;
case Keys.OemOpenBrackets: return ScanCode.LBracket;
case Keys.OemCloseBrackets: return ScanCode.RBracket;
case Keys.Return: return ScanCode.Return;
case Keys.LControlKey: return ScanCode.LControl;
case Keys.A: return ScanCode.A;
case Keys.S: return ScanCode.S;
case Keys.D: return ScanCode.D;
case Keys.F: return ScanCode.F;
case Keys.G: return ScanCode.G;
case Keys.H: return ScanCode.H;
case Keys.J: return ScanCode.J;
case Keys.K: return ScanCode.K;
case Keys.L: return ScanCode.L;
case Keys.OemSemicolon: return ScanCode.Semicolon;
case Keys.OemQuotes: return ScanCode.Apostrophe;
case Keys.Oemtilde: return ScanCode.Grave;
case Keys.LShiftKey: return ScanCode.LShift;
case Keys.OemPipe: return ScanCode.Backslash;
case Keys.Z: return ScanCode.Z;
case Keys.X: return ScanCode.X;
case Keys.C: return ScanCode.C;
case Keys.V: return ScanCode.V;
case Keys.B: return ScanCode.B;
case Keys.N: return ScanCode.N;
case Keys.M: return ScanCode.M;
case Keys.Oemcomma: return ScanCode.Comma;
case Keys.OemPeriod: return ScanCode.Period;
case Keys.OemQuestion: return ScanCode.Slash;
case Keys.RShiftKey: return ScanCode.RShift;
case Keys.Multiply: return ScanCode.Multiply;
case Keys.LMenu: return ScanCode.LMenu;
case Keys.Space: return ScanCode.Space;
case Keys.Capital: return ScanCode.Capital;
case Keys.F1: return ScanCode.F1;
case Keys.F2: return ScanCode.F2;
case Keys.F3: return ScanCode.F3;
case Keys.F4: return ScanCode.F4;
case Keys.F5: return ScanCode.F5;
case Keys.F6: return ScanCode.F6;
case Keys.F7: return ScanCode.F7;
case Keys.F8: return ScanCode.F8;
case Keys.F9: return ScanCode.F9;
case Keys.F10: return ScanCode.F10;
case Keys.NumLock: return ScanCode.NumLock;
case Keys.Scroll: return ScanCode.Scroll;
case Keys.Subtract: return ScanCode.Subtract;
case Keys.Add: return ScanCode.Add;
case Keys.OemBackslash: return ScanCode.Oem_102;
case Keys.F11: return ScanCode.F11;
case Keys.F12: return ScanCode.F12;
case Keys.F13: return ScanCode.F13;
case Keys.F14: return ScanCode.F14;
case Keys.F15: return ScanCode.F15;
}
return 0;
}
private enum ScanCode
{
Escape = 0x01,
D1 = 0x02,
D2 = 0x03,
D3 = 0x04,
D4 = 0x05,
D5 = 0x06,
D6 = 0x07,
D7 = 0x08,
D8 = 0x09,
D9 = 0x0A,
D0 = 0x0B,
Minus = 0x0C,
Equals = 0x0D,
Back = 0x0E,
Tab = 0x0F,
Q = 0x10,
W = 0x11,
E = 0x12,
R = 0x13,
T = 0x14,
Y = 0x15,
U = 0x16,
I = 0x17,
O = 0x18,
P = 0x19,
LBracket = 0x1A,
RBracket = 0x1B,
Return = 0x1C,
LControl = 0x1D,
A = 0x1E,
S = 0x1F,
D = 0x20,
F = 0x21,
G = 0x22,
H = 0x23,
J = 0x24,
K = 0x25,
L = 0x26,
Semicolon = 0x27,
Apostrophe = 0x28,
Grave = 0x29,
LShift = 0x2A,
Backslash = 0x2B,
Z = 0x2C,
X = 0x2D,
C = 0x2E,
V = 0x2F,
B = 0x30,
N = 0x31,
M = 0x32,
Comma = 0x33,
Period = 0x34,
Slash = 0x35,
RShift = 0x36,
Multiply = 0x37,
LMenu = 0x38,
Space = 0x39,
Capital = 0x3A,
F1 = 0x3B,
F2 = 0x3C,
F3 = 0x3D,
F4 = 0x3E,
F5 = 0x3F,
F6 = 0x40,
F7 = 0x41,
F8 = 0x42,
F9 = 0x43,
F10 = 0x44,
NumLock = 0x45,
Scroll = 0x46,
NumPad7 = 0x47,
NumPad8 = 0x48,
NumPad9 = 0x49,
Subtract = 0x4A,
NumPad4 = 0x4B,
NumPad5 = 0x4C,
NumPad6 = 0x4D,
Add = 0x4E,
NumPad1 = 0x4F,
NumPad2 = 0x50,
NumPad3 = 0x51,
NumPad0 = 0x52,
Decimal = 0x53,
Oem_102 = 0x56,
F11 = 0x57,
F12 = 0x58,
F13 = 0x64,
F14 = 0x65,
F15 = 0x66,
Kana = 0x70,
Abnt_C1 = 0x73,
Convert = 0x79,
NoConvert = 0x7B,
Yen = 0x7D,
Abnt_C2 = 0x7E,
NumPadEquals = 0x8D,
PrevTrack = 0x90,
AT = 0x91,
Colon = 0x92,
Underline = 0x93,
Kanji = 0x94,
Stop = 0x95,
AX = 0x96,
Unlabeled = 0x97,
NextTrack = 0x99,
NumPadEnter = 0x9C,
RControl = 0x9D,
Mute = 0xA0,
Calculator = 0xA1,
PlayPause = 0xA2,
MediaStop = 0xA4,
VolumeDown = 0xAE,
VolumeUp = 0xB0,
WebHome = 0xB2,
NumPadComma = 0xB3,
Divide = 0xB5,
SysRq = 0xB7,
RMenu = 0xB8,
Pause = 0xC5,
Home = 0xC7,
Up = 0xC8,
Prior = 0xC9,
Left = 0xCB,
Right = 0xCD,
End = 0xCF,
Down = 0xD0,
Next = 0xD1,
Insert = 0xD2,
Delete = 0xD3,
LWin = 0xDB,
RWin = 0xDC,
Apps = 0xDD,
Power = 0xDE,
Sleep = 0xDF,
Wake = 0xE3,
WebSearch = 0xE5,
WebFavorites = 0xE6,
WebRefresh = 0xE7,
WebStop = 0xE8,
WebForward = 0xE9,
WebBack = 0xEA,
MyComputer = 0xEB,
Mail = 0xEC,
MediaSelect = 0xED
}
private static readonly ScanCode[] SlimDXScanCodeMap = new ScanCode[]
{
ScanCode.D0, // 0
ScanCode.D1, // 1
ScanCode.D2, // 2
ScanCode.D3, // 3
ScanCode.D4, // 4
ScanCode.D5, // 5
ScanCode.D6, // 6
ScanCode.D7, // 7
ScanCode.D8, // 8
ScanCode.D9, // 9
ScanCode.A, // 10
ScanCode.B, // 11
ScanCode.C, // 12
ScanCode.D, // 13
ScanCode.E, // 14
ScanCode.F, // 15
ScanCode.G, // 16
ScanCode.H, // 17
ScanCode.I, // 18
ScanCode.J, // 19
ScanCode.K, // 20
ScanCode.L, // 21
ScanCode.M, // 22
ScanCode.N, // 23
ScanCode.O, // 24
ScanCode.P, // 25
ScanCode.Q, // 26
ScanCode.R, // 27
ScanCode.S, // 28
ScanCode.T, // 29
ScanCode.U, // 30
ScanCode.V, // 31
ScanCode.W, // 32
ScanCode.X, // 33
ScanCode.Y, // 34
ScanCode.Z, // 35
ScanCode.Abnt_C1, // 36
ScanCode.Abnt_C2, // 37
ScanCode.Apostrophe, // 38
ScanCode.Apps, // 39
ScanCode.AT, // 40
ScanCode.AX, // 41
ScanCode.Back, // 42
ScanCode.Backslash, // 43
ScanCode.Calculator, // 44
ScanCode.Capital, // 45
ScanCode.Colon, // 46
ScanCode.Comma, // 47
ScanCode.Convert, // 48
ScanCode.Delete, // 49
ScanCode.Down, // 50
ScanCode.End, // 51
ScanCode.Equals, // 52
ScanCode.Escape, // 53
ScanCode.F1, // 54
ScanCode.F2, // 55
ScanCode.F3, // 56
ScanCode.F4, // 57
ScanCode.F5, // 58
ScanCode.F6, // 59
ScanCode.F7, // 60
ScanCode.F8, // 61
ScanCode.F9, // 62
ScanCode.F10, // 63
ScanCode.F11, // 64
ScanCode.F12, // 65
ScanCode.F13, // 66
ScanCode.F14, // 67
ScanCode.F15, // 68
ScanCode.Grave, // 69
ScanCode.Home, // 70
ScanCode.Insert, // 71
ScanCode.Kana, // 72
ScanCode.Kanji, // 73
ScanCode.LBracket, // 74
ScanCode.LControl, // 75
ScanCode.Left, // 76
ScanCode.LMenu, // 77
ScanCode.LShift, // 78
ScanCode.LWin, // 79
ScanCode.Mail, // 80
ScanCode.MediaSelect, // 81
ScanCode.MediaStop, // 82
ScanCode.Minus, // 83
ScanCode.Mute, // 84
ScanCode.MyComputer, // 85
ScanCode.NextTrack, // 86
ScanCode.NoConvert, // 87
ScanCode.NumLock, // 88
ScanCode.NumPad0, // 89
ScanCode.NumPad1, // 90
ScanCode.NumPad2, // 91
ScanCode.NumPad3, // 92
ScanCode.NumPad4, // 93
ScanCode.NumPad5, // 94
ScanCode.NumPad6, // 95
ScanCode.NumPad7, // 96
ScanCode.NumPad8, // 97
ScanCode.NumPad9, // 98
ScanCode.NumPadComma, // 99
ScanCode.NumPadEnter, // 100
ScanCode.NumPadEquals, // 101
ScanCode.Subtract, // 102
ScanCode.Decimal, // 103
ScanCode.Add, // 104
ScanCode.Divide, // 105
ScanCode.Multiply, // 106
ScanCode.Oem_102, // 107
ScanCode.Next, // 108
ScanCode.Prior, // 109
ScanCode.Pause, // 110
ScanCode.Period, // 111
ScanCode.PlayPause, // 112
ScanCode.Power, // 113
ScanCode.PrevTrack, // 114
ScanCode.RBracket, // 115
ScanCode.RControl, // 116
ScanCode.Return, // 117
ScanCode.Right, // 118
ScanCode.RMenu, // 119
ScanCode.RShift, // 120
ScanCode.RWin, // 121
ScanCode.Scroll, // 122
ScanCode.Semicolon, // 123
ScanCode.Slash, // 124
ScanCode.Sleep, // 125
ScanCode.Space, // 126
ScanCode.Stop, // 127
ScanCode.SysRq, // 128
ScanCode.Tab, // 129
ScanCode.Underline, // 130
ScanCode.Unlabeled, // 131
ScanCode.Up, // 132
ScanCode.VolumeDown, // 133
ScanCode.VolumeUp, // 134
ScanCode.Wake, // 135
ScanCode.WebBack, // 136
ScanCode.WebFavorites, // 137
ScanCode.WebForward, // 138
ScanCode.WebHome, // 139
ScanCode.WebRefresh, // 140
ScanCode.WebSearch, // 141
ScanCode.WebStop, // 142
ScanCode.Yen, // 143
0 // 144
};
private static readonly Dictionary<ScanCode, Key> ScanCodeToSlimDXKey =
SlimDXScanCodeMap
.Select((n, i) => new { Value = n, Index = i })
.ToDictionary(n => n.Value, n => (Key)n.Index);
}
}

View File

@ -1,4 +1,6 @@
namespace BizHawk.Client.EmuHawk
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk
{
partial class LogWindow
{
@ -34,7 +36,7 @@
this.buttonCopy = new System.Windows.Forms.Button();
this.buttonCopyAll = new System.Windows.Forms.Button();
this.AddToGameDbBtn = new System.Windows.Forms.Button();
this.virtualListView1 = new BizHawk.Client.EmuHawk.VirtualListView();
this.virtualListView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
@ -118,23 +120,20 @@
//
// virtualListView1
//
this.virtualListView1.BlazingFast = false;
this.virtualListView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1});
this.virtualListView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.virtualListView1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.virtualListView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.virtualListView1.ItemCount = 0;
this.virtualListView1.VirtualListSize = 0;
this.virtualListView1.Location = new System.Drawing.Point(0, 0);
this.virtualListView1.Name = "virtualListView1";
this.virtualListView1.SelectAllInProgress = false;
this.virtualListView1.selectedItem = -1;
this.virtualListView1.Size = new System.Drawing.Size(675, 367);
this.virtualListView1.TabIndex = 8;
this.virtualListView1.UseCompatibleStateImageBehavior = false;
this.virtualListView1.View = System.Windows.Forms.View.Details;
this.virtualListView1.VirtualMode = true;
this.virtualListView1.QueryItemText += new BizHawk.Client.EmuHawk.QueryItemTextHandler(this.virtualListView1_QueryItemText);
this.virtualListView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(this.virtualListView1_QueryItemText);
this.virtualListView1.ClientSizeChanged += new System.EventHandler(this.virtualListView1_ClientSizeChanged);
this.virtualListView1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.virtualListView1_KeyDown);
//
@ -163,7 +162,7 @@
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.Button btnClear;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private VirtualListView virtualListView1;
private System.Windows.Forms.ListView virtualListView1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.Button buttonCopy;
private System.Windows.Forms.Button buttonCopyAll;

View File

@ -5,7 +5,6 @@ using System.IO;
using System.Text;
using System.Windows.Forms;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Client.Common;
@ -40,7 +39,7 @@ namespace BizHawk.Client.EmuHawk
var ss = report.Split('\n');
foreach (var s in ss)
dlg.Lines.Add(s.TrimEnd('\r'));
dlg.virtualListView1.ItemCount = ss.Length;
dlg.virtualListView1.VirtualListSize = ss.Length;
dlg.Text = title;
dlg.btnClear.Visible = false;
dlg.ShowDialog(parent);
@ -55,7 +54,7 @@ namespace BizHawk.Client.EmuHawk
if (!string.IsNullOrWhiteSpace(s))
{
Lines.Add(s.TrimEnd('\r'));
virtualListView1.ItemCount++;
virtualListView1.VirtualListSize++;
}
}
}
@ -63,7 +62,7 @@ namespace BizHawk.Client.EmuHawk
private void btnClear_Click(object sender, EventArgs e)
{
Lines.Clear();
virtualListView1.ItemCount = 0;
virtualListView1.VirtualListSize = 0;
virtualListView1.SelectedIndices.Clear();
}
@ -99,9 +98,9 @@ namespace BizHawk.Client.EmuHawk
}
}
private void virtualListView1_QueryItemText(int item, int subItem, out string text)
private void virtualListView1_QueryItemText(object sender, RetrieveVirtualItemEventArgs e)
{
text = Lines[item];
e.Item = new ListViewItem(Lines[e.ItemIndex]);
}
private void virtualListView1_ClientSizeChanged(object sender, EventArgs e)

File diff suppressed because it is too large Load Diff

View File

@ -6,21 +6,18 @@ using System.Collections.Generic;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.IEmulatorExtensions;
using BizHawk.Emulation.Cores.Atari.A7800Hawk;
using BizHawk.Emulation.Cores.Calculators;
using BizHawk.Emulation.Cores.ColecoVision;
using BizHawk.Emulation.Cores.Nintendo.NES;
using BizHawk.Emulation.Cores.Nintendo.SubNESHawk;
using BizHawk.Emulation.Cores.Nintendo.N64;
using BizHawk.Emulation.Cores.Nintendo.SNES;
using BizHawk.Emulation.Cores.Nintendo.SNES9X;
using BizHawk.Emulation.Cores.PCEngine;
using BizHawk.Emulation.Cores.Sega.MasterSystem;
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.CustomControls;
using BizHawk.Client.EmuHawk.WinFormExtensions;
using BizHawk.Client.EmuHawk.ToolExtensions;
using BizHawk.Emulation.Cores.Computers.AppleII;
@ -309,6 +306,7 @@ namespace BizHawk.Client.EmuHawk
private void OpenRomMenuItem_Click(object sender, EventArgs e)
{
AdvancedLoader = AdvancedRomLoaderType.None;
OpenRom();
}
@ -320,7 +318,9 @@ namespace BizHawk.Client.EmuHawk
return;
}
if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchNoGame)
AdvancedLoader = oac.Result;
if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchNoGame)
{
var argsNoGame = new LoadRomArgs
{
@ -334,15 +334,20 @@ namespace BizHawk.Client.EmuHawk
var filter = RomFilter;
if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchGame)
if (AdvancedLoader == AdvancedRomLoaderType.LibretroLaunchGame)
{
args.OpenAdvanced = new OpenAdvanced_Libretro();
filter = oac.SuggestedExtensionFilter;
}
else if (oac.Result == OpenAdvancedChooser.Command.ClassicLaunchGame)
else if (AdvancedLoader == AdvancedRomLoaderType.ClassicLaunchGame)
{
args.OpenAdvanced = new OpenAdvanced_OpenRom();
}
else if (AdvancedLoader == AdvancedRomLoaderType.MAMELaunchGame)
{
args.OpenAdvanced = new OpenAdvanced_MAME();
filter = "MAME Arcade ROMs (*.zip)|*.zip";
}
else
{
throw new InvalidOperationException("Automatic Alpha Sanitizer");
@ -468,8 +473,8 @@ namespace BizHawk.Client.EmuHawk
{
var result = MessageBox.Show(
this,
"Thanks for using Bizhawk! The emulation core you have selected " +
"is currently BETA-status. We appreciate your help in testing Bizhawk. " +
"Thanks for using BizHawk! The emulation core you have selected " +
"is currently BETA-status. We appreciate your help in testing BizHawk. " +
"You can record a movie on this core if you'd like to, but expect to " +
"encounter bugs and sync problems. Continue?", "BizHawk", MessageBoxButtons.YesNo);
@ -478,55 +483,10 @@ namespace BizHawk.Client.EmuHawk
return;
}
}
else if (Emulator is Snes9x)
if (!EmuHawkUtil.EnsureCoreIsAccurate(Emulator))
{
var box = new MsgBox(
"While the Snes9x core is faster, it is not nearly as accurate as bsnes. \nIt is recommended that you switch to the bsnes core for movie recording\nSwitch to bsnes?",
"Accuracy Warning",
MessageBoxIcon.Warning);
box.SetButtons(
new[] { "Switch", "Continue" },
new[] { DialogResult.Yes, DialogResult.Cancel });
box.MaximumSize = new Size(475, 350);
box.SetMessageToAutoSize();
var result = box.ShowDialog();
if (result == DialogResult.Yes)
{
Global.Config.SNES_InSnes9x = false;
RebootCore();
}
else if (result == DialogResult.Cancel)
{
// Do nothing and allow the user to continue to record the movie
}
}
else if (Emulator is QuickNES) // This is unsustainable :( But mixing the logic together is even worse, this needs to be rethought
{
var box = new MsgBox(
"While the QuickNes core is faster, it is not nearly as accurate as NesHawk. \nIt is recommended that you switch to the NesHawk core for movie recording\nSwitch to NesHawk?",
"Accuracy Warning",
MessageBoxIcon.Warning);
box.SetButtons(
new[] { "Switch", "Continue" },
new[] { DialogResult.Yes, DialogResult.Cancel });
box.MaximumSize = new Size(475, 350);
box.SetMessageToAutoSize();
var result = box.ShowDialog();
if (result == DialogResult.Yes)
{
Global.Config.NES_InQuickNES = false;
RebootCore();
}
else if (result == DialogResult.Cancel)
{
// Do nothing and allow the user to continue to record the movie
}
// Inaccurate core but allow the user to continue anyway
}
new RecordMovie(Emulator).ShowDialog();
@ -659,7 +619,7 @@ namespace BizHawk.Client.EmuHawk
private void RecordAVMenuItem_Click(object sender, EventArgs e)
{
RecordAv(null, null); // force unattended, but allow tradtional setup
RecordAv(null, null); // force unattended, but allow traditional setup
}
private void StopAVMenuItem_Click(object sender, EventArgs e)
@ -1024,9 +984,8 @@ namespace BizHawk.Client.EmuHawk
private void FirmwaresMenuItem_Click(object sender, EventArgs e)
{
if (e is RomLoader.RomErrorArgs)
if (e is RomLoader.RomErrorArgs args)
{
var args = (RomLoader.RomErrorArgs)e;
var result = new FirmwaresConfig(true, args.RomPath).ShowDialog();
args.Retry = result == DialogResult.Retry;
}
@ -1446,7 +1405,7 @@ namespace BizHawk.Client.EmuHawk
externalToolToolStripMenuItem.DropDownItems.Add(item);
}
if (externalToolToolStripMenuItem.DropDownItems.Count == 0)
{
externalToolToolStripMenuItem.DropDownItems.Add("None");
@ -1455,7 +1414,6 @@ namespace BizHawk.Client.EmuHawk
private void ExperimentalToolsSubMenu_DropDownOpened(object sender, EventArgs e)
{
AutoHawkMenuItem.Enabled = GlobalWin.Tools.IsAvailable<AutoHawk>();
NewHexEditorMenuItem.Enabled = GlobalWin.Tools.IsAvailable<NewHexEditor>();
}
@ -1475,7 +1433,7 @@ namespace BizHawk.Client.EmuHawk
if (OSTailoredCode.CurrentOS != OSTailoredCode.DistinctOS.Windows)
{
// this is apparently needed for weird mono-forms-on-different-thread issues
// dont do .Show() within Load<T>() for RamSearch - instead put an instance of it here on MainForm, then show here
// don't do .Show() within Load<T>() for RamSearch - instead put an instance of it here on MainForm, then show here
// the mono winforms implementation is.... weird and buggy
ramSearch.Show();
}
@ -1552,11 +1510,6 @@ namespace BizHawk.Client.EmuHawk
new BatchRun().ShowDialog();
}
private void AutoHawkMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<AutoHawk>();
}
private void NewHexEditorMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<NewHexEditor>();
@ -1585,7 +1538,7 @@ namespace BizHawk.Client.EmuHawk
VSControlsMenuItem.Enabled =
VSSettingsMenuItem.Enabled =
Emulator is NES && ((NES)Emulator).IsVS;
Emulator is NES nes && nes.IsVS;
NESSoundChannelsMenuItem.Enabled = GlobalWin.Tools.IsAvailable<NESSoundConfig>();
MovieSettingsMenuItem.Enabled = Emulator is NES && !Global.MovieSession.Movie.IsActive;
@ -1661,7 +1614,7 @@ namespace BizHawk.Client.EmuHawk
private void VsSettingsMenuItem_Click(object sender, EventArgs e)
{
if (Emulator is NES && ((NES)Emulator).IsVS)
if (Emulator is NES nes && nes.IsVS)
{
new NesVsSettings().ShowHawkDialog();
}
@ -1678,7 +1631,7 @@ namespace BizHawk.Client.EmuHawk
private void VsInsertCoinP1MenuItem_Click(object sender, EventArgs e)
{
if (Emulator is NES && ((NES)Emulator).IsVS)
if (Emulator is NES nes && nes.IsVS)
{
if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished)
{
@ -1690,7 +1643,7 @@ namespace BizHawk.Client.EmuHawk
private void VsInsertCoinP2MenuItem_Click(object sender, EventArgs e)
{
if (Emulator is NES && ((NES)Emulator).IsVS)
if (Emulator is NES nes && nes.IsVS)
{
if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished)
{
@ -1702,7 +1655,7 @@ namespace BizHawk.Client.EmuHawk
private void VsServiceSwitchMenuItem_Click(object sender, EventArgs e)
{
if (Emulator is NES && ((NES)Emulator).IsVS)
if (Emulator is NES nes && nes.IsVS)
{
if (!Global.MovieSession.Movie.IsPlaying || Global.MovieSession.Movie.IsFinished)
{
@ -1842,7 +1795,7 @@ namespace BizHawk.Client.EmuHawk
SMSDisplayOverscanMenuItem.Visible =
Global.Game.System == "SMS" || Global.Game.System == "SG";
SMSOverclockMenuItem.Visible =
SMSForceStereoMenuItem.Visible =
SMSdisplayToolStripMenuItem.Visible =
@ -2013,7 +1966,7 @@ namespace BizHawk.Client.EmuHawk
s.ControllerType = "Sports Pad";
PutCoreSyncSettings(s);
}
private void SMSControllerKeyboardToolStripMenuItem_Click(object sender, EventArgs e)
{
var s = ((SMS)Emulator).GetSyncSettings();
@ -2119,7 +2072,7 @@ namespace BizHawk.Client.EmuHawk
{
GBPrefs.DoGBPrefsDialog(this);
}
else // sameboy
else // SameBoy
{
GenericCoreConfig.DoDialog(this, "Gameboy Settings");
}
@ -2149,6 +2102,11 @@ namespace BizHawk.Client.EmuHawk
#region GBA
private void GBACoreSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "Gameboy Advance Settings");
}
private void GbaGpuViewerMenuItem_Click(object sender, EventArgs e)
{
GlobalWin.Tools.Load<GBAGPUView>();
@ -2168,14 +2126,8 @@ namespace BizHawk.Client.EmuHawk
private void GBACoreSelectionSubMenu_DropDownOpened(object sender, EventArgs e)
{
GBAmGBAMenuItem.Checked = Global.Config.GBA_UsemGBA == true;
GBAVBANextMenuItem.Checked = Global.Config.GBA_UsemGBA == false;
}
private void GbaWithmGBAMenuItem_Click(object sender, EventArgs e)
{
Global.Config.GBA_UsemGBA ^= true;
FlagNeedsReboot();
GBAmGBAMenuItem.Checked = Global.Config.GBA_UsemGBA;
GBAVBANextMenuItem.Checked = !Global.Config.GBA_UsemGBA;
}
#endregion
@ -2256,6 +2208,11 @@ namespace BizHawk.Client.EmuHawk
SNESOptions.DoSettingsDialog(this);
}
private void Snes9xSettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "Snes9x Settings");
}
#endregion
#region Coleco
@ -2317,7 +2274,7 @@ namespace BizHawk.Client.EmuHawk
}
else
{
// Do nothing, Reboot is being flagged already if they chaned anything
// Do nothing, Reboot is being flagged already if they changed anything
}
}
else
@ -2443,7 +2400,7 @@ namespace BizHawk.Client.EmuHawk
#region Wondersawn
private void WondersawnSettingsMenuItem_Click(object sender, EventArgs e)
private void WonderSwanSettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "WonderSwan Settings");
}
@ -2469,9 +2426,8 @@ namespace BizHawk.Client.EmuHawk
{
AppleDisksSubMenu.DropDownItems.Clear();
if (Emulator is AppleII)
if (Emulator is AppleII appleII)
{
var appleII = (AppleII)Emulator;
for (int i = 0; i < appleII.DiskCount; i++)
{
var menuItem = new ToolStripMenuItem
@ -2508,9 +2464,8 @@ namespace BizHawk.Client.EmuHawk
{
C64DisksSubMenu.DropDownItems.Clear();
if (Emulator is C64)
if (Emulator is C64 c64)
{
var c64 = (C64)Emulator;
for (int i = 0; i < c64.DiskCount; i++)
{
var menuItem = new ToolStripMenuItem
@ -2540,7 +2495,7 @@ namespace BizHawk.Client.EmuHawk
#region Intv
private void IntvSubMenu_DropDownOpened(object sender, EventArgs e)
private void IntVSubMenu_DropDownOpened(object sender, EventArgs e)
{
IntVControllerSettingsMenuItem.Enabled = !Global.MovieSession.Movie.IsActive;
}
@ -2550,260 +2505,271 @@ namespace BizHawk.Client.EmuHawk
new IntvControllerSettings().ShowDialog();
}
#endregion
#endregion
#region ZXSpectrum
#region VirtualBoy
private void VirtualBoySettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "VirtualBoy Settings");
}
private void zXSpectrumToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
{
#endregion
}
#region NeoGeoPocket
private void preferencesToolStripMenuItem4_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "ZXSpectrum Settings");
}
private void NeoGeoSettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "NeoPop Settings");
}
private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumJoystickSettings().ShowDialog();
}
#endregion
private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumCoreEmulationSettings().ShowDialog();
}
#region PC-FX
private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumNonSyncSettings().ShowDialog();
}
private void PCFXSettingsMenuItem_Click(object sender, EventArgs e)
{
GenericCoreConfig.DoDialog(this, "PC-FX Settings");
}
private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumAudioSettings().ShowDialog();
}
#endregion
private void ZXSpectrumPokeMemoryMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumPokeMemory().ShowDialog();
}
#region ZXSpectrum
private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e)
{
if (Emulator is ZXSpectrum)
{
ZXSpectrumTapesSubMenu.Enabled = ((ZXSpectrum)Emulator)._tapeInfo.Count > 0;
ZXSpectrumDisksSubMenu.Enabled = ((ZXSpectrum)Emulator)._diskInfo.Count > 0;
}
}
private void ZXSpectrumControllerConfigurationMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumJoystickSettings().ShowDialog();
}
private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e)
{
ZXSpectrumTapesSubMenu.DropDownItems.Clear();
private void ZXSpectrumCoreEmulationSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumCoreEmulationSettings().ShowDialog();
}
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
private void ZXSpectrumNonSyncSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumNonSyncSettings().ShowDialog();
}
if (Emulator is ZXSpectrum)
{
var speccy = (ZXSpectrum)Emulator;
var currSel = speccy._machine.TapeMediaIndex;
private void ZXSpectrumAudioSettingsMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumAudioSettings().ShowDialog();
}
for (int i = 0; i < speccy._tapeInfo.Count; i++)
{
string name = speccy._tapeInfo[i].Name;
private void ZXSpectrumPokeMemoryMenuItem_Click(object sender, EventArgs e)
{
new ZXSpectrumPokeMemory().ShowDialog();
}
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = currSel == i
};
private void ZXSpectrumMediaMenuItem_DropDownOpened(object sender, EventArgs e)
{
if (Emulator is ZXSpectrum)
{
ZXSpectrumTapesSubMenu.Enabled = ((ZXSpectrum)Emulator)._tapeInfo.Count > 0;
ZXSpectrumDisksSubMenu.Enabled = ((ZXSpectrum)Emulator)._diskInfo.Count > 0;
}
}
int dummy = i;
menuItem.Click += (o, ev) =>
{
speccy._machine.TapeMediaIndex = dummy;
};
items.Add(menuItem);
}
}
ZXSpectrumTapesSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e)
{
ZXSpectrumDisksSubMenu.DropDownItems.Clear();
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
if (Emulator is ZXSpectrum)
{
var speccy = (ZXSpectrum)Emulator;
var currSel = speccy._machine.DiskMediaIndex;
for (int i = 0; i < speccy._diskInfo.Count; i++)
{
string name = speccy._diskInfo[i].Name;
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = currSel == i
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
speccy._machine.DiskMediaIndex = dummy;
};
items.Add(menuItem);
}
}
ZXSpectrumDisksSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog zxSnapExpDialog = new SaveFileDialog();
zxSnapExpDialog.RestoreDirectory = true;
zxSnapExpDialog.Title = "EXPERIMENTAL - Export 3rd party snapshot formats";
zxSnapExpDialog.DefaultExt = "szx";
zxSnapExpDialog.Filter = "ZX-State files (*.szx)|*.szx";
zxSnapExpDialog.SupportMultiDottedExtensions = true;
try
{
var res = zxSnapExpDialog.ShowDialog();
if (res == DialogResult.OK)
{
var speccy = (ZXSpectrum)Emulator;
var snap = speccy.GetSZXSnapshot();
File.WriteAllBytes(zxSnapExpDialog.FileName, snap);
//File.WriteAllText(zxSnapExpDialog.FileName, snap);
}
}
catch (Exception ex)
{
var ee = ex;
}
}
#endregion
#region AmstradCPC
private void amstradCPCCoreEmulationSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCCoreEmulationSettings().ShowDialog();
}
private void AmstradCPCAudioSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCAudioSettings().ShowDialog();
}
private void AmstradCPCPokeMemoryToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCPokeMemory().ShowDialog();
}
private void AmstradCPCMediaToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
{
if (Emulator is AmstradCPC)
{
AmstradCPCTapesSubMenu.Enabled = ((AmstradCPC)Emulator)._tapeInfo.Count > 0;
AmstradCPCDisksSubMenu.Enabled = ((AmstradCPC)Emulator)._diskInfo.Count > 0;
}
}
private void AmstradCPCTapesSubMenu_DropDownOpened(object sender, EventArgs e)
{
AmstradCPCTapesSubMenu.DropDownItems.Clear();
private void ZXSpectrumTapesSubMenu_DropDownOpened(object sender, EventArgs e)
{
ZXSpectrumTapesSubMenu.DropDownItems.Clear();
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
if (Emulator is AmstradCPC)
{
var ams = (AmstradCPC)Emulator;
var currSel = ams._machine.TapeMediaIndex;
if (Emulator is ZXSpectrum speccy)
{
var tapeMediaIndex = speccy._machine.TapeMediaIndex;
for (int i = 0; i < ams._tapeInfo.Count; i++)
{
string name = ams._tapeInfo[i].Name;
for (int i = 0; i < speccy._tapeInfo.Count; i++)
{
string name = speccy._tapeInfo[i].Name;
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = currSel == i
};
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = tapeMediaIndex == i
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
ams._machine.TapeMediaIndex = dummy;
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
speccy._machine.TapeMediaIndex = dummy;
};
items.Add(menuItem);
}
}
}
ZXSpectrumTapesSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void ZXSpectrumDisksSubMenu_DropDownOpened(object sender, EventArgs e)
{
ZXSpectrumDisksSubMenu.DropDownItems.Clear();
var items = new List<ToolStripMenuItem>();
if (Emulator is ZXSpectrum speccy)
{
var diskMediaIndex = speccy._machine.DiskMediaIndex;
for (int i = 0; i < speccy._diskInfo.Count; i++)
{
string name = speccy._diskInfo[i].Name;
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = diskMediaIndex == i
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
speccy._machine.DiskMediaIndex = dummy;
};
items.Add(menuItem);
}
}
ZXSpectrumDisksSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void ZXSpectrumExportSnapshotMenuItemMenuItem_Click(object sender, EventArgs e)
{
var zxSnapExpDialog = new SaveFileDialog
{
RestoreDirectory = true
, Title = "EXPERIMENTAL - Export 3rd party snapshot formats"
, DefaultExt = "szx"
, Filter = "ZX-State files (*.szx)|*.szx"
, SupportMultiDottedExtensions = true
};
try
{
var res = zxSnapExpDialog.ShowDialog();
if (res == DialogResult.OK)
{
var speccy = (ZXSpectrum)Emulator;
var snap = speccy.GetSZXSnapshot();
File.WriteAllBytes(zxSnapExpDialog.FileName, snap);
}
}
catch (Exception ex)
{
var ee = ex;
}
}
#endregion
#region AmstradCPC
private void amstradCPCCoreEmulationSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCCoreEmulationSettings().ShowDialog();
}
private void AmstradCPCAudioSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCAudioSettings().ShowDialog();
}
private void AmstradCPCPokeMemoryToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCPokeMemory().ShowDialog();
}
private void AmstradCPCMediaToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
{
if (Emulator is AmstradCPC)
{
AmstradCPCTapesSubMenu.Enabled = ((AmstradCPC)Emulator)._tapeInfo.Count > 0;
AmstradCPCDisksSubMenu.Enabled = ((AmstradCPC)Emulator)._diskInfo.Count > 0;
}
}
private void AmstradCPCTapesSubMenu_DropDownOpened(object sender, EventArgs e)
{
AmstradCPCTapesSubMenu.DropDownItems.Clear();
var items = new List<ToolStripMenuItem>();
if (Emulator is AmstradCPC ams)
{
var tapeMediaIndex = ams._machine.TapeMediaIndex;
for (int i = 0; i < ams._tapeInfo.Count; i++)
{
string name = ams._tapeInfo[i].Name;
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = tapeMediaIndex == i
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
ams._machine.TapeMediaIndex = dummy;
};
items.Add(menuItem);
}
}
AmstradCPCTapesSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void AmstradCPCDisksSubMenu_DropDownOpened(object sender, EventArgs e)
{
private void AmstradCPCDisksSubMenu_DropDownOpened(object sender, EventArgs e)
{
AmstradCPCDisksSubMenu.DropDownItems.Clear();
List<ToolStripMenuItem> items = new List<ToolStripMenuItem>();
var items = new List<ToolStripMenuItem>();
if (Emulator is AmstradCPC)
{
var ams = (AmstradCPC)Emulator;
var currSel = ams._machine.DiskMediaIndex;
if (Emulator is AmstradCPC ams)
{
var diskMediaIndex = ams._machine.DiskMediaIndex;
for (int i = 0; i < ams._diskInfo.Count; i++)
{
string name = ams._diskInfo[i].Name;
for (int i = 0; i < ams._diskInfo.Count; i++)
{
string name = ams._diskInfo[i].Name;
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = currSel == i
};
var menuItem = new ToolStripMenuItem
{
Name = $"{i}_{name}",
Text = $"{i}: {name}",
Checked = diskMediaIndex == i
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
ams._machine.DiskMediaIndex = dummy;
};
int dummy = i;
menuItem.Click += (o, ev) =>
{
ams._machine.DiskMediaIndex = dummy;
};
items.Add(menuItem);
}
}
}
AmstradCPCDisksSubMenu.DropDownItems.AddRange(items.ToArray());
}
private void AmstradCPCNonSyncSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCNonSyncSettings().ShowDialog();
}
private void AmstradCPCNonSyncSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
new AmstradCPCNonSyncSettings().ShowDialog();
}
#endregion
#endregion
#region Help
#region Help
private void HelpSubMenu_DropDownOpened(object sender, EventArgs e)
private void HelpSubMenu_DropDownOpened(object sender, EventArgs e)
{
FeaturesMenuItem.Visible = VersionInfo.DeveloperBuild;
}
@ -2853,9 +2819,9 @@ namespace BizHawk.Client.EmuHawk
showMenuVisible = true; // need to always be able to restore this as an emergency measure
}
if (argParser._chromeless)
if (_argParser._chromeless)
{
showMenuVisible = true; // I decided this was always possible in chromeless mode, we'll see what they think
showMenuVisible = true; // I decided this was always possible in chrome-less mode, we'll see what they think
}
ShowMenuContextMenuItem.Visible =
@ -3297,7 +3263,7 @@ namespace BizHawk.Client.EmuHawk
{
try
{
FormDragDrop_Internal(sender, e);
_FormDragDrop_internal(sender, e);
}
catch (Exception ex)
{
@ -3305,113 +3271,6 @@ namespace BizHawk.Client.EmuHawk
}
}
private void FormDragDrop_Internal(object sender, DragEventArgs e)
{
_FormDragDrop_internal(sender, e);
/*
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
var isLua = false;
foreach (var path in filePaths)
{
var extension = Path.GetExtension(path);
if (extension != null && extension.ToUpper() == ".LUA")
{
OpenLuaConsole();
if (GlobalWin.Tools.Has<LuaConsole>())
{
GlobalWin.Tools.LuaConsole.LoadLuaFile(path);
}
isLua = true;
}
}
if (isLua)
{
return;
}
var ext = Path.GetExtension(filePaths[0]) ?? "";
if (ext.ToUpper() == ".LUASES")
{
OpenLuaConsole();
if (GlobalWin.Tools.Has<LuaConsole>())
{
GlobalWin.Tools.LuaConsole.LoadLuaSession(filePaths[0]);
}
}
else if (MovieService.IsValidMovieExtension(ext))
{
if (Emulator.IsNull())
{
OpenRom();
}
if (Emulator.IsNull())
{
return;
}
StartNewMovie(MovieService.Get(filePaths[0]), false);
}
else if (ext.ToUpper() == ".STATE")
{
LoadState(filePaths[0], Path.GetFileName(filePaths[0]));
}
else if (ext.ToUpper() == ".CHT")
{
Global.CheatList.Load(filePaths[0], false);
GlobalWin.Tools.Load<Cheats>();
}
else if (ext.ToUpper() == ".WCH")
{
GlobalWin.Tools.LoadRamWatch(true);
(GlobalWin.Tools.Get<RamWatch>() as RamWatch).LoadWatchFile(new FileInfo(filePaths[0]), false);
}
else if (ext.ToUpper() == ".CDL" && Emulator is PCEngine)
{
GlobalWin.Tools.Load<CDL>();
(GlobalWin.Tools.Get<CDL>() as CDL).LoadFile(filePaths[0]);
}
else if (MovieImport.IsValidMovieExtension(Path.GetExtension(filePaths[0])))
{
if (Emulator.IsNull())
{
OpenRom();
}
if (Emulator.IsNull())
{
return;
}
// tries to open a legacy movie format by importing it
string errorMsg;
string warningMsg;
var movie = MovieImport.ImportFile(filePaths[0], out errorMsg, out warningMsg);
if (!string.IsNullOrEmpty(errorMsg))
{
MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
// fix movie extension to something palatable for these purposes.
// for instance, something which doesnt clobber movies you already may have had.
// i'm evenly torn between this, and a file in %TEMP%, but since we dont really have a way to clean up this tempfile, i choose this:
StartNewMovie(movie, false);
}
GlobalWin.OSD.AddMessage(warningMsg);
}
else
{
var args = new LoadRomArgs();
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] };
LoadRom(filePaths[0], args);
}
*/
}
#endregion
}
}

View File

@ -347,7 +347,10 @@ namespace BizHawk.Client.EmuHawk
type = " (on)";
}
Global.CheatList.ToList().ForEach(x => x.Toggle());
foreach (var x in Global.CheatList)
{
x.Toggle();
}
GlobalWin.OSD.AddMessage($"Cheats toggled{type}");
}

File diff suppressed because it is too large Load Diff

View File

@ -28,147 +28,184 @@
/// </summary>
private void InitializeComponent()
{
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnLibretroLaunchNoGame = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.txtLibretroCore = new System.Windows.Forms.TextBox();
this.btnLibretroLaunchGame = new System.Windows.Forms.Button();
this.btnSetLibretroCore = new System.Windows.Forms.Button();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.btnClassicLaunchGame = new System.Windows.Forms.Button();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// label3
//
this.label3.Location = new System.Drawing.Point(6, 25);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(250, 29);
this.label3.TabIndex = 5;
this.label3.Text = "Load a rom with the classic BizHawk autodetection method. But why not just use Op" +
"en Rom?";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(6, 26);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 13);
this.label2.TabIndex = 3;
this.label2.Text = "Current Core:";
//
// btnLibretroLaunchNoGame
//
this.btnLibretroLaunchNoGame.Location = new System.Drawing.Point(217, 50);
this.btnLibretroLaunchNoGame.Name = "btnLibretroLaunchNoGame";
this.btnLibretroLaunchNoGame.Size = new System.Drawing.Size(102, 23);
this.btnLibretroLaunchNoGame.TabIndex = 1;
this.btnLibretroLaunchNoGame.Text = "Launch No Game";
this.btnLibretroLaunchNoGame.UseVisualStyleBackColor = true;
this.btnLibretroLaunchNoGame.Click += new System.EventHandler(this.btnLibretroLaunchNoGame_Click);
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(370, 176);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 2;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.txtLibretroCore);
this.groupBox2.Controls.Add(this.btnLibretroLaunchGame);
this.groupBox2.Controls.Add(this.btnSetLibretroCore);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.btnLibretroLaunchNoGame);
this.groupBox2.Location = new System.Drawing.Point(12, 12);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(433, 81);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Libretro";
//
// txtLibretroCore
//
this.txtLibretroCore.AllowDrop = true;
this.txtLibretroCore.Location = new System.Drawing.Point(81, 23);
this.txtLibretroCore.Name = "txtLibretroCore";
this.txtLibretroCore.ReadOnly = true;
this.txtLibretroCore.Size = new System.Drawing.Size(314, 20);
this.txtLibretroCore.TabIndex = 6;
this.txtLibretroCore.DragDrop += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragDrop);
this.txtLibretroCore.DragEnter += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragEnter);
//
// btnLibretroLaunchGame
//
this.btnLibretroLaunchGame.Location = new System.Drawing.Point(325, 50);
this.btnLibretroLaunchGame.Name = "btnLibretroLaunchGame";
this.btnLibretroLaunchGame.Size = new System.Drawing.Size(102, 23);
this.btnLibretroLaunchGame.TabIndex = 5;
this.btnLibretroLaunchGame.Text = "Launch Game";
this.btnLibretroLaunchGame.UseVisualStyleBackColor = true;
this.btnLibretroLaunchGame.Click += new System.EventHandler(this.btnLibretroLaunchGame_Click);
//
// btnSetLibretroCore
//
this.btnSetLibretroCore.AutoSize = true;
this.btnSetLibretroCore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnSetLibretroCore.Location = new System.Drawing.Point(401, 21);
this.btnSetLibretroCore.Name = "btnSetLibretroCore";
this.btnSetLibretroCore.Size = new System.Drawing.Size(26, 23);
this.btnSetLibretroCore.TabIndex = 4;
this.btnSetLibretroCore.Text = "...";
this.btnSetLibretroCore.UseVisualStyleBackColor = true;
this.btnSetLibretroCore.Click += new System.EventHandler(this.btnSetLibretroCore_Click);
//
// groupBox3
//
this.groupBox3.Controls.Add(this.btnClassicLaunchGame);
this.groupBox3.Controls.Add(this.label3);
this.groupBox3.Location = new System.Drawing.Point(12, 99);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(277, 100);
this.groupBox3.TabIndex = 6;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "BizHawk Classic";
//
// btnClassicLaunchGame
//
this.btnClassicLaunchGame.Location = new System.Drawing.Point(169, 71);
this.btnClassicLaunchGame.Name = "btnClassicLaunchGame";
this.btnClassicLaunchGame.Size = new System.Drawing.Size(102, 23);
this.btnClassicLaunchGame.TabIndex = 6;
this.btnClassicLaunchGame.Text = "Launch Game";
this.btnClassicLaunchGame.UseVisualStyleBackColor = true;
this.btnClassicLaunchGame.Click += new System.EventHandler(this.btnClassicLaunchGame_Click);
//
// OpenAdvancedChooser
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(457, 208);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.btnCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "OpenAdvancedChooser";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Open Advanced";
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.ResumeLayout(false);
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnLibretroLaunchNoGame = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.txtLibretroCore = new System.Windows.Forms.TextBox();
this.btnLibretroLaunchGame = new System.Windows.Forms.Button();
this.btnSetLibretroCore = new System.Windows.Forms.Button();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.btnClassicLaunchGame = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.btnMAMELaunchGame = new System.Windows.Forms.Button();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// label3
//
this.label3.Location = new System.Drawing.Point(6, 25);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(198, 45);
this.label3.TabIndex = 5;
this.label3.Text = "Load a ROM with the classic BizHawk autodetection method. But why not just use Op" +
"en Rom?";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(6, 26);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(69, 13);
this.label2.TabIndex = 3;
this.label2.Text = "Current Core:";
//
// btnLibretroLaunchNoGame
//
this.btnLibretroLaunchNoGame.Location = new System.Drawing.Point(217, 50);
this.btnLibretroLaunchNoGame.Name = "btnLibretroLaunchNoGame";
this.btnLibretroLaunchNoGame.Size = new System.Drawing.Size(102, 23);
this.btnLibretroLaunchNoGame.TabIndex = 1;
this.btnLibretroLaunchNoGame.Text = "Launch No Game";
this.btnLibretroLaunchNoGame.UseVisualStyleBackColor = true;
this.btnLibretroLaunchNoGame.Click += new System.EventHandler(this.btnLibretroLaunchNoGame_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(370, 221);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 2;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.txtLibretroCore);
this.groupBox2.Controls.Add(this.btnLibretroLaunchGame);
this.groupBox2.Controls.Add(this.btnSetLibretroCore);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.btnLibretroLaunchNoGame);
this.groupBox2.Location = new System.Drawing.Point(12, 12);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(433, 81);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Libretro";
//
// txtLibretroCore
//
this.txtLibretroCore.AllowDrop = true;
this.txtLibretroCore.Location = new System.Drawing.Point(81, 23);
this.txtLibretroCore.Name = "txtLibretroCore";
this.txtLibretroCore.ReadOnly = true;
this.txtLibretroCore.Size = new System.Drawing.Size(314, 20);
this.txtLibretroCore.TabIndex = 6;
this.txtLibretroCore.DragDrop += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragDrop);
this.txtLibretroCore.DragEnter += new System.Windows.Forms.DragEventHandler(this.txtLibretroCore_DragEnter);
//
// btnLibretroLaunchGame
//
this.btnLibretroLaunchGame.Location = new System.Drawing.Point(325, 50);
this.btnLibretroLaunchGame.Name = "btnLibretroLaunchGame";
this.btnLibretroLaunchGame.Size = new System.Drawing.Size(102, 23);
this.btnLibretroLaunchGame.TabIndex = 5;
this.btnLibretroLaunchGame.Text = "Launch Game";
this.btnLibretroLaunchGame.UseVisualStyleBackColor = true;
this.btnLibretroLaunchGame.Click += new System.EventHandler(this.btnLibretroLaunchGame_Click);
//
// btnSetLibretroCore
//
this.btnSetLibretroCore.AutoSize = true;
this.btnSetLibretroCore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnSetLibretroCore.Location = new System.Drawing.Point(401, 21);
this.btnSetLibretroCore.Name = "btnSetLibretroCore";
this.btnSetLibretroCore.Size = new System.Drawing.Size(26, 23);
this.btnSetLibretroCore.TabIndex = 4;
this.btnSetLibretroCore.Text = "...";
this.btnSetLibretroCore.UseVisualStyleBackColor = true;
this.btnSetLibretroCore.Click += new System.EventHandler(this.btnSetLibretroCore_Click);
//
// groupBox3
//
this.groupBox3.Controls.Add(this.btnClassicLaunchGame);
this.groupBox3.Controls.Add(this.label3);
this.groupBox3.Location = new System.Drawing.Point(235, 99);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(210, 100);
this.groupBox3.TabIndex = 6;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "BizHawk Classic";
//
// btnClassicLaunchGame
//
this.btnClassicLaunchGame.Location = new System.Drawing.Point(102, 71);
this.btnClassicLaunchGame.Name = "btnClassicLaunchGame";
this.btnClassicLaunchGame.Size = new System.Drawing.Size(102, 23);
this.btnClassicLaunchGame.TabIndex = 6;
this.btnClassicLaunchGame.Text = "Launch Game";
this.btnClassicLaunchGame.UseVisualStyleBackColor = true;
this.btnClassicLaunchGame.Click += new System.EventHandler(this.btnClassicLaunchGame_Click);
//
// groupBox1
//
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.btnMAMELaunchGame);
this.groupBox1.Location = new System.Drawing.Point(13, 99);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(216, 100);
this.groupBox1.TabIndex = 7;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "MAME Arcade";
//
// label1
//
this.label1.Location = new System.Drawing.Point(6, 25);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(204, 42);
this.label1.TabIndex = 1;
this.label1.Text = "Load .zip archive as MAME Arcade ROM (do not unzip)";
this.label1.Click += new System.EventHandler(this.btnMAMELaunchGame_Click);
//
// btnMAMELaunchGame
//
this.btnMAMELaunchGame.Location = new System.Drawing.Point(108, 71);
this.btnMAMELaunchGame.Name = "btnMAMELaunchGame";
this.btnMAMELaunchGame.Size = new System.Drawing.Size(102, 23);
this.btnMAMELaunchGame.TabIndex = 0;
this.btnMAMELaunchGame.Text = "Launch Game";
this.btnMAMELaunchGame.UseVisualStyleBackColor = true;
this.btnMAMELaunchGame.Click += new System.EventHandler(this.btnMAMELaunchGame_Click);
//
// OpenAdvancedChooser
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(457, 256);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.btnCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "OpenAdvancedChooser";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Open Advanced";
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
@ -182,6 +219,9 @@
private System.Windows.Forms.TextBox txtLibretroCore;
private System.Windows.Forms.Button btnLibretroLaunchGame;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Button btnClassicLaunchGame;
private System.Windows.Forms.Button btnClassicLaunchGame;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btnMAMELaunchGame;
}
}

View File

@ -7,7 +7,8 @@ using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores;
using BizHawk.Emulation.Cores.Libretro;
using BizHawk.Client.Common;
@ -20,13 +21,7 @@ namespace BizHawk.Client.EmuHawk
{
MainForm mainForm;
public enum Command
{
RetroLaunchNoGame, RetroLaunchGame,
ClassicLaunchGame
}
public Command Result;
public AdvancedRomLoaderType Result;
public string SuggestedExtensionFilter;
public OpenAdvancedChooser(MainForm mainForm)
@ -131,21 +126,28 @@ namespace BizHawk.Client.EmuHawk
filter = MainForm.FormatFilter(args.ToArray());
SuggestedExtensionFilter = filter;
Result = Command.RetroLaunchGame;
Result = AdvancedRomLoaderType.LibretroLaunchGame;
DialogResult = DialogResult.OK;
Close();
}
private void btnMAMELaunchGame_Click(object sender, EventArgs e)
{
Result = AdvancedRomLoaderType.MAMELaunchGame;
DialogResult = DialogResult.OK;
Close();
}
private void btnClassicLaunchGame_Click(object sender, EventArgs e)
{
Result = Command.ClassicLaunchGame;
Result = AdvancedRomLoaderType.ClassicLaunchGame;
DialogResult = DialogResult.OK;
Close();
}
private void btnLibretroLaunchNoGame_Click(object sender, EventArgs e)
{
Result = Command.RetroLaunchNoGame;
Result = AdvancedRomLoaderType.LibretroLaunchNoGame;
DialogResult = DialogResult.OK;
Close();
}
@ -170,6 +172,6 @@ namespace BizHawk.Client.EmuHawk
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
Global.Config.LibretroCore = filePaths[0];
RefreshLibretroCore(false);
}
}
}
}

View File

@ -30,36 +30,33 @@ namespace BizHawk.Client.EmuHawk
//try loading libraries we know we'll need
//something in the winforms, etc. code below will cause .net to popup a missing msvcr100.dll in case that one's missing
//but oddly it lets us proceed and we'll then catch it here
var d3dx9 = libLoader.LoadPlatformSpecific("d3dx9_43.dll");
var vc2015 = libLoader.LoadPlatformSpecific("vcruntime140.dll");
var vc2012 = libLoader.LoadPlatformSpecific("msvcr120.dll"); //TODO - check version?
var vc2010 = libLoader.LoadPlatformSpecific("msvcr100.dll"); //TODO - check version?
var vc2010p = libLoader.LoadPlatformSpecific("msvcp100.dll");
var fail = vc2015 == IntPtr.Zero || vc2010 == IntPtr.Zero || vc2012 == IntPtr.Zero || vc2010p == IntPtr.Zero;
var warn = d3dx9 == IntPtr.Zero;
if (fail || warn)
var d3dx9 = libLoader.LoadOrNull("d3dx9_43.dll");
var vc2015 = libLoader.LoadOrNull("vcruntime140.dll");
var vc2012 = libLoader.LoadOrNull("msvcr120.dll"); //TODO - check version?
var vc2010 = libLoader.LoadOrNull("msvcr100.dll"); //TODO - check version?
var vc2010p = libLoader.LoadOrNull("msvcp100.dll");
var reqPresent = vc2015.HasValue && vc2010.HasValue && vc2012.HasValue && vc2010p.HasValue;
var optPresent = d3dx9.HasValue;
if (!reqPresent || !optPresent)
{
var alertLines = new[]
{
"[ OK ] .NET CLR (You wouldn't even get here without it)",
$"[{(d3dx9 == IntPtr.Zero ? "WARN" : " OK ")}] Direct3d 9",
$"[{(vc2010 == IntPtr.Zero || vc2010p == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2010 SP1 Runtime",
$"[{(vc2012 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2012 Runtime",
$"[{(vc2015 == IntPtr.Zero ? "FAIL" : " OK ")}] Visual C++ 2015 Runtime"
$"[{(d3dx9.HasValue ? " OK " : "WARN")}] Direct3d 9",
$"[{(vc2010.HasValue && vc2010p.HasValue ? " OK " : "FAIL")}] Visual C++ 2010 SP1 Runtime",
$"[{(vc2012.HasValue ? " OK " : "FAIL")}] Visual C++ 2012 Runtime",
$"[{(vc2015.HasValue ? " OK " : "FAIL")}] Visual C++ 2015 Runtime"
};
var box = new BizHawk.Client.EmuHawk.CustomControls.PrereqsAlert(!fail)
var box = new CustomControls.PrereqsAlert(reqPresent)
{
textBox1 = { Text = string.Concat("\n", alertLines) }
textBox1 = { Text = string.Join(Environment.NewLine, alertLines) }
};
box.ShowDialog();
if (fail) System.Diagnostics.Process.GetCurrentProcess().Kill();
if (!reqPresent) Process.GetCurrentProcess().Kill();
}
libLoader.FreePlatformSpecific(d3dx9);
libLoader.FreePlatformSpecific(vc2015);
libLoader.FreePlatformSpecific(vc2012);
libLoader.FreePlatformSpecific(vc2010);
libLoader.FreePlatformSpecific(vc2010p);
foreach (var p in new[] { d3dx9, vc2015, vc2012, vc2010, vc2010p })
if (p.HasValue) libLoader.FreeByPtr(p.Value);
// this will look in subdirectory "dll" to load pinvoked stuff
var dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll");
@ -115,7 +112,7 @@ namespace BizHawk.Client.EmuHawk
}
}
BizHawk.Common.TempFileManager.Start();
TempFileManager.Start();
#if true // switch to if false for system-agnostic glory!
switch (EXE_PROJECT.OSTailoredCode.CurrentOS)
@ -147,8 +144,8 @@ namespace BizHawk.Client.EmuHawk
Global.Config.ResolveDefaults();
BizHawk.Client.Common.StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk;
BizHawk.Client.Common.StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE;
StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk;
StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE;
// super hacky! this needs to be done first. still not worth the trouble to make this system fully proper
if (Array.Exists(args, arg => arg.StartsWith("--gdi", StringComparison.InvariantCultureIgnoreCase)))

View File

@ -19,7 +19,7 @@ namespace BizHawk.Client.EmuHawk.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@ -120,6 +120,16 @@ namespace BizHawk.Client.EmuHawk.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ArcadeController {
get {
object obj = ResourceManager.GetObject("ArcadeController", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -870,6 +880,16 @@ namespace BizHawk.Client.EmuHawk.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap mame {
get {
object obj = ResourceManager.GetObject("mame", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -1479,6 +1499,16 @@ namespace BizHawk.Client.EmuHawk.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap StopButton {
get {
object obj = ResourceManager.GetObject("StopButton", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -1563,4 +1563,13 @@
<data name="MoveTop" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\MoveTop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="StopButton" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\images\StopButton.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ArcadeController" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\images\ControllerImages\ArcadeController.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="mame" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\images\mame.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -9,6 +9,6 @@ namespace BizHawk.Client.EmuHawk
void ApplyVolumeSettings(double volume);
int MaxSamplesDeficit { get; }
int CalculateSamplesNeeded();
void WriteSamples(short[] samples, int sampleCount);
void WriteSamples(short[] samples, int sampleOffset, int sampleCount);
}
}

View File

@ -42,7 +42,7 @@ namespace BizHawk.Client.EmuHawk
public static IEnumerable<string> GetDeviceNames()
{
return DirectSound.GetDevices().Select(d => d.Description).ToList();
return DirectSound.GetDevices().Select(d => d.Description);
}
private int BufferSizeSamples { get; set; }
@ -152,12 +152,10 @@ namespace BizHawk.Client.EmuHawk
return (end - start + size) % size;
}
public void WriteSamples(short[] samples, int sampleCount)
public void WriteSamples(short[] samples, int sampleOffset, int sampleCount)
{
if (sampleCount == 0) return;
int total = sampleCount * Sound.ChannelCount;
if (total > samples.Length) { total = samples.Length; }
_deviceBuffer.Write(samples, 0, total, _actualWriteOffsetBytes, LockFlags.None);
_deviceBuffer.Write(samples, sampleOffset * Sound.ChannelCount, sampleCount * Sound.ChannelCount, _actualWriteOffsetBytes, LockFlags.None);
_actualWriteOffsetBytes = (_actualWriteOffsetBytes + (sampleCount * Sound.BlockAlign)) % BufferSizeBytes;
_filledBufferSizeBytes += sampleCount * Sound.BlockAlign;
}

View File

@ -73,7 +73,7 @@ namespace BizHawk.Client.EmuHawk
return samplesNeeded;
}
public void WriteSamples(short[] samples, int sampleCount)
public void WriteSamples(short[] samples, int sampleOffset, int sampleCount)
{
if (sampleCount == 0) return;
_remainingSamples += sampleCount;

View File

@ -17,6 +17,7 @@ namespace BizHawk.Client.EmuHawk
private int _sourceID;
private BufferPool _bufferPool;
private int _currentSamplesQueued;
private short[] _tempSampleBuffer;
public OpenALSoundOutput(Sound sound)
{
@ -94,11 +95,17 @@ namespace BizHawk.Client.EmuHawk
return samplesNeeded;
}
public void WriteSamples(short[] samples, int sampleCount)
public void WriteSamples(short[] samples, int sampleOffset, int sampleCount)
{
if (sampleCount == 0) return;
UnqueueProcessedBuffers();
int byteCount = sampleCount * Sound.BlockAlign;
if (sampleOffset != 0)
{
AllocateTempSampleBuffer(sampleCount);
Buffer.BlockCopy(samples, sampleOffset * Sound.BlockAlign, _tempSampleBuffer, 0, byteCount);
samples = _tempSampleBuffer;
}
var buffer = _bufferPool.Obtain(byteCount);
AL.BufferData(buffer.BufferID, ALFormat.Stereo16, samples, byteCount, Sound.SampleRate);
AL.SourceQueueBuffer(_sourceID, buffer.BufferID);
@ -127,6 +134,15 @@ namespace BizHawk.Client.EmuHawk
return value;
}
private void AllocateTempSampleBuffer(int sampleCount)
{
int length = sampleCount * Sound.ChannelCount;
if (_tempSampleBuffer == null || _tempSampleBuffer.Length < length)
{
_tempSampleBuffer = new short[length];
}
}
private class BufferPool : IDisposable
{
private Stack<BufferPoolItem> _availableItems = new Stack<BufferPoolItem>();

View File

@ -49,7 +49,9 @@ namespace BizHawk.Client.EmuHawk
{
using (XAudio2 device = new XAudio2())
{
return Enumerable.Range(0, device.DeviceCount).Select(n => device.GetDeviceDetails(n).DisplayName).ToList();
return Enumerable.Range(0, device.DeviceCount)
.Select(n => device.GetDeviceDetails(n).DisplayName)
.ToList(); // enumerate before local var device is disposed
}
}
@ -110,14 +112,13 @@ namespace BizHawk.Client.EmuHawk
return samplesNeeded;
}
public void WriteSamples(short[] samples, int sampleCount)
public void WriteSamples(short[] samples, int sampleOffset, int sampleCount)
{
if (sampleCount == 0) return;
_bufferPool.Release(_sourceVoice.State.BuffersQueued);
int byteCount = sampleCount * Sound.BlockAlign;
var buffer = _bufferPool.Obtain(byteCount);
if (byteCount > (samples.Length * 2)) { byteCount = samples.Length * 2; }
Buffer.BlockCopy(samples, 0, buffer.Bytes, 0, byteCount);
Buffer.BlockCopy(samples, sampleOffset * Sound.BlockAlign, buffer.Bytes, 0, byteCount);
_sourceVoice.SubmitSourceBuffer(new AudioBuffer
{
AudioBytes = byteCount,

View File

@ -16,8 +16,6 @@ namespace BizHawk.Client.EmuHawk
public const int BlockAlign = BytesPerSample * ChannelCount;
private bool _disposed;
private bool _unjamSoundThrottle;
private readonly ISoundOutput _outputDevice;
private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(); // Buffer for Sync sources
private readonly BufferedAsync _bufferedAsync = new BufferedAsync(); // Buffer for Async sources
@ -118,9 +116,8 @@ namespace BizHawk.Client.EmuHawk
// Fill device buffer with silence but leave enough room for one frame
int samplesPerFrame = (int)Math.Round(SampleRate / (double)Global.Emulator.VsyncRate());
int silenceSamples = Math.Max(samplesNeeded - samplesPerFrame, 0);
_outputDevice.WriteSamples(new short[silenceSamples * 2], silenceSamples);
_outputDevice.WriteSamples(new short[silenceSamples * 2], 0, silenceSamples);
samplesNeeded -= silenceSamples;
_unjamSoundThrottle = isUnderrun;
if (isUnderrun)
{
@ -141,14 +138,16 @@ namespace BizHawk.Client.EmuHawk
if (atten > 1) atten = 1;
_outputDevice.ApplyVolumeSettings(atten);
short[] samples;
int samplesNeeded = _outputDevice.CalculateSamplesNeeded();
int samplesProvided;
short[] samples;
int sampleOffset;
int sampleCount;
if (atten == 0)
{
samples = new short[samplesNeeded * ChannelCount];
samplesProvided = samplesNeeded;
sampleOffset = 0;
sampleCount = samplesNeeded;
_bufferedProvider.DiscardSamples();
}
@ -156,25 +155,34 @@ namespace BizHawk.Client.EmuHawk
{
if (Global.Config.SoundThrottle)
{
_outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out samplesProvided);
_outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out sampleCount);
sampleOffset = 0;
if (Global.DisableSecondaryThrottling && samplesProvided > samplesNeeded)
if (Global.DisableSecondaryThrottling && sampleCount > samplesNeeded)
{
return;
}
while (samplesProvided > samplesNeeded)
int samplesPerMs = SampleRate / 1000;
int outputThresholdMs = 20;
while (sampleCount > samplesNeeded)
{
Thread.Sleep((samplesProvided - samplesNeeded) / (SampleRate / 1000)); // Let the audio clock control sleep time
samplesNeeded = _outputDevice.CalculateSamplesNeeded();
if (_unjamSoundThrottle)
if (samplesNeeded >= outputThresholdMs * samplesPerMs)
{
//may be garbage, but what can we do?
samplesProvided = samplesNeeded;
break;
// If we were given a large enough number of samples (e.g. larger than the device's
// buffer), the device will never need that many samples no matter how long we
// wait, so we have to start splitting up the output
_outputDevice.WriteSamples(samples, sampleOffset, samplesNeeded);
sampleOffset += samplesNeeded;
sampleCount -= samplesNeeded;
}
else
{
// Let the audio clock control sleep time
Thread.Sleep(Math.Min((sampleCount - samplesNeeded) / samplesPerMs, outputThresholdMs));
}
samplesNeeded = _outputDevice.CalculateSamplesNeeded();
}
_unjamSoundThrottle = false;
}
else
{
@ -182,7 +190,8 @@ namespace BizHawk.Client.EmuHawk
{
_outputProvider.OnVolatility();
}
_outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided);
_outputProvider.GetSamples(samplesNeeded, out samples, out sampleCount);
sampleOffset = 0;
}
}
else if (_bufferedProvider == _bufferedAsync)
@ -191,14 +200,15 @@ namespace BizHawk.Client.EmuHawk
_bufferedAsync.GetSamplesAsync(samples);
samplesProvided = samplesNeeded;
sampleOffset = 0;
sampleCount = samplesNeeded;
}
else
{
return;
}
_outputDevice.WriteSamples(samples, samplesProvided);
_outputDevice.WriteSamples(samples, sampleOffset, sampleCount);
}
public static int MillisecondsToSamples(int milliseconds)

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Client.EmuHawk
{
@ -9,14 +10,14 @@ namespace BizHawk.Client.EmuHawk
public ToolAttribute(bool released, string[] supportedSystems, string[] unsupportedCores = null)
{
Released = released;
SupportedSystems = supportedSystems;
UnsupportedCores = unsupportedCores;
SupportedSystems = supportedSystems ?? Enumerable.Empty<string>();
UnsupportedCores = unsupportedCores ?? Enumerable.Empty<string>();
}
public bool Released { get; private set; }
public bool Released { get; }
public IEnumerable<string> SupportedSystems { get; private set; }
public IEnumerable<string> SupportedSystems { get; }
public IEnumerable<string> UnsupportedCores { get; private set; }
public IEnumerable<string> UnsupportedCores { get; }
}
}

View File

@ -2,42 +2,21 @@
using System.Drawing;
using System.Windows.Forms;
namespace BizHawk.Client.Common
namespace BizHawk.Client.EmuHawk
{
public static class UIHelper
{
private static readonly AutoScaleMode _autoScaleMode = AutoScaleMode.Font;
private static readonly SizeF _autoScaleBaseSize = new SizeF(6F, 13F);
private static readonly SizeF _autoScaleCurrentSize = GetCurrentAutoScaleSize(_autoScaleMode);
public static AutoScaleMode AutoScaleMode { get; } = AutoScaleMode.Font;
private static SizeF GetCurrentAutoScaleSize(AutoScaleMode autoScaleMode)
{
using (Form form = new Form())
{
form.AutoScaleMode = autoScaleMode;
return form.CurrentAutoScaleDimensions;
}
}
public static SizeF AutoScaleBaseSize { get; } = new SizeF(6F, 13F);
public static AutoScaleMode AutoScaleMode
{
get { return _autoScaleMode; }
}
public static SizeF AutoScaleCurrentSize { get; } = GetCurrentAutoScaleSize(AutoScaleMode);
public static SizeF AutoScaleBaseSize
{
get { return _autoScaleBaseSize; }
}
public static float AutoScaleFactorX { get; } = AutoScaleCurrentSize.Width / AutoScaleBaseSize.Width;
public static float AutoScaleFactorX
{
get { return _autoScaleCurrentSize.Width / _autoScaleBaseSize.Width; }
}
public static float AutoScaleFactorY { get; } = AutoScaleCurrentSize.Height / AutoScaleBaseSize.Height;
public static float AutoScaleFactorY
{
get { return _autoScaleCurrentSize.Height / _autoScaleBaseSize.Height; }
}
public static SizeF AutoScaleFactor { get; } = new SizeF(AutoScaleFactorX, AutoScaleFactorY);
public static int ScaleX(int size)
{
@ -58,5 +37,13 @@ namespace BizHawk.Client.Common
{
return new Size(ScaleX(s.Width), ScaleY(s.Height));
}
private static SizeF GetCurrentAutoScaleSize(AutoScaleMode autoScaleMode)
{
using (var form = new Form { AutoScaleMode = autoScaleMode })
{
return form.CurrentAutoScaleDimensions;
}
}
}
}

View File

@ -3,7 +3,10 @@
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
<runtime>
<loadFromRemoteSources enabled="true"/>
</runtime>
<runtime>
<loadFromRemoteSources enabled="true"/>
</runtime>
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
</configuration>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="BizHawk.Client.EmuHawk.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>

View File

@ -302,7 +302,8 @@
this.Name = "ControllerConfig";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Controller Config";
this.Load += new System.EventHandler(this.NewControllerConfig_Load);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ControllerConfig_FormClosed);
this.Load += new System.EventHandler(this.ControllerConfig_Load);
this.tabControl1.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();

View File

@ -49,7 +49,12 @@ namespace BizHawk.Client.EmuHawk
ControllerImages.Add("Apple IIe Keyboard", Properties.Resources.AppleIIKeyboard);
ControllerImages.Add("VirtualBoy Controller", Properties.Resources.VBoyController);
ControllerImages.Add("NeoGeo Portable Controller", Properties.Resources.NGPController);
ControllerImages.Add("MAME Controller", Properties.Resources.ArcadeController);
}
private ControllerConfig()
{
InitializeComponent();
}
protected override void OnActivated(EventArgs e)
@ -64,13 +69,14 @@ namespace BizHawk.Client.EmuHawk
Input.Instance.ControlInputFocus(this, Input.InputFocus.Mouse, false);
}
private ControllerConfig()
private void ControllerConfig_Load(object sender, EventArgs e)
{
InitializeComponent();
Closing += (o, e) =>
{
buttonOK.Focus(); // A very dirty hack to avoid https://code.google.com/p/bizhawk/issues/detail?id=161
};
Text = $"{_theDefinition.Name} Configuration";
}
private void ControllerConfig_FormClosed(object sender, FormClosedEventArgs e)
{
Input.Instance.ClearEvents();
}
private delegate Control PanelCreator<T>(Dictionary<string, T> settings, List<string> buttons, Size size);
@ -187,7 +193,10 @@ namespace BizHawk.Client.EmuHawk
if (Global.Emulator.SystemId == "ZXSpectrum" || Global.Emulator.SystemId == "AmstradCPC" || Global.Emulator.SystemId == "ChannelF")
return;
string tabname = (Global.Emulator.SystemId == "C64") ? "Keyboard" : "Console"; // hack
string tabname =
(Global.Emulator.SystemId == "C64") ? "Keyboard" :
(Global.Emulator.SystemId == "MAME") ? "Misc" :
"Console"; // hack
tt.TabPages.Add(tabname);
tt.TabPages[pageidx].Controls.Add(createpanel(settings, buckets[0], tt.Size));
}
@ -365,11 +374,6 @@ namespace BizHawk.Client.EmuHawk
Close();
}
private void NewControllerConfig_Load(object sender, EventArgs e)
{
Text = $"{_theDefinition.Name} Configuration";
}
private static TabControl GetTabControl(IEnumerable controls)
{
if (controls != null)

View File

@ -42,6 +42,7 @@
this.NeverAskSaveCheckbox = new System.Windows.Forms.CheckBox();
this.label2 = new System.Windows.Forms.Label();
this.AcceptBackgroundInputCheckbox = new System.Windows.Forms.CheckBox();
this.AcceptBackgroundInputControllerOnlyCheckBox = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.RunInBackgroundCheckbox = new System.Windows.Forms.CheckBox();
this.SaveWindowPositionCheckbox = new System.Windows.Forms.CheckBox();
@ -73,6 +74,7 @@
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
this.HandleAlternateKeyboardLayoutsCheckBox = new System.Windows.Forms.CheckBox();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.groupBox1.SuspendLayout();
@ -120,10 +122,12 @@
//
// tabPage1
//
this.tabPage1.Controls.Add(this.HandleAlternateKeyboardLayoutsCheckBox);
this.tabPage1.Controls.Add(this.groupBox1);
this.tabPage1.Controls.Add(this.NeverAskSaveCheckbox);
this.tabPage1.Controls.Add(this.label2);
this.tabPage1.Controls.Add(this.AcceptBackgroundInputCheckbox);
this.tabPage1.Controls.Add(this.AcceptBackgroundInputControllerOnlyCheckBox);
this.tabPage1.Controls.Add(this.label1);
this.tabPage1.Controls.Add(this.RunInBackgroundCheckbox);
this.tabPage1.Controls.Add(this.SaveWindowPositionCheckbox);
@ -144,7 +148,7 @@
this.groupBox1.Controls.Add(this.StartFullScreenCheckbox);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.SingleInstanceModeCheckbox);
this.groupBox1.Location = new System.Drawing.Point(6, 182);
this.groupBox1.Location = new System.Drawing.Point(6, 205);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(369, 140);
this.groupBox1.TabIndex = 13;
@ -215,7 +219,7 @@
this.label2.Location = new System.Drawing.Point(26, 155);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(349, 13);
this.label2.TabIndex = 9;
this.label2.TabIndex = 10;
this.label2.Text = "When this is set, the client will receive user input even when focus is lost";
//
// AcceptBackgroundInputCheckbox
@ -227,6 +231,18 @@
this.AcceptBackgroundInputCheckbox.TabIndex = 8;
this.AcceptBackgroundInputCheckbox.Text = "Accept background input";
this.AcceptBackgroundInputCheckbox.UseVisualStyleBackColor = true;
this.AcceptBackgroundInputCheckbox.CheckedChanged += new System.EventHandler(this.AcceptBackgroundInputCheckbox_CheckedChanged);
//
// AcceptBackgroundInputControllerOnlyCheckBox
//
this.AcceptBackgroundInputControllerOnlyCheckBox.AutoSize = true;
this.AcceptBackgroundInputControllerOnlyCheckBox.Enabled = false;
this.AcceptBackgroundInputControllerOnlyCheckBox.Location = new System.Drawing.Point(156, 135);
this.AcceptBackgroundInputControllerOnlyCheckBox.Name = "AcceptBackgroundInputControllerOnlyCheckBox";
this.AcceptBackgroundInputControllerOnlyCheckBox.Size = new System.Drawing.Size(117, 17);
this.AcceptBackgroundInputControllerOnlyCheckBox.TabIndex = 9;
this.AcceptBackgroundInputControllerOnlyCheckBox.Text = "From controller only";
this.AcceptBackgroundInputControllerOnlyCheckBox.UseVisualStyleBackColor = true;
//
// label1
//
@ -313,7 +329,7 @@
this.groupBox2.Margin = new System.Windows.Forms.Padding(0);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(265, 60);
this.groupBox2.TabIndex = 27;
this.groupBox2.TabIndex = 5;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "AutoSaveRAM";
//
@ -327,7 +343,7 @@
0});
this.AutosaveSRAMtextBox.Name = "AutosaveSRAMtextBox";
this.AutosaveSRAMtextBox.Size = new System.Drawing.Size(50, 20);
this.AutosaveSRAMtextBox.TabIndex = 27;
this.AutosaveSRAMtextBox.TabIndex = 5;
//
// AutosaveSRAMradioButton1
//
@ -335,7 +351,7 @@
this.AutosaveSRAMradioButton1.Location = new System.Drawing.Point(48, 33);
this.AutosaveSRAMradioButton1.Name = "AutosaveSRAMradioButton1";
this.AutosaveSRAMradioButton1.Size = new System.Drawing.Size(36, 17);
this.AutosaveSRAMradioButton1.TabIndex = 22;
this.AutosaveSRAMradioButton1.TabIndex = 2;
this.AutosaveSRAMradioButton1.TabStop = true;
this.AutosaveSRAMradioButton1.Text = "5s";
this.AutosaveSRAMradioButton1.UseVisualStyleBackColor = true;
@ -346,7 +362,7 @@
this.label8.Location = new System.Drawing.Point(202, 35);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(12, 13);
this.label8.TabIndex = 26;
this.label8.TabIndex = 6;
this.label8.Text = "s";
//
// AutosaveSRAMradioButton2
@ -355,7 +371,7 @@
this.AutosaveSRAMradioButton2.Location = new System.Drawing.Point(90, 34);
this.AutosaveSRAMradioButton2.Name = "AutosaveSRAMradioButton2";
this.AutosaveSRAMradioButton2.Size = new System.Drawing.Size(39, 17);
this.AutosaveSRAMradioButton2.TabIndex = 23;
this.AutosaveSRAMradioButton2.TabIndex = 3;
this.AutosaveSRAMradioButton2.TabStop = true;
this.AutosaveSRAMradioButton2.Text = "5m";
this.AutosaveSRAMradioButton2.UseVisualStyleBackColor = true;
@ -366,7 +382,7 @@
this.AutosaveSRAMradioButton3.Location = new System.Drawing.Point(131, 35);
this.AutosaveSRAMradioButton3.Name = "AutosaveSRAMradioButton3";
this.AutosaveSRAMradioButton3.Size = new System.Drawing.Size(14, 13);
this.AutosaveSRAMradioButton3.TabIndex = 24;
this.AutosaveSRAMradioButton3.TabIndex = 4;
this.AutosaveSRAMradioButton3.TabStop = true;
this.AutosaveSRAMradioButton3.UseVisualStyleBackColor = true;
this.AutosaveSRAMradioButton3.CheckedChanged += new System.EventHandler(this.AutosaveSRAMradioButton3_CheckedChanged);
@ -377,7 +393,7 @@
this.AutosaveSRAMCheckbox.Location = new System.Drawing.Point(6, 62);
this.AutosaveSRAMCheckbox.Name = "AutosaveSRAMCheckbox";
this.AutosaveSRAMCheckbox.Size = new System.Drawing.Size(15, 14);
this.AutosaveSRAMCheckbox.TabIndex = 21;
this.AutosaveSRAMCheckbox.TabIndex = 4;
this.AutosaveSRAMCheckbox.UseVisualStyleBackColor = true;
this.AutosaveSRAMCheckbox.CheckedChanged += new System.EventHandler(this.AutosaveSRAMCheckbox_CheckedChanged);
//
@ -397,7 +413,7 @@
this.label7.Location = new System.Drawing.Point(3, 1);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(50, 13);
this.label7.TabIndex = 2;
this.label7.TabIndex = 0;
this.label7.Text = "Lua Core";
//
// LuaInterfaceRadio
@ -406,7 +422,7 @@
this.LuaInterfaceRadio.Location = new System.Drawing.Point(4, 36);
this.LuaInterfaceRadio.Name = "LuaInterfaceRadio";
this.LuaInterfaceRadio.Size = new System.Drawing.Size(338, 17);
this.LuaInterfaceRadio.TabIndex = 1;
this.LuaInterfaceRadio.TabIndex = 2;
this.LuaInterfaceRadio.TabStop = true;
this.LuaInterfaceRadio.Text = "Lua+LuaInterface - Faster but memory leaks, use at your own risk!";
this.LuaInterfaceRadio.UseVisualStyleBackColor = true;
@ -417,7 +433,7 @@
this.NLuaRadio.Location = new System.Drawing.Point(4, 17);
this.NLuaRadio.Name = "NLuaRadio";
this.NLuaRadio.Size = new System.Drawing.Size(194, 17);
this.NLuaRadio.TabIndex = 0;
this.NLuaRadio.TabIndex = 1;
this.NLuaRadio.TabStop = true;
this.NLuaRadio.Text = "NLua+KopiLua - Reliable but slower";
this.NLuaRadio.UseVisualStyleBackColor = true;
@ -507,7 +523,7 @@
this.BackupSRamCheckbox.Location = new System.Drawing.Point(6, 39);
this.BackupSRamCheckbox.Name = "BackupSRamCheckbox";
this.BackupSRamCheckbox.Size = new System.Drawing.Size(203, 17);
this.BackupSRamCheckbox.TabIndex = 9;
this.BackupSRamCheckbox.TabIndex = 3;
this.BackupSRamCheckbox.Text = "Backup SaveRAM to .SaveRAM.bak";
this.BackupSRamCheckbox.UseVisualStyleBackColor = true;
//
@ -536,7 +552,7 @@
this.label9.Location = new System.Drawing.Point(6, 16);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(225, 13);
this.label9.TabIndex = 28;
this.label9.TabIndex = 0;
this.label9.Text = "Save SaveRAM to .AutoSaveRAM.SaveRAM";
//
// label10
@ -545,9 +561,19 @@
this.label10.Location = new System.Drawing.Point(9, 34);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(33, 13);
this.label10.TabIndex = 29;
this.label10.TabIndex = 1;
this.label10.Text = "every";
//
// HandleAlternateKeyboardLayoutsCheckBox
//
this.HandleAlternateKeyboardLayoutsCheckBox.AutoSize = true;
this.HandleAlternateKeyboardLayoutsCheckBox.Location = new System.Drawing.Point(6, 175);
this.HandleAlternateKeyboardLayoutsCheckBox.Name = "HandleAlternateKeyboardLayoutsCheckBox";
this.HandleAlternateKeyboardLayoutsCheckBox.Size = new System.Drawing.Size(255, 17);
this.HandleAlternateKeyboardLayoutsCheckBox.TabIndex = 11;
this.HandleAlternateKeyboardLayoutsCheckBox.Text = "Handle alternate keyboard layouts (e.g. Dvorak) [experimental]";
this.HandleAlternateKeyboardLayoutsCheckBox.UseVisualStyleBackColor = true;
//
// EmuHawkOptions
//
this.AcceptButton = this.OkBtn;
@ -593,6 +619,7 @@
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.CheckBox AcceptBackgroundInputCheckbox;
private System.Windows.Forms.CheckBox AcceptBackgroundInputControllerOnlyCheckBox;
private System.Windows.Forms.CheckBox NeverAskSaveCheckbox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.CheckBox SingleInstanceModeCheckbox;
@ -625,5 +652,6 @@
private System.Windows.Forms.NumericUpDown AutosaveSRAMtextBox;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.CheckBox HandleAlternateKeyboardLayoutsCheckBox;
}
}

View File

@ -49,6 +49,8 @@ namespace BizHawk.Client.EmuHawk
SaveWindowPositionCheckbox.Checked = Global.Config.SaveWindowPosition;
RunInBackgroundCheckbox.Checked = Global.Config.RunInBackground;
AcceptBackgroundInputCheckbox.Checked = Global.Config.AcceptBackgroundInput;
AcceptBackgroundInputControllerOnlyCheckBox.Checked = Global.Config.AcceptBackgroundInputControllerOnly;
HandleAlternateKeyboardLayoutsCheckBox.Checked = Global.Config.HandleAlternateKeyboardLayouts;
NeverAskSaveCheckbox.Checked = Global.Config.SupressAskSave;
SingleInstanceModeCheckbox.Checked = Global.Config.SingleInstanceMode;
@ -83,6 +85,8 @@ namespace BizHawk.Client.EmuHawk
Global.Config.SaveWindowPosition = SaveWindowPositionCheckbox.Checked;
Global.Config.RunInBackground = RunInBackgroundCheckbox.Checked;
Global.Config.AcceptBackgroundInput = AcceptBackgroundInputCheckbox.Checked;
Global.Config.AcceptBackgroundInputControllerOnly = AcceptBackgroundInputControllerOnlyCheckBox.Checked;
Global.Config.HandleAlternateKeyboardLayouts = HandleAlternateKeyboardLayoutsCheckBox.Checked;
Global.Config.SupressAskSave = NeverAskSaveCheckbox.Checked;
Global.Config.SingleInstanceMode = SingleInstanceModeCheckbox.Checked;
@ -113,6 +117,11 @@ namespace BizHawk.Client.EmuHawk
GlobalWin.OSD.AddMessage("Customizing aborted.");
}
private void AcceptBackgroundInputCheckbox_CheckedChanged(object sender, EventArgs e)
{
AcceptBackgroundInputControllerOnlyCheckBox.Enabled = AcceptBackgroundInputCheckbox.Checked;
}
private void AutosaveSRAMCheckbox_CheckedChanged(object sender, EventArgs e)
{
groupBox2.Enabled = AutosaveSRAMCheckbox.Checked;

View File

@ -228,7 +228,8 @@
this.Name = "HotkeyConfig";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Configure Hotkeys";
this.Load += new System.EventHandler(this.NewHotkeyWindow_Load);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.HotkeyConfig_FormClosed);
this.Load += new System.EventHandler(this.HotkeyConfig_Load);
this.HotkeyTabControl.ResumeLayout(false);
this.clearBtnContextMenu.ResumeLayout(false);
this.ResumeLayout(false);

View File

@ -14,11 +14,6 @@ namespace BizHawk.Client.EmuHawk
{
InitializeComponent();
Closing += (o, e) =>
{
IDB_SAVE.Focus(); // A very dirty hack to avoid https://code.google.com/p/bizhawk/issues/detail?id=161
};
tabPage1.Focus();
}
@ -34,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
Input.Instance.ControlInputFocus(this, Input.InputFocus.Mouse, false);
}
private void NewHotkeyWindow_Load(object sender, EventArgs e)
private void HotkeyConfig_Load(object sender, EventArgs e)
{
var source = new AutoCompleteStringCollection();
source.AddRange(Global.Config.HotkeyBindings.Select(x => x.DisplayName).ToArray());
@ -47,6 +42,11 @@ namespace BizHawk.Client.EmuHawk
DoFocus();
}
private void HotkeyConfig_FormClosed(object sender, FormClosedEventArgs e)
{
Input.Instance.ClearEvents();
}
private void IDB_CANCEL_Click(object sender, EventArgs e)
{
GlobalWin.OSD.AddMessage("Hotkey config aborted");
@ -72,64 +72,49 @@ namespace BizHawk.Client.EmuHawk
foreach (var w in InputWidgets)
{
var b = Global.Config.HotkeyBindings.FirstOrDefault(x => x.DisplayName == w.WidgetName);
var b = Global.Config.HotkeyBindings.First(x => x.DisplayName == w.WidgetName);
b.Bindings = w.Bindings;
}
}
private IEnumerable<InputCompositeWidget> InputWidgets
{
get
{
var widgets = new List<InputCompositeWidget>();
for (var x = 0; x < HotkeyTabControl.TabPages.Count; x++)
{
for (var y = 0; y < HotkeyTabControl.TabPages[x].Controls.Count; y++)
{
if (HotkeyTabControl.TabPages[x].Controls[y] is InputCompositeWidget)
{
widgets.Add(HotkeyTabControl.TabPages[x].Controls[y] as InputCompositeWidget);
}
}
}
return widgets;
}
}
private IEnumerable<InputCompositeWidget> InputWidgets =>
HotkeyTabControl.TabPages.Cast<TabPage>().SelectMany(tp => tp.Controls.OfType<InputCompositeWidget>());
private void DoTabs()
{
HotkeyTabControl.SuspendLayout();
HotkeyTabControl.TabPages.Clear();
// Buckets
var tabs = Global.Config.HotkeyBindings.Select(x => x.TabGroup).Distinct().ToList();
var tabs = Global.Config.HotkeyBindings.Select(x => x.TabGroup).Distinct();
foreach (var tab in tabs)
{
var _y = UIHelper.ScaleY(14);
var _x = UIHelper.ScaleX(6);
var tb = new TabPage {Name = tab, Text = tab};
var bindings = Global.Config.HotkeyBindings.Where(x => x.TabGroup == tab).OrderBy(x => x.Ordinal).ThenBy(x => x.DisplayName).ToList();
var tb = new TabPage { Name = tab, Text = tab };
var bindings = Global.Config.HotkeyBindings.Where(n => n.TabGroup == tab).OrderBy(n => n.Ordinal).ThenBy(n => n.DisplayName);
int x = UIHelper.ScaleX(6);
int y = UIHelper.ScaleY(14);
int iwOffsetX = UIHelper.ScaleX(110);
int iwOffsetY = UIHelper.ScaleY(-4);
int iwWidth = UIHelper.ScaleX(120);
tb.SuspendLayout();
foreach (var b in bindings)
{
var l = new Label
{
Text = b.DisplayName,
Location = new Point(_x, _y),
Size = new Size(iwOffsetX - UIHelper.ScaleX(2), UIHelper.ScaleY(15)),
Location = new Point(x, y),
Size = new Size(iwOffsetX - UIHelper.ScaleX(2), UIHelper.ScaleY(15))
};
var w = new InputCompositeWidget
{
Location = new Point(_x + iwOffsetX, _y + iwOffsetY),
Location = new Point(x + iwOffsetX, y + iwOffsetY),
AutoTab = AutoTabCheckBox.Checked,
Width = iwWidth,
WidgetName = b.DisplayName,
WidgetName = b.DisplayName
};
w.SetupTooltip(toolTip1, b.ToolTip);
@ -140,11 +125,11 @@ namespace BizHawk.Client.EmuHawk
tb.Controls.Add(l);
tb.Controls.Add(w);
_y += UIHelper.ScaleY(24);
if (_y > HotkeyTabControl.Height - UIHelper.ScaleY(35))
y += UIHelper.ScaleY(24);
if (y > HotkeyTabControl.Height - UIHelper.ScaleY(35))
{
_x += iwOffsetX + iwWidth + UIHelper.ScaleX(10);
_y = UIHelper.ScaleY(14);
x += iwOffsetX + iwWidth + UIHelper.ScaleX(10);
y = UIHelper.ScaleY(14);
}
}
@ -153,13 +138,16 @@ namespace BizHawk.Client.EmuHawk
tb.Controls.Add(new Label
{
Text = "Save States hotkeys operate with branches when TAStudio is engaged.",
Location = new Point(_x, _y),
Size = new Size(iwWidth + iwOffsetX, HotkeyTabControl.Height - _y),
Location = new Point(x, y),
Size = new Size(iwWidth + iwOffsetX, HotkeyTabControl.Height - y)
});
}
HotkeyTabControl.TabPages.Add(tb);
tb.ResumeLayout();
}
HotkeyTabControl.ResumeLayout();
}
private void Defaults()
@ -232,7 +220,6 @@ namespace BizHawk.Client.EmuHawk
if (w != null)
{
HotkeyTabControl.SelectTab((TabPage)w.Parent);
Input.Instance.BindUnpress(e.KeyCode);
w.Focus();
}
}

View File

@ -14,8 +14,8 @@ namespace BizHawk.Client.EmuHawk
// TODO: when binding, make sure that the new key combo is not in one of the other bindings
private readonly Timer _timer = new Timer();
private readonly List<string> _bindings = new List<string>();
private string _wasPressed = "";
private Input.InputEvent _lastPress;
public InputCompositeWidget CompositeWidget { get; set; }
@ -88,9 +88,9 @@ namespace BizHawk.Client.EmuHawk
protected override void OnEnter(EventArgs e)
{
Input.Instance.ClearEvents();
_lastPress = null;
_timer.Start();
_wasPressed = Input.Instance.GetNextBindEvent();
BackColor = Color.FromArgb(unchecked((int)0xFFC0FFFF)); // Color.LightCyan is too light on Windows 8, this is a bit darker
}
@ -102,6 +102,12 @@ namespace BizHawk.Client.EmuHawk
base.OnLeave(e);
}
protected override void OnHandleDestroyed(EventArgs e)
{
_timer.Stop();
base.OnHandleDestroyed(e);
}
private void Timer_Tick(object sender, EventArgs e)
{
ReadKeys();
@ -129,11 +135,7 @@ namespace BizHawk.Client.EmuHawk
private void ReadKeys()
{
Input.Instance.Update();
var bindingStr = Input.Instance.GetNextBindEvent();
if (!string.IsNullOrEmpty(_wasPressed) && bindingStr == _wasPressed)
{
return;
}
var bindingStr = Input.Instance.GetNextBindEvent(ref _lastPress);
if (bindingStr != null)
{
@ -171,7 +173,6 @@ namespace BizHawk.Client.EmuHawk
_bindings.Add(bindingStr);
}
_wasPressed = bindingStr;
UpdateLabel();
Increment();
}
@ -188,8 +189,6 @@ namespace BizHawk.Client.EmuHawk
{
base.OnKeyUp(e);
}
_wasPressed = "";
}
protected override void OnKeyDown(KeyEventArgs e)

View File

@ -64,7 +64,7 @@ namespace BizHawk.Client.EmuHawk
typeof(NES.NESSyncSettings.Region),
(string)RegionComboBox.SelectedItem);
List<byte> oldRam = _syncSettings.InitialWRamStatePattern?.ToList() ?? new List<byte>();
var oldRam = _syncSettings.InitialWRamStatePattern ?? new List<byte>();
if (!string.IsNullOrWhiteSpace(RamPatternOverrideBox.Text))
{

View File

@ -115,8 +115,7 @@ namespace BizHawk.Client.EmuHawk
var paths = pathCollection
.Where(p => p.System == systemId)
.OrderBy(p => p.Ordinal)
.ThenBy(p => p.Type)
.ToList();
.ThenBy(p => p.Type);
var y = UIHelper.ScaleY(14);
foreach (var path in paths)
@ -261,10 +260,10 @@ namespace BizHawk.Client.EmuHawk
private void DoRomToggle()
{
AllPathControls
.Where(c => c.Name == "ROM")
.ToList()
.ForEach(control => control.Enabled = !RecentForROMs.Checked);
foreach (var control in AllPathControls.Where(c => c.Name == "ROM"))
{
control.Enabled = !RecentForROMs.Checked;
}
}
private IEnumerable<TextBox> AllPathBoxes

View File

@ -186,7 +186,7 @@
this.label10.Location = new System.Drawing.Point(6, 20);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(40, 13);
this.label10.TabIndex = 17;
this.label10.TabIndex = 0;
this.label10.Text = "Enable";
//
// LargeStateEnabledBox
@ -195,7 +195,7 @@
this.LargeStateEnabledBox.Location = new System.Drawing.Point(9, 87);
this.LargeStateEnabledBox.Name = "LargeStateEnabledBox";
this.LargeStateEnabledBox.Size = new System.Drawing.Size(15, 14);
this.LargeStateEnabledBox.TabIndex = 16;
this.LargeStateEnabledBox.TabIndex = 11;
this.LargeStateEnabledBox.UseVisualStyleBackColor = true;
this.LargeStateEnabledBox.CheckStateChanged += new System.EventHandler(this.LargeStateEnabledBox_CheckStateChanged);
//
@ -205,7 +205,7 @@
this.MediumStateEnabledBox.Location = new System.Drawing.Point(9, 63);
this.MediumStateEnabledBox.Name = "MediumStateEnabledBox";
this.MediumStateEnabledBox.Size = new System.Drawing.Size(15, 14);
this.MediumStateEnabledBox.TabIndex = 15;
this.MediumStateEnabledBox.TabIndex = 6;
this.MediumStateEnabledBox.UseVisualStyleBackColor = true;
this.MediumStateEnabledBox.CheckStateChanged += new System.EventHandler(this.MediumStateEnabledBox_CheckStateChanged);
//
@ -215,7 +215,7 @@
this.SmallStateEnabledBox.Location = new System.Drawing.Point(9, 39);
this.SmallStateEnabledBox.Name = "SmallStateEnabledBox";
this.SmallStateEnabledBox.Size = new System.Drawing.Size(15, 14);
this.SmallStateEnabledBox.TabIndex = 14;
this.SmallStateEnabledBox.TabIndex = 1;
this.SmallStateEnabledBox.UseVisualStyleBackColor = true;
this.SmallStateEnabledBox.CheckStateChanged += new System.EventHandler(this.SmallStateEnabledBox_CheckStateChanged);
//
@ -234,7 +234,7 @@
this.LargeLabel3.Location = new System.Drawing.Point(307, 88);
this.LargeLabel3.Name = "LargeLabel3";
this.LargeLabel3.Size = new System.Drawing.Size(38, 13);
this.LargeLabel3.TabIndex = 12;
this.LargeLabel3.TabIndex = 15;
this.LargeLabel3.Text = "frames";
//
// LargeSavestateNumeric
@ -252,7 +252,7 @@
0});
this.LargeSavestateNumeric.Name = "LargeSavestateNumeric";
this.LargeSavestateNumeric.Size = new System.Drawing.Size(38, 20);
this.LargeSavestateNumeric.TabIndex = 11;
this.LargeSavestateNumeric.TabIndex = 14;
this.LargeSavestateNumeric.Value = new decimal(new int[] {
1,
0,
@ -266,7 +266,7 @@
this.LargeLabel1.Location = new System.Drawing.Point(40, 88);
this.LargeLabel1.Name = "LargeLabel1";
this.LargeLabel1.Size = new System.Drawing.Size(179, 13);
this.LargeLabel1.TabIndex = 10;
this.LargeLabel1.TabIndex = 12;
this.LargeLabel1.Text = "Large savestates (more than 100KB)";
this.LargeLabel1.Click += new System.EventHandler(this.LargeLabel1_Click);
//
@ -276,7 +276,7 @@
this.MediumLabel2.Location = new System.Drawing.Point(227, 64);
this.MediumLabel2.Name = "MediumLabel2";
this.MediumLabel2.Size = new System.Drawing.Size(33, 13);
this.MediumLabel2.TabIndex = 9;
this.MediumLabel2.TabIndex = 8;
this.MediumLabel2.Text = "every";
//
// MediumLabel3
@ -285,7 +285,7 @@
this.MediumLabel3.Location = new System.Drawing.Point(307, 64);
this.MediumLabel3.Name = "MediumLabel3";
this.MediumLabel3.Size = new System.Drawing.Size(38, 13);
this.MediumLabel3.TabIndex = 8;
this.MediumLabel3.TabIndex = 10;
this.MediumLabel3.Text = "frames";
//
// MediumSavestateNumeric
@ -303,7 +303,7 @@
0});
this.MediumSavestateNumeric.Name = "MediumSavestateNumeric";
this.MediumSavestateNumeric.Size = new System.Drawing.Size(38, 20);
this.MediumSavestateNumeric.TabIndex = 7;
this.MediumSavestateNumeric.TabIndex = 9;
this.MediumSavestateNumeric.Value = new decimal(new int[] {
1,
0,
@ -317,7 +317,7 @@
this.MediumLabel1.Location = new System.Drawing.Point(40, 64);
this.MediumLabel1.Name = "MediumLabel1";
this.MediumLabel1.Size = new System.Drawing.Size(160, 13);
this.MediumLabel1.TabIndex = 6;
this.MediumLabel1.TabIndex = 7;
this.MediumLabel1.Text = "Medium savestates (32 - 100KB)";
this.MediumLabel1.Click += new System.EventHandler(this.MediumLabel1_Click);
//
@ -327,7 +327,7 @@
this.SmallLabel2.Location = new System.Drawing.Point(227, 40);
this.SmallLabel2.Name = "SmallLabel2";
this.SmallLabel2.Size = new System.Drawing.Size(33, 13);
this.SmallLabel2.TabIndex = 5;
this.SmallLabel2.TabIndex = 3;
this.SmallLabel2.Text = "every";
//
// SmallLabel3
@ -336,7 +336,7 @@
this.SmallLabel3.Location = new System.Drawing.Point(307, 40);
this.SmallLabel3.Name = "SmallLabel3";
this.SmallLabel3.Size = new System.Drawing.Size(38, 13);
this.SmallLabel3.TabIndex = 4;
this.SmallLabel3.TabIndex = 5;
this.SmallLabel3.Text = "frames";
//
// SmallSavestateNumeric
@ -354,7 +354,7 @@
0});
this.SmallSavestateNumeric.Name = "SmallSavestateNumeric";
this.SmallSavestateNumeric.Size = new System.Drawing.Size(38, 20);
this.SmallSavestateNumeric.TabIndex = 3;
this.SmallSavestateNumeric.TabIndex = 4;
this.SmallSavestateNumeric.Value = new decimal(new int[] {
1,
0,
@ -399,7 +399,7 @@
this.MediumStateTrackbar.Minimum = 1;
this.MediumStateTrackbar.Name = "MediumStateTrackbar";
this.MediumStateTrackbar.Size = new System.Drawing.Size(186, 45);
this.MediumStateTrackbar.TabIndex = 7;
this.MediumStateTrackbar.TabIndex = 1;
this.MediumStateTrackbar.TickFrequency = 256;
this.MediumStateTrackbar.Value = 1;
this.MediumStateTrackbar.ValueChanged += new System.EventHandler(this.MediumStateTrackbar_ValueChanged);
@ -417,7 +417,7 @@
this.groupBox2.Location = new System.Drawing.Point(12, 387);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(371, 105);
this.groupBox2.TabIndex = 8;
this.groupBox2.TabIndex = 5;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "State Size Definition";
//
@ -436,7 +436,7 @@
0});
this.LargeStateUpDown.Name = "LargeStateUpDown";
this.LargeStateUpDown.Size = new System.Drawing.Size(52, 20);
this.LargeStateUpDown.TabIndex = 14;
this.LargeStateUpDown.TabIndex = 6;
this.LargeStateUpDown.Value = new decimal(new int[] {
256,
0,
@ -459,7 +459,7 @@
0});
this.MediumStateUpDown.Name = "MediumStateUpDown";
this.MediumStateUpDown.Size = new System.Drawing.Size(52, 20);
this.MediumStateUpDown.TabIndex = 13;
this.MediumStateUpDown.TabIndex = 2;
this.MediumStateUpDown.Value = new decimal(new int[] {
1,
0,
@ -473,7 +473,7 @@
this.LargeStateSizeLabel.Location = new System.Drawing.Point(312, 71);
this.LargeStateSizeLabel.Name = "LargeStateSizeLabel";
this.LargeStateSizeLabel.Size = new System.Drawing.Size(21, 13);
this.LargeStateSizeLabel.TabIndex = 12;
this.LargeStateSizeLabel.TabIndex = 7;
this.LargeStateSizeLabel.Text = "KB";
//
// label5
@ -482,7 +482,7 @@
this.label5.Location = new System.Drawing.Point(27, 63);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(34, 13);
this.label5.TabIndex = 11;
this.label5.TabIndex = 4;
this.label5.Text = "Large";
//
// LargeStateTrackbar
@ -493,7 +493,7 @@
this.LargeStateTrackbar.Minimum = 256;
this.LargeStateTrackbar.Name = "LargeStateTrackbar";
this.LargeStateTrackbar.Size = new System.Drawing.Size(186, 45);
this.LargeStateTrackbar.TabIndex = 10;
this.LargeStateTrackbar.TabIndex = 5;
this.LargeStateTrackbar.TickFrequency = 1024;
this.LargeStateTrackbar.Value = 256;
this.LargeStateTrackbar.ValueChanged += new System.EventHandler(this.LargeStateTrackbar_ValueChanged);
@ -504,7 +504,7 @@
this.MediumStateSizeLabel.Location = new System.Drawing.Point(313, 35);
this.MediumStateSizeLabel.Name = "MediumStateSizeLabel";
this.MediumStateSizeLabel.Size = new System.Drawing.Size(21, 13);
this.MediumStateSizeLabel.TabIndex = 9;
this.MediumStateSizeLabel.TabIndex = 3;
this.MediumStateSizeLabel.Text = "KB";
//
// label2
@ -513,7 +513,7 @@
this.label2.Location = new System.Drawing.Point(18, 31);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(44, 13);
this.label2.TabIndex = 8;
this.label2.TabIndex = 0;
this.label2.Text = "Medium";
//
// groupBox3
@ -531,7 +531,7 @@
this.groupBox3.Location = new System.Drawing.Point(12, 214);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(371, 167);
this.groupBox3.TabIndex = 9;
this.groupBox3.TabIndex = 4;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Rewind Options";
//
@ -683,7 +683,7 @@
this.groupBox4.Location = new System.Drawing.Point(12, 12);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(371, 72);
this.groupBox4.TabIndex = 12;
this.groupBox4.TabIndex = 2;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Current Statistics";
//
@ -767,7 +767,7 @@
this.groupBox6.Location = new System.Drawing.Point(22, 78);
this.groupBox6.Name = "groupBox6";
this.groupBox6.Size = new System.Drawing.Size(215, 48);
this.groupBox6.TabIndex = 0;
this.groupBox6.TabIndex = 4;
this.groupBox6.TabStop = false;
this.groupBox6.Text = "Type";
//
@ -811,7 +811,7 @@
this.btnResetCompression.Location = new System.Drawing.Point(243, 34);
this.btnResetCompression.Name = "btnResetCompression";
this.btnResetCompression.Size = new System.Drawing.Size(27, 27);
this.btnResetCompression.TabIndex = 23;
this.btnResetCompression.TabIndex = 3;
this.toolTip1.SetToolTip(this.btnResetCompression, "Reset to default");
this.btnResetCompression.UseVisualStyleBackColor = true;
this.btnResetCompression.Click += new System.EventHandler(this.BtnResetCompression_Click);
@ -823,7 +823,7 @@
this.trackBarCompression.Maximum = 9;
this.trackBarCompression.Name = "trackBarCompression";
this.trackBarCompression.Size = new System.Drawing.Size(157, 45);
this.trackBarCompression.TabIndex = 20;
this.trackBarCompression.TabIndex = 1;
this.toolTip1.SetToolTip(this.trackBarCompression, "0 = None; 9 = Maximum");
this.trackBarCompression.Value = 1;
this.trackBarCompression.ValueChanged += new System.EventHandler(this.TrackBarCompression_ValueChanged);
@ -838,7 +838,7 @@
0});
this.nudCompression.Name = "nudCompression";
this.nudCompression.Size = new System.Drawing.Size(52, 20);
this.nudCompression.TabIndex = 22;
this.nudCompression.TabIndex = 2;
this.nudCompression.Value = new decimal(new int[] {
1,
0,
@ -866,7 +866,7 @@
this.groupBox7.Location = new System.Drawing.Point(389, 12);
this.groupBox7.Name = "groupBox7";
this.groupBox7.Size = new System.Drawing.Size(342, 408);
this.groupBox7.TabIndex = 2;
this.groupBox7.TabIndex = 6;
this.groupBox7.TabStop = false;
this.groupBox7.Text = "Savestate Options";
//
@ -983,7 +983,7 @@
this.label12.Location = new System.Drawing.Point(19, 21);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(96, 13);
this.label12.TabIndex = 24;
this.label12.TabIndex = 0;
this.label12.Text = "Compression Level";
//
// RewindConfig

View File

@ -89,7 +89,7 @@
this.cbEnableNormal.Location = new System.Drawing.Point(6, 20);
this.cbEnableNormal.Name = "cbEnableNormal";
this.cbEnableNormal.Size = new System.Drawing.Size(48, 17);
this.cbEnableNormal.TabIndex = 3;
this.cbEnableNormal.TabIndex = 0;
this.cbEnableNormal.Text = "Ena.";
this.cbEnableNormal.UseVisualStyleBackColor = true;
this.cbEnableNormal.CheckedChanged += new System.EventHandler(this.UpdateSoundDialog);
@ -116,7 +116,7 @@
this.nudRWFF.Location = new System.Drawing.Point(58, 223);
this.nudRWFF.Name = "nudRWFF";
this.nudRWFF.Size = new System.Drawing.Size(45, 20);
this.nudRWFF.TabIndex = 15;
this.nudRWFF.TabIndex = 7;
this.nudRWFF.Value = new decimal(new int[] {
100,
0,
@ -129,7 +129,7 @@
this.cbEnableRWFF.Location = new System.Drawing.Point(58, 20);
this.cbEnableRWFF.Name = "cbEnableRWFF";
this.cbEnableRWFF.Size = new System.Drawing.Size(48, 17);
this.cbEnableRWFF.TabIndex = 14;
this.cbEnableRWFF.TabIndex = 4;
this.cbEnableRWFF.Text = "Ena.";
this.cbEnableRWFF.UseVisualStyleBackColor = true;
//
@ -141,7 +141,7 @@
this.tbRWFF.Name = "tbRWFF";
this.tbRWFF.Orientation = System.Windows.Forms.Orientation.Vertical;
this.tbRWFF.Size = new System.Drawing.Size(42, 164);
this.tbRWFF.TabIndex = 13;
this.tbRWFF.TabIndex = 6;
this.tbRWFF.TickFrequency = 10;
this.tbRWFF.Scroll += new System.EventHandler(this.TbRwff_Scroll);
//
@ -152,7 +152,7 @@
this.label2.Location = new System.Drawing.Point(56, 42);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(50, 13);
this.label2.TabIndex = 12;
this.label2.TabIndex = 5;
this.label2.Text = "RW && FF";
//
// label1
@ -162,7 +162,7 @@
this.label1.Location = new System.Drawing.Point(6, 42);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(40, 13);
this.label1.TabIndex = 11;
this.label1.TabIndex = 1;
this.label1.Text = "Normal";
//
// tbNormal
@ -173,7 +173,7 @@
this.tbNormal.Name = "tbNormal";
this.tbNormal.Orientation = System.Windows.Forms.Orientation.Vertical;
this.tbNormal.Size = new System.Drawing.Size(42, 164);
this.tbNormal.TabIndex = 0;
this.tbNormal.TabIndex = 2;
this.tbNormal.TickFrequency = 10;
this.tbNormal.Scroll += new System.EventHandler(this.TrackBar1_Scroll);
//
@ -182,7 +182,7 @@
this.nudNormal.Location = new System.Drawing.Point(5, 223);
this.nudNormal.Name = "nudNormal";
this.nudNormal.Size = new System.Drawing.Size(45, 20);
this.nudNormal.TabIndex = 1;
this.nudNormal.TabIndex = 3;
this.nudNormal.Value = new decimal(new int[] {
100,
0,
@ -199,7 +199,7 @@
this.listBoxSoundDevices.Location = new System.Drawing.Point(138, 110);
this.listBoxSoundDevices.Name = "listBoxSoundDevices";
this.listBoxSoundDevices.Size = new System.Drawing.Size(254, 95);
this.listBoxSoundDevices.TabIndex = 7;
this.listBoxSoundDevices.TabIndex = 8;
//
// SoundDeviceLabel
//
@ -207,7 +207,7 @@
this.SoundDeviceLabel.Location = new System.Drawing.Point(135, 89);
this.SoundDeviceLabel.Name = "SoundDeviceLabel";
this.SoundDeviceLabel.Size = new System.Drawing.Size(78, 13);
this.SoundDeviceLabel.TabIndex = 6;
this.SoundDeviceLabel.TabIndex = 7;
this.SoundDeviceLabel.Text = "Sound Device:";
//
// BufferSizeLabel
@ -217,7 +217,7 @@
this.BufferSizeLabel.Location = new System.Drawing.Point(135, 210);
this.BufferSizeLabel.Name = "BufferSizeLabel";
this.BufferSizeLabel.Size = new System.Drawing.Size(61, 13);
this.BufferSizeLabel.TabIndex = 8;
this.BufferSizeLabel.TabIndex = 9;
this.BufferSizeLabel.Text = "Buffer Size:";
//
// BufferSizeNumeric
@ -236,7 +236,7 @@
0});
this.BufferSizeNumeric.Name = "BufferSizeNumeric";
this.BufferSizeNumeric.Size = new System.Drawing.Size(59, 20);
this.BufferSizeNumeric.TabIndex = 9;
this.BufferSizeNumeric.TabIndex = 10;
this.BufferSizeNumeric.Value = new decimal(new int[] {
100,
0,
@ -250,7 +250,7 @@
this.BufferSizeUnitsLabel.Location = new System.Drawing.Point(267, 210);
this.BufferSizeUnitsLabel.Name = "BufferSizeUnitsLabel";
this.BufferSizeUnitsLabel.Size = new System.Drawing.Size(63, 13);
this.BufferSizeUnitsLabel.TabIndex = 10;
this.BufferSizeUnitsLabel.TabIndex = 11;
this.BufferSizeUnitsLabel.Text = "milliseconds";
//
// grpOutputMethod
@ -261,7 +261,7 @@
this.grpOutputMethod.Location = new System.Drawing.Point(292, 12);
this.grpOutputMethod.Name = "grpOutputMethod";
this.grpOutputMethod.Size = new System.Drawing.Size(100, 90);
this.grpOutputMethod.TabIndex = 5;
this.grpOutputMethod.TabIndex = 12;
this.grpOutputMethod.TabStop = false;
this.grpOutputMethod.Text = "Output Method";
//
@ -307,7 +307,7 @@
this.cbMuteFrameAdvance.Location = new System.Drawing.Point(139, 68);
this.cbMuteFrameAdvance.Name = "cbMuteFrameAdvance";
this.cbMuteFrameAdvance.Size = new System.Drawing.Size(128, 17);
this.cbMuteFrameAdvance.TabIndex = 17;
this.cbMuteFrameAdvance.TabIndex = 6;
this.cbMuteFrameAdvance.Text = "Mute Frame Advance";
this.cbMuteFrameAdvance.UseVisualStyleBackColor = true;
//
@ -317,7 +317,7 @@
this.cbEnableMaster.Location = new System.Drawing.Point(139, 16);
this.cbEnableMaster.Name = "cbEnableMaster";
this.cbEnableMaster.Size = new System.Drawing.Size(128, 17);
this.cbEnableMaster.TabIndex = 18;
this.cbEnableMaster.TabIndex = 4;
this.cbEnableMaster.Text = "Sound Master Enable";
this.cbEnableMaster.UseVisualStyleBackColor = true;
this.cbEnableMaster.CheckedChanged += new System.EventHandler(this.UpdateSoundDialog);
@ -328,7 +328,7 @@
this.label3.Location = new System.Drawing.Point(161, 35);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(126, 26);
this.label3.TabIndex = 19;
this.label3.TabIndex = 5;
this.label3.Text = "Controls whether cores even generate audio.";
//
// SoundConfig

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

View File

@ -49,7 +49,7 @@
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.StopOnFrameCheckbox = new System.Windows.Forms.CheckBox();
this.StopOnFrameTextBox = new BizHawk.Client.EmuHawk.WatchValueBox();
this.MovieView = new BizHawk.Client.EmuHawk.VirtualListView();
this.MovieView = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
@ -269,7 +269,6 @@
this.MovieView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.MovieView.BlazingFast = false;
this.MovieView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
@ -279,16 +278,13 @@
this.MovieView.FullRowSelect = true;
this.MovieView.GridLines = true;
this.MovieView.HideSelection = false;
this.MovieView.ItemCount = 0;
this.MovieView.VirtualListSize = 0;
this.MovieView.Location = new System.Drawing.Point(12, 28);
this.MovieView.MultiSelect = false;
this.MovieView.Name = "MovieView";
this.MovieView.SelectAllInProgress = false;
this.MovieView.selectedItem = -1;
this.MovieView.Size = new System.Drawing.Size(480, 322);
this.MovieView.TabIndex = 5;
this.MovieView.UseCompatibleStateImageBehavior = false;
this.MovieView.UseCustomBackground = true;
this.MovieView.View = System.Windows.Forms.View.Details;
this.MovieView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.MovieView_ColumnClick);
this.MovieView.SelectedIndexChanged += new System.EventHandler(this.MovieView_SelectedIndexChanged);
@ -381,7 +377,7 @@
private System.Windows.Forms.Button Cancel;
private System.Windows.Forms.Button OK;
private System.Windows.Forms.Button BrowseMovies;
private VirtualListView MovieView;
private System.Windows.Forms.ListView MovieView;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;

Some files were not shown because too many files have changed in this diff Show More