From 36a7a5ac9fdca15225c8b5fbc3da04a1063b3412 Mon Sep 17 00:00:00 2001 From: Evaldas Jocys Date: Sat, 4 Jun 2016 18:28:22 +0100 Subject: [PATCH] Threading issue fixed. Updates to beta app. --- x360ce.App.Beta/Common/DiDevice.cs | 9 + .../Controls/ControllersUserControl.xaml | 25 + .../Controls/ControllersUserControl.xaml.cs | 33 + x360ce.App.Beta/MainForm.Designer.cs | 119 +- x360ce.App.Beta/MainForm.cs | 2798 +++++++++-------- x360ce.App.Beta/MainForm.resx | 146 +- x360ce.App.Beta/x360ce.App.Beta.csproj | 21 +- x360ce.App.WPF/App.ico | Bin 0 -> 146516 bytes .../Controls/DeviceTabControlGeneralTab.xaml | 447 ++- x360ce.App.WPF/MainWindow.xaml.BACKUP | Bin 26705 -> 0 bytes x360ce.App.WPF/Properties/AssemblyInfo.cs | 14 +- x360ce.App.WPF/Properties/Resources.resx | 13 +- x360ce.App.WPF/x360ce.App.WPF.csproj | 6 + .../Documents/TocaEdit_clone_as_GIT.bat | 5 + .../Documents/TocaEdit_clone_as_SVN.bat | 5 + x360ce.App/x360ce.App.csproj | 4 +- 16 files changed, 1889 insertions(+), 1756 deletions(-) create mode 100644 x360ce.App.Beta/Controls/ControllersUserControl.xaml create mode 100644 x360ce.App.Beta/Controls/ControllersUserControl.xaml.cs create mode 100644 x360ce.App.WPF/App.ico delete mode 100644 x360ce.App.WPF/MainWindow.xaml.BACKUP create mode 100644 x360ce.App/Documents/TocaEdit_clone_as_GIT.bat create mode 100644 x360ce.App/Documents/TocaEdit_clone_as_SVN.bat diff --git a/x360ce.App.Beta/Common/DiDevice.cs b/x360ce.App.Beta/Common/DiDevice.cs index 08d7ff1be..2356d9eaf 100644 --- a/x360ce.App.Beta/Common/DiDevice.cs +++ b/x360ce.App.Beta/Common/DiDevice.cs @@ -1,6 +1,7 @@ using JocysCom.ClassLibrary.IO; using SharpDX.DirectInput; using System; +using x360ce.Engine; namespace x360ce.App { @@ -15,6 +16,14 @@ public class DiDevice /// Previous DInput Device Instance. public DeviceInstance InstanceOld; + public string InstanceID + { + get + { + return EngineHelper.GetID(InstanceGuid); + } + } + public string VendorName { get diff --git a/x360ce.App.Beta/Controls/ControllersUserControl.xaml b/x360ce.App.Beta/Controls/ControllersUserControl.xaml new file mode 100644 index 000000000..bca101c69 --- /dev/null +++ b/x360ce.App.Beta/Controls/ControllersUserControl.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + diff --git a/x360ce.App.Beta/Controls/ControllersUserControl.xaml.cs b/x360ce.App.Beta/Controls/ControllersUserControl.xaml.cs new file mode 100644 index 000000000..28676651c --- /dev/null +++ b/x360ce.App.Beta/Controls/ControllersUserControl.xaml.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace x360ce.App +{ + /// + /// Interaction logic for ControllersUserControl.xaml + /// + public partial class ControllersUserControl : UserControl + { + public ControllersUserControl() + { + InitializeComponent(); + } + + private void UserControl_Loaded(object sender, RoutedEventArgs e) + { + ControllersDataGrid.ItemsSource = SettingManager.DiDevices; + } + + } +} diff --git a/x360ce.App.Beta/MainForm.Designer.cs b/x360ce.App.Beta/MainForm.Designer.cs index a030e9d8a..779a5bbde 100644 --- a/x360ce.App.Beta/MainForm.Designer.cs +++ b/x360ce.App.Beta/MainForm.Designer.cs @@ -27,9 +27,9 @@ void InitializeComponent() this.Pad4TabPage = new System.Windows.Forms.TabPage(); this.OptionsTabPage = new System.Windows.Forms.TabPage(); this.OptionsPanel = new x360ce.App.Controls.OptionsControl(); - this.GameSettingsTabPage = new System.Windows.Forms.TabPage(); + this.GamesTabPage = new System.Windows.Forms.TabPage(); this.GameSettingsPanel = new x360ce.App.Controls.GameSettingsUserControl(); - this.ControllerSettingsTabPage = new System.Windows.Forms.TabPage(); + this.SettingsTabPage = new System.Windows.Forms.TabPage(); this.SettingsDatabasePanel = new x360ce.App.Controls.ControllerSettingsUserControl(); this.IniTabPage = new System.Windows.Forms.TabPage(); this.IniTextBox = new System.Windows.Forms.TextBox(); @@ -57,16 +57,20 @@ void InitializeComponent() this.label1 = new System.Windows.Forms.Label(); this.GameToCustomizeComboBox = new System.Windows.Forms.ComboBox(); this.BusyLoadingCircle = new MRG.Controls.UI.LoadingCircle(); + this.ControllersTabPage = new System.Windows.Forms.TabPage(); + this.elementHost1 = new System.Windows.Forms.Integration.ElementHost(); + this.controllersUserControl1 = new x360ce.App.ControllersUserControl(); this.MainTabControl.SuspendLayout(); this.OptionsTabPage.SuspendLayout(); - this.GameSettingsTabPage.SuspendLayout(); - this.ControllerSettingsTabPage.SuspendLayout(); + this.GamesTabPage.SuspendLayout(); + this.SettingsTabPage.SuspendLayout(); this.IniTabPage.SuspendLayout(); this.HelpTabPage.SuspendLayout(); this.MainStatusStrip.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.HelpPictureBox)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.HeaderPictureBox)).BeginInit(); this.TrayContextMenuStrip.SuspendLayout(); + this.ControllersTabPage.SuspendLayout(); this.SuspendLayout(); // // MainTabControl @@ -79,8 +83,9 @@ void InitializeComponent() this.MainTabControl.Controls.Add(this.Pad3TabPage); this.MainTabControl.Controls.Add(this.Pad4TabPage); this.MainTabControl.Controls.Add(this.OptionsTabPage); - this.MainTabControl.Controls.Add(this.GameSettingsTabPage); - this.MainTabControl.Controls.Add(this.ControllerSettingsTabPage); + this.MainTabControl.Controls.Add(this.GamesTabPage); + this.MainTabControl.Controls.Add(this.ControllersTabPage); + this.MainTabControl.Controls.Add(this.SettingsTabPage); this.MainTabControl.Controls.Add(this.IniTabPage); this.MainTabControl.Controls.Add(this.HelpTabPage); this.MainTabControl.Controls.Add(this.AboutTabPage); @@ -88,7 +93,7 @@ void InitializeComponent() this.MainTabControl.Location = new System.Drawing.Point(6, 97); this.MainTabControl.Name = "MainTabControl"; this.MainTabControl.SelectedIndex = 0; - this.MainTabControl.Size = new System.Drawing.Size(674, 624); + this.MainTabControl.Size = new System.Drawing.Size(728, 624); this.MainTabControl.TabIndex = 1; // // Pad1TabPage @@ -96,7 +101,7 @@ void InitializeComponent() this.Pad1TabPage.ImageKey = "bullet_square_glass_grey.png"; this.Pad1TabPage.Location = new System.Drawing.Point(4, 23); this.Pad1TabPage.Name = "Pad1TabPage"; - this.Pad1TabPage.Size = new System.Drawing.Size(666, 597); + this.Pad1TabPage.Size = new System.Drawing.Size(720, 597); this.Pad1TabPage.TabIndex = 0; this.Pad1TabPage.Text = "Controller 1"; // @@ -105,7 +110,7 @@ void InitializeComponent() this.Pad2TabPage.ImageKey = "bullet_square_glass_grey.png"; this.Pad2TabPage.Location = new System.Drawing.Point(4, 23); this.Pad2TabPage.Name = "Pad2TabPage"; - this.Pad2TabPage.Size = new System.Drawing.Size(666, 597); + this.Pad2TabPage.Size = new System.Drawing.Size(720, 597); this.Pad2TabPage.TabIndex = 0; this.Pad2TabPage.Text = "Controller 2"; // @@ -114,7 +119,7 @@ void InitializeComponent() this.Pad3TabPage.ImageKey = "bullet_square_glass_grey.png"; this.Pad3TabPage.Location = new System.Drawing.Point(4, 23); this.Pad3TabPage.Name = "Pad3TabPage"; - this.Pad3TabPage.Size = new System.Drawing.Size(666, 597); + this.Pad3TabPage.Size = new System.Drawing.Size(720, 597); this.Pad3TabPage.TabIndex = 0; this.Pad3TabPage.Text = "Controller 3"; // @@ -123,7 +128,7 @@ void InitializeComponent() this.Pad4TabPage.ImageKey = "bullet_square_glass_grey.png"; this.Pad4TabPage.Location = new System.Drawing.Point(4, 23); this.Pad4TabPage.Name = "Pad4TabPage"; - this.Pad4TabPage.Size = new System.Drawing.Size(666, 597); + this.Pad4TabPage.Size = new System.Drawing.Size(720, 597); this.Pad4TabPage.TabIndex = 0; this.Pad4TabPage.Text = "Controller 4"; // @@ -133,7 +138,7 @@ void InitializeComponent() this.OptionsTabPage.Controls.Add(this.OptionsPanel); this.OptionsTabPage.Location = new System.Drawing.Point(4, 23); this.OptionsTabPage.Name = "OptionsTabPage"; - this.OptionsTabPage.Size = new System.Drawing.Size(666, 597); + this.OptionsTabPage.Size = new System.Drawing.Size(720, 597); this.OptionsTabPage.TabIndex = 0; this.OptionsTabPage.Text = "Options"; // @@ -142,44 +147,44 @@ void InitializeComponent() this.OptionsPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.OptionsPanel.Location = new System.Drawing.Point(0, 0); this.OptionsPanel.Name = "OptionsPanel"; - this.OptionsPanel.Size = new System.Drawing.Size(666, 597); + this.OptionsPanel.Size = new System.Drawing.Size(720, 597); this.OptionsPanel.TabIndex = 30; // - // GameSettingsTabPage + // GamesTabPage // - this.GameSettingsTabPage.BackColor = System.Drawing.SystemColors.Control; - this.GameSettingsTabPage.Controls.Add(this.GameSettingsPanel); - this.GameSettingsTabPage.Location = new System.Drawing.Point(4, 23); - this.GameSettingsTabPage.Name = "GameSettingsTabPage"; - this.GameSettingsTabPage.Padding = new System.Windows.Forms.Padding(3); - this.GameSettingsTabPage.Size = new System.Drawing.Size(666, 597); - this.GameSettingsTabPage.TabIndex = 2; - this.GameSettingsTabPage.Text = "Games"; + this.GamesTabPage.BackColor = System.Drawing.SystemColors.Control; + this.GamesTabPage.Controls.Add(this.GameSettingsPanel); + this.GamesTabPage.Location = new System.Drawing.Point(4, 23); + this.GamesTabPage.Name = "GamesTabPage"; + this.GamesTabPage.Padding = new System.Windows.Forms.Padding(3); + this.GamesTabPage.Size = new System.Drawing.Size(720, 597); + this.GamesTabPage.TabIndex = 2; + this.GamesTabPage.Text = "Games"; // // GameSettingsPanel // this.GameSettingsPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.GameSettingsPanel.Location = new System.Drawing.Point(3, 3); this.GameSettingsPanel.Name = "GameSettingsPanel"; - this.GameSettingsPanel.Size = new System.Drawing.Size(660, 591); + this.GameSettingsPanel.Size = new System.Drawing.Size(714, 591); this.GameSettingsPanel.TabIndex = 1; // - // ControllerSettingsTabPage + // SettingsTabPage // - this.ControllerSettingsTabPage.Controls.Add(this.SettingsDatabasePanel); - this.ControllerSettingsTabPage.Location = new System.Drawing.Point(4, 23); - this.ControllerSettingsTabPage.Name = "ControllerSettingsTabPage"; - this.ControllerSettingsTabPage.Padding = new System.Windows.Forms.Padding(3); - this.ControllerSettingsTabPage.Size = new System.Drawing.Size(666, 597); - this.ControllerSettingsTabPage.TabIndex = 1; - this.ControllerSettingsTabPage.Text = "Controller Settings"; + this.SettingsTabPage.Controls.Add(this.SettingsDatabasePanel); + this.SettingsTabPage.Location = new System.Drawing.Point(4, 23); + this.SettingsTabPage.Name = "SettingsTabPage"; + this.SettingsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.SettingsTabPage.Size = new System.Drawing.Size(720, 597); + this.SettingsTabPage.TabIndex = 1; + this.SettingsTabPage.Text = "Settings"; // // SettingsDatabasePanel // this.SettingsDatabasePanel.Dock = System.Windows.Forms.DockStyle.Fill; this.SettingsDatabasePanel.Location = new System.Drawing.Point(3, 3); this.SettingsDatabasePanel.Name = "SettingsDatabasePanel"; - this.SettingsDatabasePanel.Size = new System.Drawing.Size(660, 591); + this.SettingsDatabasePanel.Size = new System.Drawing.Size(714, 591); this.SettingsDatabasePanel.TabIndex = 0; // // IniTabPage @@ -188,7 +193,7 @@ void InitializeComponent() this.IniTabPage.Controls.Add(this.IniTextBox); this.IniTabPage.Location = new System.Drawing.Point(4, 23); this.IniTabPage.Name = "IniTabPage"; - this.IniTabPage.Size = new System.Drawing.Size(666, 597); + this.IniTabPage.Size = new System.Drawing.Size(720, 597); this.IniTabPage.TabIndex = 3; this.IniTabPage.Text = "INI"; // @@ -201,7 +206,7 @@ void InitializeComponent() this.IniTextBox.Name = "IniTextBox"; this.IniTextBox.ReadOnly = true; this.IniTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; - this.IniTextBox.Size = new System.Drawing.Size(666, 597); + this.IniTextBox.Size = new System.Drawing.Size(720, 597); this.IniTextBox.TabIndex = 1; // // HelpTabPage @@ -209,7 +214,7 @@ void InitializeComponent() this.HelpTabPage.Controls.Add(this.HelpRichTextBox); this.HelpTabPage.Location = new System.Drawing.Point(4, 23); this.HelpTabPage.Name = "HelpTabPage"; - this.HelpTabPage.Size = new System.Drawing.Size(666, 597); + this.HelpTabPage.Size = new System.Drawing.Size(720, 597); this.HelpTabPage.TabIndex = 0; this.HelpTabPage.Text = "Help"; // @@ -222,7 +227,7 @@ void InitializeComponent() this.HelpRichTextBox.Margin = new System.Windows.Forms.Padding(0); this.HelpRichTextBox.Name = "HelpRichTextBox"; this.HelpRichTextBox.ReadOnly = true; - this.HelpRichTextBox.Size = new System.Drawing.Size(666, 597); + this.HelpRichTextBox.Size = new System.Drawing.Size(720, 597); this.HelpRichTextBox.TabIndex = 0; this.HelpRichTextBox.Text = ""; // @@ -231,7 +236,7 @@ void InitializeComponent() this.AboutTabPage.BackColor = System.Drawing.Color.Transparent; this.AboutTabPage.Location = new System.Drawing.Point(4, 23); this.AboutTabPage.Name = "AboutTabPage"; - this.AboutTabPage.Size = new System.Drawing.Size(666, 597); + this.AboutTabPage.Size = new System.Drawing.Size(720, 597); this.AboutTabPage.TabIndex = 0; this.AboutTabPage.Text = "About"; // @@ -257,7 +262,7 @@ void InitializeComponent() this.StatusDllLabel}); this.MainStatusStrip.Location = new System.Drawing.Point(0, 728); this.MainStatusStrip.Name = "MainStatusStrip"; - this.MainStatusStrip.Size = new System.Drawing.Size(684, 24); + this.MainStatusStrip.Size = new System.Drawing.Size(738, 24); this.MainStatusStrip.SizingGrip = false; this.MainStatusStrip.TabIndex = 0; this.MainStatusStrip.Text = "statusStrip1"; @@ -271,7 +276,7 @@ void InitializeComponent() // toolStripStatusLabel2 // this.toolStripStatusLabel2.Name = "toolStripStatusLabel2"; - this.toolStripStatusLabel2.Size = new System.Drawing.Size(87, 19); + this.toolStripStatusLabel2.Size = new System.Drawing.Size(141, 19); this.toolStripStatusLabel2.Spring = true; // // StatusEventsLabel @@ -401,7 +406,7 @@ void InitializeComponent() this.GameToCustomizeComboBox.FormattingEnabled = true; this.GameToCustomizeComboBox.Location = new System.Drawing.Point(149, 70); this.GameToCustomizeComboBox.Name = "GameToCustomizeComboBox"; - this.GameToCustomizeComboBox.Size = new System.Drawing.Size(529, 21); + this.GameToCustomizeComboBox.Size = new System.Drawing.Size(583, 21); this.GameToCustomizeComboBox.TabIndex = 7; this.GameToCustomizeComboBox.SelectedIndexChanged += new System.EventHandler(this.GameToCustomizeComboBox_SelectedIndexChanged); // @@ -421,11 +426,31 @@ void InitializeComponent() this.BusyLoadingCircle.StylePreset = MRG.Controls.UI.LoadingCircle.StylePresets.IE7; this.BusyLoadingCircle.TabIndex = 9; // + // ControllersTabPage + // + this.ControllersTabPage.BackColor = System.Drawing.SystemColors.Control; + this.ControllersTabPage.Controls.Add(this.elementHost1); + this.ControllersTabPage.Location = new System.Drawing.Point(4, 23); + this.ControllersTabPage.Name = "ControllersTabPage"; + this.ControllersTabPage.Size = new System.Drawing.Size(720, 597); + this.ControllersTabPage.TabIndex = 4; + this.ControllersTabPage.Text = "Controllers"; + // + // elementHost1 + // + this.elementHost1.Dock = System.Windows.Forms.DockStyle.Fill; + this.elementHost1.Location = new System.Drawing.Point(0, 0); + this.elementHost1.Name = "elementHost1"; + this.elementHost1.Size = new System.Drawing.Size(720, 597); + this.elementHost1.TabIndex = 0; + this.elementHost1.Text = "elementHost1"; + this.elementHost1.Child = this.controllersUserControl1; + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(684, 752); + this.ClientSize = new System.Drawing.Size(738, 752); this.Controls.Add(this.GameToCustomizeComboBox); this.Controls.Add(this.label1); this.Controls.Add(this.MainStatusStrip); @@ -445,8 +470,8 @@ void InitializeComponent() this.Controls.SetChildIndex(this.GameToCustomizeComboBox, 0); this.MainTabControl.ResumeLayout(false); this.OptionsTabPage.ResumeLayout(false); - this.GameSettingsTabPage.ResumeLayout(false); - this.ControllerSettingsTabPage.ResumeLayout(false); + this.GamesTabPage.ResumeLayout(false); + this.SettingsTabPage.ResumeLayout(false); this.IniTabPage.ResumeLayout(false); this.IniTabPage.PerformLayout(); this.HelpTabPage.ResumeLayout(false); @@ -455,6 +480,7 @@ void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.HelpPictureBox)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.HeaderPictureBox)).EndInit(); this.TrayContextMenuStrip.ResumeLayout(false); + this.ControllersTabPage.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -479,10 +505,10 @@ void InitializeComponent() ToolStripStatusLabel StatusIsAdminLabel; ToolStripStatusLabel StatusIniLabel; ToolStripStatusLabel StatusDllLabel; - TabPage ControllerSettingsTabPage; + TabPage SettingsTabPage; public Controls.ControllerSettingsUserControl SettingsDatabasePanel; public TabControl MainTabControl; - TabPage GameSettingsTabPage; + TabPage GamesTabPage; public Controls.OptionsControl OptionsPanel; public ToolTip ToolTip; public Controls.GameSettingsUserControl GameSettingsPanel; @@ -499,5 +525,8 @@ void InitializeComponent() private MRG.Controls.UI.LoadingCircle BusyLoadingCircle; private TabPage IniTabPage; private TextBox IniTextBox; + private TabPage ControllersTabPage; + private System.Windows.Forms.Integration.ElementHost elementHost1; + private ControllersUserControl controllersUserControl1; } } \ No newline at end of file diff --git a/x360ce.App.Beta/MainForm.cs b/x360ce.App.Beta/MainForm.cs index 2786f8d66..b48bb300e 100644 --- a/x360ce.App.Beta/MainForm.cs +++ b/x360ce.App.Beta/MainForm.cs @@ -17,1401 +17,1405 @@ namespace x360ce.App { - public partial class MainForm : BaseForm - { - public MainForm() - { - InitializeComponent(); - } - - DeviceDetector detector; - - public static MainForm Current { get; set; } - - public Engine.Data.Game GetCurrentGame() - { - Engine.Data.Game game = null; - var item = GameToCustomizeComboBox.SelectedItem; - if (item != null) - { - game = (Engine.Data.Game)item; - - } - return game; - } - - public int oldIndex; - - public int ControllerIndex - { - get - { - int newIndex = -1; - if (MainTabControl.SelectedTab == Pad1TabPage) newIndex = 0; - if (MainTabControl.SelectedTab == Pad2TabPage) newIndex = 1; - if (MainTabControl.SelectedTab == Pad3TabPage) newIndex = 2; - if (MainTabControl.SelectedTab == Pad4TabPage) newIndex = 3; - return newIndex; - } - set - { - switch (value) - { - case 0: MainTabControl.SelectedTab = Pad1TabPage; break; - case 1: MainTabControl.SelectedTab = Pad2TabPage; break; - case 2: MainTabControl.SelectedTab = Pad3TabPage; break; - case 3: MainTabControl.SelectedTab = Pad4TabPage; break; - } - } - } - - public AboutControl ControlAbout; - public PadControl[] ControlPads; - public TabPage[] ControlPages; - - /// - /// Settings timer will be used to delay applying settings, which will heavy load application, as long as user is changing them. - /// - public System.Timers.Timer SettingsTimer; - - public System.Timers.Timer UpdateTimer; - - public System.Timers.Timer CleanStatusTimer; - public int DefaultPoolingInterval = 50; - - public Controller[] XiControllers = new Controller[4]; - - void MainForm_Load(object sender, EventArgs e) - { - if (IsDesignMode) return; - SettingManager.Settings.Load(); - SettingManager.Summaries.Load(); - SettingManager.Summaries.Items.ListChanged += Summaries_ListChanged; - // Make sure that data will be filtered before loading. - // Note: Make sure to load Programs before Games. - SettingManager.Programs.FilterList = Programs_FilterList; - SettingManager.Programs.Load(); - // Make sure that data will be filtered before loading. - SettingManager.Games.FilterList = Games_FilterList; - SettingManager.Games.Load(); - SettingManager.Presets.Load(); - SettingManager.PadSettings.Load(); - for (int i = 0; i < 4; i++) - { - XiControllers[i] = new Controller((UserIndex)i); - } - GameToCustomizeComboBox.DataSource = SettingManager.Games.Items; - GameToCustomizeComboBox.DisplayMember = "DisplayName"; - UpdateTimer = new System.Timers.Timer(); - UpdateTimer.AutoReset = false; - UpdateTimer.SynchronizingObject = this; - UpdateTimer.Interval = DefaultPoolingInterval; - UpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(UpdateTimer_Elapsed); - SettingsTimer = new System.Timers.Timer(); - SettingsTimer.AutoReset = false; - SettingsTimer.SynchronizingObject = this; - SettingsTimer.Interval = 500; - SettingsTimer.Elapsed += new System.Timers.ElapsedEventHandler(SettingsTimer_Elapsed); - CleanStatusTimer = new System.Timers.Timer(); - CleanStatusTimer.AutoReset = false; - CleanStatusTimer.SynchronizingObject = this; - CleanStatusTimer.Interval = 3000; - CleanStatusTimer.Elapsed += new System.Timers.ElapsedEventHandler(CleanStatusTimer_Elapsed); - Text = EngineHelper.GetProductFullName(); - SetMinimizeToTray(Settings.Default.MinimizeToTray); - // Start Timers. - UpdateTimer.Start(); - } - - IList Programs_FilterList(IList items) - { - // Make sure default settings have unique by file name. - var distinctItems = items - .GroupBy(p => p.FileName.ToLower()) - .Select(g => g.First()) - .ToList(); - return distinctItems; - } - - IList Games_FilterList(IList items) - { - // Make sure default settings have unique by file name. - var distinctItems = items - .GroupBy(p => p.FileName.ToLower()) - .Select(g => g.First()) - .ToList(); - - // Check if current app doesn't exist in the list then... - var appFile = new FileInfo(Application.ExecutablePath); - var appItem = distinctItems.FirstOrDefault(x => x.FileName.ToLower() == appFile.Name.ToLower()); - if (appItem == null) - { - // Add x360ce.exe - var item = x360ce.Engine.Data.Game.FromDisk(appFile.Name); - var program = SettingManager.Programs.Items.FirstOrDefault(x => x.FileName.ToLower() == appFile.Name.ToLower()); - item.LoadDefault(program); - distinctItems.Add(item); - } - else - { - appItem.FullPath = appFile.FullName; - } - return distinctItems; - } - - private void Summaries_ListChanged(object sender, ListChangedEventArgs e) - { - // If map to changed then re-detect devices. - var pd = e.PropertyDescriptor; - if (pd != null && pd.Name == "MapTo") - { - forceRecountDevices = true; - } - } - - void InitDevices() - { - detector = new DeviceDetector(false); - UpdateDevices(); - detector.DeviceChanged += new DeviceDetector.DeviceDetectorEventHandler(detector_DeviceChanged); - } - - void detector_DeviceChanged(object sender, DeviceDetectorEventArgs e) - { - UpdateDevices(); - } - - object UpdateDevicesLock = new object(); - - void UpdateDevices() - { - lock (UpdateDevicesLock) - { - var devices = Manager.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AllDevices).ToList(); - var deviceInstanceGuid = devices.Select(x => x.InstanceGuid).ToArray(); - var currentInstanceGuids = SettingManager.DiDevices.Select(x => x.InstanceGuid).ToArray(); - var removedDevices = SettingManager.DiDevices.Where(x => !deviceInstanceGuid.Contains(x.InstanceGuid)).ToArray(); - var addedDevices = devices.Where(x => !currentInstanceGuids.Contains(x.InstanceGuid)).ToArray(); - var updatedDevices = devices.Where(x => currentInstanceGuids.Contains(x.InstanceGuid)).ToArray(); - // Remove disconnected devices. - for (int i = 0; i < removedDevices.Length; i++) - { - SettingManager.DiDevices.Remove(removedDevices[i]); - } - // Add connected devices. - for (int i = 0; i < addedDevices.Length; i++) - { - var device = addedDevices[i]; - var di = new DiDevice(); - di.Instance = device; - var state = new Joystick(Manager, device.InstanceGuid); - di.Device = state; - var classGuid = state.Properties.ClassGuid; - // Must find better way to find Device than by Vendor ID and Product ID. - var info = DeviceDetector.GetDevices( - classGuid, - JocysCom.ClassLibrary.Win32.DIGCF.DIGCF_ALLCLASSES, - null, - state.Properties.VendorId, - state.Properties.ProductId, - 0 - ); - di.Info = info.FirstOrDefault(); - SettingManager.DiDevices.Add(di); - } - for (int i = 0; i < updatedDevices.Length; i++) - { - var device = updatedDevices[i]; - var currentDevice = SettingManager.DiDevices.First(x => x.InstanceGuid.Equals(device.InstanceGuid)); - var state = new Joystick(Manager, device.InstanceGuid); - currentDevice.Device = state; - } - } - var game = GetCurrentGame(); - if (game != null) - { - // Auto-configure new devices. - AutoConfigure(game); - } - } - - void AutoConfigure(Engine.Data.Game game) - { - var list = SettingManager.DiDevices.ToList(); - // Filter devices. - if (Settings.Default.ExcludeSupplementalDevices) - { - // Supplemental devices are specialized device with functionality unsuitable for the main control of an application, - // such as pedals used with a wheel.The following subtypes are defined. - var supplementals = list.Where(x => x.Instance.Type == SharpDX.DirectInput.DeviceType.Supplemental).ToArray(); - foreach (var supplemental in supplementals) - { - list.Remove(supplemental); - } - } - if (Settings.Default.ExcludeSupplementalDevices) - { - // Exclude virtual devices so application could feed them. - var virtualDevices = list.Where(x => x.Instance.InstanceName.Contains("vJoy")).ToArray(); - foreach (var virtualDevice in virtualDevices) - { - list.Remove(virtualDevice); - } - } - // Move gaming wheels to the top index position by default. - // Games like GTA need wheel to be first device to work properly. - var wheels = list.Where(x => - x.Instance.Type == SharpDX.DirectInput.DeviceType.Driving || - x.Instance.Subtype == (int)DeviceSubType.Wheel - ).ToArray(); - foreach (var wheel in wheels) - { - list.Remove(wheel); - list.Insert(0, wheel); - } - // Get configuration of devices for the game. - var settings = SettingManager.GetSettings(game.FileName); - var knownDevices = settings.Select(x => x.InstanceGuid).ToList(); - var newSettingsToProcess = new List(); - int i = 0; - while (true) - { - i++; - // If there are devices which occupies current position then do nothing. - if (settings.Any(x => x.MapTo == i)) continue; - // Try to select first unknown device. - var newDevice = list.FirstOrDefault(x => !knownDevices.Contains(x.InstanceGuid)); - // If no device found then break. - if (newDevice == null) break; - // Create new setting for game/device. - var newSetting = AppHelper.GetNewSetting(newDevice, game, i <= 4 ? (MapTo)i : MapTo.Disabled); - newSettingsToProcess.Add(newSetting); - // Add device to known list. - knownDevices.Add(newDevice.InstanceGuid); - } - foreach (var item in newSettingsToProcess) - { - SettingManager.Settings.Items.Add(item); - } - } - - /// - /// Link control with INI key. Value/Text of control will be automatically tracked and INI file updated. - /// - void UpdateSettingsMap() - { - // INI setting keys with controls. - SettingManager.Current.ConfigSaved += Current_ConfigSaved; - SettingManager.Current.ConfigLoaded += Current_ConfigLoaded; - OptionsPanel.UpdateSettingsManager(); - SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD1, ControlPads[0].DevicesToMapDataGridView); - SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD2, ControlPads[1].DevicesToMapDataGridView); - SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD3, ControlPads[2].DevicesToMapDataGridView); - SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD4, ControlPads[3].DevicesToMapDataGridView); - } - - void Current_ConfigSaved(object sender, SettingEventArgs e) - { - StatusSaveLabel.Text = string.Format("S {0}", e.Count); - } - - void Current_ConfigLoaded(object sender, SettingEventArgs e) - { - StatusTimerLabel.Text = string.Format("'{0}' loaded.", e.Name); - } - - public void CopyElevated(string source, string dest) - { - if (!WinAPI.IsVista) - { - File.Copy(source, dest); - return; - } - var di = new DirectoryInfo(System.IO.Path.GetDirectoryName(dest)); - var security = di.GetAccessControl(); - var fi = new FileInfo(dest); - var fileSecurity = fi.GetAccessControl(); - // Allow Users to Write. - //SecurityIdentifier SID = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); - //fileSecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.Write, AccessControlType.Allow)); - //fi.SetAccessControl(fileSecurity); - var rules = security.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)); - string message = string.Empty; - foreach (var myacc in rules) - { - var acc = (FileSystemAccessRule)myacc; - message += string.Format("IdentityReference: {0}\r\n", acc.IdentityReference.Value); - message += string.Format("Access Control Type: {0}\r\n", acc.AccessControlType.ToString()); - message += string.Format("\t{0}\r\n", acc.FileSystemRights.ToString()); - //if ((acc.FileSystemRights & FileSystemRights.FullControl) == FileSystemRights.FullControl) - //{ - // Console.Write("FullControl"); - //} - //if ((acc.FileSystemRights & FileSystemRights.ReadData) == FileSystemRights.ReadData) - //{ - // Console.Write("ReadData"); - //} - //if ((acc.FileSystemRights & FileSystemRights.WriteData) == FileSystemRights.WriteData) - //{ - // Console.Write("WriteData"); - //} - //if ((acc.FileSystemRights & FileSystemRights.ListDirectory) == FileSystemRights.ListDirectory) - //{ - // Console.Write("ListDirectory"); - //} - //if ((acc.FileSystemRights & FileSystemRights.ExecuteFile) == FileSystemRights.ExecuteFile) - //{ - // Console.Write("ExecuteFile"); - //} - } - MessageBox.Show(message); - //WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent(); - // FileSystemAccessRule rule = new FileSystemAccessRule( - // self.Name, - // FileSystemRights.FullControl, - // AccessControlType.Allow); - } - - void MainForm_KeyDown(object sender, KeyEventArgs e) - { - for (int i = 0; i < ControlPads.Length; i++) - { - // If Escape key was pressed while recording then... - if (e.KeyCode == Keys.Escape) - { - var recordingWasStopped = ControlPads[i].StopRecording(); - if (recordingWasStopped) - { - e.Handled = true; - e.SuppressKeyPress = true; - }; - } - } - StatusTimerLabel.Text = ""; - } - - void CleanStatusTimer_Elapsed(object sender, EventArgs e) - { - if (Program.IsClosing) return; - StatusTimerLabel.Text = ""; - } - - #region Setting Events - - object eventsLock = new object(); - int eventsSuspendCount; - - public void SuspendEvents() - { - lock (eventsLock) - { - eventsSuspendCount++; - StatusEventsLabel.Text = string.Format("Suspend: {0}", eventsSuspendCount); - // If events already suspended then return. - if (eventsSuspendCount > 1) return; - // Don't allow controls to fire events. - var controls = SettingManager.Current.SettingsMap.Select(x => x.Control).ToArray(); - foreach (var control in controls) - { - if (control is NumericUpDown) ((NumericUpDown)control).ValueChanged -= new EventHandler(Control_ValueChanged); - if (control is ListBox) ((ListBox)control).SelectedIndexChanged -= new EventHandler(Control_SelectedIndexChanged); - if (control is TrackBar) ((TrackBar)control).ValueChanged -= new EventHandler(Control_ValueChanged); - if (control is CheckBox) ((CheckBox)control).CheckedChanged -= new EventHandler(Control_CheckedChanged); - if (control is ComboBox) - { - var cbx = (ComboBox)control; - if (cbx.DropDownStyle == ComboBoxStyle.DropDownList) - { - cbx.SelectedIndexChanged -= new EventHandler(Control_TextChanged); - } - else - { - cbx.TextChanged -= new EventHandler(Control_TextChanged); - } - } - } - } - } - - public void ResumeEvents() - { - lock (eventsLock) - { - eventsSuspendCount--; - StatusEventsLabel.Text = string.Format("Suspend: {0}", eventsSuspendCount); - // If events already resumed then return. - if (eventsSuspendCount < 1) return; - // Allow controls to fire events. - var controls = SettingManager.Current.SettingsMap.Select(x => x.Control); - foreach (var control in controls) - { - if (control is NumericUpDown) ((NumericUpDown)control).ValueChanged += new EventHandler(Control_ValueChanged); - if (control is ListBox) ((ListBox)control).SelectedIndexChanged += new EventHandler(Control_SelectedIndexChanged); - if (control is TrackBar) ((TrackBar)control).ValueChanged += new EventHandler(Control_ValueChanged); - if (control is CheckBox) ((CheckBox)control).CheckedChanged += new EventHandler(Control_CheckedChanged); - if (control is ComboBox) - { - var cbx = (ComboBox)control; - if (cbx.DropDownStyle == ComboBoxStyle.DropDownList) - { - cbx.SelectedIndexChanged += new EventHandler(Control_TextChanged); - } - else - { - cbx.TextChanged += new EventHandler(Control_TextChanged); - } - } - } - } - } - - #region Control Changed Events - - Dictionary ListBoxCounts = new Dictionary(); - - /// Monitor changes remove/add inside ListBoxes. - void Control_SelectedIndexChanged(object sender, EventArgs e) - { - lock (ListBoxCounts) - { - var lb = (ListBox)sender; - // If list contains count of ListBoxes items. - if (ListBoxCounts.ContainsKey(lb.Name)) - { - // If ListBoxe haven't changed then return; - if (ListBoxCounts[lb.Name] == lb.Items.Count) return; - ListBoxCounts[lb.Name] = lb.Items.Count; - } - else - { - ListBoxCounts.Add(lb.Name, lb.Items.Count); - } - } - // Save setting and notify if value changed. - NotifySettingsChange((Control)sender); - } - - void Control_TextChanged(object sender, EventArgs e) - { - // Save setting and notify if value changed. - NotifySettingsChange((Control)sender); - } - - void Control_ValueChanged(object sender, EventArgs e) - { - // Save setting and notify if value changed. - NotifySettingsChange((Control)sender); - } - - void Control_CheckedChanged(object sender, EventArgs e) - { - // Save setting and notify if value changed. - NotifySettingsChange((Control)sender); - } - - /// - /// Delay settings trough timer so interface will be more responsive on TrackBars. - /// Or fast changes. Library will be reloaded as soon as user calms down (no setting changes in 500ms). - /// - public void NotifySettingsChange(Control changedControl) - { - var game = GetCurrentGame(); - var iniContent = SettingManager.Current.GetIniContent(game); - if (IniTextBox.Text != iniContent) - { - IniTextBox.Text = iniContent; - } - // If settings changed then... - if (SettingManager.Current.WriteSettingToIni(changedControl)) - { - // Stop updating forms and controls. - // Update Timer will be started inside Settings timer. - UpdateTimer.Stop(); - SettingsTimer.Stop(); - SettingsTimer.Start(); - } - } - - void SettingsTimer_Elapsed(object sender, EventArgs e) - { - if (Program.IsClosing) return; - //settingsChanged = true; - UpdateTimer.Start(); - } - - #endregion - - //public void ReloadXinputSettings() - //{ - // SuspendEvents(); - // SettingManager.Current.ReadSettings(); - // ResumeEvents(); - //} - - //public void SaveSettings() - //{ - // UpdateTimer.Stop(); - // // Save settings to INI file. - // SettingManager.Current.WriteAllSettingsToInit(); - // // Overwrite Temp file. - // var ini = new FileInfo(SettingManager.IniFileName); - // ini.CopyTo(SettingManager.TmpFileName, true); - // StatusTimerLabel.Text = "Settings saved"; - // UpdateTimer.Start(); - //} - - #endregion - - public static object XInputLock = new object(); - - void MainForm_FormClosing(object sender, FormClosingEventArgs e) - { - Program.IsClosing = true; - if (UpdateTimer != null) UpdateTimer.Stop(); - // Disable force feedback effect before closing app. - try - { - lock (XInputLock) - { - for (int i = 0; i < 4; i++) - { - if (ControlPads[i].LeftMotorTestTrackBar.Value > 0 || ControlPads[i].RightMotorTestTrackBar.Value > 0) - { - var gamePad = XiControllers[i]; - if (XInput.IsLoaded && gamePad.IsConnected) - { - gamePad.SetVibration(new Vibration()); - } - } - } - //BeginInvoke((MethodInvoker)delegate() - //{ - // XInput.FreeLibrary(); - //}); - } - System.Threading.Thread.Sleep(100); - } - catch (Exception) { } - var tmp = new FileInfo(SettingManager.TmpFileName); - var ini = new FileInfo(SettingManager.IniFileName); - if (tmp.Exists) - { - // Before renaming file check for changes. - var changed = false; - if (tmp.Length != ini.Length) { changed = true; } - else - { - var tmpChecksum = EngineHelper.GetFileChecksum(tmp.FullName); - var iniChecksum = EngineHelper.GetFileChecksum(ini.FullName); - changed = !tmpChecksum.Equals(iniChecksum); - } - if (changed) - { - var form = new MessageBoxForm(); - form.StartPosition = FormStartPosition.CenterParent; - var result = form.ShowForm( - "Do you want to save changes you made to configuration?", - "Save Changes?", - MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); - if (result == DialogResult.Yes) - { - // Do nothing since INI contains latest updates. - } - else if (result == DialogResult.No) - { - // Rename temp to INI. - tmp.CopyTo(SettingManager.IniFileName, true); - } - else if (result == DialogResult.Cancel) - { - e.Cancel = true; - return; - } - } - // delete temp. - tmp.Delete(); - } - Settings.Default.Save(); - SettingManager.Settings.Save(); - SettingManager.Summaries.Save(); - SettingManager.Programs.Save(); - SettingManager.Games.Save(); - SettingManager.Presets.Save(); - SettingManager.PadSettings.Save(); - } - - #region Timer - - public bool forceRecountDevices = true; - - //string deviceInstancesOld = ""; - //string deviceInstancesNew = ""; - public Guid AutoSelectControllerInstance = Guid.Empty; - - public DirectInput Manager = new DirectInput(); - - ///// - ///// Get direct input devices. - ///// - //DeviceInstance[] GetDevices() - //{ - // var devices = Manager.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AllDevices).ToList(); - // if (SettingManager.Current.ExcludeSuplementalDevices) - // { - // // Supplemental devices are specialized device with functionality unsuitable for the main control of an application, - // // such as pedals used with a wheel.The following subtypes are defined. - // var supplementals = devices.Where(x => x.Type == SharpDX.DirectInput.DeviceType.Supplemental).ToArray(); - // foreach (var supplemental in supplementals) - // { - // devices.Remove(supplemental); - // } - // } - // if (SettingManager.Current.ExcludeVirtualDevices) - // { - // // Exclude virtual devices so application could feed them. - // var virtualDevices = devices.Where(x => x.InstanceName.Contains("vJoy")).ToArray(); - // foreach (var virtualDevice in virtualDevices) - // { - // devices.Remove(virtualDevice); - // } - // } - // // Move gaming wheels to the top index position by default. - // // Games like GTA need wheel to be first device to work properly. - // var wheels = devices.Where(x => x.Type == SharpDX.DirectInput.DeviceType.Driving || x.Subtype == (int)DeviceSubType.Wheel).ToArray(); - // foreach (var wheel in wheels) - // { - // devices.Remove(wheel); - // devices.Insert(0, wheel); - // } - // var orderedDevices = new DeviceInstance[4]; - // // Assign devices to their positions. - // for (int d = 0; d < devices.Count; d++) - // { - // var ig = devices[d].InstanceGuid; - // var section = SettingManager.Current.GetInstanceSection(ig); - // var ini2 = new Ini(SettingManager.IniFileName); - // string v = ini2.GetValue(section, SettingName.MapToPad); - // int mapToPad = 0; - // if (int.TryParse(v, out mapToPad) && mapToPad > 0 && mapToPad <= 4) - // { - // // If position is not occupied then... - // if (orderedDevices[mapToPad - 1] == null) - // { - // orderedDevices[mapToPad - 1] = devices[d]; - // } - // } - // } - // // Get list of unassigned devices. - // var unassignedDevices = devices.Except(orderedDevices).ToArray(); - // for (int i = 0; i < unassignedDevices.Length; i++) - // { - // // Assign to first empty slot. - // for (int d = 0; d < orderedDevices.Length; d++) - // { - // // If position is not occupied then... - // if (orderedDevices[d] == null) - // { - // orderedDevices[d] = unassignedDevices[i]; - // break; - // } - // } - // } - // return orderedDevices; - //} - - - ///// - ///// Access this only inside Timer_Click! - ///// - //bool RefreshCurrentInstances(bool forceReload = false) - //{ - // bool instancesChanged = false; - // DeviceInstance[] devices = null; - // //var types = DeviceType.Driving | DeviceType.Flight | DeviceType.Gamepad | DeviceType.Joystick | DeviceType.FirstPerson; - // if (forceRecountDevices || forceReload) - // { - // devices = GetDevices(); - // // Store device instances and their order. - // deviceInstancesNew = string.Join(",", devices.Select(x => x == null ? "" : x.InstanceGuid.ToString())); - // forceRecountDevices = false; - // } - // // If device list changed then... - // if (deviceInstancesNew != deviceInstancesOld) - // { - // deviceInstancesOld = deviceInstancesNew; - // if (devices == null) devices = GetDevices(); - // var instances = devices; - // // Dispose previous list of devices. - // for (int i = 0; i < 4; i++) - // { - // if (DiDevices[i].State != null) - // { - // // Dispose current device. - // DiDevices[i].State.Unacquire(); - // DiDevices[i].State.Dispose(); - // } - // } - // // Create new list of devices. - // for (int i = 0; i < 4; i++) - // { - // var inst = instances[i]; - // if (inst == null) - // { - // DiDevices[i].State = null; - // DiDevices[i].Info = null; - // } - // else - // { - - // var j = new Joystick(Manager, inst.InstanceGuid); - // DiDevices[i].State = j; - // var classGuid = j.Properties.ClassGuid; - // var interfacePath = j.Properties.InterfacePath; - // // Must find better way to find Device than by Vendor ID and Product ID. - // var devs = DeviceDetector.GetDevices(classGuid, JocysCom.ClassLibrary.Win32.DIGCF.DIGCF_ALLCLASSES, null, j.Properties.VendorId, j.Properties.ProductId, 0); - // DiDevices[i].Info = devs.FirstOrDefault(); - // } - // } - // SettingsDatabasePanel.BindDevices(instances); - // SettingsDatabasePanel.BindFiles(); - // for (int i = 0; i < 4; i++) - // { - // // Backup old instance. - // DiDevices[i].InstanceOld = DiDevices[i].Instance; - // // Assign new instance. - // DiDevices[i].Instance = instances[i]; - // } - // instancesChanged = true; - // } - // // Return true if instances changed. - // return instancesChanged; - //} - - // This value will be modified to true when settings on the form changes and - // XInput library needs to be reload. - bool settingsChanged = false; - State emptyState = new State(); - - //bool[] cleanPadStatus = new bool[4]; - - object formLoadLock = new object(); - public bool update1Enabled = true; - public bool? update2Enabled; - public bool update3Enabled = false; - - void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - if (Program.IsClosing) return; - Program.TimerCount++; - lock (formLoadLock) - { - if (update1Enabled) - { - update1Enabled = false; - UpdateForm1(); - // Update 2 part will be enabled after all issues are checked. - } - if (update2Enabled.HasValue && update2Enabled.Value) - { - update2Enabled = false; - UpdateForm2(); - update3Enabled = true; - } - if (update3Enabled) - { - UpdateForm3(); - } - } - UpdateTimer.Start(); - } - - void UpdateForm1() - { - InitDevices(); - //if (DesignMode) return; - OptionsPanel.InitOptions(); - // Set status. - StatusSaveLabel.Visible = false; - StatusEventsLabel.Visible = false; - // Load Tab pages. - ControlPages = new TabPage[4]; - ControlPages[0] = Pad1TabPage; - ControlPages[1] = Pad2TabPage; - ControlPages[2] = Pad3TabPage; - ControlPages[3] = Pad4TabPage; - //BuletImageList.Images.Add("bullet_square_glass_blue.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_blue.png"))); - //BuletImageList.Images.Add("bullet_square_glass_green.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_green.png"))); - //BuletImageList.Images.Add("bullet_square_glass_grey.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_grey.png"))); - //BuletImageList.Images.Add("bullet_square_glass_red.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_red.png"))); - //BuletImageList.Images.Add("bullet_square_glass_yellow.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_yellow.png"))); - foreach (var item in ControlPages) item.ImageKey = "bullet_square_glass_grey.png"; - // Hide status values. - StatusDllLabel.Text = ""; - MainStatusStrip.Visible = false; - // Check for various issues. - InitWarnigForm(); - InitDeviceForm(); - } - - void UpdateForm2() - { - // Set status labels. - StatusIsAdminLabel.Text = WinAPI.IsVista - ? string.Format("Elevated: {0}", WinAPI.IsElevated()) - : ""; - StatusIniLabel.Text = SettingManager.IniFileName; - CheckEncoding(SettingManager.TmpFileName); - CheckEncoding(SettingManager.IniFileName); - // Show status values. - MainStatusStrip.Visible = true; - // Load PAD controls. - ControlPads = new PadControl[4]; - for (int i = 0; i < ControlPads.Length; i++) - { - ControlPads[i] = new Controls.PadControl((MapTo)i + 1); - ControlPads[i].Name = string.Format("ControlPad{0}", i + 1); - ControlPads[i].Dock = DockStyle.Fill; - ControlPages[i].Controls.Add(ControlPads[i]); - ControlPads[i].InitPadControl(); - } - // Initialize pre-sets. Execute only after name of cIniFile is set. - //SettingsDatabasePanel.InitPresets(); - // Allow events after PAD control are loaded. - MainTabControl.SelectedIndexChanged += new System.EventHandler(this.MainTabControl_SelectedIndexChanged); - // Load about control. - ControlAbout = new AboutControl(); - ControlAbout.Dock = DockStyle.Fill; - AboutTabPage.Controls.Add(ControlAbout); - // Update settings map. - UpdateSettingsMap(); - //ReloadXinputSettings(); - //// start capture events. - if (WinAPI.IsVista && WinAPI.IsElevated() && WinAPI.IsInAdministratorRole) this.Text += " (Administrator)"; - } - - - /// - /// This method will run continuously by the UpdateTimer. - /// - void UpdateForm3() - { - // If settings changed then... - if (settingsChanged) - { - ReloadLibrary(); - } - else - { - for (int i = 0; i < 4; i++) - { - var game = MainForm.Current.GetCurrentGame(); - var currentFile = (game == null) ? null : game.FileName; - // Get devices mapped to game and specific controller index. - var devices = SettingManager.GetDevices(currentFile, (MapTo)(i + 1)); - // DInput instance is ON if active devices was found. - var diOn = devices.Count > 0; - // XInput instance is ON. - var xiOn = false; - State currentGamePad = emptyState; - lock (XInputLock) - { - var gamePad = XiControllers[i]; - if (XInput.IsLoaded && gamePad.IsConnected) - { - currentGamePad = gamePad.GetState(); - xiOn = true; - } - } - var padControl = ControlPads[i]; - // Update Form from DInput state. - padControl.UpdateFromDInput(); - // Update Form from XInput state. - padControl.UpdateFromXInput(currentGamePad, xiOn); - // Update LED of GamePad state. - string image = diOn - // DInput ON, XInput ON - ? xiOn ? "green" - // DInput ON, XInput OFF - : "red" - // DInput OFF, XInput ON - : xiOn ? "yellow" - // DInput OFF, XInput OFF - : "grey"; - string bullet = string.Format("bullet_square_glass_{0}.png", image); - if (ControlPages[i].ImageKey != bullet) ControlPages[i].ImageKey = bullet; - } - UpdateStatus(); - } - } - - public void ReloadLibrary() - { - Program.ReloadCount++; - //settingsChanged = false; - var dllInfo = EngineHelper.GetDefaultDll(); - if (dllInfo != null && dllInfo.Exists) - { - bool byMicrosoft; - var dllVersion = EngineHelper.GetDllVersion(dllInfo.FullName, out byMicrosoft); - StatusDllLabel.Text = dllInfo.Name + " " + dllVersion.ToString() + (byMicrosoft ? " (Microsoft)" : ""); - // If fast reload of settings is supported then... - lock (XInputLock) - { - if (XInput.IsResetSupported) - { - XInput.Reset(); - } - // Slow: Reload whole x360ce.dll. - Exception error; - //forceRecountDevices = true; - XInput.ReLoadLibrary(dllInfo.Name, out error); - if (!XInput.IsLoaded) - { - var caption = string.Format("Failed to load '{0}'", dllInfo.Name); - var text = string.Format("{0}", error == null ? "Unknown error" : error.Message); - var form = new MessageBoxForm(); - form.StartPosition = FormStartPosition.CenterParent; - form.ShowForm(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - else - { - for (int i = 0; i < 4; i++) - { - - var currentPadControl = ControlPads[i]; - currentPadControl.UpdateForceFeedBack(); - } - } - } - } - else - { - StatusDllLabel.Text = ""; - } - } - - public void UpdateStatus(string message = "") - { - AppHelper.SetText(StatusTimerLabel, "Count: {0}, Reloads: {1}, Errors: {2} {3}", - Program.TimerCount, Program.ReloadCount, Program.ErrorCount, message); - } - #endregion - - bool HelpInit = false; - - void MainTabControl_SelectedIndexChanged(object sender, EventArgs e) - { - if (MainTabControl.SelectedTab == HelpTabPage && !HelpInit) - { - // Move this here so interface will load one second faster. - HelpInit = true; - var stream = EngineHelper.GetResource("Documents.Help.htm"); - var sr = new StreamReader(stream); - NameValueCollection list = new NameValueCollection(); - list.Add("font-name-default", "'Microsoft Sans Serif'"); - list.Add("font-size-default", "16"); - HelpRichTextBox.Rtf = Html2Rtf.Converter.Html2Rtf(sr.ReadToEnd(), list); - HelpRichTextBox.SelectAll(); - HelpRichTextBox.SelectionIndent = 8; - HelpRichTextBox.SelectionRightIndent = 8; - HelpRichTextBox.DeselectAll(); - } - else if (MainTabControl.SelectedTab == ControllerSettingsTabPage) - { - if (OptionsPanel.InternetCheckBox.Checked && OptionsPanel.InternetAutoloadCheckBox.Checked) - { - SettingsDatabasePanel.RefreshGrid(true); - } - } - var tab = MainTabControl.SelectedTab; - if (tab != null) SetHeaderSubject(tab.Text); - } - - public void XInputEnable(bool enable) - { - lock (XInputLock) - { - XInput.XInputEnable(enable); - } - } - - #region Check Files - - void CheckEncoding(string path) - { - if (!File.Exists(path)) return; - var sr = new StreamReader(path, true); - var content = sr.ReadToEnd(); - sr.Close(); - if (sr.CurrentEncoding != System.Text.Encoding.Unicode) - { - File.WriteAllText(path, content, System.Text.Encoding.Unicode); - } - } - - bool IsFileSame(string fileName) - { - return false; - //if (!System.IO.File.Exists(fileName)) return false; - //var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); - //StreamReader sr; - //// Get MD5 of file on the disk. - //sr = new StreamReader(fileName); - //var dMd5 = new Guid(md5.ComputeHash(sr.BaseStream)); - //// Get MD5 of resource file. - //if (fileName == dllFile0) fileName = dllFile; - //if (fileName == dllFile1) fileName = dllFile; - //if (fileName == dllFile2) fileName = dllFile; - //if (fileName == dllFile3) fileName = dllFile; - //var assembly = Assembly.GetExecutingAssembly(); - //sr = new StreamReader(assembly.GetManifestResourceStream(this.GetType().Namespace + ".Presets." + fileName)); - //var rMd5 = new Guid(md5.ComputeHash(sr.BaseStream)); - //// return result. - //return rMd5.Equals(dMd5); - } - - public bool CreateFile(string resourceName, string destinationFileName, ProcessorArchitecture oldArchitecture, ProcessorArchitecture newArchitecture) - { - if (destinationFileName == null) destinationFileName = resourceName; - DialogResult answer; - var form = new MessageBoxForm(); - form.StartPosition = FormStartPosition.CenterParent; - var oldDesc = EngineHelper.GetProcessorArchitectureDescription(oldArchitecture); - var newDesc = EngineHelper.GetProcessorArchitectureDescription(newArchitecture); - var fileName = new FileInfo(destinationFileName).Name; - answer = form.ShowForm( - string.Format("You are running {2} application but {0} on the disk was built for {1} architecture.\r\n\r\nDo you want to replace {0} file with {2} version?", fileName, oldDesc, newDesc), - "Processor architecture mismatch.", - MessageBoxButtons.YesNo, MessageBoxIcon.Information); - if (answer == DialogResult.Yes) - { - return AppHelper.WriteFile(resourceName, destinationFileName); - } - return true; - } - - public bool CreateFile(string resourceName, string destinationFileName, Version oldVersion = null, Version newVersion = null) - { - if (destinationFileName == null) destinationFileName = resourceName; - DialogResult answer; - var form = new MessageBoxForm(); - form.StartPosition = FormStartPosition.CenterParent; - var fileName = new FileInfo(destinationFileName).FullName; - if (newVersion == null) - { - answer = form.ShowForm( - string.Format("'{0}' was not found.\r\nThis file is required for emulator to function properly.\r\n\r\nDo you want to create this file?", fileName), - string.Format("'{0}' was not found.", destinationFileName), - MessageBoxButtons.YesNo, MessageBoxIcon.Warning); - } - else - { - answer = form.ShowForm( - string.Format("New version of this file is available:\r\n{0}\r\n\r\nOld version: {1}\r\nNew version: {2}\r\n\r\nDo you want to update this file?", fileName, oldVersion, newVersion), - string.Format("New version of '{0}' file is available.", destinationFileName), - MessageBoxButtons.YesNo, MessageBoxIcon.Information); - } - if (answer == DialogResult.Yes) - { - return AppHelper.WriteFile(resourceName, destinationFileName); - } - return true; - } - - #endregion - - #region Allow only one copy of Application at a time - - /// Stores the unique windows message id from the RegisterWindowMessage call. - int _WindowMessage; - /// Used to determine if the application is already open. - System.Threading.Mutex _Mutex; - - public const int wParam_Restore = 1; - public const int wParam_Close = 2; - - /// - /// Broadcast message to other instances of this application. - /// - /// Send parameter to other instances of this application. - /// True - other instances exists; False - other instances doesn't exist. - public bool BroadcastMessage(int wParam) - { - Exception error; - // Check for previous instance of this app. - var uid = Application.ProductName; - _Mutex = new System.Threading.Mutex(false, uid); - // Register the windows message - _WindowMessage = NativeMethods.RegisterWindowMessage(uid, out error); - var firsInstance = _Mutex.WaitOne(1, true); - // If this is not the first instance then... - if (!firsInstance) - { - // Broadcast a message with parameters to another instance. - var recipients = (int)BSM.BSM_APPLICATIONS; - var flags = BSF.BSF_IGNORECURRENTTASK | BSF.BSF_POSTMESSAGE; - var ret = NativeMethods.BroadcastSystemMessage((int)flags, ref recipients, _WindowMessage, wParam, 0, out error); - } - return !firsInstance; - } - - /// - /// NOTE: you must be careful with this method, because this method is responsible for all the - /// windows messages that are coming to the form. - /// - /// - /// This overrides the windows messaging processing - protected override void DefWndProc(ref Message m) - { - // If message value was found then... - if (m.Msg == _WindowMessage) - { - // Show currently running instance. - if (m.WParam.ToInt32() == wParam_Restore) - { - // Note: FormWindowState.Minimized and FormWindowState.Normal was used to make sure that Activate() wont fail because of this: - // Windows NT 5.0 and later: An application cannot force a window to the foreground while the user is working with another window. - // Instead, SetForegroundWindow will activate the window (see SetActiveWindow) and call theFlashWindowEx function to notify the user. - if (WindowState != FormWindowState.Minimized) WindowState = FormWindowState.Minimized; - this.Activate(); - if (WindowState == FormWindowState.Minimized) WindowState = FormWindowState.Normal; - } - // Close currently running instance. - if (m.WParam.ToInt32() == wParam_Close) - { - Close(); - } - } - // Let the normal windows messaging process it. - base.DefWndProc(ref m); - } - - #endregion - - #region Warning Form - - WarningsForm _WarningForm; - object warningFormLock = new object(); - - void InitWarnigForm() - { - lock (warningFormLock) - { - _WarningForm = new WarningsForm(); - _WarningForm.CheckTimer.Start(); - } - } - - void DisposeWarnigForm() - { - lock (warningFormLock) - { - if (_WarningForm != null) - { - _WarningForm.Dispose(); - _WarningForm = null; - } - } - } - - #endregion - - #region Device Form - - MapDeviceToControllerForm _DeviceForm; - object DeviceFormLock = new object(); - - void InitDeviceForm() - { - lock (DeviceFormLock) - { - _DeviceForm = new MapDeviceToControllerForm(); - } - } - - void DisposeDeviceForm() - { - lock (DeviceFormLock) - { - if (_DeviceForm != null) - { - _DeviceForm.Dispose(); - _DeviceForm = null; - } - } - } - - public DiDevice ShowDeviceForm() - { - DiDevice selectedItem = null; - lock (DeviceFormLock) - { - if (_DeviceForm == null) return null; - _DeviceForm.StartPosition = FormStartPosition.CenterParent; - var result = _DeviceForm.ShowDialog(); - if (result == DialogResult.OK) - { - selectedItem = _DeviceForm.SelectedDevice; - } - } - return selectedItem; - } - - #endregion - - /// - /// Clean up any - /// being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - if (_Mutex != null) - { - _Mutex.Dispose(); - } - DisposeWarnigForm(); - DisposeDeviceForm(); - if (detector != null) - { - detector.Dispose(); - detector = null; - } - Manager.Dispose(); - Manager = null; - components.Dispose(); - //lock (checkTimerLock) - //{ - // // If timer is disposed then return; - // if (checkTimer == null) return; - // CheckAll(); - //} - } - base.Dispose(disposing); - } - - private void OpenApplicationToolStripMenuItem_Click(object sender, EventArgs e) - { - RestoreFromTray(); - } - - private void ExitToolStripMenuItem_Click(object sender, EventArgs e) - { - Close(); - } - - #region Restore and Minimize - - FormWindowState? oldWindowState; - object lastStateLock = new object(); - - /// Will be used to prevent form flickering when restoring from tray. - bool ignoreMinimizeToTray; - - private void MainForm_Resize(object sender, EventArgs e) - { - // Track window state changes. - lock (lastStateLock) - { - var newWindowState = WindowState; - if (!oldWindowState.HasValue || oldWindowState.Value != newWindowState) - { - oldWindowState = newWindowState; - UpdateStatusBar(newWindowState); - } - } - } - - void UpdateStatusBar(FormWindowState state) - { - if (state == FormWindowState.Minimized) - { - if (!ignoreMinimizeToTray) - { - if (ShowInTaskbar == Settings.Default.MinimizeToTray) - { - ShowInTaskbar = !Settings.Default.MinimizeToTray; - } - } - } - else - { - ignoreMinimizeToTray = false; - if (ShowInTaskbar == false) - { - ShowInTaskbar = true; - } - } - } - - public bool MinimizeToTrayChanging; - public void SetMinimizeToTray(bool value) - { - if (MinimizeToTrayChanging) return; - MinimizeToTrayChanging = true; - if (OptionsPanel.MinimizeToTrayCheckBox.Checked != value) - { - OptionsPanel.MinimizeToTrayCheckBox.Checked = value; - } - if (Settings.Default.MinimizeToTray != value) - { - Settings.Default.MinimizeToTray = value; - } - UpdateStatusBar(WindowState); - MinimizeToTrayChanging = false; - } - - /// - /// Method to Minimize the window and Hide the window item in the TaskBar. - /// - public void MinimizeToTray(bool showBalloonTip) - { - // Show only first time. - if (showBalloonTip) - { - TrayNotifyIcon.BalloonTipText = "Password Generator..."; - // Show balloon tip for 2 seconds. - TrayNotifyIcon.ShowBalloonTip(2); - } - // hold - program. - // NOTE: also it would be possible to track which direction mouse will move in or move out on TrayIcon. - // For example: open program if mouse moves in from left and moves out from top. - TrayNotifyIcon.Text = "Click: double - program, left - generate, right - menu."; - if (WindowState != FormWindowState.Minimized) WindowState = FormWindowState.Minimized; - } - - /// - /// Restores the window. - /// - public void RestoreFromTray() - { - ignoreMinimizeToTray = true; - // Show in task bar before restoring windows state in order to prevent flickering. - ShowInTaskbar = true; - if (WindowState != FormWindowState.Normal) - { - WindowState = FormWindowState.Normal; - } - BringToFront(); - } - - void MinimizeToTrayToolStripMenuItem_Click(object sender, EventArgs e) - { - SetMinimizeToTray(!Settings.Default.MinimizeToTray); - } - - #endregion - - private void TrayNotifyIcon_DoubleClick(object sender, EventArgs e) - { - RestoreFromTray(); - } - - private void GameToCustomizeComboBox_SelectedIndexChanged(object sender, EventArgs e) - { - - } - } + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + } + + DeviceDetector detector; + + public static MainForm Current { get; set; } + + public Engine.Data.Game GetCurrentGame() + { + Engine.Data.Game game = null; + var item = GameToCustomizeComboBox.SelectedItem; + if (item != null) + { + game = (Engine.Data.Game)item; + + } + return game; + } + + public int oldIndex; + + public int ControllerIndex + { + get + { + int newIndex = -1; + if (MainTabControl.SelectedTab == Pad1TabPage) newIndex = 0; + if (MainTabControl.SelectedTab == Pad2TabPage) newIndex = 1; + if (MainTabControl.SelectedTab == Pad3TabPage) newIndex = 2; + if (MainTabControl.SelectedTab == Pad4TabPage) newIndex = 3; + return newIndex; + } + set + { + switch (value) + { + case 0: MainTabControl.SelectedTab = Pad1TabPage; break; + case 1: MainTabControl.SelectedTab = Pad2TabPage; break; + case 2: MainTabControl.SelectedTab = Pad3TabPage; break; + case 3: MainTabControl.SelectedTab = Pad4TabPage; break; + } + } + } + + public AboutControl ControlAbout; + public PadControl[] ControlPads; + public TabPage[] ControlPages; + + /// + /// Settings timer will be used to delay applying settings, which will heavy load application, as long as user is changing them. + /// + public System.Timers.Timer SettingsTimer; + + public System.Timers.Timer UpdateTimer; + + public System.Timers.Timer CleanStatusTimer; + public int DefaultPoolingInterval = 50; + + public Controller[] XiControllers = new Controller[4]; + + void MainForm_Load(object sender, EventArgs e) + { + if (IsDesignMode) return; + SettingManager.Settings.Load(); + SettingManager.Summaries.Load(); + SettingManager.Summaries.Items.ListChanged += Summaries_ListChanged; + // Make sure that data will be filtered before loading. + // Note: Make sure to load Programs before Games. + SettingManager.Programs.FilterList = Programs_FilterList; + SettingManager.Programs.Load(); + // Make sure that data will be filtered before loading. + SettingManager.Games.FilterList = Games_FilterList; + SettingManager.Games.Load(); + SettingManager.Presets.Load(); + SettingManager.PadSettings.Load(); + for (int i = 0; i < 4; i++) + { + XiControllers[i] = new Controller((UserIndex)i); + } + GameToCustomizeComboBox.DataSource = SettingManager.Games.Items; + GameToCustomizeComboBox.DisplayMember = "DisplayName"; + UpdateTimer = new System.Timers.Timer(); + UpdateTimer.AutoReset = false; + UpdateTimer.SynchronizingObject = this; + UpdateTimer.Interval = DefaultPoolingInterval; + UpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(UpdateTimer_Elapsed); + SettingsTimer = new System.Timers.Timer(); + SettingsTimer.AutoReset = false; + SettingsTimer.SynchronizingObject = this; + SettingsTimer.Interval = 500; + SettingsTimer.Elapsed += new System.Timers.ElapsedEventHandler(SettingsTimer_Elapsed); + CleanStatusTimer = new System.Timers.Timer(); + CleanStatusTimer.AutoReset = false; + CleanStatusTimer.SynchronizingObject = this; + CleanStatusTimer.Interval = 3000; + CleanStatusTimer.Elapsed += new System.Timers.ElapsedEventHandler(CleanStatusTimer_Elapsed); + Text = EngineHelper.GetProductFullName(); + SetMinimizeToTray(Settings.Default.MinimizeToTray); + // Start Timers. + UpdateTimer.Start(); + } + + IList Programs_FilterList(IList items) + { + // Make sure default settings have unique by file name. + var distinctItems = items + .GroupBy(p => p.FileName.ToLower()) + .Select(g => g.First()) + .ToList(); + return distinctItems; + } + + IList Games_FilterList(IList items) + { + // Make sure default settings have unique by file name. + var distinctItems = items + .GroupBy(p => p.FileName.ToLower()) + .Select(g => g.First()) + .ToList(); + + // Check if current app doesn't exist in the list then... + var appFile = new FileInfo(Application.ExecutablePath); + var appItem = distinctItems.FirstOrDefault(x => x.FileName.ToLower() == appFile.Name.ToLower()); + if (appItem == null) + { + // Add x360ce.exe + var item = x360ce.Engine.Data.Game.FromDisk(appFile.Name); + var program = SettingManager.Programs.Items.FirstOrDefault(x => x.FileName.ToLower() == appFile.Name.ToLower()); + item.LoadDefault(program); + distinctItems.Add(item); + } + else + { + appItem.FullPath = appFile.FullName; + } + return distinctItems; + } + + private void Summaries_ListChanged(object sender, ListChangedEventArgs e) + { + // If map to changed then re-detect devices. + var pd = e.PropertyDescriptor; + if (pd != null && pd.Name == "MapTo") + { + forceRecountDevices = true; + } + } + + void InitDevices() + { + detector = new DeviceDetector(false); + UpdateDevices(); + detector.DeviceChanged += new DeviceDetector.DeviceDetectorEventHandler(detector_DeviceChanged); + } + + void detector_DeviceChanged(object sender, DeviceDetectorEventArgs e) + { + BeginInvoke(new Action(() => + { + UpdateDevices(); + })); + } + + object UpdateDevicesLock = new object(); + + void UpdateDevices() + { + lock (UpdateDevicesLock) + { + var devices = Manager.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AllDevices).ToList(); + var deviceInstanceGuid = devices.Select(x => x.InstanceGuid).ToArray(); + var currentInstanceGuids = SettingManager.DiDevices.Select(x => x.InstanceGuid).ToArray(); + var removedDevices = SettingManager.DiDevices.Where(x => !deviceInstanceGuid.Contains(x.InstanceGuid)).ToArray(); + var addedDevices = devices.Where(x => !currentInstanceGuids.Contains(x.InstanceGuid)).ToArray(); + var updatedDevices = devices.Where(x => currentInstanceGuids.Contains(x.InstanceGuid)).ToArray(); + // Remove disconnected devices. + for (int i = 0; i < removedDevices.Length; i++) + { + + SettingManager.DiDevices.Remove(removedDevices[i]); + } + // Add connected devices. + for (int i = 0; i < addedDevices.Length; i++) + { + var device = addedDevices[i]; + var di = new DiDevice(); + di.Instance = device; + var state = new Joystick(Manager, device.InstanceGuid); + di.Device = state; + var classGuid = state.Properties.ClassGuid; + // Must find better way to find Device than by Vendor ID and Product ID. + var info = DeviceDetector.GetDevices( + classGuid, + JocysCom.ClassLibrary.Win32.DIGCF.DIGCF_ALLCLASSES, + null, + state.Properties.VendorId, + state.Properties.ProductId, + 0 + ); + di.Info = info.FirstOrDefault(); + SettingManager.DiDevices.Add(di); + } + for (int i = 0; i < updatedDevices.Length; i++) + { + var device = updatedDevices[i]; + var currentDevice = SettingManager.DiDevices.First(x => x.InstanceGuid.Equals(device.InstanceGuid)); + var state = new Joystick(Manager, device.InstanceGuid); + currentDevice.Device = state; + } + } + var game = GetCurrentGame(); + if (game != null) + { + // Auto-configure new devices. + AutoConfigure(game); + } + } + + void AutoConfigure(Engine.Data.Game game) + { + var list = SettingManager.DiDevices.ToList(); + // Filter devices. + if (Settings.Default.ExcludeSupplementalDevices) + { + // Supplemental devices are specialized device with functionality unsuitable for the main control of an application, + // such as pedals used with a wheel.The following subtypes are defined. + var supplementals = list.Where(x => x.Instance.Type == SharpDX.DirectInput.DeviceType.Supplemental).ToArray(); + foreach (var supplemental in supplementals) + { + list.Remove(supplemental); + } + } + if (Settings.Default.ExcludeSupplementalDevices) + { + // Exclude virtual devices so application could feed them. + var virtualDevices = list.Where(x => x.Instance.InstanceName.Contains("vJoy")).ToArray(); + foreach (var virtualDevice in virtualDevices) + { + list.Remove(virtualDevice); + } + } + // Move gaming wheels to the top index position by default. + // Games like GTA need wheel to be first device to work properly. + var wheels = list.Where(x => + x.Instance.Type == SharpDX.DirectInput.DeviceType.Driving || + x.Instance.Subtype == (int)DeviceSubType.Wheel + ).ToArray(); + foreach (var wheel in wheels) + { + list.Remove(wheel); + list.Insert(0, wheel); + } + // Get configuration of devices for the game. + var settings = SettingManager.GetSettings(game.FileName); + var knownDevices = settings.Select(x => x.InstanceGuid).ToList(); + var newSettingsToProcess = new List(); + int i = 0; + while (true) + { + i++; + // If there are devices which occupies current position then do nothing. + if (settings.Any(x => x.MapTo == i)) continue; + // Try to select first unknown device. + var newDevice = list.FirstOrDefault(x => !knownDevices.Contains(x.InstanceGuid)); + // If no device found then break. + if (newDevice == null) break; + // Create new setting for game/device. + var newSetting = AppHelper.GetNewSetting(newDevice, game, i <= 4 ? (MapTo)i : MapTo.Disabled); + newSettingsToProcess.Add(newSetting); + // Add device to known list. + knownDevices.Add(newDevice.InstanceGuid); + } + foreach (var item in newSettingsToProcess) + { + SettingManager.Settings.Items.Add(item); + } + } + + /// + /// Link control with INI key. Value/Text of control will be automatically tracked and INI file updated. + /// + void UpdateSettingsMap() + { + // INI setting keys with controls. + SettingManager.Current.ConfigSaved += Current_ConfigSaved; + SettingManager.Current.ConfigLoaded += Current_ConfigLoaded; + OptionsPanel.UpdateSettingsManager(); + SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD1, ControlPads[0].DevicesToMapDataGridView); + SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD2, ControlPads[1].DevicesToMapDataGridView); + SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD3, ControlPads[2].DevicesToMapDataGridView); + SettingManager.AddMap(SettingManager.MappingsSection, () => SettingName.PAD4, ControlPads[3].DevicesToMapDataGridView); + } + + void Current_ConfigSaved(object sender, SettingEventArgs e) + { + StatusSaveLabel.Text = string.Format("S {0}", e.Count); + } + + void Current_ConfigLoaded(object sender, SettingEventArgs e) + { + StatusTimerLabel.Text = string.Format("'{0}' loaded.", e.Name); + } + + public void CopyElevated(string source, string dest) + { + if (!WinAPI.IsVista) + { + File.Copy(source, dest); + return; + } + var di = new DirectoryInfo(System.IO.Path.GetDirectoryName(dest)); + var security = di.GetAccessControl(); + var fi = new FileInfo(dest); + var fileSecurity = fi.GetAccessControl(); + // Allow Users to Write. + //SecurityIdentifier SID = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); + //fileSecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.Write, AccessControlType.Allow)); + //fi.SetAccessControl(fileSecurity); + var rules = security.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)); + string message = string.Empty; + foreach (var myacc in rules) + { + var acc = (FileSystemAccessRule)myacc; + message += string.Format("IdentityReference: {0}\r\n", acc.IdentityReference.Value); + message += string.Format("Access Control Type: {0}\r\n", acc.AccessControlType.ToString()); + message += string.Format("\t{0}\r\n", acc.FileSystemRights.ToString()); + //if ((acc.FileSystemRights & FileSystemRights.FullControl) == FileSystemRights.FullControl) + //{ + // Console.Write("FullControl"); + //} + //if ((acc.FileSystemRights & FileSystemRights.ReadData) == FileSystemRights.ReadData) + //{ + // Console.Write("ReadData"); + //} + //if ((acc.FileSystemRights & FileSystemRights.WriteData) == FileSystemRights.WriteData) + //{ + // Console.Write("WriteData"); + //} + //if ((acc.FileSystemRights & FileSystemRights.ListDirectory) == FileSystemRights.ListDirectory) + //{ + // Console.Write("ListDirectory"); + //} + //if ((acc.FileSystemRights & FileSystemRights.ExecuteFile) == FileSystemRights.ExecuteFile) + //{ + // Console.Write("ExecuteFile"); + //} + } + MessageBox.Show(message); + //WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent(); + // FileSystemAccessRule rule = new FileSystemAccessRule( + // self.Name, + // FileSystemRights.FullControl, + // AccessControlType.Allow); + } + + void MainForm_KeyDown(object sender, KeyEventArgs e) + { + for (int i = 0; i < ControlPads.Length; i++) + { + // If Escape key was pressed while recording then... + if (e.KeyCode == Keys.Escape) + { + var recordingWasStopped = ControlPads[i].StopRecording(); + if (recordingWasStopped) + { + e.Handled = true; + e.SuppressKeyPress = true; + }; + } + } + StatusTimerLabel.Text = ""; + } + + void CleanStatusTimer_Elapsed(object sender, EventArgs e) + { + if (Program.IsClosing) return; + StatusTimerLabel.Text = ""; + } + + #region Setting Events + + object eventsLock = new object(); + int eventsSuspendCount; + + public void SuspendEvents() + { + lock (eventsLock) + { + eventsSuspendCount++; + StatusEventsLabel.Text = string.Format("Suspend: {0}", eventsSuspendCount); + // If events already suspended then return. + if (eventsSuspendCount > 1) return; + // Don't allow controls to fire events. + var controls = SettingManager.Current.SettingsMap.Select(x => x.Control).ToArray(); + foreach (var control in controls) + { + if (control is NumericUpDown) ((NumericUpDown)control).ValueChanged -= new EventHandler(Control_ValueChanged); + if (control is ListBox) ((ListBox)control).SelectedIndexChanged -= new EventHandler(Control_SelectedIndexChanged); + if (control is TrackBar) ((TrackBar)control).ValueChanged -= new EventHandler(Control_ValueChanged); + if (control is CheckBox) ((CheckBox)control).CheckedChanged -= new EventHandler(Control_CheckedChanged); + if (control is ComboBox) + { + var cbx = (ComboBox)control; + if (cbx.DropDownStyle == ComboBoxStyle.DropDownList) + { + cbx.SelectedIndexChanged -= new EventHandler(Control_TextChanged); + } + else + { + cbx.TextChanged -= new EventHandler(Control_TextChanged); + } + } + } + } + } + + public void ResumeEvents() + { + lock (eventsLock) + { + eventsSuspendCount--; + StatusEventsLabel.Text = string.Format("Suspend: {0}", eventsSuspendCount); + // If events already resumed then return. + if (eventsSuspendCount < 1) return; + // Allow controls to fire events. + var controls = SettingManager.Current.SettingsMap.Select(x => x.Control); + foreach (var control in controls) + { + if (control is NumericUpDown) ((NumericUpDown)control).ValueChanged += new EventHandler(Control_ValueChanged); + if (control is ListBox) ((ListBox)control).SelectedIndexChanged += new EventHandler(Control_SelectedIndexChanged); + if (control is TrackBar) ((TrackBar)control).ValueChanged += new EventHandler(Control_ValueChanged); + if (control is CheckBox) ((CheckBox)control).CheckedChanged += new EventHandler(Control_CheckedChanged); + if (control is ComboBox) + { + var cbx = (ComboBox)control; + if (cbx.DropDownStyle == ComboBoxStyle.DropDownList) + { + cbx.SelectedIndexChanged += new EventHandler(Control_TextChanged); + } + else + { + cbx.TextChanged += new EventHandler(Control_TextChanged); + } + } + } + } + } + + #region Control Changed Events + + Dictionary ListBoxCounts = new Dictionary(); + + /// Monitor changes remove/add inside ListBoxes. + void Control_SelectedIndexChanged(object sender, EventArgs e) + { + lock (ListBoxCounts) + { + var lb = (ListBox)sender; + // If list contains count of ListBoxes items. + if (ListBoxCounts.ContainsKey(lb.Name)) + { + // If ListBoxe haven't changed then return; + if (ListBoxCounts[lb.Name] == lb.Items.Count) return; + ListBoxCounts[lb.Name] = lb.Items.Count; + } + else + { + ListBoxCounts.Add(lb.Name, lb.Items.Count); + } + } + // Save setting and notify if value changed. + NotifySettingsChange((Control)sender); + } + + void Control_TextChanged(object sender, EventArgs e) + { + // Save setting and notify if value changed. + NotifySettingsChange((Control)sender); + } + + void Control_ValueChanged(object sender, EventArgs e) + { + // Save setting and notify if value changed. + NotifySettingsChange((Control)sender); + } + + void Control_CheckedChanged(object sender, EventArgs e) + { + // Save setting and notify if value changed. + NotifySettingsChange((Control)sender); + } + + /// + /// Delay settings trough timer so interface will be more responsive on TrackBars. + /// Or fast changes. Library will be reloaded as soon as user calms down (no setting changes in 500ms). + /// + public void NotifySettingsChange(Control changedControl) + { + var game = GetCurrentGame(); + var iniContent = SettingManager.Current.GetIniContent(game); + if (IniTextBox.Text != iniContent) + { + IniTextBox.Text = iniContent; + } + // If settings changed then... + if (SettingManager.Current.WriteSettingToIni(changedControl)) + { + // Stop updating forms and controls. + // Update Timer will be started inside Settings timer. + UpdateTimer.Stop(); + SettingsTimer.Stop(); + SettingsTimer.Start(); + } + } + + void SettingsTimer_Elapsed(object sender, EventArgs e) + { + if (Program.IsClosing) return; + //settingsChanged = true; + UpdateTimer.Start(); + } + + #endregion + + //public void ReloadXinputSettings() + //{ + // SuspendEvents(); + // SettingManager.Current.ReadSettings(); + // ResumeEvents(); + //} + + //public void SaveSettings() + //{ + // UpdateTimer.Stop(); + // // Save settings to INI file. + // SettingManager.Current.WriteAllSettingsToInit(); + // // Overwrite Temp file. + // var ini = new FileInfo(SettingManager.IniFileName); + // ini.CopyTo(SettingManager.TmpFileName, true); + // StatusTimerLabel.Text = "Settings saved"; + // UpdateTimer.Start(); + //} + + #endregion + + public static object XInputLock = new object(); + + void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Program.IsClosing = true; + if (UpdateTimer != null) UpdateTimer.Stop(); + // Disable force feedback effect before closing app. + try + { + lock (XInputLock) + { + for (int i = 0; i < 4; i++) + { + if (ControlPads[i].LeftMotorTestTrackBar.Value > 0 || ControlPads[i].RightMotorTestTrackBar.Value > 0) + { + var gamePad = XiControllers[i]; + if (XInput.IsLoaded && gamePad.IsConnected) + { + gamePad.SetVibration(new Vibration()); + } + } + } + //BeginInvoke((MethodInvoker)delegate() + //{ + // XInput.FreeLibrary(); + //}); + } + System.Threading.Thread.Sleep(100); + } + catch (Exception) { } + var tmp = new FileInfo(SettingManager.TmpFileName); + var ini = new FileInfo(SettingManager.IniFileName); + if (tmp.Exists) + { + // Before renaming file check for changes. + var changed = false; + if (tmp.Length != ini.Length) { changed = true; } + else + { + var tmpChecksum = EngineHelper.GetFileChecksum(tmp.FullName); + var iniChecksum = EngineHelper.GetFileChecksum(ini.FullName); + changed = !tmpChecksum.Equals(iniChecksum); + } + if (changed) + { + var form = new MessageBoxForm(); + form.StartPosition = FormStartPosition.CenterParent; + var result = form.ShowForm( + "Do you want to save changes you made to configuration?", + "Save Changes?", + MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); + if (result == DialogResult.Yes) + { + // Do nothing since INI contains latest updates. + } + else if (result == DialogResult.No) + { + // Rename temp to INI. + tmp.CopyTo(SettingManager.IniFileName, true); + } + else if (result == DialogResult.Cancel) + { + e.Cancel = true; + return; + } + } + // delete temp. + tmp.Delete(); + } + Settings.Default.Save(); + SettingManager.Settings.Save(); + SettingManager.Summaries.Save(); + SettingManager.Programs.Save(); + SettingManager.Games.Save(); + SettingManager.Presets.Save(); + SettingManager.PadSettings.Save(); + } + + #region Timer + + public bool forceRecountDevices = true; + + //string deviceInstancesOld = ""; + //string deviceInstancesNew = ""; + public Guid AutoSelectControllerInstance = Guid.Empty; + + public DirectInput Manager = new DirectInput(); + + ///// + ///// Get direct input devices. + ///// + //DeviceInstance[] GetDevices() + //{ + // var devices = Manager.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AllDevices).ToList(); + // if (SettingManager.Current.ExcludeSuplementalDevices) + // { + // // Supplemental devices are specialized device with functionality unsuitable for the main control of an application, + // // such as pedals used with a wheel.The following subtypes are defined. + // var supplementals = devices.Where(x => x.Type == SharpDX.DirectInput.DeviceType.Supplemental).ToArray(); + // foreach (var supplemental in supplementals) + // { + // devices.Remove(supplemental); + // } + // } + // if (SettingManager.Current.ExcludeVirtualDevices) + // { + // // Exclude virtual devices so application could feed them. + // var virtualDevices = devices.Where(x => x.InstanceName.Contains("vJoy")).ToArray(); + // foreach (var virtualDevice in virtualDevices) + // { + // devices.Remove(virtualDevice); + // } + // } + // // Move gaming wheels to the top index position by default. + // // Games like GTA need wheel to be first device to work properly. + // var wheels = devices.Where(x => x.Type == SharpDX.DirectInput.DeviceType.Driving || x.Subtype == (int)DeviceSubType.Wheel).ToArray(); + // foreach (var wheel in wheels) + // { + // devices.Remove(wheel); + // devices.Insert(0, wheel); + // } + // var orderedDevices = new DeviceInstance[4]; + // // Assign devices to their positions. + // for (int d = 0; d < devices.Count; d++) + // { + // var ig = devices[d].InstanceGuid; + // var section = SettingManager.Current.GetInstanceSection(ig); + // var ini2 = new Ini(SettingManager.IniFileName); + // string v = ini2.GetValue(section, SettingName.MapToPad); + // int mapToPad = 0; + // if (int.TryParse(v, out mapToPad) && mapToPad > 0 && mapToPad <= 4) + // { + // // If position is not occupied then... + // if (orderedDevices[mapToPad - 1] == null) + // { + // orderedDevices[mapToPad - 1] = devices[d]; + // } + // } + // } + // // Get list of unassigned devices. + // var unassignedDevices = devices.Except(orderedDevices).ToArray(); + // for (int i = 0; i < unassignedDevices.Length; i++) + // { + // // Assign to first empty slot. + // for (int d = 0; d < orderedDevices.Length; d++) + // { + // // If position is not occupied then... + // if (orderedDevices[d] == null) + // { + // orderedDevices[d] = unassignedDevices[i]; + // break; + // } + // } + // } + // return orderedDevices; + //} + + + ///// + ///// Access this only inside Timer_Click! + ///// + //bool RefreshCurrentInstances(bool forceReload = false) + //{ + // bool instancesChanged = false; + // DeviceInstance[] devices = null; + // //var types = DeviceType.Driving | DeviceType.Flight | DeviceType.Gamepad | DeviceType.Joystick | DeviceType.FirstPerson; + // if (forceRecountDevices || forceReload) + // { + // devices = GetDevices(); + // // Store device instances and their order. + // deviceInstancesNew = string.Join(",", devices.Select(x => x == null ? "" : x.InstanceGuid.ToString())); + // forceRecountDevices = false; + // } + // // If device list changed then... + // if (deviceInstancesNew != deviceInstancesOld) + // { + // deviceInstancesOld = deviceInstancesNew; + // if (devices == null) devices = GetDevices(); + // var instances = devices; + // // Dispose previous list of devices. + // for (int i = 0; i < 4; i++) + // { + // if (DiDevices[i].State != null) + // { + // // Dispose current device. + // DiDevices[i].State.Unacquire(); + // DiDevices[i].State.Dispose(); + // } + // } + // // Create new list of devices. + // for (int i = 0; i < 4; i++) + // { + // var inst = instances[i]; + // if (inst == null) + // { + // DiDevices[i].State = null; + // DiDevices[i].Info = null; + // } + // else + // { + + // var j = new Joystick(Manager, inst.InstanceGuid); + // DiDevices[i].State = j; + // var classGuid = j.Properties.ClassGuid; + // var interfacePath = j.Properties.InterfacePath; + // // Must find better way to find Device than by Vendor ID and Product ID. + // var devs = DeviceDetector.GetDevices(classGuid, JocysCom.ClassLibrary.Win32.DIGCF.DIGCF_ALLCLASSES, null, j.Properties.VendorId, j.Properties.ProductId, 0); + // DiDevices[i].Info = devs.FirstOrDefault(); + // } + // } + // SettingsDatabasePanel.BindDevices(instances); + // SettingsDatabasePanel.BindFiles(); + // for (int i = 0; i < 4; i++) + // { + // // Backup old instance. + // DiDevices[i].InstanceOld = DiDevices[i].Instance; + // // Assign new instance. + // DiDevices[i].Instance = instances[i]; + // } + // instancesChanged = true; + // } + // // Return true if instances changed. + // return instancesChanged; + //} + + // This value will be modified to true when settings on the form changes and + // XInput library needs to be reload. + bool settingsChanged = false; + State emptyState = new State(); + + //bool[] cleanPadStatus = new bool[4]; + + object formLoadLock = new object(); + public bool update1Enabled = true; + public bool? update2Enabled; + public bool update3Enabled = false; + + void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + if (Program.IsClosing) return; + Program.TimerCount++; + lock (formLoadLock) + { + if (update1Enabled) + { + update1Enabled = false; + UpdateForm1(); + // Update 2 part will be enabled after all issues are checked. + } + if (update2Enabled.HasValue && update2Enabled.Value) + { + update2Enabled = false; + UpdateForm2(); + update3Enabled = true; + } + if (update3Enabled) + { + UpdateForm3(); + } + } + UpdateTimer.Start(); + } + + void UpdateForm1() + { + InitDevices(); + //if (DesignMode) return; + OptionsPanel.InitOptions(); + // Set status. + StatusSaveLabel.Visible = false; + StatusEventsLabel.Visible = false; + // Load Tab pages. + ControlPages = new TabPage[4]; + ControlPages[0] = Pad1TabPage; + ControlPages[1] = Pad2TabPage; + ControlPages[2] = Pad3TabPage; + ControlPages[3] = Pad4TabPage; + //BuletImageList.Images.Add("bullet_square_glass_blue.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_blue.png"))); + //BuletImageList.Images.Add("bullet_square_glass_green.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_green.png"))); + //BuletImageList.Images.Add("bullet_square_glass_grey.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_grey.png"))); + //BuletImageList.Images.Add("bullet_square_glass_red.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_red.png"))); + //BuletImageList.Images.Add("bullet_square_glass_yellow.png", new Bitmap(Helper.GetResource("Images.bullet_square_glass_yellow.png"))); + foreach (var item in ControlPages) item.ImageKey = "bullet_square_glass_grey.png"; + // Hide status values. + StatusDllLabel.Text = ""; + MainStatusStrip.Visible = false; + // Check for various issues. + InitWarnigForm(); + InitDeviceForm(); + } + + void UpdateForm2() + { + // Set status labels. + StatusIsAdminLabel.Text = WinAPI.IsVista + ? string.Format("Elevated: {0}", WinAPI.IsElevated()) + : ""; + StatusIniLabel.Text = SettingManager.IniFileName; + CheckEncoding(SettingManager.TmpFileName); + CheckEncoding(SettingManager.IniFileName); + // Show status values. + MainStatusStrip.Visible = true; + // Load PAD controls. + ControlPads = new PadControl[4]; + for (int i = 0; i < ControlPads.Length; i++) + { + ControlPads[i] = new Controls.PadControl((MapTo)i + 1); + ControlPads[i].Name = string.Format("ControlPad{0}", i + 1); + ControlPads[i].Dock = DockStyle.Fill; + ControlPages[i].Controls.Add(ControlPads[i]); + ControlPads[i].InitPadControl(); + } + // Initialize pre-sets. Execute only after name of cIniFile is set. + //SettingsDatabasePanel.InitPresets(); + // Allow events after PAD control are loaded. + MainTabControl.SelectedIndexChanged += new System.EventHandler(this.MainTabControl_SelectedIndexChanged); + // Load about control. + ControlAbout = new AboutControl(); + ControlAbout.Dock = DockStyle.Fill; + AboutTabPage.Controls.Add(ControlAbout); + // Update settings map. + UpdateSettingsMap(); + //ReloadXinputSettings(); + //// start capture events. + if (WinAPI.IsVista && WinAPI.IsElevated() && WinAPI.IsInAdministratorRole) this.Text += " (Administrator)"; + } + + + /// + /// This method will run continuously by the UpdateTimer. + /// + void UpdateForm3() + { + // If settings changed then... + if (settingsChanged) + { + ReloadLibrary(); + } + else + { + for (int i = 0; i < 4; i++) + { + var game = MainForm.Current.GetCurrentGame(); + var currentFile = (game == null) ? null : game.FileName; + // Get devices mapped to game and specific controller index. + var devices = SettingManager.GetDevices(currentFile, (MapTo)(i + 1)); + // DInput instance is ON if active devices was found. + var diOn = devices.Count > 0; + // XInput instance is ON. + var xiOn = false; + State currentGamePad = emptyState; + lock (XInputLock) + { + var gamePad = XiControllers[i]; + if (XInput.IsLoaded && gamePad.IsConnected) + { + currentGamePad = gamePad.GetState(); + xiOn = true; + } + } + var padControl = ControlPads[i]; + // Update Form from DInput state. + padControl.UpdateFromDInput(); + // Update Form from XInput state. + padControl.UpdateFromXInput(currentGamePad, xiOn); + // Update LED of GamePad state. + string image = diOn + // DInput ON, XInput ON + ? xiOn ? "green" + // DInput ON, XInput OFF + : "red" + // DInput OFF, XInput ON + : xiOn ? "yellow" + // DInput OFF, XInput OFF + : "grey"; + string bullet = string.Format("bullet_square_glass_{0}.png", image); + if (ControlPages[i].ImageKey != bullet) ControlPages[i].ImageKey = bullet; + } + UpdateStatus(); + } + } + + public void ReloadLibrary() + { + Program.ReloadCount++; + //settingsChanged = false; + var dllInfo = EngineHelper.GetDefaultDll(); + if (dllInfo != null && dllInfo.Exists) + { + bool byMicrosoft; + var dllVersion = EngineHelper.GetDllVersion(dllInfo.FullName, out byMicrosoft); + StatusDllLabel.Text = dllInfo.Name + " " + dllVersion.ToString() + (byMicrosoft ? " (Microsoft)" : ""); + // If fast reload of settings is supported then... + lock (XInputLock) + { + if (XInput.IsResetSupported) + { + XInput.Reset(); + } + // Slow: Reload whole x360ce.dll. + Exception error; + //forceRecountDevices = true; + XInput.ReLoadLibrary(dllInfo.Name, out error); + if (!XInput.IsLoaded) + { + var caption = string.Format("Failed to load '{0}'", dllInfo.Name); + var text = string.Format("{0}", error == null ? "Unknown error" : error.Message); + var form = new MessageBoxForm(); + form.StartPosition = FormStartPosition.CenterParent; + form.ShowForm(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + for (int i = 0; i < 4; i++) + { + + var currentPadControl = ControlPads[i]; + currentPadControl.UpdateForceFeedBack(); + } + } + } + } + else + { + StatusDllLabel.Text = ""; + } + } + + public void UpdateStatus(string message = "") + { + AppHelper.SetText(StatusTimerLabel, "Count: {0}, Reloads: {1}, Errors: {2} {3}", + Program.TimerCount, Program.ReloadCount, Program.ErrorCount, message); + } + #endregion + + bool HelpInit = false; + + void MainTabControl_SelectedIndexChanged(object sender, EventArgs e) + { + if (MainTabControl.SelectedTab == HelpTabPage && !HelpInit) + { + // Move this here so interface will load one second faster. + HelpInit = true; + var stream = EngineHelper.GetResource("Documents.Help.htm"); + var sr = new StreamReader(stream); + NameValueCollection list = new NameValueCollection(); + list.Add("font-name-default", "'Microsoft Sans Serif'"); + list.Add("font-size-default", "16"); + HelpRichTextBox.Rtf = Html2Rtf.Converter.Html2Rtf(sr.ReadToEnd(), list); + HelpRichTextBox.SelectAll(); + HelpRichTextBox.SelectionIndent = 8; + HelpRichTextBox.SelectionRightIndent = 8; + HelpRichTextBox.DeselectAll(); + } + else if (MainTabControl.SelectedTab == SettingsTabPage) + { + if (OptionsPanel.InternetCheckBox.Checked && OptionsPanel.InternetAutoloadCheckBox.Checked) + { + SettingsDatabasePanel.RefreshGrid(true); + } + } + var tab = MainTabControl.SelectedTab; + if (tab != null) SetHeaderSubject(tab.Text); + } + + public void XInputEnable(bool enable) + { + lock (XInputLock) + { + XInput.XInputEnable(enable); + } + } + + #region Check Files + + void CheckEncoding(string path) + { + if (!File.Exists(path)) return; + var sr = new StreamReader(path, true); + var content = sr.ReadToEnd(); + sr.Close(); + if (sr.CurrentEncoding != System.Text.Encoding.Unicode) + { + File.WriteAllText(path, content, System.Text.Encoding.Unicode); + } + } + + bool IsFileSame(string fileName) + { + return false; + //if (!System.IO.File.Exists(fileName)) return false; + //var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); + //StreamReader sr; + //// Get MD5 of file on the disk. + //sr = new StreamReader(fileName); + //var dMd5 = new Guid(md5.ComputeHash(sr.BaseStream)); + //// Get MD5 of resource file. + //if (fileName == dllFile0) fileName = dllFile; + //if (fileName == dllFile1) fileName = dllFile; + //if (fileName == dllFile2) fileName = dllFile; + //if (fileName == dllFile3) fileName = dllFile; + //var assembly = Assembly.GetExecutingAssembly(); + //sr = new StreamReader(assembly.GetManifestResourceStream(this.GetType().Namespace + ".Presets." + fileName)); + //var rMd5 = new Guid(md5.ComputeHash(sr.BaseStream)); + //// return result. + //return rMd5.Equals(dMd5); + } + + public bool CreateFile(string resourceName, string destinationFileName, ProcessorArchitecture oldArchitecture, ProcessorArchitecture newArchitecture) + { + if (destinationFileName == null) destinationFileName = resourceName; + DialogResult answer; + var form = new MessageBoxForm(); + form.StartPosition = FormStartPosition.CenterParent; + var oldDesc = EngineHelper.GetProcessorArchitectureDescription(oldArchitecture); + var newDesc = EngineHelper.GetProcessorArchitectureDescription(newArchitecture); + var fileName = new FileInfo(destinationFileName).Name; + answer = form.ShowForm( + string.Format("You are running {2} application but {0} on the disk was built for {1} architecture.\r\n\r\nDo you want to replace {0} file with {2} version?", fileName, oldDesc, newDesc), + "Processor architecture mismatch.", + MessageBoxButtons.YesNo, MessageBoxIcon.Information); + if (answer == DialogResult.Yes) + { + return AppHelper.WriteFile(resourceName, destinationFileName); + } + return true; + } + + public bool CreateFile(string resourceName, string destinationFileName, Version oldVersion = null, Version newVersion = null) + { + if (destinationFileName == null) destinationFileName = resourceName; + DialogResult answer; + var form = new MessageBoxForm(); + form.StartPosition = FormStartPosition.CenterParent; + var fileName = new FileInfo(destinationFileName).FullName; + if (newVersion == null) + { + answer = form.ShowForm( + string.Format("'{0}' was not found.\r\nThis file is required for emulator to function properly.\r\n\r\nDo you want to create this file?", fileName), + string.Format("'{0}' was not found.", destinationFileName), + MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + } + else + { + answer = form.ShowForm( + string.Format("New version of this file is available:\r\n{0}\r\n\r\nOld version: {1}\r\nNew version: {2}\r\n\r\nDo you want to update this file?", fileName, oldVersion, newVersion), + string.Format("New version of '{0}' file is available.", destinationFileName), + MessageBoxButtons.YesNo, MessageBoxIcon.Information); + } + if (answer == DialogResult.Yes) + { + return AppHelper.WriteFile(resourceName, destinationFileName); + } + return true; + } + + #endregion + + #region Allow only one copy of Application at a time + + /// Stores the unique windows message id from the RegisterWindowMessage call. + int _WindowMessage; + /// Used to determine if the application is already open. + System.Threading.Mutex _Mutex; + + public const int wParam_Restore = 1; + public const int wParam_Close = 2; + + /// + /// Broadcast message to other instances of this application. + /// + /// Send parameter to other instances of this application. + /// True - other instances exists; False - other instances doesn't exist. + public bool BroadcastMessage(int wParam) + { + Exception error; + // Check for previous instance of this app. + var uid = Application.ProductName; + _Mutex = new System.Threading.Mutex(false, uid); + // Register the windows message + _WindowMessage = NativeMethods.RegisterWindowMessage(uid, out error); + var firsInstance = _Mutex.WaitOne(1, true); + // If this is not the first instance then... + if (!firsInstance) + { + // Broadcast a message with parameters to another instance. + var recipients = (int)BSM.BSM_APPLICATIONS; + var flags = BSF.BSF_IGNORECURRENTTASK | BSF.BSF_POSTMESSAGE; + var ret = NativeMethods.BroadcastSystemMessage((int)flags, ref recipients, _WindowMessage, wParam, 0, out error); + } + return !firsInstance; + } + + /// + /// NOTE: you must be careful with this method, because this method is responsible for all the + /// windows messages that are coming to the form. + /// + /// + /// This overrides the windows messaging processing + protected override void DefWndProc(ref Message m) + { + // If message value was found then... + if (m.Msg == _WindowMessage) + { + // Show currently running instance. + if (m.WParam.ToInt32() == wParam_Restore) + { + // Note: FormWindowState.Minimized and FormWindowState.Normal was used to make sure that Activate() wont fail because of this: + // Windows NT 5.0 and later: An application cannot force a window to the foreground while the user is working with another window. + // Instead, SetForegroundWindow will activate the window (see SetActiveWindow) and call theFlashWindowEx function to notify the user. + if (WindowState != FormWindowState.Minimized) WindowState = FormWindowState.Minimized; + this.Activate(); + if (WindowState == FormWindowState.Minimized) WindowState = FormWindowState.Normal; + } + // Close currently running instance. + if (m.WParam.ToInt32() == wParam_Close) + { + Close(); + } + } + // Let the normal windows messaging process it. + base.DefWndProc(ref m); + } + + #endregion + + #region Warning Form + + WarningsForm _WarningForm; + object warningFormLock = new object(); + + void InitWarnigForm() + { + lock (warningFormLock) + { + _WarningForm = new WarningsForm(); + _WarningForm.CheckTimer.Start(); + } + } + + void DisposeWarnigForm() + { + lock (warningFormLock) + { + if (_WarningForm != null) + { + _WarningForm.Dispose(); + _WarningForm = null; + } + } + } + + #endregion + + #region Device Form + + MapDeviceToControllerForm _DeviceForm; + object DeviceFormLock = new object(); + + void InitDeviceForm() + { + lock (DeviceFormLock) + { + _DeviceForm = new MapDeviceToControllerForm(); + } + } + + void DisposeDeviceForm() + { + lock (DeviceFormLock) + { + if (_DeviceForm != null) + { + _DeviceForm.Dispose(); + _DeviceForm = null; + } + } + } + + public DiDevice ShowDeviceForm() + { + DiDevice selectedItem = null; + lock (DeviceFormLock) + { + if (_DeviceForm == null) return null; + _DeviceForm.StartPosition = FormStartPosition.CenterParent; + var result = _DeviceForm.ShowDialog(); + if (result == DialogResult.OK) + { + selectedItem = _DeviceForm.SelectedDevice; + } + } + return selectedItem; + } + + #endregion + + /// + /// Clean up any + /// being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + if (_Mutex != null) + { + _Mutex.Dispose(); + } + DisposeWarnigForm(); + DisposeDeviceForm(); + if (detector != null) + { + detector.Dispose(); + detector = null; + } + Manager.Dispose(); + Manager = null; + components.Dispose(); + //lock (checkTimerLock) + //{ + // // If timer is disposed then return; + // if (checkTimer == null) return; + // CheckAll(); + //} + } + base.Dispose(disposing); + } + + private void OpenApplicationToolStripMenuItem_Click(object sender, EventArgs e) + { + RestoreFromTray(); + } + + private void ExitToolStripMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + #region Restore and Minimize + + FormWindowState? oldWindowState; + object lastStateLock = new object(); + + /// Will be used to prevent form flickering when restoring from tray. + bool ignoreMinimizeToTray; + + private void MainForm_Resize(object sender, EventArgs e) + { + // Track window state changes. + lock (lastStateLock) + { + var newWindowState = WindowState; + if (!oldWindowState.HasValue || oldWindowState.Value != newWindowState) + { + oldWindowState = newWindowState; + UpdateStatusBar(newWindowState); + } + } + } + + void UpdateStatusBar(FormWindowState state) + { + if (state == FormWindowState.Minimized) + { + if (!ignoreMinimizeToTray) + { + if (ShowInTaskbar == Settings.Default.MinimizeToTray) + { + ShowInTaskbar = !Settings.Default.MinimizeToTray; + } + } + } + else + { + ignoreMinimizeToTray = false; + if (ShowInTaskbar == false) + { + ShowInTaskbar = true; + } + } + } + + public bool MinimizeToTrayChanging; + public void SetMinimizeToTray(bool value) + { + if (MinimizeToTrayChanging) return; + MinimizeToTrayChanging = true; + if (OptionsPanel.MinimizeToTrayCheckBox.Checked != value) + { + OptionsPanel.MinimizeToTrayCheckBox.Checked = value; + } + if (Settings.Default.MinimizeToTray != value) + { + Settings.Default.MinimizeToTray = value; + } + UpdateStatusBar(WindowState); + MinimizeToTrayChanging = false; + } + + /// + /// Method to Minimize the window and Hide the window item in the TaskBar. + /// + public void MinimizeToTray(bool showBalloonTip) + { + // Show only first time. + if (showBalloonTip) + { + TrayNotifyIcon.BalloonTipText = "Password Generator..."; + // Show balloon tip for 2 seconds. + TrayNotifyIcon.ShowBalloonTip(2); + } + // hold - program. + // NOTE: also it would be possible to track which direction mouse will move in or move out on TrayIcon. + // For example: open program if mouse moves in from left and moves out from top. + TrayNotifyIcon.Text = "Click: double - program, left - generate, right - menu."; + if (WindowState != FormWindowState.Minimized) WindowState = FormWindowState.Minimized; + } + + /// + /// Restores the window. + /// + public void RestoreFromTray() + { + ignoreMinimizeToTray = true; + // Show in task bar before restoring windows state in order to prevent flickering. + ShowInTaskbar = true; + if (WindowState != FormWindowState.Normal) + { + WindowState = FormWindowState.Normal; + } + BringToFront(); + } + + void MinimizeToTrayToolStripMenuItem_Click(object sender, EventArgs e) + { + SetMinimizeToTray(!Settings.Default.MinimizeToTray); + } + + #endregion + + private void TrayNotifyIcon_DoubleClick(object sender, EventArgs e) + { + RestoreFromTray(); + } + + private void GameToCustomizeComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + + } + } } diff --git a/x360ce.App.Beta/MainForm.resx b/x360ce.App.Beta/MainForm.resx index 074110de5..14923ea5e 100644 --- a/x360ce.App.Beta/MainForm.resx +++ b/x360ce.App.Beta/MainForm.resx @@ -124,79 +124,79 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADA - EAAAAk1TRnQBSQFMAgEBBQEAAfABAAHwAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABIAMAAQEBAAEgBgABIP8A/wD/ACIAAUQBVwH/AQgBTwGCAf8BCwFWAYkB/wEKAVQBiAH/AQoBVAGI - Af8BCgFUAYgB/wEKAVQBiAH/AQsBVgGJAf8BCAFPAYIB/wEAAUUBWAH/2AABAwFKAV8B/wFdAecC/wGG - Ae8C/wGFAe4C/wGFAe4C/wGFAe4C/wGFAe4C/wGGAe8C/wFcAegC/wEDAUoBXwH/2AABAgFJAV4B/wFQ - AecB/gH/AVkB6gH8Af8BWAHpAfsB/wFYAekB+wH/AVgB6QH7Af8BWAHpAfsB/wFZAeoB/AH/AVAB5wH+ - Af8BAgFJAV4B/9kAAUIBVQH/AUABzgHmAf8BRAHQAeIB/wFDAc8B4gH/AUMBzwHiAf8BQwHPAeIB/wFD - Ac8B4gH/AUQB0AHiAf8BPwHPAeYB/wEAAUIBVQH/2QABOgFOAf8BLQG4AdEB/wEuAbgBzgH/AS4BtwHN - Af8BLgG3Ac0B/wEuAbcBzQH/AS4BtwHNAf8BLgG4Ac4B/wEtAbgB0QH/AQABOgFOAf/ZAAE0AUYB/wEd - AaIBugH/ARoBngG2Af8BFgGdAbQB/wEWAZ0BtAH/ARYBnQG0Af8BFgGdAbQB/wEaAZ4BtgH/AR0BogG6 - Af8BAAE0AUYB/9kAASsBPQH/ATUBogG2Af8BPQGkAbYB/wE8AaIBtQH/AToBogG1Af8BOgGiAbUB/wE8 - AaIBtQH/AT0BpAG2Af8BNQGiAbYB/wEAAS0BPwH/2QABIwE1Af8BUQGoAbgB/wGCAbIBvwH/AYABsAG+ - Af8BgAGwAb4B/wGAAbABvgH/AYABsAG+Af8BggGyAb8B/wFRAagBuAH/AQABJAE2Af/ZAAEcASwB/wFR - AaIBsAH/AZABtgHBAf8BjgG0Ab8B/wGOAbQBvwH/AY4BtAG/Af8BjgG0Ab8B/wGQAbYBwQH/AVEBogGw - Af8BAAEbASsB/9kAARcBJgH/AQABGAEnAf8BAAEYAScB/wEAARgBJwH/AQABGAEnAf8BAAEYAScB/wEA - ARgBJwH/AQABGAEnAf8BAAEYAScB/wEAARgBJwH//wD/AP8A/wD/AP8A3gABRwEoAQAB/wFWATABAAH/ - AVwBNQEAAf8BXAE0AQAB/wFcATQBAAH/AVwBNAEAAf8BXAE0AQAB/wFcATUBAAH/AVYBMAEAAf8BSAEo - AQAB/xkAAUUBEQH/AQIBVAEYAf8BBAFZARoB/wEDAVkBGgH/AQMBWQEaAf8BAwFZARoB/wEDAVkBGgH/ - AQQBWQEaAf8BAgFUARgB/wEAAUYBEQH/GAABOQEzASoB/wFCATsBMgH/AUgBQQE3Af8BSAFBATcB/wFI - AUEBNwH/AUgBQQE3Af8BSAFBATcB/wFIAUEBNwH/AUIBOwEyAf8BOQEzASoB/xoAAVcB/wEJAQgBggH/ - AgsBiQH/AQsBCgGIAf8BCwEKAYgB/wELAQoBiAH/AQsBCgGIAf8CCwGJAf8BCQEIAYIB/wIAAVgB/xgA - AU8BLAEAAv8BwgFFAv8BygFWAf8B/gHJAVUB/wH+AckBVQH/Af4ByQFVAf8B/gHJAVUC/wHKAVYC/wHB - AUUB/wFQASwBAAH/GQABTQEUAf8BSAH/AZoB/wFVAf8BqwH/AVMB/wGqAf8BUwH/AaoB/wFTAf8BqgH/ - AVMB/wGqAf8BVQH/AasB/wFIAf8BmgH/AQABTQEWAf8YAAE+ATgBLwH/AdsBzwG2Af8B4QHWAbsB/wHg - AdUBugH/AeAB1QG6Af8B4AHVAboB/wHgAdUBugH/AeEB1gG7Af8B2wHOAbYB/wE+ATcBLgH/GAABBAED - AV8B/wFdAYAC/wGGAZEC/wGFAY8C/wGFAY8C/wGFAY8C/wGFAY8C/wGGAZEC/wFcAYAC/wEEAQMBXwH/ - GAABTgErAQAB/wHvAbEBQAH/Ae0BuAFOAf8B7AG3AU0B/wHsAbcBTQH/AewBtwFNAf8B7AG3AU0B/wHt - AbgBTgH/Ae8BsQFAAf8BTgEqAQAB/xkAAUsBEwH/AUAB6QGRAf8BSwHmAZwB/wFKAeUBmwH/AUoB5QGb - Af8BSgHlAZsB/wFKAeUBmwH/AUsB5gGcAf8BQAHpAZEB/wEAAUsBEwH/GAABPQE3AS4B/wHJAb0BqAH/ - Ac0BwgGrAf8BzAHAAaoB/wHMAcABqgH/AcwBwAGqAf8BzAHAAaoB/wHNAcIBqwH/AckBvQGoAf8BPQE3 - AS4B/xgAAQMBAgFeAf8BUAFZAf4B/wFZAYIB/AH/AVgBgQH7Af8BWAGBAfsB/wFYAYEB+wH/AVgBgQH7 - Af8BWQGCAfwB/wFQAVkB/gH/AQMBAgFeAf8YAAFFASQBAAH/AdQBnQE0Af8B0QGgATwB/wHRAZ8BOgH/ - AdEBnwE6Af8B0QGfAToB/wHRAZ8BOgH/AdEBoAE8Af8B1AGdATQB/wFFASQBAAH/GQABQgENAf8BMwHR - AWAB/wE5Ac8BhAH/ATgBzgGDAf8BOAHOAYMB/wE4Ac4BgwH/ATgBzgGDAf8BOQHPAYQB/wEzAdEBYAH/ - AQABQgENAf8YAAE3ATEBKAH/AbUBrAGXAf8BtQGtAZkB/wG1AawBmAH/AbUBrAGYAf8BtQGsAZgB/wG1 - AawBmAH/AbUBrQGZAf8BtQGsAZcB/wE3ATABKAH/GgABVQH/AUABRgHmAf8BRAFOAeIB/wFDAUwB4gH/ - AUMBTAHiAf8BQwFMAeIB/wFDAUwB4gH/AUQBTgHiAf8BPwFGAeYB/wIAAVUB/xgAATwBHQEAAf8BuwGH - ASMB/wG6AYcBJgH/AbkBhwEmAf8BuQGHASYB/wG5AYcBJgH/AbkBhwEmAf8BugGHASYB/wG7AYcBIwH/ - ATwBHQEAAf8ZAAE6AQsB/wEjAbcBTQH/ASYBtAFPAf8BJgG0AU8B/wEmAbQBTwH/ASYBtAFPAf8BJgG0 - AU8B/wEmAbQBTwH/ASMBtwFNAf8BAAE6AQsB/xgAATEBKgEjAf8BoQGXAYYB/wGgAZYBhQH/AaABlgGF - Af8BoAGWAYUB/wGgAZYBhQH/AaABlgGFAf8BoAGWAYUB/wGhAZcBhgH/ATEBKgEjAf8aAAFOAf8BLQEx - AdEB/wEuATQBzgH/AS4BNAHNAf8BLgE0Ac0B/wEuATQBzQH/AS4BNAHNAf8BLgE0Ac4B/wEtATEB0QH/ - AgABTgH/GAABMwEXAQAB/wGiAVcBFwH/AZ8BVAEVAf8BmwFRARIB/wGbAVEBEgH/AZsBUQESAf8BmwFR - ARIB/wGfAVQBFQH/AaIBVwEXAf8BMwEXAQAB/xkAATEBBgH/ARgBnwE8Af8BFgGbAToB/wETAZkBNwH/ - ARMBmQE3Af8BEwGZATcB/wETAZkBNwH/ARYBmwE6Af8BGAGfATwB/wEAATEBBgH/GAABKgEkAR0B/wGN - AYQBWQH/AYoBgQFWAf8BhwFgAVMB/wGHAWABUwH/AYcBYAFTAf8BhwFgAVMB/wGKAYEBVgH/AY0BhAFZ - Af8BKgEkAR0B/xoAAUYB/wEdASEBugH/ARoBHgG2Af8BFgEbAbQB/wEWARsBtAH/ARYBGwG0Af8BFgEb - AbQB/wEaAR4BtgH/AR0BIQG6Af8CAAFGAf8YAAEqAQ8BAAH/AZ8BXwEzAf8BoQGEATwB/wGgAYIBOgH/ - AZ8BgQE5Af8BnwGBATkB/wGgAYIBOgH/AaEBhAE8Af8BnwFfATMB/wEqAREBAAH/GQABKAEAAf8BNQGd - AUwB/wE+AZ8BVAH/ATwBngFSAf8BOgGdAVEB/wE6AZ0BUQH/ATwBngFSAf8BPgGfAVQB/wE1AZ0BTAH/ - AQABKAEAAf8YAAEjAR4BGAH/AZQBjgGDAf8BlwGRAYkB/wGWAZABhwH/AZUBjwGGAf8BlQGPAYYB/wGW - AZABhwH/AZcBkQGJAf8BlAGOAYMB/wEjAR4BGAH/GgABPQH/ATUBNgG2Af8BPQE/AbYB/wE8AT0BtQH/ - AToBOwG1Af8BOgE7AbUB/wE8AT0BtQH/AT0BPwG2Af8BNQE2AbYB/wIAAT8B/xgAASABCAEAAf8BpQGO - AVQB/wGuAZoBhAH/Aa0BmgGCAf8BrQGaAYIB/wGtAZoBggH/Aa0BmgGCAf8BrgGaAYQB/wGlAY4BVAH/ - ASABBwEAAf8ZAAEeAQAB/wFUAaQBgQH/AYUBrQGQAf8BgwGsAY8B/wGDAawBjwH/AYMBrAGPAf8BgwGs - AY8B/wGFAa0BkAH/AVUBpAGBAf8BAAEfAQAB/xgAARwBFgERAf8BoAGbAZUB/wGqAaYBogH/AaoBpgGh - Af8BqgGmAaEB/wGqAaYBoQH/AaoBpgGhAf8BqgGmAaIB/wGgAZsBlQH/ARwBFgERAf8aAAE1Af8CUQG4 - Af8CggG/Af8CgAG+Af8CgAG+Af8CgAG+Af8CgAG+Af8CggG/Af8CUQG4Af8CAAE2Af8YAAEUAgAB/wGc - AYsBVwH/AbABpQGUAf8BrwGjAZIB/wGvAaMBkgH/Aa8BowGSAf8BrwGjAZIB/wGwAaUBlAH/AZwBigFX - Af8BFQEBAQAB/xkAARMBAAH/AVgBmwGAAf8BlQGxAZ0B/wGTAa8BmwH/AZMBrwGbAf8BkwGvAZsB/wGT - Aa8BmwH/AZUBsQGdAf8BVgGbAYAB/wEAARQBAAH/GAABEgEOAQoB/wGbAZcBkwH/AbEBrwGsAf8BrwGt - AaoB/wGvAa0BqgH/Aa8BrQGqAf8BrwGtAaoB/wGxAa8BrAH/AZsBlwGTAf8BEwEOAQoB/xoAASwB/wJR - AbAB/wKQAcEB/wKOAb8B/wKOAb8B/wKOAb8B/wKOAb8B/wKQAcEB/wJRAbAB/wIAASsB/xgAARACAAH/ - AQ8CAAH/AQ8CAAH/AQ8CAAH/AQ8CAAH/AQ8CAAH/AQ8CAAH/AQ8CAAH/AQ8CAAH/ARECAAH/GQABEAEA - Af8BAAEOAQAB/wEAAQ4BAAH/AQABDgEAAf8BAAEOAQAB/wEAAQ4BAAH/AQABDgEAAf8BAAEOAQAB/wEA - AQ4BAAH/AQABEQEAAf8YAAEQAQwBBwH/AQ8BCwEFAf8BDwEKAQYB/wEPAQoBBQH/AQ8BCgEFAf8BDwEK - AQUB/wEPAQoBBQH/AQ8BCgEGAf8BDwELAQUB/wERAQ0BCQH/GgABJgH/AgABJwH/AgABJwH/AgABJwH/ - AgABJwH/AgABJwH/AgABJwH/AgABJwH/AgABJwH/AgABJwH//wD/AP8ADwABQgFNAT4HAAE+AwABKAMA - AUADAAEgAwABAQEAAQEGAAEBFgAD/wEAAv8GAAL/BgAC/wYAAeABBwYAAeABBwYAAeABBwYAAeABBwYA - AeABBwYAAeABBwYAAeABBwYAAeABBwYAAeABBwYAAeABBwYAAv8GAAL/BgAC/wYAGP8B4AEHAeABBwHg - AQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHg - AQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHg - AQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHGP8L + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAC+ + EAAAAk1TRnQBSQFMAgEBBQEAAfgBAAH4AQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIP8A/wD/ACIAAUMBVgH/AQcBTgGCAf8BCgFVAYkB/wEJAVMBiAH/AQkBUwGI + Af8BCQFTAYgB/wEJAVMBiAH/AQoBVQGJAf8BBwFOAYIB/wEAAUQBVwH/2AABAgFJAV4B/wFcAecC/wGG + Ae8C/wGFAe4C/wGFAe4C/wGFAe4C/wGFAe4C/wGGAe8C/wFbAegC/wECAUkBXgH/2AABAQFIAV0B/wFP + AecB/gH/AVgB6gH8Af8BVwHpAfsB/wFXAekB+wH/AVcB6QH7Af8BVwHpAfsB/wFYAeoB/AH/AU8B5wH+ + Af8BAQFIAV0B/9kAAUEBVAH/AT8BzgHmAf8BQwHQAeIB/wFCAc8B4gH/AUIBzwHiAf8BQgHPAeIB/wFC + Ac8B4gH/AUMB0AHiAf8BPgHPAeYB/wEAAUEBVAH/2QABOQFNAf8BLAG4AdEB/wEtAbgBzgH/AS0BtwHN + Af8BLQG3Ac0B/wEtAbcBzQH/AS0BtwHNAf8BLQG4Ac4B/wEsAbgB0QH/AQABOQFNAf/ZAAEzAUUB/wEc + AaIBugH/ARkBngG2Af8BFQGdAbQB/wEVAZ0BtAH/ARUBnQG0Af8BFQGdAbQB/wEZAZ4BtgH/ARwBogG6 + Af8BAAEzAUUB/9kAASoBPAH/ATQBogG2Af8BPAGkAbYB/wE7AaIBtQH/ATkBogG1Af8BOQGiAbUB/wE7 + AaIBtQH/ATwBpAG2Af8BNAGiAbYB/wEAASwBPgH/2QABIgE0Af8BUAGoAbgB/wGCAbIBvwH/AYABsAG+ + Af8BgAGwAb4B/wGAAbABvgH/AYABsAG+Af8BggGyAb8B/wFQAagBuAH/AQABIwE1Af/ZAAEbASsB/wFQ + AaIBsAH/AZABtgHBAf8BjgG0Ab8B/wGOAbQBvwH/AY4BtAG/Af8BjgG0Ab8B/wGQAbYBwQH/AVABogGw + Af8BAAEaASoB/9kAARYBJQH/AQABFwEmAf8BAAEXASYB/wEAARcBJgH/AQABFwEmAf8BAAEXASYB/wEA + ARcBJgH/AQABFwEmAf8BAAEXASYB/wEAARcBJgH//wD/AP8A/wD/AP8A3gABRgEnAQAB/wFVAS8BAAH/ + AVsBNAEAAf8BWwEzAQAB/wFbATMBAAH/AVsBMwEAAf8BWwEzAQAB/wFbATQBAAH/AVUBLwEAAf8BRwEn + AQAB/xkAAUQBEAH/AQEBUwEXAf8BAwFYARkB/wECAVgBGQH/AQIBWAEZAf8BAgFYARkB/wECAVgBGQH/ + AQMBWAEZAf8BAQFTARcB/wEAAUUBEAH/GAABOAEyASkB/wFBAToBMQH/AUcBQAE2Af8BRwFAATYB/wFH + AUABNgH/AUcBQAE2Af8BRwFAATYB/wFHAUABNgH/AUEBOgExAf8BOAEyASkB/xoAAVYB/wEIAQcBggH/ + AgoBiQH/AQoBCQGIAf8BCgEJAYgB/wEKAQkBiAH/AQoBCQGIAf8CCgGJAf8BCAEHAYIB/wIAAVcB/xgA + AU4BKwEAAv8BwgFEAv8BygFVAf8B/gHJAVQB/wH+AckBVAH/Af4ByQFUAf8B/gHJAVQC/wHKAVUC/wHB + AUQB/wFPASsBAAH/GQABTAETAf8BRwH/AZoB/wFUAf8BqwH/AVIB/wGqAf8BUgH/AaoB/wFSAf8BqgH/ + AVIB/wGqAf8BVAH/AasB/wFHAf8BmgH/AQABTAEVAf8YAAE9ATcBLgH/AdsBzwG2Af8B4QHWAbsB/wHg + AdUBugH/AeAB1QG6Af8B4AHVAboB/wHgAdUBugH/AeEB1gG7Af8B2wHOAbYB/wE9ATYBLQH/GAABAwEC + AV4B/wFcAYAC/wGGAZEC/wGFAY8C/wGFAY8C/wGFAY8C/wGFAY8C/wGGAZEC/wFbAYAC/wEDAQIBXgH/ + GAABTQEqAQAB/wHvAbEBPwH/Ae0BuAFNAf8B7AG3AUwB/wHsAbcBTAH/AewBtwFMAf8B7AG3AUwB/wHt + AbgBTQH/Ae8BsQE/Af8BTQEpAQAB/xkAAUoBEgH/AT8B6QGRAf8BSgHmAZwB/wFJAeUBmwH/AUkB5QGb + Af8BSQHlAZsB/wFJAeUBmwH/AUoB5gGcAf8BPwHpAZEB/wEAAUoBEgH/GAABPAE2AS0B/wHJAb0BqAH/ + Ac0BwgGrAf8BzAHAAaoB/wHMAcABqgH/AcwBwAGqAf8BzAHAAaoB/wHNAcIBqwH/AckBvQGoAf8BPAE2 + AS0B/xgAAQIBAQFdAf8BTwFYAf4B/wFYAYIB/AH/AVcBgQH7Af8BVwGBAfsB/wFXAYEB+wH/AVcBgQH7 + Af8BWAGCAfwB/wFPAVgB/gH/AQIBAQFdAf8YAAFEASMBAAH/AdQBnQEzAf8B0QGgATsB/wHRAZ8BOQH/ + AdEBnwE5Af8B0QGfATkB/wHRAZ8BOQH/AdEBoAE7Af8B1AGdATMB/wFEASMBAAH/GQABQQEMAf8BMgHR + AV8B/wE4Ac8BhAH/ATcBzgGDAf8BNwHOAYMB/wE3Ac4BgwH/ATcBzgGDAf8BOAHPAYQB/wEyAdEBXwH/ + AQABQQEMAf8YAAE2ATABJwH/AbUBrAGXAf8BtQGtAZkB/wG1AawBmAH/AbUBrAGYAf8BtQGsAZgB/wG1 + AawBmAH/AbUBrQGZAf8BtQGsAZcB/wE2AS8BJwH/GgABVAH/AT8BRQHmAf8BQwFNAeIB/wFCAUsB4gH/ + AUIBSwHiAf8BQgFLAeIB/wFCAUsB4gH/AUMBTQHiAf8BPgFFAeYB/wIAAVQB/xgAATsBHAEAAf8BuwGH + ASIB/wG6AYcBJQH/AbkBhwElAf8BuQGHASUB/wG5AYcBJQH/AbkBhwElAf8BugGHASUB/wG7AYcBIgH/ + ATsBHAEAAf8ZAAE5AQoB/wEiAbcBTAH/ASUBtAFOAf8BJQG0AU4B/wElAbQBTgH/ASUBtAFOAf8BJQG0 + AU4B/wElAbQBTgH/ASIBtwFMAf8BAAE5AQoB/xgAATABKQEiAf8BoQGXAYYB/wGgAZYBhQH/AaABlgGF + Af8BoAGWAYUB/wGgAZYBhQH/AaABlgGFAf8BoAGWAYUB/wGhAZcBhgH/ATABKQEiAf8aAAFNAf8BLAEw + AdEB/wEtATMBzgH/AS0BMwHNAf8BLQEzAc0B/wEtATMBzQH/AS0BMwHNAf8BLQEzAc4B/wEsATAB0QH/ + AgABTQH/GAABMgEWAQAB/wGiAVYBFgH/AZ8BUwEUAf8BmwFQAREB/wGbAVABEQH/AZsBUAERAf8BmwFQ + AREB/wGfAVMBFAH/AaIBVgEWAf8BMgEWAQAB/xkAATABBQH/ARcBnwE7Af8BFQGbATkB/wESAZkBNgH/ + ARIBmQE2Af8BEgGZATYB/wESAZkBNgH/ARUBmwE5Af8BFwGfATsB/wEAATABBQH/GAABKQEjARwB/wGN + AYQBWAH/AYoBgQFVAf8BhwFfAVIB/wGHAV8BUgH/AYcBXwFSAf8BhwFfAVIB/wGKAYEBVQH/AY0BhAFY + Af8BKQEjARwB/xoAAUUB/wEcASABugH/ARkBHQG2Af8BFQEaAbQB/wEVARoBtAH/ARUBGgG0Af8BFQEa + AbQB/wEZAR0BtgH/ARwBIAG6Af8CAAFFAf8YAAEpAQ4BAAH/AZ8BXgEyAf8BoQGEATsB/wGgAYIBOQH/ + AZ8BgQE4Af8BnwGBATgB/wGgAYIBOQH/AaEBhAE7Af8BnwFeATIB/wEpARABAAH/GQABJwEAAf8BNAGd + AUsB/wE9AZ8BUwH/ATsBngFRAf8BOQGdAVAB/wE5AZ0BUAH/ATsBngFRAf8BPQGfAVMB/wE0AZ0BSwH/ + AQABJwEAAf8YAAEiAR0BFwH/AZQBjgGDAf8BlwGRAYkB/wGWAZABhwH/AZUBjwGGAf8BlQGPAYYB/wGW + AZABhwH/AZcBkQGJAf8BlAGOAYMB/wEiAR0BFwH/GgABPAH/ATQBNQG2Af8BPAE+AbYB/wE7ATwBtQH/ + ATkBOgG1Af8BOQE6AbUB/wE7ATwBtQH/ATwBPgG2Af8BNAE1AbYB/wIAAT4B/xgAAR8BBwEAAf8BpQGO + AVMB/wGuAZoBhAH/Aa0BmgGCAf8BrQGaAYIB/wGtAZoBggH/Aa0BmgGCAf8BrgGaAYQB/wGlAY4BUwH/ + AR8BBgEAAf8ZAAEdAQAB/wFTAaQBgQH/AYUBrQGQAf8BgwGsAY8B/wGDAawBjwH/AYMBrAGPAf8BgwGs + AY8B/wGFAa0BkAH/AVQBpAGBAf8BAAEeAQAB/xgAARsBFQEQAf8BoAGbAZUB/wGqAaYBogH/AaoBpgGh + Af8BqgGmAaEB/wGqAaYBoQH/AaoBpgGhAf8BqgGmAaIB/wGgAZsBlQH/ARsBFQEQAf8aAAE0Af8CUAG4 + Af8CggG/Af8CgAG+Af8CgAG+Af8CgAG+Af8CgAG+Af8CggG/Af8CUAG4Af8CAAE1Af8YAAETAgAB/wGc + AYsBVgH/AbABpQGUAf8BrwGjAZIB/wGvAaMBkgH/Aa8BowGSAf8BrwGjAZIB/wGwAaUBlAH/AZwBigFW + Af8BFAIAAf8ZAAESAQAB/wFXAZsBgAH/AZUBsQGdAf8BkwGvAZsB/wGTAa8BmwH/AZMBrwGbAf8BkwGv + AZsB/wGVAbEBnQH/AVUBmwGAAf8BAAETAQAB/xgAAREBDQEJAf8BmwGXAZMB/wGxAa8BrAH/Aa8BrQGq + Af8BrwGtAaoB/wGvAa0BqgH/Aa8BrQGqAf8BsQGvAawB/wGbAZcBkwH/ARIBDQEJAf8aAAErAf8CUAGw + Af8CkAHBAf8CjgG/Af8CjgG/Af8CjgG/Af8CjgG/Af8CkAHBAf8CUAGwAf8CAAEqAf8YAAEPAgAB/wEO + AgAB/wEOAgAB/wEOAgAB/wEOAgAB/wEOAgAB/wEOAgAB/wEOAgAB/wEOAgAB/wEQAgAB/xkAAQ8BAAH/ + AQABDQEAAf8BAAENAQAB/wEAAQ0BAAH/AQABDQEAAf8BAAENAQAB/wEAAQ0BAAH/AQABDQEAAf8BAAEN + AQAB/wEAARABAAH/GAABDwELAQYB/wEOAQoBBAH/AQ4BCQEFAf8BDgEJAQQB/wEOAQkBBAH/AQ4BCQEE + Af8BDgEJAQQB/wEOAQkBBQH/AQ4BCgEEAf8BEAEMAQgB/xoAASUB/wIAASYB/wIAASYB/wIAASYB/wIA + ASYB/wIAASYB/wIAASYB/wIAASYB/wIAASYB/wIAASYB//8A/wD/AA8AAUIBTQE+BwABPgMAASgDAAFA + AwABIAMAAQEBAAEBBgABARYAA/8BAAL/BgAC/wYAAv8GAAHgAQcGAAHgAQcGAAHgAQcGAAHgAQcGAAHg + AQcGAAHgAQcGAAHgAQcGAAHgAQcGAAHgAQcGAAHgAQcGAAL/BgAC/wYAAv8GABj/AeABBwHgAQcB4AEH + AeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEH + AeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBwHgAQcB4AEH + AeABBwHgAQcB4AEHAeABBwHgAQcB4AEHAeABBxj/Cw== diff --git a/x360ce.App.Beta/x360ce.App.Beta.csproj b/x360ce.App.Beta/x360ce.App.Beta.csproj index 425e1eb08..26438653c 100644 --- a/x360ce.App.Beta/x360ce.App.Beta.csproj +++ b/x360ce.App.Beta/x360ce.App.Beta.csproj @@ -140,6 +140,8 @@ + + Resources\SharpDX\SharpDX.dll False @@ -160,11 +162,15 @@ + + Resources\vJoy\vJoyInterfaceWrap.dll False + + @@ -253,6 +259,9 @@ + + ControllersUserControl.xaml + UserControl @@ -649,6 +658,12 @@ False + + + Designer + MSBuild:Compile + + if $(ConfigurationName) == Release ( -if $(PlatformName) == x86 $(SolutionDir)x360ce.App\Resources\NetZ\netz.exe -pl x86 -s -so -z $(TargetPath) -if $(PlatformName) == x64 $(SolutionDir)x360ce.App\Resources\NetZ\netz.exe -pl x64 -s -so -z $(TargetPath) -if $(PlatformName) == AnyCPU $(SolutionDir)\x360ce.App\Resources\NetZ\netz.exe -s -so -z $(TargetPath) +if $(PlatformName) == x86 $(SolutionDir)$(ProjectName)\Resources\NetZ\netz.exe -pl x86 -s -so -z $(TargetPath) +if $(PlatformName) == x64 $(SolutionDir)$(ProjectName)\Resources\NetZ\netz.exe -pl x64 -s -so -z $(TargetPath) +if $(PlatformName) == AnyCPU $(SolutionDir)\$(ProjectName)\Resources\NetZ\netz.exe -s -so -z $(TargetPath) ) ::if $(PlatformName) == x86 COPY /Y "$(TargetPath)" "$(SolutionDir)x360ce\x360ce\bin\$(ConfigurationName)" ::if $(PlatformName) == x64 COPY /Y "$(TargetPath)" "$(SolutionDir)x360ce\x360ce\bin64\$(ConfigurationName)" diff --git a/x360ce.App.WPF/App.ico b/x360ce.App.WPF/App.ico new file mode 100644 index 0000000000000000000000000000000000000000..6289c0f3f394ea1b2d0cea68fb8582de3476edd2 GIT binary patch literal 146516 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 z zj1(*%6a7b(;|Dh;JoDp-k%GIlK3X#OjU1uj#wb1xQ>_CW{C2L}*58RuN$+cUZSie*bWs@jnt;^TN6wR5vql`Kp zL1NCo_$I+nxu$<+nMg4PL>Blhy2y@c682`8X=j7R7n5SI-h7G608v2W@@3HFV_U{mM%oCbVl3of~-6oYy+>fhgh93&0)WmH@w+t zEEjg9i5+9wsul&|KyT*rhB5^c#r>?Z*g0GKo38+kjgi9djxHR5Xw6tLKx6Q=?y!H! zk0@9CX_DT%Ht?*HtP0ZeH2eY{qhn&zF>Y2`ZNznd6J+7nB#R}+t4%vhBy;^GnJu=g zMyKFbJ)%X8E9y4HjKXF=BgiPE{;>J&X4dLk^>Rz^eAAvAYf!J(gm9Re42;ZV`|~ewB4vb24ESEN-j!U?rF|R{g;zEx}|Z2K->{Yw6wv4lirLq+u1}PoEDew2OfNj zp9iFwS4G2!j^VW>6}>7SQtZ2(#%^-k-uxzz%}H;dx-&~BE*UF&`^nSZuIIp;n%w|# z7dWA>Bi`Y-`gDy!fSE0TN>vY(I(M_|^ffdRn3LyiX?h4E1sJMP_)Ja+bDb0y_=Rc> z<;Q#C2ak3~c5Q5u9>$HptY_Z?Xpgqf4bGCqcE2t^S~Yxjqud^*ePjO}547ZV*)M#T zeB&&9oP!%9ZhU7BZW3jF8n1bRD6V3Jt|oi}edqCgjyeg}Hk9kK86F;7oDi*B>$tyJ z4%i|}$ruyTO~3qIZE9ss|81;iP_%;qNRJ6-mhkF$Rgj8}A6t%dBWtsHvtzkMk^d$X z4NJMrG@UK!`ib9?JxOcc)d)O%@#;+)P?_mY*ZyQ-g3uBTYLi{TLzz714IsG4$x9

~HY4nOc6_sb}Rf}I)%<48%B182%} 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

