(12/12/01~)

12/12/01

RAD Studio XE3 キャンペーン
 2012/12/26 までのキャンペーンが 4 つ同時に行われており、ワケワカメ状態となっています。

  1. ジャンプアップキャンペーン (Delphi 1~2007 及び Starter ユーザ)
    Delphi 1~2007 及び Starter SKU ではこちらとなります。
  2. バリューアップキャンペーン1 (Delphi 2009~XE2 ユーザ)
    Delphi 2009~XE2 ユーザはバリューアップキャンペーンのアップグレード版を購入する事になります。
  3. バリューアップキャンペーン2
    Enterprise と同等の金額で Ultimate / Architect を購入できるキャンペーンです。実際には Enterprise の方が若干安いです。
  4. バリューアップキャンペーン3 (XE3 Professional ユーザ)
    XE3 Professional ユーザ限定の、Enterprise へアップグレードできるキャンペーンです。

 2009 ユーザには実質このキャンペーンが最後のお得なキャンペーンとなります...何故ならば、"2009 は 2012/12/31 以降、アップグレード対象製品とならない" からです。

 XE3 をお得に購入する方法は上記の表のようになると思われます。相変わらずややこしいですね。今回、どの製品からの購入でも Ultimate を購入する理由はありません。Ultimate と Architect の値段が同じだからです。

 新規に XE3 Enterprise を購入する場合には、ジャンプアップで XE3 Professional を購入し、バリューアップの "Pro to Ent" で Enterprise にした方が安くて済むようです。

ジャンプアップキャンペーン (1~2007 ユーザー及び Starter Edition ユーザー向け) Professional


バリューアップキャンペーン3 (XE3 Professional ユーザ向け)

 以下はジャンプアップのみで素直に Enterprise 版を購入した場合の金額です。"ジャンプアップ (to XE3 Pro) -> バリューアップ (XE3 Pro to XE3 Ent)" の合算金額より高い事が判ると思います。

ジャンプアップキャンペーン (1~2007 ユーザー及び Starter Edition ユーザー向け) Enterprise

 ※この方法が本当に可能かどうかはエンバカさんやショップに問い合わせてみてください。
 ※価格にポイント等は反映されていません。また、価格は変動する事がありますのでショップで必ず確かめるようにして下さい。
 ※追記 (2012/12/03): この方法はアリだそうです。心配な場合には事前にエンバカさんにお問い合わせを。

何でそんなややこしい組み合わせのアップグレードを紹介するのか?
 バリューアップキャンペーンの特典のうち、

 この 3 つはジャンプアップにもありますが、ジャンプアップキャンペーン発表時には

 コレが含まれていませんでした。HTML5 Builder が無償ダウンロードできるのはバリューアップキャンペーンのみのようなのです。つまり、ジャンプアップキャンペーンだけで購入すると、高くつく上に HTML5 Builder が貰えない可能性があります。

 但し、これはあくまでキャンペーンページにある条件だけで調べたものなので、"HTML5 Builder が無償ダウンロード可能な条件" はエンバカさんに確認してください。

 ※ 追記 (2012/12/03): 期間中であれば、ジャンプアップキャンペーンでも HTML 5 Builder は無償ダウンロード可能だそうです。心配な場合には事前にエンバカさんにお問い合わせを。


12/12/02

IBConsole 日本語版+α Windows Unicode Edition rel.23
 Delphi XE3 で再コンパイルされています。rel.22 には TIBTable のバグが含まれており、データを閲覧しようとするとインデックスのエラーが発生してしまうバグがありました。

 余談ですが、"IBX は VCL Style と相性が悪い" 的な話をディスカッションフォーラムで読んだ事があるのですが...どこだったかなぁ?真偽不明だったので検証してみたかったのだけれど。

MECSUtils ver 1.56
 Delphi XE2 / XE3 でも修正なしでコンパイルできるようにしてあります...OS X 対応の前準備です。

Mac OS X 10.6 'Snow Leopard'
 会社の iMac 用に 'Snow Leopard' を購入した。結果的に役に立ったけれど、デブキャンの資料用にわざわざ購入した訳ではない...いやいや、そんな事はもはやどうでもいい。

 'Snow Leopard' は上記のような特徴があるのだけれど、2012/7末あたりで販売終了になっていた。だから、仕方がないので Amazon で注文したさ、物理メディアの 'Snow Leopard' を。

 ...そしたら、Apple の野郎、このタイミングで Snow Leopard を再販開始しやがったさ。しかも \1,700 で。

