1
0
mirror of synced 2024-11-05 02:59:16 +00:00

Added an auto update check

This commit is contained in:
Mark van Renswoude 2012-11-19 20:59:08 +00:00
parent 9e2fa518aa
commit 25aa106abc
5 changed files with 262 additions and 32 deletions

View File

@ -28,7 +28,7 @@ object MainForm: TMainForm
Margins.Top = 8 Margins.Top = 8
Margins.Right = 8 Margins.Right = 8
Margins.Bottom = 8 Margins.Bottom = 8
ActivePage = tsFSX ActivePage = tsAbout
Align = alClient Align = alClient
TabOrder = 1 TabOrder = 1
object tsFSX: TTabSheet object tsFSX: TTabSheet
@ -438,6 +438,7 @@ object MainForm: TMainForm
object tsAbout: TTabSheet object tsAbout: TTabSheet
Caption = 'About' Caption = 'About'
ImageIndex = 1 ImageIndex = 1
ExplicitLeft = 12
object lblVersionCaption: TLabel object lblVersionCaption: TLabel
Left = 16 Left = 16
Top = 67 Top = 67
@ -486,6 +487,19 @@ object MainForm: TMainForm
Height = 13 Height = 13
Caption = 'E-mail:' Caption = 'E-mail:'
end end
object lblProxy: TLabel
Left = 36
Top = 368
Width = 246
Height = 13
Caption = 'This might not work if you'#39're behind a proxy, sorry!'
Font.Charset = DEFAULT_CHARSET
Font.Color = clGrayText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
end
object lblWebsiteLink: TLinkLabel object lblWebsiteLink: TLinkLabel
Left = 75 Left = 75
Top = 111 Top = 111
@ -508,6 +522,23 @@ object MainForm: TMainForm
TabOrder = 1 TabOrder = 1
OnLinkClick = lblLinkLinkClick OnLinkClick = lblLinkLinkClick
end end
object cbCheckUpdates: TCheckBox
Left = 16
Top = 344
Width = 305
Height = 17
Caption = ' Automatically check for &updates'
TabOrder = 2
end
object btnCheckUpdates: TButton
Left = 344
Top = 340
Width = 83
Height = 25
Caption = '&Check now'
TabOrder = 3
OnClick = btnCheckUpdatesClick
end
end end
end end
object pnlG940: TPanel object pnlG940: TPanel
@ -900,7 +931,7 @@ object MainForm: TMainForm
Width = 75 Width = 75
Height = 25 Height = 25
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
Caption = 'Retry' Caption = '&Retry'
TabOrder = 0 TabOrder = 0
Visible = False Visible = False
OnClick = btnRetryClick OnClick = btnRetryClick

View File

