google-code-prettifyでソースコードを色づけする

google-code-prettifyは、ソースコードをきれいに表示してくれるJavaScriptのライブラリです。

一番簡単な使い方は、次のコードを追加します。

<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>

クラス名が「prettyprint」である要素の内容を色づけしてくれます。

このブログでは、次のようにしてpreタグのクラス名に「prettyprint」を設定して、google-code-prettifyで色づけしています。

<script type="text/javascript">
        var elements = document.getElementsByTagName("pre"); 
        for (var i = 0; i < elements.length; i++) {
            elements[i].className = "prettyprint";
        }
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>

Delphi 10.1 BelrinのFireMonkeyアプリケーションで文字列を選択するリストピッカーを表示するには

リストピッカーはIFMXPickerServiceのCreateListPickerメソッドで作成できます。

uses
  FMX.Platform;

  if TPlatformServices.Current.SupportsPlatformService(IFMXPickerService, PickerService) then
  begin
    FListPicker := PickerService.CreateListPicker;
    …

作成したリストピッカーのイベントや選択項目を設定します。

FListPicker.Parent := Button1;

// イベントの設定
FListPicker.OnValueChanged := DoListPickerValueChanged;
FListPicker.OnHide := DoListPickerHide;
FListPicker.OnShow := DoListPickerShow;

// 選択項目の設定
FListPicker.Values.Add('Delphi');
FListPicker.Values.Add('C++Builder');
FListPicker.Values.Add('RAD Studio');

// 選択されている項目の設定
FListPicker.ItemIndex := 1;

Showメソッドを呼び出すと、リストピッカーを表示できます。

FListPicker.Show;

サンプルアプリケーション

フォームにボタン(TButton)とメモ(TMemo)を配置します。

interfaceのusesにFMX.Pickersを追加します。

interface

uses
…, FMX.Pickers; //追加

フォームにprivate変数を追加します。

type
TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
private
    { private 宣言 }
    FListPicker: TCustomListPicker; //追加

フォームのOnCreateイベントを追加します。

リストピッカーを作成し、イベントや選択項目を設定します。

uses
  FMX.Platform;

procedure TForm1.FormCreate(Sender: TObject);
var
PickerService: IFMXPickerService;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXPickerService, PickerService) then
  begin
    FListPicker := PickerService.CreateListPicker;
    FListPicker.Parent := Button1;

    // イベントの設定
    FListPicker.OnValueChanged := DoListPickerValueChanged;
    FListPicker.OnHide := DoListPickerHide;
    FListPicker.OnShow := DoListPickerShow;

    // 選択項目の設定
    FListPicker.Values.Add('Delphi');
    FListPicker.Values.Add('C++Builder');
    FListPicker.Values.Add('RAD Studio');

    // 選択されている項目の設定
    FListPicker.ItemIndex := 1;
  end;
end;

リストピッカーのイベントを追加します。
イベントが発生するとMemo1に出力します。

type
TForm1 = class(TForm)
  Button1: TButton;
  Memo1: TMemo;
  procedure FormCreate(Sender: TObject);
private
  { private 宣言 }
  FListPicker: TCustomListPicker;
  procedure DoListPickerValueChanged(Sender: TObject; const AValueIndex: Integer); // 追加
  procedure DoListPickerHide(Sender: TObject); // 追加
  procedure DoListPickerShow(Sender: TObject); // 追加
public
  { public 宣言 }
end;

procedure TForm1.DoListPickerHide(Sender: TObject);
begin
  Memo1.Lines.Add('DoListPickerHide');
end;

procedure TForm1.DoListPickerShow(Sender: TObject);
begin
  Memo1.Lines.Add('DoListPickerShow');
end;

procedure TForm1.DoListPickerValueChanged(Sender: TObject; const AValueIndex: Integer);
begin
  Memo1.Lines.Add('DoListPickerValueChanged AValueIndex=' + IntToStr(AValueIndex));
end;

ボタン(Button1)のOnClickイベントを追加します。
ボタンを押すとリストピッカーを表示します。

procedure TForm1.Button1Click(Sender: TObject);
begin
  FListPicker.Show;