TIBTable のバグを直す (XE3)
 XE3 の TIBTable にはバグがあります。QC によると With 文の削りすぎでバグが発生しているとの事...なんでそんな事をするかなぁ。

 修正方法はフォーラムに投稿されているのですが、ソースが整形されておらず読みにくいので、手順をちょっとだけ詳しく説明しておきます。

  1. IBTable.pas を開く
  2. TIBTable.UpdateIndexDefs の実装部を以下のコードで置き換える
    procedure TIBTable.UpdateIndexDefs;
    var
      Opts: TIndexOptions;
      Flds: string;
      Query, SubQuery: TIBSQL;
      cIndexDef: TIndexDef;
    begin
      if not(csReading in ComponentState) then
      begin
        if not Active and not FSwitchingIndex then
          FieldDefs.Update;
        IndexDefs.Clear;
        Database.InternalTransaction.StartTransaction;
        Query := TIBSQL.Create(Self);
        try
          FPrimaryIndexFields := '';
          Query.GoToFirstRecordOnExecute := False;
          Query.Database := Database;
          Query.Transaction := Database.InternalTransaction;
          Query.SQL.Text :=
            'Select I.RDB$INDEX_NAME, I.RDB$UNIQUE_FLAG, I.RDB$INDEX_TYPE, ' + { do not localize }
            'I.RDB$SEGMENT_COUNT, S.RDB$FIELD_NAME from RDB$INDICES I, ' + { do not localize }
            'RDB$INDEX_SEGMENTS S where I.RDB$INDEX_NAME = S.RDB$INDEX_NAME ' + { do not localize }
            'and I.RDB$RELATION_NAME = ' + '''' + { do not localize }
            FormatIdentifierValue(Database.SQLDialect,
            QuoteIdentifier(Database.SQLDialect, FTableName)) + '''';
          Query.Prepare;
          Query.ExecQuery;
          while (not Query.EOF) and (Query.Next <> nildo
          begin
            cIndexDef := IndexDefs.AddIndexDef;
            cIndexDef.Name := TrimRight(Query.Current.ByName('RDB$INDEX_NAME').AsString); { do not localize }
            Opts := [];
            if Pos('RDB$PRIMARY', Name) = 1 then
              Include(Opts, ixPrimary); { do not localize }
            { mbcs ok }
            if Query.Current.ByName('RDB$UNIQUE_FLAG').AsInteger = 1 then
              Include(Opts, ixUnique); { do not localize }
            if Query.Current.ByName('RDB$INDEX_TYPE').AsInteger = 1 then
              Include(Opts, ixDescending); { do not localize }
            cIndexDef.Options := Opts;
            if (Query.Current.ByName('RDB$SEGMENT_COUNT').AsInteger = 1then { do not localize }
              cIndexDef.Fields := Trim(Query.Current.ByName('RDB$FIELD_NAME').AsString) { do not localize }
            else
            begin
              SubQuery := TIBSQL.Create(Self);
              try
                SubQuery.GoToFirstRecordOnExecute := False;
                SubQuery.Database := Database;
                SubQuery.Transaction := Database.InternalTransaction;
                SubQuery.SQL.Text :=
                  'Select RDB$FIELD_NAME from RDB$INDEX_SEGMENTS where RDB$INDEX_NAME =' + {do not localize}
                '''' + {do not localize}
                FormatIdentifierValue(Database.SQLDialect,
                QuoteIdentifier(DataBase.SQLDialect, cIndexDef.Name)) +
                '''' + ' ORDER BY RDB$FIELD_POSITION'{do not localize}
                SubQuery.Prepare;
                SubQuery.ExecQuery;
                Flds := '';
                while (not SubQuery.EOF) and (SubQuery.Next <> nildo
                begin
                  if (Flds = ''then
                    Flds := TrimRight(SubQuery.Current.ByName('RDB$FIELD_NAME').AsString) { do not localize }
                  else
                  begin
                    Query.Next;
                    Flds := Flds + ';' + TrimRight(SubQuery.Current[0].AsString);
                  end;
                end;
                cIndexDef.Fields := Flds;
              finally
                SubQuery.free;
              end;
            end;
            if (ixDescending in Opts) then
              cIndexDef.DescFields := cIndexDef.Fields;
            if ixPrimary in Opts then
              FPrimaryIndexFields := cIndexDef.Fields;
          end;
        finally
          Query.free;
          Database.InternalTransaction.Commit;
        end;
      end;
    end;
  3. TIBTable.GenerateUpdateSQL の実装部を以下のコードで置き換える (関数内関数に注意)
    procedure TIBTable.GenerateUpdateSQL;
    var
      InsertFieldList, InsertParamList, UpdateFieldList: string;
      WherePrimaryFieldList, WhereAllFieldList: string;
    
      procedure GenerateFieldLists;
      var
        I: Integer;
      begin
        for I := 0 to FieldDefs.Count - 1 do
        begin
          if not(FieldDefs[I].InternalCalcField or
            (faReadOnly in FieldDefs[I].Attributes) or
            (FieldDefs[I].DataType = ftUnknown)) then
          begin
            if (InsertFieldList <> ''then
            begin
              InsertFieldList := InsertFieldList + ', '{ do not localize }
              InsertParamList := InsertParamList + ', '{ do not localize }
              UpdateFieldList := UpdateFieldList + ', '{ do not localize }
              if (FieldDefs[I].DataType <> ftBlob) and
                (FieldDefs[I].DataType <> ftMemo) and
                (FieldDefs[I].DataType <> ftWideMemo) then
                WhereAllFieldList := WhereAllFieldList + ' AND '{ do not localize }
            end;
            InsertFieldList := InsertFieldList +
              QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name);
            InsertParamList := InsertParamList + ':' + { do not localize }
              QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name);
            UpdateFieldList := UpdateFieldList +
              QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name) + ' = :' + { do not localize }
              QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name);
            if (FieldDefs[I].DataType <> ftBlob) and
              (FieldDefs[I].DataType <> ftMemo) and
              (FieldDefs[I].DataType <> ftWideMemo) then
              WhereAllFieldList := WhereAllFieldList +
                QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name) + ' = :' + { do not localize }
                QuoteIdentifier(Database.SQLDialect, FieldDefs[I].Name);
          end;
        end;
      end;
    
      procedure GenerateWherePrimaryFieldList;
      var
        I: Integer;
        tmp: String;
      begin
        I := 1;
        while I <= Length(FPrimaryIndexFields) do
        begin
          tmp := ExtractFieldName(FPrimaryIndexFields, I);
          tmp := QuoteIdentifier(Database.SQLDialect, tmp) + ' = :' + { do not localize }
            QuoteIdentifier(Database.SQLDialect, tmp);
          if WherePrimaryFieldList <> '' then
            WherePrimaryFieldList := WherePrimaryFieldList + ' AND ' + tmp { do not localize }
          else
            WherePrimaryFieldList := tmp;
        end;
      end;
    
    begin
      if InternalGetUpdatable = False then
        FReadOnly := True
      else
      begin
        DeleteSQL.Text := 'delete from ' + { do not localize }
          QuoteIdentifier(Database.SQLDialect, FTableName) + 
          ' where RDB$DB_KEY = ' + ':IBX_INTERNAL_DBKEY'{ do not localize }
        GenerateFieldLists;
        if InsertFieldList <> '' then
        begin
          InsertSQL.Text := 'insert into ' + { do not localize }
            QuoteIdentifier(Database.SQLDialect, FTableName) + 
            ' (' + InsertFieldList + { do not localize }
            ') values (' + InsertParamList + ')'{ do not localize }
          ModifySQL.Text := 'update ' + { do not localize }
            QuoteIdentifier(Database.SQLDialect, FTableName) + 
            ' set ' + UpdateFieldList + { do not localize }
            ' where RDB$DB_KEY = :IBX_INTERNAL_DBKEY'{ do not localize }
          WhereAllRefreshSQL.Text := 'select ' + { do not localize }
            QuoteIdentifier(Database.SQLDialect, FTableName) + '.*, ' { do not localize }
            + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' { do not localize }
            + QuoteIdentifier(Database.SQLDialect, FTableName) + 
            ' where ' + WhereAllFieldList; { do not localize }
          if FPrimaryIndexFields <> '' then
          begin
            GenerateWherePrimaryFieldList;
            WherePrimaryRefreshSQL.Text := 'select ' + { do not localize }
              QuoteIdentifier(Database.SQLDialect, FTableName) + '.*, ' { do not localize }
              + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' { do not localize }
              + QuoteIdentifier(Database.SQLDialect, FTableName) + ' where ' +
              WherePrimaryFieldList; { do not localize }
          end;
        end
        else
          FReadOnly := True;
        try
          InternalUnprepare;
          InternalPrepare;
        except
          FReadOnly := True;
        end;
      end;
    end;

 ソースフォルダの IBTable.pas を直接書き換えるのではなく、IBTable.pas をプロジェクトフォルダにコピーしてから書き換える事をオススメします。

 「よく業務アプリの検証で引っかからなかったなー?」 と一瞬思いましたが、よく考えたら検証した業務アプリでは TIBTable を一切使っていなかったのでした。

 ※ 追記 (2012/12/10): この問題は XE3 Update 1 で解消された模様です。

IDE が落ちまくるのをどうにかする (XE3)
 結論から言えば AQTime のせいです。

 修正方法は以下の通りです。

  1. Delphi を終了する
  2. レジストリエディタ (regedit.exe) を開く
  3. [HKEY_CURRENT_USER\Software\Embarcadero\BDS\10.0\Known IDE Packages] を開く
  4. AQtime のキーを削除する

 AQtime のキーは 32bit OS だと

 64bit OS だと

 このようになっているハズです。これをキーごと削除してください。この QC は Resolved で Checked In なので、次のアップデータで修正されている可能性があります。

 本来ならコントロールパネルの "プログラムと機能" から AQTime をアンインストールすればいいのでしょうが、何故か当方の環境ではリスト中に AQTime が存在しませんでした。

 ※ 追記 (2012/12/10): この問題は XE3 Update 1 で解消された模様です。


12/12/03