@ -15,6 +15,7 @@ uses
OtlComm, OtlComm,
OtlEventMonitor, OtlEventMonitor,
OtlTaskControl, OtlTaskControl,
OtlTask,
pngimage, pngimage,
X2UtPersistIntf, X2UtPersistIntf,
@ -23,10 +24,15 @@ uses
LEDStateProvider; LEDStateProvider;
const
CM_ASKAUTOUPDATE = WM_APP + 1;
MSG_UPDATE = 1;
MSG_NOUPDATE = 2;
type type
TComboBoxArray = array[0..7] of TComboBoxEx; TComboBoxArray = array[0..7] of TComboBoxEx;
TMainForm = class(TForm) TMainForm = class(TForm)
imgStateNotFound: TImage; imgStateNotFound: TImage;
lblG940Throttle: TLabel; lblG940Throttle: TLabel;
@ -79,6 +85,9 @@ type
lblEmailLink: TLinkLabel; lblEmailLink: TLinkLabel;
lblWebsite: TLabel; lblWebsite: TLabel;
lblEmail: TLabel; lblEmail: TLabel;
cbCheckUpdates: TCheckBox;
btnCheckUpdates: TButton;
lblProxy: TLabel;
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure btnRetryClick(Sender: TObject); procedure btnRetryClick(Sender: TObject);
@ -88,6 +97,7 @@ type
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FunctionComboBoxChange(Sender: TObject); procedure FunctionComboBoxChange(Sender: TObject);
procedure lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType); procedure lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
procedure btnCheckUpdatesClick(Sender: TObject);
private private
FEventMonitor: TOmniEventMonitor; FEventMonitor: TOmniEventMonitor;
FStateConsumerTask: IOmniTaskControl; FStateConsumerTask: IOmniTaskControl;
@ -100,8 +110,10 @@ type
procedure ReadFunctions(AReader: IX2PersistReader; AComboBoxes: TComboBoxArray); procedure ReadFunctions(AReader: IX2PersistReader; AComboBoxes: TComboBoxArray);
procedure ReadFSXExtra(AReader: IX2PersistReader); procedure ReadFSXExtra(AReader: IX2PersistReader);
procedure ReadAutoUpdate(AReader: IX2PersistReader);
procedure WriteFunctions(AWriter: IX2PersistWriter; AComboBoxes: TComboBoxArray); procedure WriteFunctions(AWriter: IX2PersistWriter; AComboBoxes: TComboBoxArray);
procedure WriteFSXExtra(AWriter: IX2PersistWriter); procedure WriteFSXExtra(AWriter: IX2PersistWriter);
procedure WriteAutoUpdate(AWriter: IX2PersistWriter);
procedure LoadDefaultProfile; procedure LoadDefaultProfile;
procedure SaveDefaultProfile; procedure SaveDefaultProfile;
@ -114,6 +126,9 @@ type
procedure UpdateMapping; procedure UpdateMapping;
procedure CheckForUpdatesThread(const ATask: IOmniTask);
procedure CheckForUpdates(AReportNoUpdates: Boolean);
procedure EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage); procedure EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
procedure EventMonitorTerminated(const task: IOmniTaskControl); procedure EventMonitorTerminated(const task: IOmniTaskControl);
@ -122,6 +137,8 @@ type
procedure HandleProviderKilled(ATask: IOmniTaskControl; AMessage: TOmniMessage); procedure HandleProviderKilled(ATask: IOmniTaskControl; AMessage: TOmniMessage);
procedure HandleProviderKilledFSX(ATask: IOmniTaskControl; AMessage: TOmniMessage); procedure HandleProviderKilledFSX(ATask: IOmniTaskControl; AMessage: TOmniMessage);
procedure CMAskAutoUpdate(var Msg: TMessage); message CM_ASKAUTOUPDATE;
property EventMonitor: TOmniEventMonitor read FEventMonitor; property EventMonitor: TOmniEventMonitor read FEventMonitor;
property StateConsumerTask: IOmniTaskControl read FStateConsumerTask; property StateConsumerTask: IOmniTaskControl read FStateConsumerTask;
end; end;
@ -134,8 +151,9 @@ uses
ShellAPI, ShellAPI,
SysUtils, SysUtils,
IdException,
IdHTTP,
OtlCommon, OtlCommon,
OtlTask,
X2UtApp, X2UtApp,
X2UtPersistRegistry, X2UtPersistRegistry,
@ -154,8 +172,10 @@ const
TEXT_STATE_NOTFOUND = 'Not found'; TEXT_STATE_NOTFOUND = 'Not found';
TEXT_STATE_FOUND = 'Connected'; TEXT_STATE_FOUND = 'Connected';
KEY_DEFAULTPROFILE = '\Software\X2Software\G940LEDControl\DefaultProfile\'; KEY_SETTINGS = '\Software\X2Software\G940LEDControl\';
SECTION_DEFAULTPROFILE = 'DefaultProfile';
SECTION_FSX = 'FSX'; SECTION_FSX = 'FSX';
SECTION_SETTINGS = 'Settings';
type type
@ -221,6 +241,17 @@ begin
end; end;
procedure TMainForm.CMAskAutoUpdate(var Msg: TMessage);
begin
if MessageBox(Self.Handle, 'I''m sorry to delay your flight, but I will only ask this once.'#13#10 +
'Do you want to automatically check for updates?', 'Check for updates', MB_YESNO or MB_ICONQUESTION) = ID_YES then
begin
cbCheckUpdates.Checked := True;
CheckForUpdates(False);
end;
end;
procedure TMainForm.SetDeviceState(const AMessage: string; AFound: Boolean); procedure TMainForm.SetDeviceState(const AMessage: string; AFound: Boolean);
begin begin
lblG940ThrottleState.Caption := AMessage; lblG940ThrottleState.Caption := AMessage;
@ -326,6 +357,32 @@ begin
end; end;
procedure TMainForm.ReadAutoUpdate(AReader: IX2PersistReader);
var
checkUpdates: Boolean;
askAutoUpdate: Boolean;
begin
askAutoUpdate := True;
if AReader.BeginSection(SECTION_SETTINGS) then
try
if AReader.ReadBoolean('CheckUpdates', checkUpdates) then
begin
cbCheckUpdates.Checked := checkUpdates;
askAutoUpdate := False;
end;
finally
AReader.EndSection;
end;
if askAutoUpdate then
PostMessage(Self.Handle, CM_ASKAUTOUPDATE, 0, 0)
else if cbCheckUpdates.Checked then
CheckForUpdates(False);
end;
procedure TMainForm.WriteFunctions(AWriter: IX2PersistWriter; AComboBoxes: TComboBoxArray); procedure TMainForm.WriteFunctions(AWriter: IX2PersistWriter; AComboBoxes: TComboBoxArray);
var var
comboBox: TComboBoxEx; comboBox: TComboBoxEx;
@ -362,6 +419,17 @@ begin
end; end;
procedure TMainForm.WriteAutoUpdate(AWriter: IX2PersistWriter);
begin
if AWriter.BeginSection(SECTION_SETTINGS) then
try
AWriter.WriteBoolean('CheckUpdates', cbCheckUpdates.Checked);
finally
AWriter.EndSection;
end;
end;
procedure TMainForm.LoadDefaultProfile; procedure TMainForm.LoadDefaultProfile;
var var
registryReader: TX2UtPersistRegistry; registryReader: TX2UtPersistRegistry;
@ -371,12 +439,19 @@ begin
registryReader := TX2UtPersistRegistry.Create; registryReader := TX2UtPersistRegistry.Create;
try try
registryReader.RootKey := HKEY_CURRENT_USER; registryReader.RootKey := HKEY_CURRENT_USER;
registryReader.Key := KEY_DEFAULTPROFILE; registryReader.Key := KEY_SETTINGS;
reader := registryReader.CreateReader; reader := registryReader.CreateReader;
ReadFunctions(reader, FFSXComboBoxes); if reader.BeginSection(SECTION_DEFAULTPROFILE) then
ReadFSXExtra(reader); try
ReadFunctions(reader, FFSXComboBoxes);
ReadFSXExtra(reader);
finally
reader.EndSection;
end;
ReadAutoUpdate(reader);
finally finally
FreeAndNil(registryReader); FreeAndNil(registryReader);
end; end;
@ -392,11 +467,18 @@ begin
registryWriter := TX2UtPersistRegistry.Create; registryWriter := TX2UtPersistRegistry.Create;
try try
registryWriter.RootKey := HKEY_CURRENT_USER; registryWriter.RootKey := HKEY_CURRENT_USER;
registryWriter.Key := KEY_DEFAULTPROFILE; registryWriter.Key := KEY_SETTINGS;
writer := registryWriter.CreateWriter; writer := registryWriter.CreateWriter;
WriteFunctions(writer, FFSXComboBoxes); if writer.BeginSection(SECTION_DEFAULTPROFILE) then
WriteFSXExtra(writer); try
WriteFunctions(writer, FFSXComboBoxes);
WriteFSXExtra(writer);
finally
writer.EndSection;
end;
WriteAutoUpdate(writer);
finally finally
FreeAndNil(registryWriter); FreeAndNil(registryWriter);
end; end;
@ -426,12 +508,123 @@ begin
end; end;
function FetchNextNumber(var AValue: string; out ANumber: Integer): Boolean;
var
dotPos: Integer;
number: string;
begin
ANumber := 0;
dotPos := AnsiPos('.', AValue);
if dotPos > 0 then
begin
number := Copy(AValue, 1, Pred(dotPos));
Delete(AValue, 1, dotPos);
end
else
begin
number := AValue;
AValue := '';
end;
Result := TryStrToInt(number, ANumber);
end;
function VersionIsNewer(const AVersion1, AVersion2: string): Boolean;
var
version1: string;
version2: string;
number1: Integer;
number2: Integer;
begin
if Length(AVersion1) = 0 then
begin
Result := True;
Exit;
end;
Result := False;
version1 := AVersion1;
version2 := AVersion2;
while (not Result) and
FetchNextNumber(version1, number1) and
FetchNextNumber(version2, number2) do
begin
if number2 > number1 then
Result := True
else if number2 < number1 then
Break;
end;
end;
procedure TMainForm.CheckForUpdatesThread(const ATask: IOmniTask);
var
httpClient: TIdHTTP;
msgSent: Boolean;
latestVersion: string;
begin
msgSent := False;
try
httpClient := TIdHTTP.Create(nil);
try
latestVersion := httpClient.Get('http://g940.x2software.net/version');
if VersionIsNewer(Format('%d.%d.%d', [App.Version.Major, App.Version.Minor, App.Version.Release]), latestVersion) then
ATask.Comm.Send(MSG_UPDATE)
else
begin
if ATask.Param.ByName('ReportNoUpdates').AsBoolean then
ATask.Comm.Send(MSG_NOUPDATE, True);
end;
msgSent := True;
finally
FreeAndNil(httpClient);
end;
except
on E:EIdSilentException do;
on E:Exception do
begin
if not msgSent then
ATask.Comm.Send(MSG_NOUPDATE, False);
end;
end;
end;
procedure TMainForm.CheckForUpdates(AReportNoUpdates: Boolean);
begin
btnCheckUpdates.Enabled := False;
CreateTask(CheckForUpdatesThread, 'CheckForUpdatesThread')
.MonitorWith(EventMonitor)
.SetParameter('ReportNoUpdates', AReportNoUpdates)
.Run;
end;
procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage); procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
begin begin
case msg.MsgID of case msg.MsgID of
MSG_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg); MSG_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg);
MSG_RUN_IN_MAINTHREAD: HandleRunInMainThreadMessage(task, msg); MSG_RUN_IN_MAINTHREAD: HandleRunInMainThreadMessage(task, msg);
MSG_PROVIDER_KILLED: HandleProviderKilled(task, msg); MSG_PROVIDER_KILLED: HandleProviderKilled(task, msg);
MSG_UPDATE:
if MessageBox(Self.Handle, 'An update is available on the G940 LED Control website.'#13#10'Do you want to go there now?',
'Update available', MB_YESNO or MB_ICONINFORMATION) = ID_YES then
ShellExecute(Self.Handle, 'open', PChar('http://g940.x2software.net/#download'), nil, nil, SW_SHOWNORMAL);
MSG_NOUPDATE:
if msg.MsgData.AsBoolean then
MessageBox(Self.Handle, 'You are using the latest version.', 'No update available', MB_OK or MB_ICONINFORMATION)
else
MessageBox(Self.Handle, 'Failed to check for updates. Maybe try again later?', 'Uh-oh', MB_OK or MB_ICONWARNING);
end; end;
end; end;
@ -442,7 +635,8 @@ begin
begin begin
FStateConsumerTask := nil; FStateConsumerTask := nil;
Close; Close;
end; end else if task.Name = 'CheckForUpdatesThread' then
btnCheckUpdates.Enabled := True;
end; end;
@ -495,6 +689,11 @@ begin
end; end;
procedure TMainForm.btnCheckUpdatesClick(Sender: TObject);
begin
CheckForUpdates(True);
end;
procedure TMainForm.btnFSXConnectClick(Sender: TObject); procedure TMainForm.btnFSXConnectClick(Sender: TObject);
begin begin
SaveDefaultProfile; SaveDefaultProfile;

