воскресенье, 11 мая 2014 г.

Getting gesture distance in Delphi

There are two types of touch screens supported in Windows - one that detect gestures natively and uses special messages for them and another that uses mouse emulation and sends standard mouse messages on touch events. Delphi detects both these types and uses appropriate gesture engine internally. There is however a problem with mouse gesture engine in that it does not report distance that you swiped on the screen. This means that there could be false positives when user just wanted to press button but system detects it as gesture. Fortunately it is pretty easy to replace mouse gesture engine with custom implementation. This implementation will be almost exactly the same as standard TMouseGestureEngine. Since it is a sealed class we cannot inherit from it so we will need to copy it completely to new unit from Vcl.Touch.Gestures and call it for example TMouseGestureEngineEx Here are modifications that are needed for this class

// function that calculates distance between to points
function Distance(Point1, Point2: TPoint): Integer;
begin
  Result := Round(Sqrt(Sqr(Point1.X - Point2.X) + Sqr(Point1.Y - Point2.Y)));
end;

procedure TMouseGestureEngineEx.Notification(const Message: TMessage);

// .....

            if (LGestureList.Count > 0) and
               TGestureEngine.IsGesture(Points, LGestureList, [gtStandard] + [gtRecorded, gtRegistered], LEventInfo) then
            begin
              // add this line to set distance
              LEventInfo.Distance := Distance(Points[Low(Points)], Points[High(Points)]);
              BroadcastGesture(TargetControl, LEventInfo);
            end;

// ...

// registering our new gesture engine
initialization
  TGestureEngine.DefaultEngineClass := TMouseGestureEngineEx;
end.

Now in gesture event we can check EventInfo.Distance field

procedure TForm1.FormGesture(Sender: TObject;
  const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
  Label1.Caption := 'Distance ' + IntToStr(EventInfo.Distance);
end;

This kind of calculation will work only for simple gestures because it calculates distance only between first and last points of swipe.

SQL Server express silent installation


SQL server setup supports silent installation options but it may be inconvenient to distribute this installation. One simple solution to this is to create your own installer as self extracting archive that embeds SQL server installation. There are different programs that support this functionality, I used 7-zip because it is open source. So here is an example of batch file that creates silent installation of SQL server 2014 express, it's pretty much the same for all older versions. Assumption is that downloaded SQLEXPR_x64_ENU.exe is located in the same folder as batch file. As a result it creates SQLServerExpress2014x64.exe which can be run to install SQL server.

set InstallName=SQLServerExpress2014x64.exe
set ArchiveName=SQLEXPR_x64_ENU.7z
if exist %InstallName% del /Q %InstallName%
if exist %ArchiveName% del /Q %ArchiveName%
"%PROGRAMFILES%\7-zip\7z.exe" a -t7z -r0 %ArchiveName% SQLEXPR_x64_ENU.exe

@echo ;!@Install@!UTF-8! >config.txt
@echo Title="SQL Server Express version 2014 64-bit">>config.txt
@echo BeginPrompt="Do you want to install SQL Server Express version 2014 64-bit?">>config.txt
:: here you can change options for SQL server installation, full list of options is here http://msdn.microsoft.com/en-us/library/ms144259.aspx
@echo RunProgram="SQLEXPR_x64_ENU.exe /q /ACTION=Install /SECURITYMODE=SQL /TCPENABLED=1 /INSTANCENAME=MSSQLSERVER /IACCEPTSQLSERVERLICENSETERMS /SAPWD=gfhjkm856 /ADDCURRENTUSERASSQLADMIN=True /SQLSVCACCOUNT=\"NT AUTHORITY\\Network Service\"">>config.txt
@echo ;!@InstallEnd@!>>config.txt

::SFX module can be downloaded from here http://downloads.sourceforge.net/sevenzip/7z920_extra.7z
copy /b "%ProgramFiles%\7-Zip\Extra\7zS.sfx" + config.txt + %ArchiveName% %InstallName%
if exist %ArchiveName% del /Q %ArchiveName%
if exist config.txt del /Q config.txt

One problem with this approach is that installer window is hidden so you can't see when it's finished, the only way to check for it is to see %temp%\SqlSetup.log file. You will also need to check this file to see if installation was successful, in this case exit code will be 0.