行儀の悪いセンサーをどうにかする (XE3)
 XE3 では ONKYO TW317A5 のセンサー (Pegatron G-Sensor) が列挙されない件を以前書きましたが、これは XE3 が悪いのではなく、センサードライバが悪いのです。デバッガで追っかけてみた所、やはりセンサードライバが正しいカテゴリを返さないようです。

 なんじゃ?この GUID は。Winapi.Sensors.pas を確認すれば判りますが、こんなカテゴリ ({201631E3-AD91-4122-A05C-9254A2B3FCD0}) は存在しません...で、この行儀の悪いセンサーはどうすれば良いかと言うと、

  1. System.Win.Sensors.pas をプロジェクトフォルダにコピー (最近こんなのばっかだな)
  2. TWindowsSensorManager.GetSensorObject の実装部を以下のように書き換え
    function TWindowsSensorManager.GetSensorObject(const Sensor: ISensor): TCustomSensor;
    begin
    
      ...
      else if Category = SENSOR_CATEGORY_ELECTRICAL then
        Result := TWindowsElectricalSensor.Create(Self, Sensor)
      else                                                  // ADD
        Result := TWindowsMotionSensor.Create(Self, Sensor) // ADD
    end;

  「このカテゴリだろう」 と思うカテゴリで決め打ちしてしまうというものです。こんな行儀の悪いセンサーはそうそうないと思いますので、やっつけな解決方法でいいかと思います。

 例ではモーションセンサー (SENSOR_CATEGORY_MOTION) として決め打ちしていますが、ひょっとすると TW317A のセンサーはオリエンテーションセンサー (SENSOR_CATEGORY_ORIENTATION) として実装されているかもしれません (物理的には 3 軸加速度センサーです)。実際にどういう実装になっているのかはセンサーのデータを確認してみるしかないですね。

 本来、Windows のセンサーはカテゴリからだけでなく固有 ID で直接ピックアップできるのですが、RTL の実装は TCustomSensor に Category プロパティがある関係でカテゴリが正しくないとセンサーとして列挙されません (インターフェイスとしてのセンサーは認識するが、センサークラスとしては認識されない)。もちろん、これが間違った実装だとは思いません。当初から言っているようにセンサードライバ側の問題です。それが証拠に、この Pegatron G-Sensor はコントロールパネルの "位置センサーとその他のセンサー" で確認した時、アイコンがモーションセンサーあるいはオリエンテーションセンサーのものになっていません。

 もちろん、センサークラスを使わないで Winapi.Sensorsapi を直接操作すれば C++(Builder) 同様、行儀の悪いセンサーでも列挙できます。"FireMonkey の事を考えるとそれをやりたくない" というだけの話なのです。

SkRegExp version 2.0.1 リリース
 小宮さん作の正規表現ライブラリです。SkRegExp のバージョンアップの変遷を見ていると 「"継続は力なり" とはよく言ったものだ」 と考えさせられます...素直に感心。


12/12/04

行儀の悪すぎるセンサーを考える
 なるホドな。ONKYO TW-317A5 のセンサードライバは Microsoft DDK のサンプルに毛が生えた程度の出来なのか。

 XE3 で試したけど、モーションセンサーでもオリエンテーションセンサーでもなかった。コイツは生データ (カスタムデータ) しか返さないのだ。モーションセンサーでもオリエンテーションセンサーでも反応はするけど、値が NAN で返ってくる...つまり、回転のイベントは取れるけど現在の角度等は取得できない...まったくもって意味がない。

 このセンサーからマトモなデータを取ろうとすると、Winapi.Sensorsapi を直接操作するしかなさそうだ。しかも直接操作してもちゃんとしたデータが取れるとは限らない。兄弟機の EXOPC のフォーラムでは .NET を使ったセンサーの操作を行っていたが、最終的な手段は "Windows API Code Pack の DLL にパッチを当てる"という力技だった...おいおい。

 XE3 のセンサークラスも生データ (カスタムデータ) を取得できる構造になっている (HasCustomData プロパティ / GetCustomData メソッドがある) のだけれど、僕が書いた現在の実装では False / Null しか返さない。

procedure TForm1.MotionSensor1DataChanged(Sender: TObject);
const
  MessageKey: TPropertyKey = (fmtid: '{72B26341-1CEA-4473-82C1-CCEEB9748790}'; pid: 2);
var
  Value: PropVariant;
begin
  if MotionSensor1.Sensor.HasCustomData[MessageKey] then
    begin
      Value := MotionSensor1.Sensor.CustomData[MessageKey];
      ...
    end;
end;

 こんな感じ。この GUID がどこから出てきたかというと、ExoPC の HotButton Code kit ソースコード内から。センサードライバがおかしいので、XE3 のセンサークラスがおかしいのか GUID がおかしいのかやり方がマズいのかサッパリ判らないという...。

 別にセンサーで何かやらなければいけない仕事があるわけじゃないのでこの件は放置する事にした。こんなのやってる暇があったら、マトモなセンサーから値を取得するサンプルでも書いてこのサイトで公開した方がよっぽど建設的だと思ったからだ。

行儀の悪すぎるセンサーを考える (その2)
 ...うん、GUID が間違っとった。GUID に 10 進と 16 進混ぜるなや。とりあえず以下のコードでホットキーが押されたのか画面が回転したのかを判定できるようになった。

procedure TForm1.MotionSensor1DataChanged(Sender: TObject);
const
  PEGATRON_KEY = '{72B26341-1CEA-4473-82C1-CCEEB974875A}';
  MESSAGE_KEY: TPropertyKey=(fmtid: PEGATRON_KEY; pid: 2);
  X_VALUE_KEY: TPropertyKey=(fmtid: PEGATRON_KEY; pid: 3);
  Y_VALUE_KEY: TPropertyKey=(fmtid: PEGATRON_KEY; pid: 4);
  Z_VALUE_KEY: TPropertyKey=(fmtid: PEGATRON_KEY; pid: 5);
var
  Value: OleVariant;
begin
  if MotionSensor1.Sensor.HasCustomData[MESSAGE_KEY] then
    begin
      Value := MotionSensor1.Sensor.CustomData[MESSAGE_KEY];
      case TPropVariant(Value).bVal of
        $95:begin
              Edit1.Text := 'HotKey Down';
            end;
        $EA:begin
              Edit1.Text := 'Rotation Change';
              ...
            end;  
      end;
    end;
end;

 でもこのまま CustomData を取得しても X / Y / Z がエラー (VT_ERROR) で返ってくる。SetProperty しなきゃいけないのだろうか?リアルタイムで返る値なのにプロパティで取れと?


12/12/05

System.Zip.TZipFile のアレをちょっといじると? (XE2 / XE3)
 XE2 用の手順の 14. と XE3 用の手順の 10. を以下のように書き換えると "文字化けする Mac の ZIP" も扱えます (こちらの方が何かと都合がいいので元記事のコードも書き換えてあります)。

// procedure TZipFileEx.Open(ZipFileStream: TStream; OpenMode: TZipMode);
procedure TZipFileEx.Open(ZipFileStream: TStream; OpenMode: TZipMode; IsUTF8: Boolean; CodePage: word); // MOD
begin
  ...
  if OpenMode in [zmRead, zmReadWrite] then
  try
    // Read the Central Header to verify it's a valid zipfile
    FCodePage := CodePage; // ADD
    ReadCentralHeader;
  except
    // If it's an invalid zipfile, cleanup
    FStream := nil;
    raise;
  end;
  FMode := OpenMode;

  // ADD From Here
  if OpenMode in [zmWrite, zmReadWrite] then
    begin
      UTF8Support := IsUTF8;
      FCodePage := CodePage;
    end;
  // ADD Until Here