View File

@ -3,14 +3,14 @@ program G940LEDControl;
uses uses
Forms, Forms,
MainFrm in 'Forms\MainFrm.pas' {MainForm}, MainFrm in 'Forms\MainFrm.pas' {MainForm},
FSXLEDStateProvider in 'Units\FSXLEDStateProvider.pas',
LEDStateConsumer in 'Units\LEDStateConsumer.pas',
LEDStateProvider in 'Units\LEDStateProvider.pas',
LEDFunctionMap in 'Units\LEDFunctionMap.pas',
G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas',
LogiJoystickDLL in '..\Shared\LogiJoystickDLL.pas', LogiJoystickDLL in '..\Shared\LogiJoystickDLL.pas',
SimConnect in '..\Shared\SimConnect.pas', SimConnect in '..\Shared\SimConnect.pas',
ButtonSelectFrm in 'Forms\ButtonSelectFrm.pas' {ButtonSelectForm}; ButtonSelectFrm in 'Forms\ButtonSelectFrm.pas' {ButtonSelectForm},
FSXLEDStateProvider in 'Units\FSXLEDStateProvider.pas',
G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas',
LEDFunctionMap in 'Units\LEDFunctionMap.pas',
LEDStateConsumer in 'Units\LEDStateConsumer.pas',
LEDStateProvider in 'Units\LEDStateProvider.pas';
{$R *.res} {$R *.res}