end;

Windows 10で日本語入力システムが変更されてしまうの対策

Windows 10を使っていて、意図せず、日本語入力がATOKからMicrosoft IMEに変わってしまうことがある。

原因は、日本語入力を切り替えるキーを押してしまっているため。

そこで、設定を変更して、日本語入力の切り替えを無効にする。

  1. Windowsのスタートボタンを右クリックして、「コントロールパネル」を選択する

    001

  2. 「入力方法の変更」を選択する

    002

  3. 「詳細設定」を選択する

    003

  4. 「入力方式の切り替え」の「言語バーのホットキーの変更」をクリックする

    004

  5. 「キーシーケンスの変更」ボタンをクリックする

    005

  6. 「キーボードレイアウトの切り替え」の「割り当てなし」をチェックする

    006

  7. 「OK」ボタンをクリックする

以上で、設定完了です。

カスタム属性をつけたフィールドの値を取得するサンプル

カスタム属性をつけたフィールドの値を取得するサンプルを作り、カスタム属性の使い方を試してみます。

まず、次のようなカスタム属性を作成します。

type
  LogAttribute = class(TCustomAttribute)
  end;

このLogAttributeをつけたフィールドだけを出力するプログラムを作成します。

type
  TSample = class
  private
    [Log]
    FVal1: string;
    [Log]
    FVal2: string;
    FVal3: string;
  public
    constructor Create(const AVal1, AVal2, AVal3: string);
  end;

constructor TSample.Create(const AVal1, AVal2, AVal3: string);
begin
  FVal1 := AVal1;
  FVal2 := AVal2;
  FVal3 := AVal3;
end;

FVal1とFVal2に属性をつけました。 FVal3には属性はつけていません。

var
  Sample: TSample;

begin
  Sample := TSample.Create('aa', 'bbb', 'cccc');
  PrintLogAttr(Sample);
  Sample.Free;
end.

このコードを実行すると、PrintLogAttr関数でLogAttributeの属性がついているフィールドの値を出力します。

PrintLogAttr関数の実装は次のようになります。

RTTIを使用してオブジェクトの情報を取得します。 フィールドにつけた属性はTRttiFieldのGetAttributesメソッドで取得できます。

procedure PrintLogAttr(const Arg: TSample);
var
  LContext: TRttiContext;
  LType: TRttiType;
  LField: TRttiField;
  LAttr: TCustomAttribute;
  LFieldValue: string;
begin
  LContext := TRttiContext.Create;
  LType := LContext.GetType(TSample);

  // すべてのフィールドを取得する
  for LField in LType.GetFields do
  begin
    // フィールドの属性を取得する
    for LAttr in LField.GetAttributes do
    begin
      // 属性がLogAttributeであるか調べる
      if LAttr is LogAttribute then
      begin
        // 属性がLogAttributeのときはフィールドの値を取得する
        LFieldValue := LField.GetValue(Arg).AsString;
        // フィールドの値を出力する
        WriteLn(LField.Name + '=' + LFieldValue);
      end;
    end;
  end;
end;

実行結果は次のようになります。

FVal1=aa
FVal2=bbb

linux MintのFcitxで変換キー・無変換キーでオン・オフを切り替える

「Menu」→「コントロールセンター」→「Fcitx 設定」を選択する。

Screenshot at 2016-05-28 13_01_03

「全体の設定」タブを選択する。

「拡張オプションの表示」をチェックする。

Screenshot at 2016-05-28 12_49_37

「入力メソッドをオンに」の「空」のボタンを押す。
「設定したいキーの組み合わせを押してください」と表示されるので、変換キーを押す。

「入力メソッドをオフに」の「空」のボタンを押す。
「設定したいキーの組み合わせを押してください」と表示されるので、無変換キーを押す。

Screenshot at 2016-05-28 12_43_20

以上で設定できました。

インターフェース参照 vs ジェネリックインターフェース制約

インターフェース参照を使用すると参照カウンターが使用されるので、意図しないタイミングでオブジェクトが破棄されてしまうことがあります。

たとえば、TPersonクラスはIPersonインターフェースを継承しています。