end;

 ZipFiles.pas を使った Mac の ZIP を解凍するコードはこちらになります。

procedure TForm1.Button1Click(Sender: TObject);
begin
  DecompressZipFile('C:\test_MAC.zip''C:\TEST_MAC', False, 65001);
end;

 "Mac の文字化けする ZIP" というのは UTF-8 のフラグを立てずに UTF-8 な文字コードになっているのが原因 (これまた規格外の ZIP) ですので、上記のような指定で解凍できます (__MACOSX というフォルダができるかもしれませんが無視して下さい)。もちろん同様の指定で圧縮も可能ですが、積極的にこの形式にする理由はないでしょう。

 ファイル名の Unicode 正規化方法が Windows / Mac で異なるという点には充分注意して下さい (いつぞやのデブキャンのネタの一つですね)。

 お客さんが 「(お客さんから) メールで貰った資料が文字化けするんだけど」 と言ってきたので、ついでに XE2/ XE3 で Mac ZIP を確認したという流れです。資料は PDF で、OS X Mountain Lion で作られたものでした...やっぱりか。


12/12/06

今日から東京デェス。
 明日の "第24回エンバカデロ・デベロッパーキャンプ" のためデェスけどね。"第 3 回 Delphi Talks" にも参加予定デェス。

デブキャンの Ustrem 中継
 "第24回エンバカデロ・デベロッパーキャンプ"Ustrem でも中継されるようなのデェス (基本、A 会場のみのようデェスが...)。

デブキャンの twitter ハッシュタグ
 デブキャンのハッシュタグはいつもと同じで #dcamp_jp デェス。

「何でデスマス (ポケモン) の口調なのだ?」
 くみん先輩から 「なんかすごいね DEKO ちゃんって」 と言われたと勘違いして舞い上がってるだけデェス...あぁ...いい加減寝よう。


12/12/07

"第 3 回 Delphi Talks"
 皆さんとイロイロな話ができて有意義でした。やはりというかなんというか、同じ Delphi ユーザであっても得意分野が違ってたり、過去の実績が違ってたりで新鮮です。僕は参加する機会を作るのが難しいので、ひょっとしたら最初で最後の参加だったかもしれませんが、このイベントは是非今後も続けて頂いて Delphi ユーザ同士の親睦を深めて頂けたらな、と思います。

"第24回エンバカデロ・デベロッパーキャンプ"
 僕は自分の担当のセッションが終わった後に諸事情で会場を後にしてしまいましたので、セッション資料は持っていますが聴講していません。後日ビデオが公開されたらそちらの方で確認させて頂きます。