View File

@ -163,17 +163,17 @@
<DCCReference Include="Forms\MainFrm.pas"> <DCCReference Include="Forms\MainFrm.pas">
<Form>MainForm</Form> <Form>MainForm</Form>
</DCCReference> </DCCReference>
<DCCReference Include="Units\FSXLEDStateProvider.pas"/>
<DCCReference Include="Units\LEDStateConsumer.pas"/>
<DCCReference Include="Units\LEDStateProvider.pas"/>
<DCCReference Include="Units\LEDFunctionMap.pas"/>
<DCCReference Include="Units\G940LEDStateConsumer.pas"/>
<DCCReference Include="..\Shared\LogiJoystickDLL.pas"/> <DCCReference Include="..\Shared\LogiJoystickDLL.pas"/>
<DCCReference Include="..\Shared\SimConnect.pas"/> <DCCReference Include="..\Shared\SimConnect.pas"/>
<DCCReference Include="Forms\ButtonSelectFrm.pas"> <DCCReference Include="Forms\ButtonSelectFrm.pas">
<Form>ButtonSelectForm</Form> <Form>ButtonSelectForm</Form>
<FormType>dfm</FormType> <FormType>dfm</FormType>
</DCCReference> </DCCReference>
<DCCReference Include="Units\FSXLEDStateProvider.pas"/>
<DCCReference Include="Units\G940LEDStateConsumer.pas"/>
<DCCReference Include="Units\LEDFunctionMap.pas"/>
<DCCReference Include="Units\LEDStateConsumer.pas"/>
<DCCReference Include="Units\LEDStateProvider.pas"/>
<BuildConfiguration Include="Debug"> <BuildConfiguration Include="Debug">
<Key>Cfg_2</Key> <Key>Cfg_2</Key>
<CfgParent>Base</CfgParent> <CfgParent>Base</CfgParent>

