Archive

Posts Tagged ‘Delphi’

HowTo: show a confirmation dialog with Delphi FireMonkey UI library

Here’s my answer at https://stackoverflow.com/a/71728787/903783 on how to show a confirmation dialog with Delphi’s cross-platform FireMonkey UI library.

Based on other answers, I’ve added a “Confirm” class function (adapted to return a Boolean) to TApplicationHelper (which also has an untested function to get the executable filename), currently maintained under the READCOM_App repository.

Update: had to modify the answer to use a callback so that it also works on platforms where FMX supports only asynchronous dialogs, like Android

unit Zoomicon.Helpers.FMX.Forms.ApplicationHelper;

interface
uses
  FMX.Forms; //for TApplication

type
  TApplicationHelper = class helper for TApplication
  public
    function ExeName: String;
    class function Confirm(Prompt: String): Boolean;
  end;

implementation
  uses
    {$IFDEF ANDROID}
    System.SysUtils, //TODO: is this needed?
    Androidapi.Helpers, //for TAndroidHelper, JStringToString
    Androidapi.Jni.JavaTypes, //to avoid "H2443 Inline function 'JStringToString' has not been expanded"
    {$ENDIF}
    System.UITypes, //for TMsgDlgType
    FMX.DialogService, //for TDialogService
    FMX.Dialogs; //for mbYesNo

{$region 'TApplicationHelper'}

//from https://gist.github.com/freeonterminate/2f7b2e29e40fa30ed3c4
function TApplicationHelper.ExeName: String;
begin
  Result := ParamStr(0);

  {$IFDEF ANDROID}
  if (Result.IsEmpty) then
    Result := JStringToString(TAndroidHelper.Context.getPackageCodePath);
  {$ENDIF}
end;

//based on https://stackoverflow.com/questions/42852945/delphi-correctly-displaying-a-message-dialog-in-firemonkey-and-returning-the-m
class procedure TApplicationHelper.Confirm(const Prompt: String; const SetConfirmationResult: TProc<Boolean>);
begin
  with TDialogService do
  begin
    PreferredMode := TPreferredMode.Platform;
    MessageDialog(Prompt, TMsgDlgType.mtConfirmation, mbYesNo, TMsgDlgBtn.mbNo, 0,
      procedure(const AResult: TModalResult)
      begin
        //Note: assuming this is executed on the main/UI thread later on, so we just call the "SetResult" callback procedure passing it the dialog result value
        case AResult of
          mrYes: SetConfirmationResult(true);
          mrNo: SetConfirmationResult(false);
        end;
      end
    );
  end;
end;

{$endregion}

end.

usage example is in the MainForm of READCOM_App

procedure TMainForm.HUDactionNewExecute(Sender: TObject);
begin
  TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too)
    procedure(Confirmed: Boolean)
    begin
      if Confirmed and (not LoadDefaultDocument) then
        NewRootStoryItem;
    end
  );
end;

where MSG_CONFIRM_CLEAR_STORY is declared as

resourcestring
  MSG_CONFIRM_CLEAR_STORY = 'Clearing story: are you sure?';

Fix: Delphi error MSBuildToolsPath is not specified for the ToolsVersion …

This is my answer at:

http://stackoverflow.com/questions/32936544/delphi-10-seattle-trial-fails-to-compile-anything-gives-an-msbuild-error

for the issue of Delphi showing on build the error

MSBuildToolsPath is not specified for the ToolsVersion “12.0” defined at “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0”, or the value specified evaluated to the empty string

note that in my case it was also showing underlined unit names in the code editor at uses clause with “Cannot resolve unit name xx”


It is a known issue, documented here: https://community.embarcadero.com/article/technical-articles/16202-msbuildtoolspath-is-not-specified-for-the-toolsversion