type
  IPerson = interface
    procedure Say;
  end;

  TPerson = class(TInterfacedObject, IPerson)
  private
    FName: string;
  public
    constructor Create(const AName: string);
    destructor Destroy; override;
    procedure Say;
  end;

{ TPerson }

constructor TPerson.Create(const AName: string);
begin
  FName := AName;
end;

destructor TPerson.Destroy;
begin
  WriteLn('Destroy');
  inherited;
end;

procedure TPerson.Say;
begin
  WriteLn('Hello ' + FName);
end;

TTestクラスのSay関数はインターフェースを引数に取ります。

type
  TTest = class
    class procedure Say(Arg: IPerson); overload; static;
  end;

class procedure TTest.Say(Arg: IPerson);
begin
  Arg.Say;
end;

次のようにTPersonクラスのオブジェクトを、インターフェースを引数に取る関数に渡すと、関数が終わったときにオブジェクトが破棄されてしまいます。

var
  Person: TPerson;
begin
  Person := TPerson.Create('Alice');
  TTest.Say(Person); // ここでPersonオブジェクトが破棄される
  Person.Say;
end.

ジェネリックインターフェース制約は参照カウンターを使用しません。

そのため、上のような問題は発生しません。

type
  TTest = class
    class procedure Say<T: IPerson>(Arg: T); overload; static;
  end;

class procedure TTest.Say<T>(Arg: T);
begin
  Arg.Say;
end;

このようにジェネリックインターフェース制約を使用します。

そうすると、参照カウンターは使用されず、オブジェクトは破棄されません。

var
  Person: TPerson;

begin
  Person := TPerson.Create('Alice');
  TTest.Say(Person); // ここでPersonオブジェクトが破棄されない
  Person.Say;
end.

Linux Mint 17.3にVisual Studio Codeをインストールする

debファイルからインストールする方法と、Ubuntu Makeでインストールする方法を紹介します。

debファイルからインストールする

Visual Studio Codeのダウンロードページから、「deb」ファイルをダウンロードします。

ダウンロードしたら、次のコマンドでインストールします。

sudo dpkg -i vscode-amd64.deb

インストールが終わったら、起動できることを確認します。

code .

以上でインストール出来ました。

Ubuntu Makeでインストールする

Ubuntu Makeをインストールします。

sudo add-apt-repository ppa:ubuntu-desktop/ubuntu-make
sudo apt-get update
sudo apt-get install ubuntu-make

インストールできたことを確認します。

umake --help

Visual Studio Codeをインストールします。

umake ide visual-studio-code

インストールが始まると、Visual Studio Codeのインストール場所の問い合わせがあります。 初期値のままで良ければ、Enterキーを押します。

Choose installation path: /home/yamamoto/.local/share/umake/ide/visual-studio-code

次に、ライセンスの同意を求められます。
同意する場合はaキーを押します。