View File

@ -11,19 +11,19 @@ uses
const const
MSG_CLEAR_FUNCTIONS = 1; MSG_CLEAR_FUNCTIONS = 1001;
MSG_SET_FUNCTION = 2; MSG_SET_FUNCTION = 1002;
MSG_INITIALIZE_PROVIDER = 3; MSG_INITIALIZE_PROVIDER = 1003;
MSG_FINALIZE_PROVIDER = 4; MSG_FINALIZE_PROVIDER = 1004;
MSG_PROCESS_MESSAGES = 5; MSG_PROCESS_MESSAGES = 1005;
MSG_FINALIZE = 6; MSG_FINALIZE = 1006;
MSG_PROVIDER_KILLED = 7; MSG_PROVIDER_KILLED = 1007;
MSG_RUN_IN_MAINTHREAD = 8; MSG_RUN_IN_MAINTHREAD = 1008;
MSG_CONSUMER_OFFSET = MSG_RUN_IN_MAINTHREAD; MSG_CONSUMER_OFFSET = MSG_RUN_IN_MAINTHREAD;
TIMER_PROCESSMESSAGES = 1; TIMER_PROCESSMESSAGES = 1001;
TIMER_CONSUMER_OFFSET = TIMER_PROCESSMESSAGES; TIMER_CONSUMER_OFFSET = TIMER_PROCESSMESSAGES;