Delphi Advent Calendar 2012
 酔っぱらっていた時、細川さんが何か言っていたと思ったら、A7M さん共々、スケジュールに組み込まれていました。「これが世にいう "ポルナレフ状態" なのだな」 と妙に納得してしまいました (w


12/12/08

"第24回エンバカデロ・デベロッパーキャンプ" 【A2】セッションのデモプログラムについて
 本日分のトピックは Delphi Advent Calendar 2012 の記事となります。

 さて、今回のセッション用に用意したデモは全部で 11 個ありました。時間の都合で省略したものもありますが、それらも全部ひっくるめて解説したいと思います。印刷されたセッション資料をお持ちの方は方は右上の (S) マークが確認できると思いますが、このマークがあるものはデモが用意されていました。ソースコード一式はセッション資料と一緒に "そのうち" DL できるようになると思います。

 もちろん、今回のセッションに参加されていない方にも内容がわかるように解説します。

  1. 3D (P.20) / マルチプラットフォーム (P.21)

    以前作った "右手座標系サンプル" を XE3 用に書き直したものです。プラットフォームを Mac OSX にすれば普通に Mac で動きます。
    "3D Shape を持つ XE2 で作られたアプリケーション" を XE3 にマイグレーションすると、TLightMaterialSource や TTextureMaterialSource が山のように生成されてしまう事に注意が必要です。これは FM2 でマテリアルソース (テクスチャとか環境光とか) を共用できるようになった事の弊害です。
  2. 高解像度アプリケーション対応 (P.22)

    左側に Edit コントロール等を持つ入力パネル (TScaledLayout: Align = alFitLeft)、右側には高解像度の画像を表示する TImage (Align = alClient) が貼られたアプリケーションです。
    左側はスケーリング対応なので、フォームをリサイズするとコントロールが追従して拡大/縮小します。入力コントロールが小さくて見づらい場合にはフォームをリサイズすればアスペクト比を保ったまま入力コントロールが拡大/縮小されます。
    右側の画像はスケーリングが行われていません。つまり、フォームを広げれば広げるほど鮮明な画像が得られます。
  3. FireMonkey に向いているビジネスアプリ (3) (P.27)

    物体の大きさを視覚的に判断できる 3D アプリケーションです。sizeasy という、"物のサイズを比較する" サイトがあるのをご存じでしょうか?これの簡易版的なものを FireMonkey で作ってみたという訳です。
  4. IM(E) モードをどうにかしたい (暫定) (P.32)

    Windows で IME をどうにかする方法は過去の雑談でやりましたが、OS X での方法は書いていませんでした。C++Builder でやる方法は、先日高橋さんが Team Japan ブログで書いてらっしゃいました
    OS X で IME モードをどうにかする方法を調べてみたのですが、よくわからなかったのでローテクで回避しました。"ことえり" の文字種変更ショートカットのキーコードを送信するというやり方です。
    uses
      ...
      {$IFDEF MSWINDOWS}, Vcl.Controls, FMX.Platform.Win{$ENDIF}
      {$IFDEF MACOS}, Macapi.CoreGraphics, Macapi.CocoaTypes, Macapi.CoreFoundation{$ENDIF};
    
    procedure TfrmMain.SetIMEMode_Provisional(Mode: FMX.Types.TImeMode);
    // IM(E) モードを変更する (暫定)
    {$IFDEF MACOS}
    const
      kVK_ANSI_J         = $26;
      kVK_ANSI_K         = $28;
      kVK_ANSI_Semicolon = $29;
    {$ENDIF}
    var
    {$IFDEF MSWINDOWS}
      dMode: Vcl.Controls.TImeMode;
    {$ENDIF}
    {$IFDEF MACOS}
      Src: CGEventSourceRef;
      EventUp, EventDown: CGEventRef;
    {$ENDIF}
    begin
      {$IFDEF MSWINDOWS}
      if Mode <> FMX.Types.TImeMode.imDontCare then
        begin
          case Mode of
            FMX.Types.TImeMode.imClose:
              dMode := imClose;
            FMX.Types.TImeMode.imOpen:
              dMode := imOpen;
            FMX.Types.TImeMode.imSAlpha:
              dMode := imSAlpha;
            FMX.Types.TImeMode.imAlpha:
              dMode := imAlpha;
            FMX.Types.TImeMode.imHira:
              dMode := imHira;
            FMX.Types.TImeMode.imSKata:
              dMode := imSKata;
            FMX.Types.TImeMode.imKata:
              dMode := imKata;
            FMX.Types.TImeMode.imHanguel:
              dMode := imHanguel;
            FMX.Types.TImeMode.imSHanguel:
              dMode := imSHanguel;
          else
            dMode := imDisable;
          end;
          SetImeMode(FmxHandleToHWND(Self.Handle), dMode);
        end;
      {$ENDIF}
      {$IFDEF MACOS}
      Src := CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
      case Mode of
        FMX.Types.TImeMode.imHira:
          begin
            // Ctrl + Shift + J のキーイベントを生成 (ことえりのひらがなモードショートカット)
            EventDown := CGEventCreateKeyboardEvent(Src, kVK_ANSI_J, Integer(True));
            CGEventSetFlags(EventDown, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
            EventUp   := CGEventCreateKeyboardEvent(Src, kVK_ANSI_J, Integer(False));
            CGEventSetFlags(EventUp, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
          end;
        FMX.Types.TImeMode.imKata:
          begin
            // Ctrl + Shift + K のキーイベントを生成 (ことえりのカタカナモードショートカット)
            EventDown := CGEventCreateKeyboardEvent(Src, kVK_ANSI_K, Integer(True));
            CGEventSetFlags(EventDown, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
            EventUp   := CGEventCreateKeyboardEvent(Src, kVK_ANSI_K, Integer(False));
            CGEventSetFlags(EventUp, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
          end;
      else
        // Ctrl + Shift + ; のキーイベントを生成 (ことえりの英数モードショートカット)
        EventDown := CGEventCreateKeyboardEvent(Src, kVK_ANSI_Semicolon, Integer(True));
        CGEventSetFlags(EventDown, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
        EventUp   := CGEventCreateKeyboardEvent(Src, kVK_ANSI_Semicolon, Integer(False));
        CGEventSetFlags(EventUp, kCGEventFlagMaskControl or kCGEventFlagMaskShift);
      end;
      CGEventPost(kCGSessionEventTap, EventDown);
      CGEventPost(kCGSessionEventTap, EventUp  );
      CFRelease(EventUp  );
      CFRelease(EventDown);
      CFRelease(Src);
      {$ENDIF}
    end;

    正直 OS X には詳しくないので、「こうすりゃできるのに...」 という情報をお持ちの方はブログで書いてください (^^;A
  5. 埋め込みブラウザは? (P.35)

    Delphi Chromium Embedded Framework (DCEF) とロケーションセンサーコンポーネントを組み合わせたサンプルです。
    DCEF はそのままでは XE3 で動作しません。XE3 で動作させるにはここにあるパッチが必要となります (DCEF_20121009.7z を探してみてください)。
  6. ドライバによる画面回転とソフトウェアによる回転 (P.37) - ハードウェア回転デモは VCL アプリケーション
    ドライバの機能を使った回転と、FireMonkey の RotationAngle で回転させた時の実行速度を調べるデモです。ボタンが 2 つあり、一つは画面回転、もう一つはアプリケーションを終了するボタンです。回転させると (回転が終了すると) 画面が白から緑になります。
    Windows 8 ではドライバによる回転が高速化しているようですが、書き換え過程が見えてしまい回転時のアニメーションも行われないので、スマホや iPad 等の非 Windows タブレットを利用している方には耐えられないと思います。
    FireMonkey の回転は非常に高速なので、回転アニメーションを入れても余裕でしょう。こちらのデモプログラムは 2 つあります。
  7. タイリングな背景

    TImage を alClient で貼り、WrapMode プロパティ を iwTile にして、小さめの画像を読み込ませてみましょう。HTML の背景画像のような効果が得られます。
  8. 動く (企業) ロゴ (P.40)

    画像を 3 枚重ねて、中間の一枚だけをループ回転させて企業ロゴ的な何かを作るという物です。目にモザイク掛けてもあまり効果がなかったので目線も入れてみました。「俺の目を盗みやがったな!」 とか言う以前の問題で、顔を盗まれた FireMonkey くんはさながら "にしこくん" です (資料参照)。
  9. TPopup でアラート (FM2)

    TPopup を使ってアラート (ダイアログ) を作ってみるというものです。
  10. FireMonkey が機能不足で VCL の機能が必要な場合 (P.42 ~ P.44) - VCL アプリケーション

    VCL と FMX を混在させる一つの方法です。以前紹介した MonkeyMixer は XE3 に対応しておらず、その上作者がブログを閉鎖してしまいました (MonkeyMixer は現在でも先のリンクから DL 可能ですが、いつまで DL できるかはわかりません)。MonkeyMixer 同等の事を手動でできなくもないのですが、手順が非常に面倒です。
    Panel をコンテナにして FMX フォームを埋め込む方法は、高橋さんが Team Japan ブログで書かれていました。しかしながら、フォームをリサイズしても埋め込まれた FMX フォームが追従しないという問題があります。
    これを回避するには、DSharp.Windows.FMXAdapter.pas (http://delphisorcery.blogspot.jp/2011/09/delphi-xe2-heating-up-hype-playing.html) を使います...しかし、これまた XE2 用でして、XE3 ではコンパイルエラーとなってしまいます。
    サンプルソースコードには、XE3 でコンパイル可能な DSharp.Windows.FMXAdapter.pas が収録されています。

 【A2】セッション関連の DL ファイルには以下のソースコードを収録予定です。

 セッション資料が DL できるようになったら、サンプルプロジェクトをコンパイルして遊んでみて下さいね。ただ、残念な事にこのソースコードは XE3 専用となっています (単一ソースコードで FM / FM2 対応にするのは結構難しいのです)。XE3 をお持ちでない方は評価版を DL して試してみてください。

 え?既に評価版の有効期限が切れていて試せない?「RAD Studio XE3 評価版の有効期限が切れたのなら、Delphi XE3 の評価版を使えばいいじゃない?」 (^^;A


12/12/10

XE3 Update1 リリース
 Rad Studio / Delphi / C++Builder XE3 の Update 1 がリリースされました。

 先日の "TIBTable の問題""AQTime の問題" は解決しているようです。試していませんが、QC のステータスから推測するに BDE 絡みの問題も解決してそうです。

 また、IBX と VCL Style の組み合わせでアプリケーション終了時にメモリリークが報告されたり AV が発生する問題も解決しているようです。実は Update 1 リリース以前に IBX を使っているプロジェクトを "XE3 / XE2" にマイグレーションして、VCL Style を適用するという事を試してみたのですが、この際に先述の問題が発生するのを確認しました。ただ、問題が発生するプロジェクトと発生しないプロジェクトがある事も確認しています...ちょっと厄介ですね。

 それと、このアップデータには C++Builder の 64bit コンパイラも含まれているようですね。

IBConsole 日本語版+α Windows Unicode Edition rel.24
 IBX のバグが複数修正されているようなので、XE3 Update 1 でリビルドしました。

RAD Studio / Delphi / C++Builder XE3 Architect Trial
 トライアル版も Update 1 が適用された模様です。

 Delphi XE3 の機能または C++Builder XE3 の機能を評価する期間は 30日 + 30日 で 60日あるという事です。流石にこの評価期間で評価しきれないという事はないと思います (w


12/12/11

RAD Studio (Delphi / C++Builder) の入れすぎで何かがおかしくなった場合には?
 タイトルが人聞きの悪い事になっていますが、ご容赦ください。このトピックは Delphi Advent Calendar 2012 の記事となります。

 XE3 を購入するとアカデミックやスターター版でない限り、古いバージョンの Delphi を貰えます。もちろん嬉しい事ではあるのですが、調子に乗ってインストールしていると、最悪 OS の調子が悪くなることがあります...これまた人聞きが悪いですね。どういう事かと申しますと、開発者の PC ってのは様々な開発環境がインストールされている訳ですが、システム環境変数 PATH が長くなりすぎると一部にパスが通らなくなったりするのです (1024 文字制限)。

 通らなくなったパスがアプリケーション固有のものであれば影響の範囲はそのアプリケーションだけに留まるのですが、システムに影響するような環境変数だと OS そのものの調子が悪くなる事があります。

 ...つまり、RAD Studio (Delphi / C++Builder) のせいだけではないのですが、環境変数の観点からみれば "RAD Studio は、なまじ複数のバージョンを同居できるばかりに環境変数 Path の問題を起こしやすい" というのも事実だったりします。前置きが長くなりましたが、解決方法の手順を以下に示します。

  1. システムの環境変数を開く。
    (systempropertiesadvanced.exe の [環境変数] ボタン)
  2. "システム環境変数" リストから Path 環境変数を探し出しダブルクリックする。
  3. 変数値をコピーし、テキストエディタに貼り付けて保存しておく (必ずバックアップを取る)。
  4. [新規] ボタンを押し、以下の環境変数を追加する。

    [インストールフォルダ用環境変数の導入 (64bit Windows の場合)]
    変数名 変数値
    BDS18 C:\Program Files (x86)\Embarcadero\Studio\18.0
    BDS17 C:\Program Files (x86)\Embarcadero\Studio\17.0
    BDS16 C:\Program Files (x86)\Embarcadero\Studio\16.0
    BDS15 C:\Program Files (x86)\Embarcadero\Studio\15.0
    BDS14 C:\Program Files (x86)\Embarcadero\Studio\14.0
    BDS13 C:\Program Files (x86)\Embarcadero\Appmethod\13.0
    BDS12 C:\Program Files (x86)\Embarcadero\RAD Studio\12.0
    BDS11 C:\Program Files (x86)\Embarcadero\RAD Studio\11.0
    BDS10 C:\Program Files (x86)\Embarcadero\RAD Studio\10.0
    BDS9 C:\Program Files (x86)\Embarcadero\RAD Studio\9.0
    BDS8 C:\Program Files (x86)\Embarcadero\RAD Studio\8.0
    BDS7 C:\Program Files (x86)\Embarcadero\RAD Studio\7.0
    BDS6 C:\Program Files (x86)\CodeGear\RAD Studio\6.0
    BDS5 C:\Program Files (x86)\CodeGear\RAD Studio\5.0
    BDS4 C:\Program Files (x86)\Borland\BDS\4.0
    BDS3 C:\Program Files (x86)\Borland\BDS\3.0
    BDS2 C:\Program Files (x86)\Borland\BDS\2.0
    BDS1 C:\Program Files (x86)\Borland\BDS\1.0
    [インストールフォルダ用環境変数の導入 (32bit Windows の場合)]
    変数名 変数値
    BDS18 C:\Program Files\Embarcadero\Studio\18.0
    BDS17 C:\Program Files\Embarcadero\Studio\17.0
    BDS16 C:\Program Files\Embarcadero\Studio\16.0
    BDS15 C:\Program Files\Embarcadero\Studio\15.0
    BDS14 C:\Program Files\Embarcadero\Studio\14.0
    BDS13 C:\Program Files\Embarcadero\Appmethod\13.0
    BDS12 C:\Program Files\Embarcadero\RAD Studio\12.0
    BDS11 C:\Program Files\Embarcadero\RAD Studio\11.0
    BDS10 C:\Program Files\Embarcadero\RAD Studio\10.0
    BDS9 C:\Program Files\Embarcadero\RAD Studio\9.0
    BDS8 C:\Program Files\Embarcadero\RAD Studio\8.0
    BDS7 C:\Program Files\Embarcadero\RAD Studio\7.0
    BDS6 C:\Program Files\CodeGear\RAD Studio\6.0
    BDS5 C:\Program Files\CodeGear\RAD Studio\5.0
    BDS4 C:\Program Files\Borland\BDS\4.0
    BDS3 C:\Program Files\Borland\BDS\3.0
    BDS2 C:\Program Files\Borland\BDS\2.0
    BDS1 C:\Program Files\Borland\BDS\1.0
    [ドキュメントフォルダ用環境変数の導入 (32bit / 64bit Windows 共通)]
    変数名 変数値
    BDS18D C:\Users\Public\Documents\Embarcadero\Studio\18.0
    BDS17D C:\Users\Public\Documents\Embarcadero\Studio\17.0
    BDS16D C:\Users\Public\Documents\Embarcadero\Studio\16.0
    BDS15D C:\Users\Public\Documents\Embarcadero\Studio\15.0
    BDS14D C:\Users\Public\Documents\Embarcadero\Studio\14.0
    BDS13D C:\Users\Public\Documents\Embarcadero\Appmethod\13.0
    BDS12D C:\Users\Public\Documents\RAD Studio\12.0
    BDS11D C:\Users\Public\Documents\RAD Studio\11.0
    BDS10D C:\Users\Public\Documents\RAD Studio\10.0
    BDS9D C:\Users\Public\Documents\RAD Studio\9.0
    BDS8D C:\Users\Public\Documents\RAD Studio\8.0
    BDS7D C:\Users\Public\Documents\RAD Studio\7.0
    BDS6D C:\Users\Public\Documents\RAD Studio\6.0
    BDS5D C:\Users\Public\Documents\RAD Studio\5.0
  5. システム環境変数 Path 内の "上記 4. の変数値と同じ文字列" を対応する変数名で置換する。
    例えば、Path に "C:\Program Files\Embarcadero\RAD Studio\9.0" が含まれるのなら、"%BDS9%" で置換する (%~% で括るのを忘れずに)。
    言うまでもない事かもしれませんが、置換は任意のテキストエディタで行うと間違いも少なくていいと思います。
  6. 念のために Windows を再起動

 これで正しく動作するようになります。BDS1D~BDS4D がないのは記載漏れではなく、Delphi 8 ~ BDS2006 (Turbo) は All Users のドキュメントフォルダを利用していないのです。

 それでも 1024 文字を超えるようなら、Borland / Inprise / CodeGear / Embarcadero 関連を環境変数 _BDS とかにまとめて、それを環境変数 Path に設定するといいでしょう。
 他の開発環境も環境変数 Path に大量のパスを追加している事がありますので、これを機に一度環境変数を整理してみてはいかがでしょうか?

第24回 エンバカデロ・デベロッパーキャンプ - セッション資料ダウンロード
 先日のデベロッパーキャンプの資料が DL できるようになりました (デベロッパーキャンプ・アーカイブの方はまだ更新されていないのでご注意を)。

 【A2】セッションのデモの詳細は 12/8 の記事にあります。デモソースコード一式は、リンク先または以下から DL する事ができます。

 デモソースコードの大半は Delphi XE3 でしかコンパイルできないと思います。XE3 をお持ちでない方は評価版でお試しください。また、アーカイブにバイナリは含まれていません。「どうやって実現しているのか?」、「どういう意図なのか?」 を実際のソースコードで確認して貰うという趣旨で作られていますから、バイナリだけ実行しても面白くないでしょう、多分。


12/12/12

Oh!クラウディア♪
 らいなたんさんが作ったもの、それは...スクショを見ただけで理解できるハズ。

 うはー♪

 ...しかし、過去に細川さんも同じ事をやろうとしていたって事は、他にも "痛 IDE プラグイン" を作ろうとしたヒトが居るのだろうな...素直に手を挙げるように (w

Mac OSX でのコンソールアプリ (XE2 / XE3)
 Delphi のコンソールアプリは "VCL フォームアプリケーションではない" のでターゲットプラットフォームに "OS X" を指定できます

 Delphi Advent Calendar 2012 の本日分の記事 "コンソールアプリケーション1(Delphi Advent Calendar 2012-12-12)" と同じ事を OS X でやってみると以下のようになります。

 文字コードの指定等は特に必要ありません。普通に日本語が通ります。関数やクラスのテストならコンソールアプリの方が楽かもですね、デプロイ時間も短いですし。

TRichEdit で英数字等のフォントが勝手に変わる (Delphi 2009 以降)
 Delphi の TRichEdit がラップしている RichEdit のバージョンが Delphi 2009 以降で変更になっているためにこの現象が起きます。

 以前、Embarcadero Discussion Forums で解決方法を書いたのですが、記事は消えてしまいました。質問のあった Delphi free-ML にも解決方法を書いたのですが、相変わらずコードが読みにくいのでこちらにも書いておきます。

unit uRichEditHelper;

interface

uses
  Windows, Messages, ComCtrls;

type
  TRichEditHelper = class helper for TRichEdit
  private
    function GetLangOptions: DWORD;
    procedure SetLangOptions(const Value: DWORD);
  published
    property LangOptions: DWORD read GetLangOptions write SetLangOptions;
  end;

const
  IMF_AUTOKEYBOARD        = $00000001;
  IMF_AUTOFONT            = $00000002;
  IMF_IMECANCELCOMPLETE   = $00000004;
  IMF_IMEALWAYSSENDNOTIFY = $00000008;
  IMF_AUTOFONTSIZEADJUST  = $00000010;
  IMF_UIFONTS             = $00000020;
  IMF_NOIMPLICITLANG      = $00000040; 
  IMF_DUALFONT            = $00000080;
  IMF_NOKBDLIDFIXUP       = $00000200;
  IMF_NORTFFONTSUBSTITUTE = $00000400;
  IMF_SPELLCHECKING       = $00000800;
  IMF_TKBPREDICTION       = $00001000implementation

{ TRichEditHelper }

function TRichEditHelper.GetLangOptions: DWORD;
const
  EM_GETLANGOPTIONS = WM_USER + 121;
begin
  result := SendMessage(Self.Handle, EM_GETLANGOPTIONS, 00);
end;

procedure TRichEditHelper.SetLangOptions(const Value: DWORD);
const
  EM_SETLANGOPTIONS = WM_USER + 120;
begin
  SendMessage(Self.Handle, EM_SETLANGOPTIONS, 0, Value);
end;
end.

 この uRichEditHelper.pas を uses して、

  RichEdit1.LangOptions := RichEdit1.LangOptions and (not IMF_DUALFONT);

 こんなコードを書いておくと、デュアルフォントが無効になり、従来の Delphi の TRichEdit と同じ動作になります。定数の値は "Windows SDK for Windows 8" の Richedit.h から持ってきています。EM_GETLANGOPTIONS message (Windows) にフラグの詳細な説明がありますが、ここには Richedit.h に記載のないフラグも載っているようです。

サイトプチリニューアル
 画像 5 枚でプチリニューアルしてみました。所謂 "ハッタリ" です。サイトの雰囲気が変わったような気がするでしょうが、中身は全く変わっておりません。こないだのデブキャンで言っていたのはこういう事だったりします。

IDE Fix Pack 5.1 for 2009-XE3
 ふーさん経由の情報ですが、IDE Fix Pack の 5.1 がリリースされたようです。XE3 にも対応したようですね。ソースファイルのコードの行数が多くなってしまうと、フォームとコードの切り替えにえらく時間が掛かるようになってしまいますが、IDE Fix Pack をインストールする事により、これを回避する事ができます (参考: [delphi-users:2747] フォーム表示の切り替え時間)。

第24回エンバカデロ・デベロッパーキャンプ togetter
 トゥギャってあるようです。

 「見たようなアイコンがないなー?」 と思ったら自分のアイコンがなかった...そりゃそうか。デベロッパーキャンプ・アーカイブ も更新され、ビデオも追加され始めたので、後でゆっくりと確認しよう。


12/12/13

Delphi 3 Q&A 150 選 (PDF)
 Delphi Advent Calendar 2012 の本日分は、大野さんの "Delphi 発売前夜" だった訳ですが、ここに超重要な事が書いてありました。

Delphi について、私自身で3冊の書籍を出しました(バージョン1から3まで)。
なんだか、amazon でけっこうな値段になっている「Delphi 3 Q&A 150選」ですが(なぜ?)、こちらのサイトで丸ごと公開しています。
あまり今のバージョンでは意味がないと思いますが、よかったらご覧ください。本当は、前の版の方がかわいいイラストが入っているのですが、それはまたの機会にでも公開しようと思います。

 ...な・ん・だ・と?

 コレが6年前からタダで読めるようになってたとは!しかも付属していた CD-ROM の収録物まで!ちなみに定価で \2,000、Amazon で \5,000 オーバーです。

 追記 (2012/12/14): 大野さん曰く、「6 年前から公開してた訳じゃないよ」 との事です。


12/12/14

痛 IDE プラグイン ver 0.02
 Delphi Advent Calendar 2012 の本日分は、らいなたんさんの "[Delphi]IDEにおける背景変更機能の導入による開発効率への影響とその考察。" という名の "痛 IDE プラグイン解説" です。ver 0.02 は Delphi 6 / 7, RAD Studio 2007 / 2010 / XE2 に対応しています。

 以前、僕がやろうとしたのは素直に (?) OTA 経由での実装だったのですけれど、マトモに画像を表示させる事ができませんでした。この "痛 IDE プラグイン" を初めて見た時、「をおぅ!コイツはスゲェぜ!」 という感想しか出てこなかったのですが、それは実際に "痛 IDE プラグイン" を作ろうとした事があるからこその反応なのかもしれませんね。

 Delphi Advent Calendar 2012 の本日分が 2 つあった?それは気のせいなんだぜ (w


12/12/16

とりあえず、デベロッパーキャンプの資料を読んでみようか。(Delphi VCL Tips)
 もはやこのカテゴリの Tips であるのが妥当とは思えませんが惰性で。現状で公開されている資料をすべてまとめておきました。

Embarcadero のデモの神様について (togetter)
 お約束のネタです。今回も実績が積み重ねられてしまいましたが、セッションスピーカの面々はこれを風物詩的に捉えて楽しんでいるフシもあります。

 細川さんが 「GoToWebinar と因果関係があるのでは?」 と仰っていましたが、確かに Web 配信が行われるようになってから降臨される頻度が多くなった気がします。デモ用 PC の画面をリモートデスクトップで飛ばすようにすれば影響は少なくて済むのかもしれませんが、そうなると構成 (セットアップ) が面倒なのがネックですね。

 それはそうと、デモの神様の擬人化は誰がやってくれるのかな?

クインテッセンス (Quintessence: Delphi iOS beta)
 XE3 (Professional 以上) をお持ちの方は、EDN のメンバーサービスにログインし、左側の My eligible field tests に入ると、例の "Mobile Studio (仮)" のベータプログラムに参加できます。

 参加申し込みを行っても、すぐに Quintessence リソースにアクセスできる訳ではありません。確認メールが届くのを待ちましょう。なお、環境として OS X 10.7 Leopard 以降が稼動する Mac が必要となります。


12/12/22

SkRegExp version 2.0.4 リリース (Delphi / C++Builder)
 小宮さん作の正規表現ライブラリです。ちょっと前にリリースされていました。2.x では以前のバージョンと違うトコがあります。正規表現の違いはマニュアルやブログに譲るとして、とりあえずは...

RegExp.Match[n] RegExp.Groups[n].Strings
RegExp.MatchPos[n] RegExp.Groups[n].Index
RegExp.MatchLen[n] RegExp.Groups[n].Length

 よく使うこの 3 つのプロパティの差異だけ覚えておけばいいでしょう。SkRegularExpressions の .NET 互換クラスを使っている場合にはこの差異を気にする必要はありません。

痛 IDE プラグイン ver 0.03 (Delphi / C++Builder)
 らいなたんさん作 "痛 IDE プラグイン" の ver 0.03 がリリースされました。Delphi 6 / 7, RAD Studio 2007 / 2010 / XE2 / XE3 に対応しています。

 ver 0.03 は高速化されており、私が開発に使っている PC (Flash Builder 4.6 だとコードとデザイナの切り替えに 2~3 分掛かる事があるというシロモノ) でも快適に動作します。

TEditor Unicode 版開発に着手!?
 このサイトに置いてある Unicode 版 TEditor は Mae 氏が作られたものを僕がいじったものですが、掲示板によると、本田さんが Unicode 版の開発に着手された模様です (^o^)/

Microsoft Expression Design がフリーソフトに
 Creature House が開発し、日本では P&A が販売していたドローソフト。その Creature House が Microsoft に買収され、Microsoft Expression となり、フリーソフトになったのが ver3.3 の頃。

 しかしながらこの 3.3 は日本語環境で動作せず、ゴニョゴニョしなければ動作しなかった。ま、ゴニョゴニョすれば動作したし、日本語化する事もできた。その後、Expression は "Microsoft Expression Design" と名前を変え有償製品となった...それから幾年月、Expression (Design) はまたもフリーソフト化された。

 で、この Microsoft Expression Design、何が便利かって "EMF が編集できる" というこの一点だけでもうステキ。ドロー系のソフトは数あれど、この EMF を直接編集できて保存もできて日本語も化けないというのは意外に少ないのです。

 Delphi 使いに何のメリットがあるのかというと、

 このような事に使える訳です。このテのツールは DL できなくなる前に確保しとくのが吉ですヨ...ん?ひょっとして EMF 形式の出力には対応してないのか?だとしたら魅力半減だなぁ。


12/12/27

HotKey2Windowskey ver1.00
 ONKYO TW317 シリーズ用のアプリケーションです。ホットキーが押されたら Windows キーが押された事にします。

HotKey2Windowskey の技術的な話
 Delphi XE3 製です。フォームが存在しないので、FireMonkey のセンサーコンポーネントではなく System.Sensors / System.win.Sensors を利用しています。概要については 12/04 の雑談をご覧下さい。

 センサーでホットキーが押されたかどうかを判断し、ホットキーが押された場合には Windows キー (VK_LWIN) が押された事にします。Windows 7 だとスタートメニューが開き、Windows 8 だと (理屈上は) デスクトップからスタート画面へ戻れるようになります。

HotKey2Windowskey を作った理由
 ONKYO TW317 シリーズには Windows 7 が搭載されていますが、ホットキー以外の物理キーは電源ボタンしかないため、例えばスタートメニューを隠して画面を広く使うという事ができません。HotKey2Windowskey を常駐させておけば、ホットキーでスタートメニューが開くので画面を広く使う事ができます。

 また、Windows 8 搭載スレート PC にはスマホの Home ボタンに相当するボタン (Windows ボタン) が大抵付いていますが、Windows 7 世代のスレート PC にはこれがないものが多いです。Windows 7 世代のスレート PC に Windows 8 をインストールした時不便なのは "スマホの Home ボタンに相当するボタンがない" 事です。

 余談ですが、Windows 8 用マルチタッチディスプレイにも Windows ボタンを付けるべきだと思うのですよね (スワイプで戻れることは承知の上)。各メーカー様におかれましてはキーボード&マウスレスでの運用も視野に入れた作りにして頂けると有難いのですが...。

痛 IDE プラグイン ver 0.04 (Delphi / C++Builder)
 らいなたんさん作 "痛 IDE プラグイン" の ver 0.04 がリリースされました。Delphi 6 / 7, RAD Studio 2007 / 2009 (New!) / 2010 / XE (New!) / XE2 / XE3 に対応しています。

 クラウディアたんと言えば、コミPo!にクラウディアたんのデータが追加されたようです。

SkRegExp version 2.1.0 リリース (Delphi / C++Builder)
 小宮さん作の正規表現ライブラリです。精力的にバージョンアップされていますね。


12/12/28

Brain F*ck コンソールアプリケーション版
 BrainF*ck (Delphi VCL Algorithm) の記事自体は結構前からあるのですが、コンソールアプリケーション版を作っていなかったので追加してみました。Windows 依存のユニットを使っていないので、Mac OS X プラットフォームでもコンパイルできます。

TBarImage 2.00 / TQRBarImage 0.8
 seizo さん作の TBarImage 2.00 / TQRBarImage 0.8 がリリースされました。

ドスパラの Android タブレット (DOSPARA TABLET A07I-D15A) を触ってみた。
 僕が買ったのではありませんが...。Google Play のインストール方法は、価格.com のクチコミ掲示板に記述があります。Google Play をインストールしても "対応していない機種" と言われて弾かれる事が多いので、Novo 7 Crystal のカスタムファームを導入した方がいいかもしれません。

Amazon レビューがおかしい Bluetooth キーボードを触ってみた。
 子供へのクリスマスプレゼントの一つ。実際に叩いてみたけれど意外 (?) に使いやすい。こちらの話も興味深かった。

 Fn キーを押しながら電源を入れるとペアリングできるようになり、"Nintendo Wireless Keyboard" で認識される。

 唯一の不満点は、電池のフタに滑り止めのゴム足が付いている事。キーボードの左側を引きずるように持ち上げると電池のフタが取れてしまうことがある...フタがゆるいのは個体差かもしれないが。


12/12/29

XMLIniFile (Delphi XE 以降)
 XML を環境ファイルとして使いたいというニーズは昔からあり、XMLIniFile はあちこちで実装された。このサイトにも XMLIniFile の実装がある。何気に Delphi のソースフォルダを眺めていたら Embarcadero 純正の XMLIniFile がある事に気付く。何時からだろうと調べてみたら、XE で追加されたようだ。XE の新機能には記載がないのでまったく気付かなかった。

 ...というか、現時点でも TXMLIniFile / TXMLMemIniFile のドキュメントは存在しない。折角いいものを作っても、"誰も知らなければ意味がない" と思うのだよねぇ。

 追記: OldTPFun さんによると Marco Cantu さんの "Delphi XE HANDBOOK" には記載があるそうです。


 BACK   古いのを読む   新しいのを読む