[I Accept (a)/I don't accept (N)] a

ダウンロードとインストールが始まります。

インストールが終わったら、起動できることを確認します。

code .

以上でインストール出来ました。

Delphi 10.1 BerlinでLive Bindingsを使ってデータベースとRadioButtonを連結するサンプル

Delphi 10.1 BerlinのFireMonkeyアプリケーションでLive Bindingsを使ってデータベースの1つのフィールドと複数のRadioButtonを連結するサンプルプログラムです。

プロジェクトはこちらからダウンロードできます。

このサンプルプログラムのフォームはこのようになっています。

LiveBindings03

データベースのフィールドとラジオボタンはLive Bindingsで連結しています。

フィールドの値が「1」のときはRadioButton1をチェック
フィールドの値が「2」のときはRadioButton2をチェック
フィールドの値が「3」のときはRadioButton3をチェック
します。

Edit1に入力するとデータベースの値が更新され、ラジオボタンのチェックが更新されます。

LiveBindings02

データベースのフィールドは「Value」はInteger型のフィールドで連結する値を持ちます。
データベースのフィールドは「RadioButton1」「RadioButton2」「RadioButton3」はBoolean型のフィールドで、計算項目です。
「Value」フィールドの値が「1」のときは「RadioButton1」フィールドはTrue、 「Value」フィールドの値が「2」のときは「RadioButton2」フィールドはTrue、 「Value」フィールドの値が「3」のときは「RadioButton3」フィールドはTrue、 になります。

LiveBindings01

procedure TForm1.FDMemTable1CalcFields(DataSet: TDataSet);
begin
  DataSet.FieldByName('RadioButton1').AsBoolean := (DataSet.FieldByName('Value').AsInteger = 1);
  DataSet.FieldByName('RadioButton2').AsBoolean := (DataSet.FieldByName('Value').AsInteger = 2);
  DataSet.FieldByName('RadioButton3').AsBoolean := (DataSet.FieldByName('Value').AsInteger = 3);
end;

TMemIniFileに変更があれば自動的に保存する

Delphi 10.1 BerlinではTMemIniFileにAutoSaveプロパティが追加されました。

AutoSaveプロパティがTrueのときは、インスタンスの破棄時に変更があれば自動的に保存されます。

var
  Ini: TMemIniFile;
begin
  Ini := TMemIniFile.Create('C:\temp\test.ini', // ファイル名
    TEncoding.UTF8, // エンコーディング
    True); // セクションとキーの名前の大文字小文字を区別するか
  try
    Ini.AutoSave := True; // 変更があれば自動的に保存する
    …
  finally
    Ini.Free; // 変更があれば自動的に保存されます
  end;
end;

Delphi 10.1 BerlinのAndroidアプリケーションで通話履歴を取得するには

Delphi 10.1 BerlinのAndroidアプリケーションで通話履歴を取得するサンプルコードです。

サンプルコードを実行するには、権限を追加する必要があります。
メニューの「プロジェクト」→「オプション」→「使用する権限」→「通話履歴の読み取り」をチェックします。

すべての通話履歴を取得するサンプルコード

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Provider;

var
  Cursor: JCursor;
  Name: string;
begin
  Cursor := TAndroidHelper.Activity.getContentResolver.query(
    TJCallLog_Calls.JavaClass.CONTENT_URI,
    nil,
    nil,
    nil,
    nil);
  if Cursor.moveToFirst then
  begin
    while True do
    begin
      Name := JStringToString
        (Cursor.getString(Cursor.getColumnIndex(StringToJString('NAME'))));
      Memo1.Lines.Add(Name);
      if not Cursor.moveToNext then
        Exit;
    end;
  end;
end;

期間を指定して取得するサンプルコード

ContentResolverのqueryメソッドは3番目の引数に条件を指定できます。
ここに日付を上限と下限を指定します。

DelphiのDateTimeToUnixやUnixToDateTimeの単位は秒ですが、Javaはミリ秒です。 そのため調整が必要になります。

‘NAME’や’DATE’は定数を使うべきかもしれません。
コードをシンプルにするため値を使用しています。

uses
  System.DateUtils,
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.Provider;

var
  Cursor: JCursor;
  Name: string;
  UnixDate: Int64;
  Date: TDateTime;
  Selection: string;
begin
  // 2016年4月1日から2016年6月1日まで
  Selection := Format(
    'DATE>%d and DATE<%d',
    [DateTimeToUnix(EncodeDate(2016, 4, 1)) * 1000,
    DateTimeToUnix(EncodeDate(2016, 6, 1)) * 1000]);

  // 3番目の引数で条件を指定する
  Cursor := TAndroidHelper.Activity.getContentResolver.query(
    TJCallLog_Calls.JavaClass.CONTENT_URI,
    nil,
    StringToJString(Selection),
    nil,
    nil);
  if Cursor.moveToFirst then
  begin
    while True do
    begin
      Name := JStringToString
        (Cursor.getString(Cursor.getColumnIndex(StringToJString('NAME'))));
      UnixDate := Cursor.getLong
        (Cursor.getColumnIndex(StringToJString('DATE')));
      Date := UnixToDateTime(UnixDate div 1000);
      Memo1.Lines.Add(Name + ' ' + FormatDateTime('yyyy/mm/dd hh:nn:ss', Date));

      if not Cursor.moveToNext then
        Exit;
    end;
  end;
end;