This error is caused by incorrect values in the registry. On a 32 OS, run regedit and navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild. On a 64 bit OS, run regedit and navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSBuild. First, backup this registry key by selecting File | Export. Next, look at the numbers below the ToolsVersions key. Delete any number not found at the MSBuild level. … There is anecdotal evidence to suggest this registry key imbalance is caused by uninstalling some versions of Visual Studio, but it has not been confirmed at this time.

Since I’ve been installing/uninstalling various Visual Studio versions (including previews), guess it has indeed been caused by that

Error “A default tools version “2.0” was specified, but its definition could not be found.” may appear then if you deleted the 2.0 key following the 1st article’s advice. Solution for that one is to edit each value under MSBuild key in the registry locations mentioned for x32 and x64 and change DefaultToolsVersion to 14.0 or other highest MSBuild tools version that is installed

Στιγμιότυπο οθόνης (504)

image

Note that on x64 machine you need to fix these two issues for both x32 and x64 registry locations, since the IDE is 32-bit process and if you fix x64 location only it will fail internally, underlining all Standard units at uses clause in your source code at uses clause and showing “Cannot resolve unit name xx”

Στιγμιότυπο οθόνης (506)

image

Also it may be useful to install this: https://www.microsoft.com/en-us/download/confirmation.aspx?id=48159

This may also be useful to know (copying from https://msdn.microsoft.com/en-us/library/bb383985.aspx):

Order of Precedence

The order of precedence, from highest to lowest, used to determine the ToolsVersion is: The ToolsVersion attribute on the MSBuild task used to build the project, if any.

The /toolsversion (or /tv) switch that’s used in the msbuild.exe command, if any.

If the environment variable MSBUILDTREATALLTOOLSVERSIONSASCURRENT is set, then use the current ToolsVersion.

If the environment variable MSBUILDTREATHIGHERTOOLSVERSIONASCURRENT is set and the ToolsVersion defined in the project file is greater than the current ToolsVersion, use the current ToolsVersion.

If the environment variable MSBUILDLEGACYDEFAULTTOOLSVERSION is set, or if ToolsVersion is not set, then the following steps are used:

The ToolsVersion attribute of the Project element of the project file. If this attribute doesn’t exist, it is assumed to be the current version.

The default tools version in the MSBuild.exe.config file.

The default tools version in the registry. For more information, see Standard and Custom Toolset Configurations.

If the environment variable MSBUILDLEGACYDEFAULTTOOLSVERSION is not set, then the following steps are used:

If the environment variable MSBUILDDEFAULTTOOLSVERSION is set to a ToolsVersion that exists, use it.

If DefaultOverrideToolsVersion is set in MSBuild.exe.config, use it.

If DefaultOverrideToolsVersion is set in the registry, use it.

Otherwise, use the current ToolsVersion.

Categories: Posts Tags: , , , ,

Converting C structs and unions to Pascal (or Object Pascal / Delphi) records

I’ve been recently adding support for QuickTime TimeCode tracks to the JEDI QuickTime library’s “qt_QuickTimeComponents.pas” file and I thought I should share a quick reminder on how we convert C structs (records) and unions (sets) into Pascal (Delphi / Object Pascal in this case) records:

Structs:

struct TimeCodeCounter {
long counter;
};
typedef struct TimeCodeCounter TimeCodeCounter;

type
long=integer; //in JEDI QuickTime I opted to create aliases for common C types to avoid converting them to Pascal equivalents everywhere
TimeCodeCounter = record
counter:long;
end;

Unions:

union TimeCodeRecord {
TimeCodeTime t;
TimeCodeCounter c;
};

type TimeCodeRecord = record
case integer of //C’s union
0: (t: TimeCodeTime);
1: (c: TimeCodeCounter);
end;

Do note that you should use “packed record” in Pascal if the C code uses respective #pragma command to define 0-packing gap between record fields (the default for C and Pascal compilers is to do field alignment to word [16-bit] boundaries for optimization purposes)

Categories: Posts Tags: , , , , ,