M&_@27Yu*l1Hc{XJ-7eB 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

ER>mZd%ZeASkuTG|YKC2srfeO!Lg4%V+3 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 C`=E;e literal 0 HcmV?d00001 diff --git a/x360ce.App.WPF/Controls/DeviceTabControlGeneralTab.xaml b/x360ce.App.WPF/Controls/DeviceTabControlGeneralTab.xaml index 896e224bb..072ee28fb 100644 --- a/x360ce.App.WPF/Controls/DeviceTabControlGeneralTab.xaml +++ b/x360ce.App.WPF/Controls/DeviceTabControlGeneralTab.xaml @@ -6,240 +6,239 @@ xmlns:local="clr-namespace:x360ce.App.Controls" mc:Ignorable="d"> - - - - - - - - - - - + + + + + + + + + + + + + - - - - - + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + - - + - - + - - + - + diff --git a/x360ce.App.WPF/MainWindow.xaml.BACKUP b/x360ce.App.WPF/MainWindow.xaml.BACKUP deleted file mode 100644 index feaa17ab2607940c0ccade43b392904163a340a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26705 zcmeIuF#!Mo0K%a4Pi+hzh(KY$fB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* j1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r4BQ6>Xi)$G diff --git a/x360ce.App.WPF/Properties/AssemblyInfo.cs b/x360ce.App.WPF/Properties/AssemblyInfo.cs index 76b5f2b4c..d29d8ca61 100644 --- a/x360ce.App.WPF/Properties/AssemblyInfo.cs +++ b/x360ce.App.WPF/Properties/AssemblyInfo.cs @@ -7,12 +7,12 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("x360ce.App")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyTitle("TocaEdit X360 Controller Emulator")] +[assembly: AssemblyDescription("Wrapper library that translates XInput calls to DirectInput calls, for support old, no XInput compatible gamepads.")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("x360ce.App")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyCompany("TocaEdit")] +[assembly: AssemblyProduct("X360 Controller Emulator")] +[assembly: AssemblyCopyright("Copyright © TocaEdit 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("4.0.0.0")] +[assembly: AssemblyFileVersion("4.0.0.0")] diff --git a/x360ce.App.WPF/Properties/Resources.resx b/x360ce.App.WPF/Properties/Resources.resx index ffecec851..29dcb1b3a 100644 --- a/x360ce.App.WPF/Properties/Resources.resx +++ b/x360ce.App.WPF/Properties/Resources.resx @@ -46,7 +46,7 @@ mimetype: application/x-microsoft.net.object.binary.base64 value : The object must be serialized with - : System.Serialization.Formatters.Binary.BinaryFormatter + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : and then encoded with base64 encoding. mimetype: application/x-microsoft.net.object.soap.base64 @@ -60,6 +60,7 @@ : and then encoded with base64 encoding. --> + @@ -68,9 +69,10 @@ - + + @@ -85,9 +87,10 @@ - + + @@ -109,9 +112,9 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file diff --git a/x360ce.App.WPF/x360ce.App.WPF.csproj b/x360ce.App.WPF/x360ce.App.WPF.csproj index ac18f7501..b0ba0a081 100644 --- a/x360ce.App.WPF/x360ce.App.WPF.csproj +++ b/x360ce.App.WPF/x360ce.App.WPF.csproj @@ -37,6 +37,9 @@ 4 + + App.ico + @@ -220,6 +223,9 @@ + + + if $(ConfigurationName) == Release ( -if $(PlatformName) == x86 $(SolutionDir)x360ce.App\Resources\NetZ\netz.exe -pl x86 -s -so -z $(TargetPath) -if $(PlatformName) == x64 $(SolutionDir)x360ce.App\Resources\NetZ\netz.exe -pl x64 -s -so -z $(TargetPath) +if $(PlatformName) == x86 $(SolutionDir)$(ProjectName)\Resources\NetZ\netz.exe -pl x86 -s -so -z $(TargetPath) +if $(PlatformName) == x64 $(SolutionDir)$(ProjectName)\Resources\NetZ\netz.exe -pl x64 -s -so -z $(TargetPath) if $(PlatformName) == AnyCPU $(SolutionDir)\x360ce.App\Resources\NetZ\netz.exe -s -so -z $(TargetPath) ) ::if $(PlatformName) == x86 COPY /Y "$(TargetPath)" "$(SolutionDir)x360ce\x360ce\bin\$(ConfigurationName)"