2017-02-26 19:23:31 +00:00
using System ;
using System.Collections.Generic ;
using System.Drawing.IconLib ;
2020-04-23 08:16:16 +00:00
using System.Drawing ;
2017-02-26 19:23:31 +00:00
using System.IO ;
2020-04-23 08:16:16 +00:00
using System.Linq ;
2017-02-26 19:23:31 +00:00
using System.Reflection ;
using System.Runtime.InteropServices ;
using System.Windows.Forms ;
2020-04-23 08:16:16 +00:00
using HeliosPlus.Resources ;
using HeliosPlus.Shared ;
2020-04-27 10:55:44 +00:00
using HeliosPlus.GameLibraries ;
2020-05-01 10:30:27 +00:00
using System.Globalization ;
2017-02-26 19:23:31 +00:00
2020-04-23 08:16:16 +00:00
namespace HeliosPlus.UIForms
2017-02-26 19:23:31 +00:00
{
public partial class ShortcutForm : Form
{
2020-04-28 10:38:43 +00:00
List < SteamGame > _allSteamGames ;
2020-05-03 08:39:35 +00:00
internal Profile [ ] _allProfiles ;
2017-02-26 19:23:31 +00:00
public ShortcutForm ( )
{
InitializeComponent ( ) ;
2020-05-03 08:39:35 +00:00
2017-02-26 19:23:31 +00:00
}
public ShortcutForm ( Profile profile ) : this ( )
{
2020-05-01 10:30:27 +00:00
SelectedProfile = profile ;
2017-02-26 19:23:31 +00:00
}
2020-04-22 11:46:31 +00:00
public string ProcessNameToMonitor
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
get
{
if ( rb_switch_temp . Checked & & rb_standalone . Checked ) {
if ( rb_wait_executable . Checked )
{
return txt_process_name . Text ;
}
}
return string . Empty ;
}
2017-08-07 16:38:48 +00:00
set
{
2020-04-23 08:16:16 +00:00
// We we're setting this entry, then we want to set it to a particular entry
txt_process_name . Text = value ;
rb_wait_executable . Checked = true ;
2017-08-07 16:38:48 +00:00
}
2017-02-26 19:23:31 +00:00
}
2020-05-01 10:30:27 +00:00
public Profile SelectedProfile
2020-04-22 11:46:31 +00:00
{
get = > dv_profile . Profile ;
2020-04-23 08:16:16 +00:00
set
{
// Check the profile is valid
// Create an array of display profiles we have
2020-05-09 13:02:07 +00:00
var profiles = Profile . LoadAllProfiles ( ) . ToArray ( ) ;
2020-05-03 08:39:35 +00:00
_allProfiles = profiles ;
2020-04-23 08:16:16 +00:00
// Check if the user supplied a --profile option using the profiles' ID
var profileIndex = profiles . Length > 0 ? Array . FindIndex ( profiles , p = > p . Id . Equals ( value . Id , StringComparison . InvariantCultureIgnoreCase ) ) : - 1 ;
// If the profileID wasn't there, maybe they used the profile name?
if ( profileIndex = = - 1 )
{
// Try and lookup the profile in the profiles' Name fields
profileIndex = profiles . Length > 0 ? Array . FindIndex ( profiles , p = > p . Name . StartsWith ( value . Name , StringComparison . InvariantCultureIgnoreCase ) ) : - 1 ;
}
// If the profileID still isn't there, then raise the alarm
if ( profileIndex = = - 1 )
{
MessageBox . Show (
2020-05-01 10:30:27 +00:00
$"ShortcutForm: Setting SelectProfile: Couldn't find either Profile Name '{SelectedProfile.Name}'or ID '{SelectedProfile.Id}' supplied to Profile property." ,
2020-04-23 08:16:16 +00:00
Language . Executable ,
MessageBoxButtons . OK ,
MessageBoxIcon . Exclamation ) ;
}
dv_profile . Profile = value ;
}
2020-04-22 11:46:31 +00:00
}
public string ExecutableNameAndPath
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
get = > rb_switch_temp . Checked & & rb_launcher . Checked ? txt_executable . Text : string . Empty ;
2017-02-26 19:23:31 +00:00
set
{
2020-04-22 11:46:31 +00:00
if ( File . Exists ( txt_executable . Text ) )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
rb_switch_temp . Checked = true ;
rb_launcher . Checked = true ;
2017-02-26 19:23:31 +00:00
txt_executable . Text = value ;
}
}
}
2020-04-22 11:46:31 +00:00
public uint ExecutableTimeout
2018-10-20 00:27:25 +00:00
{
2020-04-22 11:46:31 +00:00
get
{
if ( rb_wait_executable . Checked )
{
return ( uint ) nud_timeout_executable . Value ;
}
return 0 ;
}
set
{
nud_timeout_executable . Value = value ;
}
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
2020-04-22 11:46:31 +00:00
public string ExecutableArguments
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
get = > cb_args_executable . Checked ? txt_args_executable . Text : string . Empty ;
2017-02-26 19:23:31 +00:00
set
{
2020-04-22 11:46:31 +00:00
txt_args_executable . Text = value ;
cb_args_executable . Checked = true ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-22 11:46:31 +00:00
public uint GameAppId
2017-08-07 16:38:48 +00:00
{
2020-04-28 10:38:43 +00:00
get = > rb_switch_temp . Checked & & rb_launcher . Checked ? ( uint ) Convert . ToInt32 ( txt_game_id . Text ) : 0 ;
2020-04-22 11:46:31 +00:00
set
{
rb_switch_temp . Checked = true ;
rb_launcher . Checked = true ;
2020-04-28 10:38:43 +00:00
txt_game_id . Text = value . ToString ( ) ;
2020-04-22 11:46:31 +00:00
}
2017-08-07 16:38:48 +00:00
}
2020-04-22 11:46:31 +00:00
public string GameName
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
get = > rb_switch_temp . Checked & & rb_launcher . Checked ? txt_game_name . Text : string . Empty ;
2017-02-26 19:23:31 +00:00
set
{
2020-04-22 11:46:31 +00:00
rb_switch_temp . Checked = true ;
rb_launcher . Checked = true ;
txt_game_name . Text = value ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-22 11:46:31 +00:00
public SupportedGameLibrary GameLibrary
2017-02-26 19:23:31 +00:00
{
2020-04-28 10:38:43 +00:00
get
{
if ( rb_switch_temp . Checked & & rb_launcher . Checked )
{
if ( txt_game_launcher . Text . Contains ( "Steam" ) )
{
return SupportedGameLibrary . Steam ;
}
else if ( txt_game_launcher . Text . Contains ( "Uplay" ) )
{
return SupportedGameLibrary . Uplay ;
}
}
return SupportedGameLibrary . Unknown ;
}
2020-04-22 11:46:31 +00:00
set
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
rb_switch_temp . Checked = true ;
rb_launcher . Checked = true ;
switch ( value )
2018-10-20 00:27:25 +00:00
{
2020-04-22 11:46:31 +00:00
case SupportedGameLibrary . Steam :
2020-04-28 10:38:43 +00:00
txt_game_launcher . Text = Enum . GetName ( typeof ( SupportedGameLibrary ) , SupportedGameLibrary . Steam ) ;
2020-04-22 11:46:31 +00:00
break ;
case SupportedGameLibrary . Uplay :
2020-04-28 10:38:43 +00:00
txt_game_launcher . Text = Enum . GetName ( typeof ( SupportedGameLibrary ) , SupportedGameLibrary . Uplay ) ;
2020-04-22 11:46:31 +00:00
break ;
2018-10-20 00:27:25 +00:00
}
2020-04-22 11:46:31 +00:00
// TODO - If SupportedGameLibrary.Unknown; then we need to show an error message.
}
}
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
public uint GameTimeout
{
get
{
if ( rb_switch_temp . Checked & & rb_launcher . Checked )
2018-10-20 00:27:25 +00:00
{
2020-04-22 11:46:31 +00:00
return ( uint ) nud_timeout_game . Value ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
return 0 ;
}
set
{
2020-04-22 11:46:31 +00:00
nud_timeout_game . Value = value ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-22 11:46:31 +00:00
public string GameArguments
{
get = > cb_args_game . Checked ? txt_args_game . Text : string . Empty ;
set
{
txt_args_game . Text = value ;
cb_args_game . Checked = true ;
}
}
2020-05-01 10:30:27 +00:00
private static bool IsLowQuality ( IconImage iconImage )
{
return iconImage . PixelFormat = = System . Drawing . Imaging . PixelFormat . Format1bppIndexed | |
iconImage . PixelFormat = = System . Drawing . Imaging . PixelFormat . Format4bppIndexed | |
iconImage . PixelFormat = = System . Drawing . Imaging . PixelFormat . Format8bppIndexed ;
}
private static Bitmap ExtractVistaIcon ( Icon icoIcon )
{
Bitmap bmpPngExtracted = null ;
try
{
byte [ ] srcBuf = null ;
using ( System . IO . MemoryStream stream = new System . IO . MemoryStream ( ) )
{ icoIcon . Save ( stream ) ; srcBuf = stream . ToArray ( ) ; }
const int SizeICONDIR = 6 ;
const int SizeICONDIRENTRY = 16 ;
int iCount = BitConverter . ToInt16 ( srcBuf , 4 ) ;
for ( int iIndex = 0 ; iIndex < iCount ; iIndex + + )
{
int iWidth = srcBuf [ SizeICONDIR + SizeICONDIRENTRY * iIndex ] ;
int iHeight = srcBuf [ SizeICONDIR + SizeICONDIRENTRY * iIndex + 1 ] ;
int iBitCount = BitConverter . ToInt16 ( srcBuf , SizeICONDIR + SizeICONDIRENTRY * iIndex + 6 ) ;
if ( iWidth = = 0 & & iHeight = = 0 & & iBitCount = = 32 )
{
int iImageSize = BitConverter . ToInt32 ( srcBuf , SizeICONDIR + SizeICONDIRENTRY * iIndex + 8 ) ;
int iImageOffset = BitConverter . ToInt32 ( srcBuf , SizeICONDIR + SizeICONDIRENTRY * iIndex + 12 ) ;
System . IO . MemoryStream destStream = new System . IO . MemoryStream ( ) ;
System . IO . BinaryWriter writer = new System . IO . BinaryWriter ( destStream ) ;
writer . Write ( srcBuf , iImageOffset , iImageSize ) ;
destStream . Seek ( 0 , System . IO . SeekOrigin . Begin ) ;
bmpPngExtracted = new Bitmap ( destStream ) ; // This is PNG! :)
break ;
}
}
}
catch { return null ; }
return bmpPngExtracted ;
}
private static string GetValidFilename ( string uncheckedFilename )
{
string invalid = new string ( Path . GetInvalidFileNameChars ( ) ) + new string ( Path . GetInvalidPathChars ( ) ) ;
foreach ( char c in invalid )
{
uncheckedFilename = uncheckedFilename . Replace ( c . ToString ( ) , "" ) ;
}
return uncheckedFilename ;
}
2020-04-22 11:46:31 +00:00
2017-02-26 19:23:31 +00:00
private void btn_app_executable_Click ( object sender , EventArgs e )
{
if ( dialog_open . ShowDialog ( this ) = = DialogResult . OK )
2018-10-20 00:27:25 +00:00
{
if ( File . Exists ( dialog_open . FileName ) & & Path . GetExtension ( dialog_open . FileName ) = = @".exe" )
2017-02-26 19:23:31 +00:00
{
txt_executable . Text = dialog_open . FileName ;
dialog_open . FileName = string . Empty ;
}
else
{
MessageBox . Show (
Language . Selected_file_is_not_a_valid_executable_file ,
Language . Executable ,
MessageBoxButtons . OK ,
MessageBoxIcon . Exclamation ) ;
}
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2017-08-07 16:38:48 +00:00
private void btn_save_Click ( object sender , EventArgs e )
{
DialogResult = DialogResult . None ;
2018-10-20 00:27:25 +00:00
2017-08-07 16:38:48 +00:00
try
{
2020-04-28 10:38:43 +00:00
// Set the Shortcut save folder to the Desktop as that's where people will want it most likely
dialog_save . InitialDirectory = Environment . GetFolderPath ( Environment . SpecialFolder . Desktop ) ;
2020-04-27 10:55:44 +00:00
// Try to set up some sensible suggestions for the Shortcut name
if ( rb_switch_perm . Checked )
{
2020-05-01 10:30:27 +00:00
dialog_save . FileName = SelectedProfile . Name ;
2020-04-27 10:55:44 +00:00
}
else
{
if ( rb_standalone . Checked )
{
2020-05-01 10:30:27 +00:00
dialog_save . FileName = String . Concat ( Path . GetFileNameWithoutExtension ( ExecutableNameAndPath ) , @" (" , SelectedProfile . Name . ToLower ( ) , @")" ) ;
2020-04-27 10:55:44 +00:00
}
else
{
2020-05-01 10:30:27 +00:00
dialog_save . FileName = String . Concat ( GameName , @" (" , SelectedProfile . Name , @")" ) ;
2020-04-27 10:55:44 +00:00
}
}
// Show the Save Shortcut window
2017-08-07 16:38:48 +00:00
if ( dialog_save . ShowDialog ( this ) = = DialogResult . OK )
{
if ( CreateShortcut ( dialog_save . FileName ) )
2018-10-20 00:27:25 +00:00
{
2017-08-07 16:38:48 +00:00
MessageBox . Show (
2020-04-27 10:55:44 +00:00
Language . Shortcut_placed_successfully ,
2017-08-07 16:38:48 +00:00
Language . Shortcut ,
MessageBoxButtons . OK ,
MessageBoxIcon . Information ) ;
2018-10-20 00:27:25 +00:00
}
2017-08-07 16:38:48 +00:00
else
2018-10-20 00:27:25 +00:00
{
2017-08-07 16:38:48 +00:00
MessageBox . Show (
Language . Failed_to_create_the_shortcut_Unexpected_exception_occurred ,
Language . Shortcut ,
MessageBoxButtons . OK ,
MessageBoxIcon . Exclamation ) ;
2018-10-20 00:27:25 +00:00
}
2017-08-07 16:38:48 +00:00
dialog_save . FileName = string . Empty ;
DialogResult = DialogResult . OK ;
}
}
catch ( Exception ex )
{
MessageBox . Show ( ex . Message , Language . Shortcut , MessageBoxButtons . OK , MessageBoxIcon . Warning ) ;
}
}
2017-02-26 19:23:31 +00:00
// ReSharper disable once FunctionComplexityOverflow
2017-08-07 16:38:48 +00:00
// ReSharper disable once CyclomaticComplexity
2017-02-26 19:23:31 +00:00
private bool CreateShortcut ( string fileName )
{
2020-04-27 10:55:44 +00:00
string programName = Path . GetFileNameWithoutExtension ( txt_executable . Text ) ;
string shortcutDescription = string . Empty ;
2020-05-01 10:30:27 +00:00
MultiIcon shortcutIcon ;
2020-04-27 10:55:44 +00:00
string shortcutIconFileName = string . Empty ;
2020-04-22 11:46:31 +00:00
2017-02-26 19:23:31 +00:00
var args = new List < string >
{
2020-04-22 11:46:31 +00:00
// Add the SwitchProfile command as the first argument to start to switch to another profile
2020-04-28 10:38:43 +00:00
$"{HeliosStartupAction.SwitchProfile}"
2017-02-26 19:23:31 +00:00
} ;
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
// Only add the rest of the options if the temporary switch radio button is set
if ( rb_switch_temp . Checked )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
// Only add this set of options if the standalone programme radio button is set
2017-02-26 19:23:31 +00:00
if ( rb_standalone . Checked )
{
2020-04-22 11:46:31 +00:00
// Doublecheck the Executable text field is filled in
2020-04-27 10:55:44 +00:00
if ( string . IsNullOrWhiteSpace ( ExecutableNameAndPath ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Executable_address_can_not_be_empty ) ;
2018-10-20 00:27:25 +00:00
}
2020-04-22 11:46:31 +00:00
// Doublecheck the Executable text field is a path to a real file
2020-04-27 10:55:44 +00:00
if ( ! File . Exists ( ExecutableNameAndPath ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Executable_file_not_found ) ;
2018-10-20 00:27:25 +00:00
}
2020-04-22 11:46:31 +00:00
// Add the executable command and the executable name to the shortcut arguments
2020-04-27 10:55:44 +00:00
args . Add ( $"execute \" { ExecutableNameAndPath } \ "" ) ;
2018-10-20 00:27:25 +00:00
2020-04-28 10:38:43 +00:00
// Add the Profile Name as the first option (use that rather than ID - though ID still will work!)
2020-05-01 10:30:27 +00:00
args . Add ( $"--profile \" { SelectedProfile . Name } \ "" ) ;
2020-04-28 10:38:43 +00:00
2020-04-22 11:46:31 +00:00
// Check that the wait for executable radiobutton is on
if ( rb_wait_executable . Checked )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
// Doublecheck the process name has text in it
2020-04-27 10:55:44 +00:00
if ( ! string . IsNullOrWhiteSpace ( ProcessNameToMonitor ) )
2020-04-22 11:46:31 +00:00
{
// Add the waitfor argument and the process name to the shortcut arguments
2020-04-27 10:55:44 +00:00
args . Add ( $"--waitfor \" { ProcessNameToMonitor } \ "" ) ;
2020-04-22 11:46:31 +00:00
}
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
// Add the timeout argument and the timeout duration in seconds to the shortcut arguments
2020-04-27 10:55:44 +00:00
args . Add ( $"--timeout {ExecutableTimeout}" ) ;
2020-04-22 11:46:31 +00:00
2020-04-27 10:55:44 +00:00
if ( cb_args_executable . Checked )
2020-04-22 11:46:31 +00:00
{
2020-04-27 10:55:44 +00:00
args . Add ( $"--arguments \" { ExecutableArguments } \ "" ) ;
2020-04-22 11:46:31 +00:00
}
// Prepare text for the shortcut description field
2020-05-01 10:30:27 +00:00
shortcutDescription = string . Format ( Language . Executing_application_with_profile , programName , SelectedProfile . Name ) ;
2020-04-27 10:55:44 +00:00
// Work out the name of the shortcut we'll save.
2020-05-01 10:30:27 +00:00
shortcutIconFileName = Path . Combine ( Program . ShortcutIconCachePath , String . Concat ( @"executable-" , GetValidFilename ( SelectedProfile . Name ) . ToLower ( CultureInfo . InvariantCulture ) , "-" , Path . GetFileNameWithoutExtension ( ExecutableNameAndPath ) , @".ico" ) ) ;
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
// Grab an icon for the selected executable
2017-02-26 19:23:31 +00:00
try
{
2020-04-27 10:55:44 +00:00
// We'll first try to extract the Icon from the executable the user provided
2020-05-01 10:30:27 +00:00
//shortcutIcon.Load(ExecutableNameAndPath);
2017-02-26 19:23:31 +00:00
}
2017-08-07 16:38:48 +00:00
catch ( Exception )
2017-02-26 19:23:31 +00:00
{
2020-04-27 10:55:44 +00:00
// but if that doesn't work, then we use our own one.
2020-05-01 10:30:27 +00:00
//shortcutIcon.Load(Assembly.GetExecutingAssembly().Location);
2017-02-26 19:23:31 +00:00
}
}
2020-04-22 11:46:31 +00:00
// Only add the rest of the options if the temporary switch radio button is set
// and if the game launching radio button is set
2020-04-19 05:37:29 +00:00
else if ( rb_launcher . Checked )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
// TODO need to make this work so at least one game library is installed
// i.e. if (!SteamGame.SteamInstalled && !UplayGame.UplayInstalled )
2020-04-27 10:55:44 +00:00
if ( GameLibrary = = SupportedGameLibrary . Steam )
2018-10-20 00:27:25 +00:00
{
2020-04-27 10:55:44 +00:00
if ( ! SteamGame . SteamInstalled )
{
throw new Exception ( Language . Steam_is_not_installed ) ;
}
2018-10-20 00:27:25 +00:00
2020-04-27 10:55:44 +00:00
List < SteamGame > allSteamGames = SteamGame . GetAllInstalledGames ( ) ;
2020-04-22 11:46:31 +00:00
2020-04-27 10:55:44 +00:00
SteamGame steamGameToRun = null ;
foreach ( SteamGame steamGameToCheck in allSteamGames )
{
if ( steamGameToCheck . GameId = = GameAppId )
{
steamGameToRun = steamGameToCheck ;
break ;
}
2020-04-22 11:46:31 +00:00
2020-04-27 10:55:44 +00:00
}
2020-04-22 11:46:31 +00:00
2018-10-20 00:27:25 +00:00
2020-04-27 10:55:44 +00:00
// Work out the name of the shortcut we'll save.
2020-05-01 10:30:27 +00:00
shortcutIconFileName = Path . Combine ( Program . ShortcutIconCachePath , String . Concat ( @"steam-" , GetValidFilename ( SelectedProfile . Name ) . ToLower ( CultureInfo . InvariantCulture ) , "-" , GameAppId . ToString ( ) , @".ico" ) ) ;
shortcutIcon = new ProfileIcon ( SelectedProfile ) . ToIconOverly ( steamGameToRun . GameIconPath ) ;
shortcutIcon . Save ( shortcutIconFileName , MultiIconFormat . ICO ) ;
2020-04-27 10:55:44 +00:00
2020-05-01 10:30:27 +00:00
args . Add ( $"steam {GameAppId}" ) ;
2020-04-27 10:55:44 +00:00
}
else if ( GameLibrary = = SupportedGameLibrary . Uplay )
2018-10-20 00:27:25 +00:00
{
2020-04-27 10:55:44 +00:00
if ( ! UplayGame . UplayInstalled )
2017-02-26 19:23:31 +00:00
{
2020-04-27 10:55:44 +00:00
throw new Exception ( Language . Steam_is_not_installed ) ;
2017-02-26 19:23:31 +00:00
}
2020-04-27 10:55:44 +00:00
List < UplayGame > allUplayGames = UplayGame . GetAllInstalledGames ( ) ;
UplayGame uplayGameToRun = null ;
foreach ( UplayGame uplayGameToCheck in allUplayGames )
2017-02-26 19:23:31 +00:00
{
2020-04-27 10:55:44 +00:00
if ( uplayGameToCheck . GameId = = GameAppId )
{
uplayGameToRun = uplayGameToCheck ;
break ;
}
2017-02-26 19:23:31 +00:00
}
2020-04-27 10:55:44 +00:00
2020-05-01 10:30:27 +00:00
//shortcutIcon = uplayGameToRun.GameIcon;
2020-04-27 10:55:44 +00:00
// Work out the name of the shortcut we'll save.
2020-05-01 10:30:27 +00:00
shortcutIconFileName = Path . Combine ( Program . ShortcutIconCachePath , String . Concat ( @"uplay-" , GetValidFilename ( SelectedProfile . Name ) . ToLower ( CultureInfo . InvariantCulture ) , "-" , GameAppId . ToString ( ) , @".ico" ) ) ;
shortcutIcon = new ProfileIcon ( SelectedProfile ) . ToIconOverly ( uplayGameToRun . GameIconPath ) ;
shortcutIcon . Save ( shortcutIconFileName , MultiIconFormat . ICO ) ;
2020-04-27 10:55:44 +00:00
2020-05-01 10:30:27 +00:00
args . Add ( $"uplay {GameAppId}" ) ;
2020-04-27 10:55:44 +00:00
2018-10-20 00:27:25 +00:00
}
2020-04-27 10:55:44 +00:00
2020-04-28 10:38:43 +00:00
// Add the Profile Name as the first option (use that rather than ID - though ID still will work!)
2020-05-01 10:30:27 +00:00
args . Add ( $"--profile \" { SelectedProfile . Name } \ "" ) ;
2020-04-28 10:38:43 +00:00
2020-04-27 10:55:44 +00:00
// Add the game timeout argument and the timeout duration in seconds to the shortcut arguments
args . Add ( $"--timeout {GameTimeout}" ) ;
if ( cb_args_game . Checked )
2018-10-20 00:27:25 +00:00
{
2020-04-27 10:55:44 +00:00
args . Add ( $"--arguments \" { GameArguments } \ "" ) ;
2018-10-20 00:27:25 +00:00
}
2020-04-27 10:55:44 +00:00
// Prepare text for the shortcut description field
2020-05-01 10:30:27 +00:00
shortcutDescription = string . Format ( Language . Executing_application_with_profile , GameName , SelectedProfile . Name ) ;
2020-04-27 10:55:44 +00:00
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
}
2020-04-22 11:46:31 +00:00
// Only add the rest of the options if the permanent switch radio button is set
2017-02-26 19:23:31 +00:00
else
{
2020-04-28 10:38:43 +00:00
// Add the action switch to make the permanent switch to a different profile
args . Add ( $"permanent" ) ;
// Add the Profile Name as the first option (use that rather than ID - though ID still will work!)
2020-05-01 10:30:27 +00:00
args . Add ( $"--profile \" { SelectedProfile . Name } \ "" ) ;
2020-04-28 10:38:43 +00:00
2020-04-22 11:46:31 +00:00
// Prepare text for the shortcut description field
2020-05-01 10:30:27 +00:00
shortcutDescription = string . Format ( Language . Switching_display_profile_to_profile , SelectedProfile . Name ) ;
2020-04-27 10:55:44 +00:00
// Work out the name of the shortcut we'll save.
2020-05-01 10:30:27 +00:00
shortcutIconFileName = Path . Combine ( Program . ShortcutIconCachePath , String . Concat ( @"permanent-" , GetValidFilename ( SelectedProfile . Name ) . ToLower ( CultureInfo . InvariantCulture ) , @".ico" ) ) ;
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
// Grab an icon for the selected profile
2017-02-26 19:23:31 +00:00
try
{
2020-05-01 10:30:27 +00:00
shortcutIcon = new ProfileIcon ( SelectedProfile ) . ToIcon ( ) ;
shortcutIcon . Save ( shortcutIconFileName , MultiIconFormat . ICO ) ;
2017-02-26 19:23:31 +00:00
}
catch
{
2020-04-27 10:55:44 +00:00
// but if that doesn't work, then we use our own one.
2020-05-01 10:30:27 +00:00
shortcutIcon = new ProfileIcon ( SelectedProfile ) . ToIconOverly ( Assembly . GetExecutingAssembly ( ) . Location ) ;
shortcutIcon . Save ( shortcutIconFileName , MultiIconFormat . ICO ) ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-22 11:46:31 +00:00
// Now we are ready to create a shortcut based on the filename the user gave us
2017-02-26 19:23:31 +00:00
fileName = Path . ChangeExtension ( fileName , @"lnk" ) ;
2018-10-20 00:27:25 +00:00
2020-04-22 11:46:31 +00:00
// If the user supplied a file
2017-02-26 19:23:31 +00:00
if ( fileName ! = null )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
try
{
// Remove the old file to replace it
if ( File . Exists ( fileName ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
File . Delete ( fileName ) ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
2020-04-22 11:46:31 +00:00
// Actually create the shortcut!
2017-02-26 19:23:31 +00:00
var wshShellType = Type . GetTypeFromCLSID ( new Guid ( "72C24DD5-D70A-438B-8A42-98424B88AFB8" ) ) ;
dynamic wshShell = Activator . CreateInstance ( wshShellType ) ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
try
{
var shortcut = wshShell . CreateShortcut ( fileName ) ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
try
{
shortcut . TargetPath = Application . ExecutablePath ;
shortcut . Arguments = string . Join ( " " , args ) ;
2020-04-27 10:55:44 +00:00
shortcut . Description = shortcutDescription ;
2017-02-26 19:23:31 +00:00
shortcut . WorkingDirectory = Path . GetDirectoryName ( Application . ExecutablePath ) ? ?
string . Empty ;
2018-10-20 00:27:25 +00:00
2020-04-27 10:55:44 +00:00
shortcut . IconLocation = shortcutIconFileName ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
shortcut . Save ( ) ;
}
finally
{
Marshal . FinalReleaseComObject ( shortcut ) ;
}
}
finally
{
Marshal . FinalReleaseComObject ( wshShell ) ;
}
}
catch
{
// Clean up a failed attempt
if ( File . Exists ( fileName ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
File . Delete ( fileName ) ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
}
2020-04-22 11:46:31 +00:00
// Return a status on how it went
// true if it was a success or false if it was not
2018-10-20 00:27:25 +00:00
return fileName ! = null & & File . Exists ( fileName ) ;
2017-02-26 19:23:31 +00:00
}
private void txt_executable_TextChanged ( object sender , EventArgs e )
{
2020-05-01 10:30:27 +00:00
if ( File . Exists ( txt_executable . Text ) )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
2020-05-01 10:30:27 +00:00
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
// Try and discern the process name for this
// if the user hasn't entered anything already
if ( txt_process_name . Text = = String . Empty )
{
try
{
txt_process_name . Text = Path . GetFileNameWithoutExtension ( txt_executable . Text ) ? . ToLower ( ) ? ? txt_process_name . Text ;
}
catch
{
// ignored
}
}
} else
2017-02-26 19:23:31 +00:00
{
2020-05-01 10:30:27 +00:00
// Turn off the CreateShortcut Button
btn_save . Enabled = false ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-19 05:37:29 +00:00
2020-04-22 11:46:31 +00:00
private void rb_switch_perm_CheckedChanged ( object sender , EventArgs e )
{
if ( rb_switch_perm . Checked )
{
// Disable the Temporary Group
g_temporary . Enabled = false ;
}
2020-05-01 10:30:27 +00:00
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
2020-04-22 11:46:31 +00:00
}
2020-04-19 05:37:29 +00:00
private void rb_switch_temp_CheckedChanged ( object sender , EventArgs e )
{
2020-04-22 11:46:31 +00:00
if ( rb_switch_temp . Checked )
{
// Enable the Temporary Group
g_temporary . Enabled = true ;
2020-05-01 10:30:27 +00:00
// If it's been set already to a valid gamelauncher, then enable the button
if ( txt_game_launcher . Text . Length > 0 & & txt_game_id . Text . Length > 0 & & txt_game_name . Text . Length > 0 )
{
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
}
// else if it's a valid executable
else if ( txt_executable . Text . Length > 0 & & File . Exists ( txt_executable . Text ) )
{
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
}
else
{
// Turn on the CreateShortcut Button
btn_save . Enabled = false ;
}
}
2020-04-19 05:37:29 +00:00
}
2020-04-22 11:46:31 +00:00
private void rb_standalone_CheckedChanged ( object sender , EventArgs e )
{
if ( rb_standalone . Checked )
{
// Enable the Standalone Panel
p_standalone . Enabled = true ;
// Disable the Game Panel
p_game . Enabled = false ;
2020-05-01 10:30:27 +00:00
if ( txt_executable . Text . Length > 0 & & File . Exists ( txt_executable . Text ) )
{
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
}
else
{
// Turn on the CreateShortcut Button
btn_save . Enabled = false ;
}
2020-04-22 11:46:31 +00:00
}
2020-05-01 10:30:27 +00:00
2020-04-22 11:46:31 +00:00
}
private void rb_launcher_CheckedChanged ( object sender , EventArgs e )
{
if ( rb_launcher . Checked )
{
// Enable the Game Panel
p_game . Enabled = true ;
// Disable the Standalone Panel
p_standalone . Enabled = false ;
2020-05-01 10:30:27 +00:00
// If it's been set already to a valid gamelauncher, then enable the button
if ( txt_game_launcher . Text . Length > 0 & & txt_game_id . Text . Length > 0 & & txt_game_name . Text . Length > 0 )
{
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
}
else
{
// Turn on the CreateShortcut Button
btn_save . Enabled = false ;
}
2020-04-22 11:46:31 +00:00
}
}
2020-04-19 05:37:29 +00:00
private void cb_args_executable_CheckedChanged ( object sender , EventArgs e )
{
2020-04-22 11:46:31 +00:00
// Disable the Process Name Text field
if ( cb_args_executable . Checked )
{
// Enable the Executable Arguments Text field
txt_args_executable . Enabled = true ;
}
else
{
// Disable the Executable Arguments Text field
txt_args_executable . Enabled = false ;
}
}
2020-04-23 08:16:16 +00:00
private async void ShortcutForm_Load ( object sender , EventArgs e )
2020-04-22 11:46:31 +00:00
{
2020-04-23 08:16:16 +00:00
// Set the Profile name
lbl_profile . Text = $"Selected Profile: {dv_profile.Profile?.Name ?? Language.None}" ;
2020-05-03 08:39:35 +00:00
/ * // Reload the profiles in case we swapped to another program to change it
ReloadProfiles ( ) ;
// If nothing is selected then select the currently used profile
if ( lv_profiles . SelectedItems . Count = = 0 )
{
lv_profiles . Items [ 0 ] . Selected = true ;
}
* /
2020-04-27 10:55:44 +00:00
// Start finding the games and loading the Games ListView
List < SteamGame > allSteamGames = SteamGame . GetAllInstalledGames ( ) ;
2020-04-28 10:38:43 +00:00
_allSteamGames = allSteamGames ;
2020-04-27 10:55:44 +00:00
foreach ( var game in allSteamGames . OrderBy ( game = > game . GameName ) )
2020-05-01 10:30:27 +00:00
{
if ( File . Exists ( game . GameIconPath ) )
{
try
{
if ( game . GameIconPath . EndsWith ( ".ico" ) )
{
// if it's an icon try to load it as a bitmap
il_games . Images . Add ( Image . FromFile ( game . GameIconPath ) ) ;
}
else if ( game . GameIconPath . EndsWith ( ".exe" , StringComparison . InvariantCultureIgnoreCase ) | | game . GameIconPath . EndsWith ( ".dll" , StringComparison . InvariantCultureIgnoreCase ) )
{
// otherwise use IconExtractor
/ * IconExtractor IconEx = new IconExtractor ( game . GameIconPath ) ;
Icon icoAppIcon = IconEx . GetIcon ( 0 ) ; // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.*/
Icon icoAppIcon = Icon . ExtractAssociatedIcon ( game . GameIconPath ) ;
// We first try high quality icons
Bitmap extractedBitmap = ExtractVistaIcon ( icoAppIcon ) ;
if ( extractedBitmap = = null )
extractedBitmap = icoAppIcon . ToBitmap ( ) ;
il_games . Images . Add ( extractedBitmap ) ;
}
}
catch ( Exception )
{
il_games . Images . Add ( Image . FromFile ( "Resources/Steam.ico" ) ) ;
}
} else
{
//(Icon)global::Calculate.Properties.Resources.ResourceManager.GetObject("Steam.ico");
il_games . Images . Add ( Image . FromFile ( "Resources/Steam.ico" ) ) ;
}
2020-04-22 11:46:31 +00:00
if ( ! Visible )
{
return ;
}
lv_games . Items . Add ( new ListViewItem
{
2020-04-27 10:55:44 +00:00
Text = game . GameName ,
2020-04-22 11:46:31 +00:00
Tag = game ,
ImageIndex = il_games . Images . Count - 1
} ) ;
2020-04-23 08:16:16 +00:00
}
2020-04-22 11:46:31 +00:00
}
private void rb_wait_process_CheckedChanged ( object sender , EventArgs e )
{
if ( rb_wait_process . Checked )
{
// Enable the Process Name Text field
txt_process_name . Enabled = true ;
2020-04-23 08:16:16 +00:00
} else
{
txt_process_name . Enabled = false ;
2020-04-22 11:46:31 +00:00
}
}
private void rb_wait_executable_CheckedChanged ( object sender , EventArgs e )
{
if ( rb_wait_executable . Checked )
{
// Disable the Process Name Text field
txt_process_name . Enabled = false ;
2020-04-23 08:16:16 +00:00
} else
{
txt_process_name . Enabled = true ;
2020-04-22 11:46:31 +00:00
}
}
private void btn_app_process_Click ( object sender , EventArgs e )
{
if ( dialog_open . ShowDialog ( this ) = = DialogResult . OK )
{
if ( File . Exists ( dialog_open . FileName ) & & Path . GetExtension ( dialog_open . FileName ) = = @".exe" )
{
txt_process_name . Text = dialog_open . FileName ;
dialog_open . FileName = string . Empty ;
}
else
{
MessageBox . Show (
Language . Selected_file_is_not_a_valid_executable_file ,
Language . Executable ,
MessageBoxButtons . OK ,
MessageBoxIcon . Exclamation ) ;
}
}
2020-04-19 05:37:29 +00:00
}
2020-04-23 08:16:16 +00:00
private void cb_args_game_CheckedChanged ( object sender , EventArgs e )
{
if ( cb_args_game . Checked )
{
txt_args_game . Enabled = true ;
} else
{
txt_args_game . Enabled = false ;
}
}
2020-04-28 10:38:43 +00:00
private void btn_choose_game_Click ( object sender , EventArgs e )
{
if ( lv_games . SelectedItems . Count > 0 )
{
txt_game_name . Text = lv_games . SelectedItems [ 0 ] . Text ;
foreach ( SteamGame game in _allSteamGames )
{
if ( game . GameName = = txt_game_name . Text )
{
2020-05-01 10:30:27 +00:00
txt_game_launcher . Text = SteamGame . GameLibrary . ToString ( ) ;
2020-04-28 10:38:43 +00:00
txt_game_id . Text = game . GameId . ToString ( ) ;
}
}
2020-05-01 10:30:27 +00:00
// Turn on the CreateShortcut Button
btn_save . Enabled = true ;
2020-04-28 10:38:43 +00:00
}
}
2020-05-03 08:39:35 +00:00
/ * private void RefreshProfilesStatus ( )
{
Profile . RefreshActiveStatus ( ) ;
lv_profiles . Invalidate ( ) ;
}
private void ReloadProfiles ( )
{
Profile . RefreshActiveStatus ( ) ;
var profiles = Profile . GetAllProfiles ( ) . ToArray ( ) ;
lv_profiles . Items . Clear ( ) ;
il_profiles . Images . Clear ( ) ;
if ( ! profiles . Any ( profile = > profile . IsActive ) )
{
AddProfile ( ) . Selected = true ;
}
foreach ( var profile in profiles )
{
AddProfile ( profile ) ;
}
lv_profiles . SelectedIndices . Clear ( ) ;
lv_profiles . Invalidate ( ) ;
}
* /
private void cb_selected_profile_SelectedIndexChanged ( object sender , EventArgs e )
{
foreach ( Profile profile in _allProfiles )
{
if ( SelectedProfile . Name = = cb_selected_profile . SelectedItem . ToString ( ) )
{
SelectedProfile = profile ;
}
}
}
2017-02-26 19:23:31 +00:00
}
}