ざつだ ん。 (2016/12/01~)
2016/12/10

第33回エンバカデロデベロッパーキャンプ

参加しました!

うん、ちょっと失敗した (てへぺろ)。

デモの神様が荒ぶる荒ぶる。お供え物が必要なレベルでした。

Delphi が Linux 対応

Delphi が Linux 対応します (クロスコンパイラ)。正式な製品は来年3月くらいでしょうか?

デブキャン情報だと Ubuntu と Redhat に対応するようですが、Redhat に対応するなら CentOS 7 とかでも動作する可能性が高いですね。


2016/12/11

DERUO Switcher

デベロッパーキャンプで使おうと思い用意していた秘密兵器 (?)。

が。デモの神様の関係で使わない事に。あまりにも勿体ないのでソースコードを公開。

/* Windows 10 Virtual Desktop */
#include <Arduboy2.h>
#include <Keyboard.h>
#include <Mouse.h>
#include "bitmaps.h"

Arduboy2 arduboy;

// KEY
int PRESSED_KEY = 0;
bool WITH_CTRL = false;
bool WITH_GUI = false;

void setup() {
  arduboy.begin();          // Initialize the hardware
  arduboy.setFrameRate(15); // Setting the frame rate (15..60)
  arduboy.initRandomSeed(); // Initialize random number generator
  Keyboard.begin();
  Mouse.begin();

  arduboy.clear();
  arduboy.drawSlowXYBitmap(32, 0, deruo, 64, 64, 1);
  arduboy.display();
}

void loop() {
  if (!(arduboy.nextFrame()))
    return;

  /* LED ON */
  PRESSED_KEY = 0;
  WITH_CTRL = false;
  WITH_GUI = false;
  if        (arduboy.pressed(LEFT_BUTTON  )) {
    PRESSED_KEY = KEY_LEFT_ARROW;
    arduboy.setRGBled(8, 0, 0);
  } else if (arduboy.pressed(RIGHT_BUTTON )) {
    PRESSED_KEY = KEY_RIGHT_ARROW;
    arduboy.setRGBled(0, 8, 0);
  } else if (arduboy.pressed(UP_BUTTON    )) {
    PRESSED_KEY = 223; // +
    WITH_GUI = true;
    arduboy.setRGBled(0, 0, 8);
  } else if (arduboy.pressed(DOWN_BUTTON  )) {
    PRESSED_KEY = 222; // -
    WITH_GUI = true;
    arduboy.setRGBled(4, 4, 0);
  } else if (arduboy.pressed(A_BUTTON     )) {
    PRESSED_KEY = KEY_LEFT_ARROW;
    WITH_CTRL = true;
    WITH_GUI = true;
   arduboy.setRGBled(0, 4, 4);
  } else if (arduboy.pressed(B_BUTTON     )) {
    PRESSED_KEY = KEY_RIGHT_ARROW;
    WITH_CTRL = true;
    WITH_GUI = true;
    arduboy.setRGBled(4, 0, 4);
  }  else
    return;

  /* KEY SEND */
  if (WITH_CTRL) {
    Keyboard.press(KEY_LEFT_CTRL);
  }  
  if (WITH_GUI) {
    Keyboard.press(KEY_LEFT_GUI);
  }  
  Keyboard.press(PRESSED_KEY);
  delay(50);
  Keyboard.releaseAll();
  delay(200);

  /* MOUSE CLICK (for Forcus) */
  if (WITH_CTRL && WITH_GUI) {
//    Mouse.click();
  }  

  /* LED OFF */
  arduboy.setRGBled(0, 0, 0);
}
#include <avr/pgmspace.h>
#ifndef BITMAPS_H
#define BITMAPS_H

extern const unsigned char deruo[];

#endif
#include "bitmaps.h"

// http://www.andrewlowndes.co.uk/blog/graphics/arduboy-image-converter

PROGMEM const unsigned char deruo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x07, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x03, 0xFF, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x09, 0xF8, 0x00, 0x00, 
0x00, 0x00, 0x02, 0x7F, 0x09, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x19, 0xF8, 0x00, 0x00, 
0x00, 0x00, 0x02, 0x7F, 0x1B, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x06, 0xFF, 0x13, 0xF8, 0x00, 0x00, 
0x00, 0x00, 0x06, 0xFF, 0x33, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xF9, 0xE0, 0x00, 
0x00, 0x00, 0x07, 0xC0, 0x3F, 0xF9, 0x78, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x03, 0xF9, 0x7F, 0x00, 
0x00, 0x00, 0x70, 0x00, 0x00, 0xFB, 0x7F, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x1E, 0x7E, 0x00, 
0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFE, 0x00, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x03, 0xFE, 0x00, 
0x00, 0x02, 0x00, 0x1F, 0x80, 0x01, 0xFE, 0x00, 0x00, 0x06, 0x00, 0x1F, 0x80, 0x00, 0xFE, 0x00, 
0x00, 0x04, 0x00, 0x1F, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7C, 0x00, 
0x03, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x06, 0x00, 0x07, 0x80, 0x00, 0x00, 0x38, 0x00, 
0x0C, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x18, 0x40, 0x08, 0x00, 0x00, 0x38, 0x00, 0x00, 0x17, 0xE0, 
0x18, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1F, 0x60, 0x18, 0x00, 0x00, 0x03, 0x80, 0x00, 0x18, 0x60, 
0x18, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x19, 0xE0, 0x18, 0x99, 0x00, 0x00, 0x70, 0x00, 0x1F, 0xE0, 
0x18, 0x99, 0x80, 0x00, 0x38, 0x00, 0x1F, 0xE0, 0x18, 0x99, 0x80, 0x00, 0x0C, 0x00, 0x0F, 0xE0, 
0x18, 0x99, 0x80, 0x00, 0x0C, 0x00, 0x0F, 0xE0, 0x0C, 0xED, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xF0, 
0x0F, 0xFF, 0xFF, 0xFF, 0xCC, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x0E, 0x08, 0x00, 0x1E, 0x00, 
0x00, 0x00, 0x00, 0x1C, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x00, 0x10, 0x00, 
0x00, 0x00, 0x00, 0xC0, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x20, 0x00, 0x60, 0x00, 
0x00, 0x00, 0x0C, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x60, 0x00, 0x40, 0x00, 
0x00, 0x00, 0x36, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x66, 0x00, 0x80, 0x01, 0x80, 0x00, 
0x00, 0x00, 0xE3, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x01, 0x98, 0x01, 0x80, 0x03, 0x00, 0x00, 
0x00, 0x03, 0x18, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x80, 0x06, 0x7F, 0xF6, 0x00, 0x00, 
0x00, 0x04, 0xC0, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x06, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0xE0, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

操作は画像にある通りですが、一応解説しておきます (Windows 10 を想定)。

キー Windows 備考
↑ 〔Win〕+〔+〕 ズームイン (拡大)
↓ 〔Win〕+〔-〕 ズームアウト (縮小)
← 〔←〕 前へ
→ 〔→〕 次へ
A 〔Ctrl〕+〔Win〕+〔←〕 前の仮想デスクトップへ
B 〔Ctrl〕+〔Win〕+〔→〕 次の仮想デスクトップへ

ノートパソコンのキーボードでももちろんやれるのですが、〔Ctrl〕+〔Win〕+〔→〕とか3キーのコンビネーションはキッチリ押されず不発になったりするので、ボタン一発操作が確実なのです。

神野甘音 (かみのあまね)

ある意味、今回のデベロッパーキャンプの最大の目玉。

イラストレーターはおといちさん。

この度 "Delphi" のイメージキャラクター神野甘音のデザインとイラスト担当させて頂きました。掲載の許可を頂きましたのでご紹介です。皆さま宜しくお願いします! #dcamp_jp pic.twitter.com/erlBSjIJMq

— おといち (@oto_ichi3) 2016年12月10日

2016/12/12

10.1 Berlin Update 2 更新時に DBX パッケージでエラーになる

10.1 Berlin Update 2 をインストールしたら、起動時に DBX のパッケージがボコボコエラーになってたんですが「まぁ DBX 使わないからいいか...」と放置していました。

さて、久しぶりに Android のプロジェクトでもビルドしてみるかとやってみたら paclient error 217 が出てデプロイできないんです (コンパイルは正常に終わっている)。ググってみると全く同じ話が公式フォーラムにもありました。

「再インストールしたら直った」とかありますが、そんなのは解決方法じゃありません。やだよもう一回あの作業やるの。で、さらにググってみたら興味深い記事が。

これ、そもそもの原因は DBX パッケージなのだそうですよ...一見すると全く関係なさそうなんですけどね。

具体的な解決方法は、

  1. C:\Users\Public\Documents\Embarcadero\Studio\dbExpress\18.0 にあるファイルを移動するかリネーム
  2. [コンポーネント | パッケージのインストール] で (チェックが外れているであろう) DBX 関連のパッケージにチェックを入れる

配置の際に DBX に依存している何かがあるのかな?DBX を使うのであれば、もちろん再インストールするなり、dbxconnections.ini と dbxdrivers.ini をちゃんとしたものに置き換える必要があります。

僕の場合には C:\Users\Public\Documents\Embarcadero\Studio\dbExpress\18.0 に dbxconnections.win と dbxdrivers.win があったので、

コレでイケました。

Delphi Advent Calendar 2016

今年もやってます、Delphi Advent Calendar!

私は5日目と13日目に参加しました。


2016/12/13

第33回エンバカデロデベロッパーキャンプ (大阪)

本日開催!

動画配信はあるのかな?


2016/12/17

最新 Delphi / RAD Studio でこれが楽しい 旧バージョンからの移行 "マインド" 入門 ~ reprise (前編) ~

はっじまるよー♪

移行という事で、Delphi をそこそこ知っている人向けの記事です。

Starter Edition の話

10.1 Berlin Starter Edition が無償化されたのは既報の通りです。言語に関する新機能は一通り試せますので、最新の (有償版) Delphi をお持ちでない方は Starter Edition を常用するといいでしょう。

但し、10.1 Berlin の何らかのライセンスを持っている場合...例えば有償版やトライアルのライセンスを持っている場合に Starter Edition をインストールしても Starter Edition にならない事があります。これはインストーラが SKU に関わらず同一だからです。

おかしくなってしまった場合には、ライセンスマネージャを用いて当該ライセンスを削除した上で、完全手動アンインストールを行いましょう。

無償版のリリースにより、また Delphi を触り始めたヒト...おかえりなさい。

Delphi の情報をどこで得るのか?

昔々に遡れば、Delphi の情報はパソコン通信のニフティサーブにあった FDELPHI というフォーラムで得られました。このため、インターネット時代になっても @nifty のアットホームページを利用する方が多かったのです...Nifty の有料会員であれば、所謂ホームページを持てたので。

そして @Homepage が 2016/11/10 を以て終了しました。これにより、Delphi 関連サイトが一気に消失しました。現在、Delphi の新しい情報を得ようと思った場合、即応性が高いのは twitter や Facebook 等の SNS です (質問への回答が早いという意味ではありません)。

昔の貴重な情報が無くなったのは悲しい事ですが、昔の Delphi のネガティブな情報...特に現状に当てはまらないような文句や、「今ならそんな書き方しなくても済むのに...」といった更新されていないコードも一緒に消失したので悪い事ばかりでもないのかもしれません。

Facebook はともかく、Twitter はアカウント作らなくてもツイートは見れます (質問とかツッコミができるので本当はアカウント作った方がいいのですが)。以下のリンク先をブックマークしておくと、芋づる式に情報が得られるでしょう。

あ、こないだ僕が病気になったときにお亡くなりになっていたら今年末でこのサイトも消滅していた事に気付き、慌てて契約を数年分延長しました。

これでオリンピックイヤーまでは大丈夫デス (w

最近の IDE の機能

一覧にしたのは以下の機能:

IDE に統合されたソースコードフォーマッタは Starter Edition にはありませんが、細川さん作のプラグインでコマンドライン版コードフォーマッタを呼び出せば同等の事を行えます。

旧 IDE っぽくする方法はデブキャンでブッ込んでおきました。Castalia 拡張と Konopka 拡張は好みが別れると思います。

Castalia 拡張 (XE8 以降) の機能の一つであるクリップボード履歴は、表示していなくてもクリップボードの内容をキャプチャしてるため、例えばユーザー名やパスワードをコピペすると履歴に残ります。しかもこの履歴を消す方法がありません。

Castaliaとの統合で追加されたクリップボード履歴がパスワード管理ツールと併用するとセキュリティ的に微妙という話が某所で出てるけど、管理ツール全体のリスクじゃね?というのも正しいし、かといってオフにできない機能を提供するのもどうなんよ?というのも一理ある

— Lyna (@lynatan) 2016年11月26日

Konopka 拡張 (10.1 Berlin 以降) は主にプロパティエディタなのですが、例えば TAlign のプロパティエディタは、オブジェクトインスペクタをキーボードで使う人には不評です。カーソルキーでフォーカスが移動しないからです (TAB を使えば移動するけれど)。

Delphi 10.1 Berlin Update 2の新しいTAlign型のビジュアルなプロパティエディタを無効化するプラグイン Actual source for DisableAlignPropertyEditor https://t.co/OqIyfLtIKx pic.twitter.com/nN0oL6u1LK

— Owl's perspective (@owlsperspective) 2016年12月1日

好みが別れるのは GetIt で提供するようにすればいいのに。そんな Konopka 拡張ですが、一つだけオススメ機能があります。僕はこの機能を自作してました。

[クイックコピー名] という変な和訳になってしまっているのが残念ですが、意味合いはコンポーネント名のコピーです。

最近の言語&ライブラリの機能

一覧にしたのは以下の機能:

言語仕様については「OBJECT PASCAL HANDBOOK を読め!」としか言いようがないですね。少々お高いのですが、DocWiki をあてもなくなく彷徨うより短期間で知識が得られます。

ライブラリについては、まずは System 名前空間内の把握ですかね。ここには VCL / FireMonkey 共通...つまりマルチプラットフォームで使えるものが増えています。

「何コレ?知らんぞ?」というのは一つや二つじゃないハズです。XE7 までくらいの強烈なリファクタリングは大体落ち着いたので、座標 / ベクトル / 行列関連レコード等も安心して使えます。


2016/12/18

最新 Delphi / RAD Studio でこれが楽しい 旧バージョンからの移行 "マインド" 入門 ~ reprise (後編) ~

仕切り直して、はっじまるよー♪

まさかの Windows 再起動で記事をフッ飛ばしてしまいました。

移行を阻害しているものは何?

イロイロ要因はあると思いますが...

今までリリースされた Delphi と、現状の Delphi を考慮すると上記のような結論に至ると思います。

Professional 版と IBX と ZeosLib と。

Professional 版では DBX / FireDAC によるサーバー接続ができないので、以下のどちらかを選択する必要があります。

FireDAC C/S Pack を購入しても DBX でサーバー接続できるようにはならないし、DataSnap も使えませんので、イロイロ DB 接続したいのなら Enterprise 以上が必要になります。

そもそも Professional 版では DB サーバに接続できないとか全く理不尽な制限で、アップデートサブスクリプション強制になって製品価格が上昇しており、新規購入の場合には "19万も出して C/S アプリも作れない" という状況は、正直擁護のしようもありません。アップデートサブスクリプションに加入していれば毎年の費用はそうでもないのですが、アップグレードですらちょっと引く金額になっています (12万円超)。

なので、プロジェクトを移行したいけれど予算がない場合には Professional 版で IBX や ZeosLib を使う事も検討してみてください。なお、開発ツール自体を変えるとまずデスマーチ決定なのでやめておいたほうがいいと思いますヨ?

IBX + Firebird の組み合わせは DB にお金をかけられない場合に有効ですが、UTF8 だとおかしくなります。これは Interbase の UTF8 と Firebird の UTF8 の実装が異なるからです。今の Firebird では "Unicode_FSS ≒ UTF8" なので、Unicode_FSS にすれば UTF8 が使えますが、気持ち悪いなら IBX のファイルを3つだけプロジェクトフォルダにコピーし、ソースコードを修正して使いましょう。

[IBX.IBSQL.pas] - 関数を置き換えます
function TIBXSQLVAR.GetCharsetSize: Integer;
begin
  case SqlVar.SqlSubtype and $FF of
     5, // SJIS_0208
     6, // EUCJ_0208
     8, // UNICODE_BE / UCS2BE (InterBase)
    44, // KSC_5601
    56, // BIG_5
    57, // GB_2312
    64, // UNICODE_LE / UCS2LE (InterBase)
    67, // GBK (Firebird)
    68: // CP943C (Firebird)
      result := 2;
    3: // UNICODE_FSS
      begin
        // System Tables incorrectly state they are in Unicode_Fss character set but they are not
        if SqlVar.RelName.StartsWith('RDB$') or (SqlVar.SqlLen mod 3 <> 0) then
          result := 1
        else
          result := 3;
      end;
     4, // UTF8 (Firebird)
    59, // UTF8 / UTF_8 (InterBase)
    69: // GB18030 (Firebird)
      result := 4;
  else
    result := 1;
  end;
end;

[IBX.IBDatabase.pas] - 手続きの最後に追記します
procedure BuildDPBConstants;
begin

  ...

  CodePages.Add('DOS775', 775);      {do not localize} // 15
  CodePages.Add('DOS858', 858);      {do not localize} // 16
  CodePages.Add('DOS862', 862);      {do not localize} // 17
  CodePages.Add('DOS864', 864);      {do not localize} // 18
  CodePages.Add('ISO8859_2', 28592); {do not localize} // 22
  CodePages.Add('ISO8859_8', 1255);  {do not localize} // 38
  CodePages.Add('DOS866', 866);      {do not localize} // 48
  CodePages.Add('DOS869', 1255);     {do not localize} // 49
  CodePages.Add('BIG_5', 950);       {do not localize} // 56
  CodePages.Add('WIN1255', 1255);    {do not localize} // 58
  CodePages.Add('WIN1256', 1256);    {do not localize} // 59
  CodePages.Add('WIN1257', 1257);    {do not localize} // 60
  CodePages.Add('KOI8R', 20866);     {do not localize} // 63
  CodePages.Add('WIN1258', 1258);    {do not localize} // 65
  CodePages.Add('GBK', 936);         {do not localize} // 67
  CodePages.Add('TIS620', 874);      {do not localize} // 66
  CodePages.Add('CP943C', 932);      {do not localize} // 68
  CodePages.Add('GB18030', 54936);   {do not localize} // 69
end;

[IBX.IBExtract.pas] - 4行コメントアウトします
function TIBExtract.ExtractDDL(Flag: Boolean; TableName: String) : Boolean;
begin

  ...

  if TableName <> '' then
  begin
    if not ExtractListTable(TableName, '', true) then
      Result := false;
  end
  else
  begin
    ListCreateDb;
//    ListEUAUsers;
//    ListEncryptions;
//    if ConnectAsOwner then
//      BuildConnectString;
    ListFilters;
    ListFunctions;
    ListDomains;
    ListAllTables(flag);
    ListIndex;

  ...

end;

ZeosLib は Starter Edition にもインストール可能で、以下の DB に対応しています。

大抵の DB にはつなげますよね。ただ、Stable (7.1.4) は XE7 までしか対応していないので、XE8 以降の定義を Zeos.inc に追加してやる必要があります。

[Zeos.inc] - 追記します
// Compilation directives for Delphi XE8
{$IFDEF VER290}
  {$DEFINE VER200BELOW} // Used in code
  {$DEFINE DELPHI12_UP} // Used in code
  {$DEFINE DELPHI14_UP} // used in tests only
  {$DEFINE DELPHI15_UP} // Used in zeos.inc only
  {$DEFINE DELPHI16_UP} // Used in code
  {$DEFINE DELPHI17_UP} // Used in zeos.inc only
  {$DEFINE DELPHI18_UP} // Used in zeos.inc only
  {$DEFINE DELPHI19_UP} // Used in zeos.inc only
  {$DEFINE DELPHI20_UP} // By dieletro Used in zeos.inc only
  {$DEFINE DELPHI21_UP} // Used in zeos.inc only
  {$DEFINE DELPHI22_UP} // Used in zeos.inc only
  {$DEFINE BDS4_UP} // Used in code
  {$DEFINE BDS5_UP} // Used in code
{$ENDIF}

// Compilation directives for Delphi 10 Seatle
{$IFDEF VER300}
  {$DEFINE VER200BELOW} // Used in code
  {$DEFINE DELPHI12_UP} // Used in code
  {$DEFINE DELPHI14_UP} // used in tests only
  {$DEFINE DELPHI15_UP} // Used in zeos.inc only
  {$DEFINE DELPHI16_UP} // Used in code
  {$DEFINE DELPHI17_UP} // Used in zeos.inc only
  {$DEFINE DELPHI18_UP} // Used in zeos.inc only
  {$DEFINE DELPHI19_UP} // Used in zeos.inc only
  {$DEFINE DELPHI20_UP} // By dieletro Used in zeos.inc only
  {$DEFINE DELPHI21_UP} // Used in zeos.inc only
  {$DEFINE DELPHI22_UP} // Used in zeos.inc only
  {$DEFINE DELPHI23_UP} // Used in zeos.inc only
  {$DEFINE BDS4_UP} // Used in code
  {$DEFINE BDS5_UP} // Used in code
{$ENDIF}

// Compilation directives for Delphi 10.1 Berlin
{$IFDEF VER310}
  {$DEFINE VER200BELOW} // Used in code
  {$DEFINE DELPHI12_UP} // Used in code
  {$DEFINE DELPHI14_UP} // used in tests only
  {$DEFINE DELPHI15_UP} // Used in zeos.inc only
  {$DEFINE DELPHI16_UP} // Used in code
  {$DEFINE DELPHI17_UP} // Used in zeos.inc only
  {$DEFINE DELPHI18_UP} // Used in zeos.inc only
  {$DEFINE DELPHI19_UP} // Used in zeos.inc only
  {$DEFINE DELPHI20_UP} // By dieletro Used in zeos.inc only
  {$DEFINE DELPHI21_UP} // Used in zeos.inc only
  {$DEFINE DELPHI22_UP} // Used in zeos.inc only
  {$DEFINE DELPHI23_UP} // Used in zeos.inc only
  {$DEFINE DELPHI24_UP} // Used in zeos.inc only
  {$DEFINE BDS4_UP} // Used in code
  {$DEFINE BDS5_UP} // Used in code
{$ENDIF}
// END of per Delphi version defines

最新の ZeosLib は大丈夫かもしれませんが、この Stable (7.1.4) は BLOB の扱いがアフォで、一行 SELECT する度に BLOB の中身をキャッシュします。簡単に言うと、SELECT 文を実行して Next するたびに BLOB フィールドのサイズずつメモリを食い潰します。考えなしに一万件回したりすると死ねます...お気を付けあれ。

高度な文字列検索と抽出

Delphi では XE から正規表現が使えますが、パフォーマンスが出ない場合には小宮さんの SkRegExp を使う事を検討してみてください。ラッパークラスを使う分には高い互換性があります。

「正規表現使うと文字列抽出がスマートに書けますよー」と言って出したサンプルが 自分で作った [クイックコピー名] です。

[GetComponentNames.dpr]
program GetComponentNames;

uses
  Classes, ClipBrd, RegularExpressions;

const
  Exp = 'object +(?<Component>.+):’;
var
  RegEx: TRegEx;
  Match: TMatch;
  SL: TStringList;
begin
  RegEx := TRegEx.Create(Exp);
  Match := RegEx.Match(Clipboard.AsText);
  SL := TStringList.Create;
  try
    while Match.Success do
      begin
        SL.Add(Match.Groups.Item['Component'].Value);
        Match := Match.NextMatch;
      end;
    Clipboard.AsText := SL.Text;
  finally
    SL.Free;
  end;
end.

EXE を生成しておき、[ツール | ツールの構成] で登録しておけば、

  1. 名前を取得したいコンポーネントをフォームデザイナで選択
  2. 〔Ctrl〕+〔C〕でコピー
  3. [ツール | GetComponentNames] で GetComponentNames.exe を起動
  4. クリップボードにコンポーネントの名前が入っている
  5. コードエディタにペースト

...という使い方ができます。

Swift のような for 文 (Stride)

こないだの雑談ネタなので省略します。

プリミティブ型のヘルパー

プリミティブ型のヘルパーは XE4 以降で使えます。標準のプリミティブ型のヘルパーが使いにくいのなら、ヘルパーを上書きしてしまえばいいのです。

[uAltHelper.pas]
unit uAltHelper;

interface

uses
  System.SysUtils;

type
  TIntegerHelper = record helper for Integer
    function ToString: string;
  end;

implementation

{ TIntegerHelper }

function TIntegerHelper.ToString: string;
begin
  result := FormatFloat('#,##0', Self);
end;

end.

この Integer 型ヘルパーは ToString で桁区切りした文字列を返します。

See Also:

型変換のコードを減らす

これ、実は第28回デブキャンでもやってます。

自由に改変して使ってみてください。同様にコンボボックス用とかも作ってみると面白いかもしれません。

SQL をベタ書きしたくない (1)

一つ目のレコード TChainSelectSQL。

メソッドチェーンにより、コード補完で入力可能。WHERE や ORDER も追加できるし省略もできる。Term() メソッドで SQL をビルドする。

SQL をベタ書きしたくない (2)

二つ目のレコード TSelectSQL。

SQL の要素を一部だけ書き換えられるため、ちょっとだけ違う SQL を簡単に作ることができる。Build() メソッドで SQL をビルドする。

SQL[1] := 'COUNT(*)';

似たような事を既存の SQL プロパティでやれない事はないけれど、SQL が変更になったらワケワカラン事になる...バグの元。

SQL をベタ書きしたくない (3)

レコードという事は、const でこんな書き方もできるという事。

上記二つのレコードを含むユニット uSQLBuilder.pas は以下から DL 可能。

もちろん SELECT / UPDATE / INSERT / DELETE 用レコードも用意されています。

実際の所、似たような実装は探せばいくつかみつかるのですが、ギッチギチに作ってあったりするので却って使いにくいと思います。SQL には方言があるのでゆるふわで作ってあった方が融通が利くのです。

LINQ (to Object) っぽい実装

以前、雑談で書いたので省略。

FieldByName() を書きたくない

これのキモは uClassBaseClass.pas なのです。このユニットに

この機能があるため、FieldByName / ParamByName を記述しなくて済みます。

具体的な使い方ですが、

  1. テーブル毎に TClassBaseClass (uClassBaseClass.pas で定義されている) を継承したクラスを書く。単純にゲッターセッターだけのクラスでを書く。但し、クラスのフィールド名はテーブルのフィールド名でなくてはならない (クラスのフィールド名に使えない文字を使っている場合には、SQL 側で別名を付けるなりして対処する)。クラスが記述されたファイルは機械的に作れるので、ジェネレータプログラムを作るとよい。
  2. 継承クラスの Dataset プロパティに任意の Query コンポーネントをセットする。
  3. SELECT クエリーの場合、GetFields メソッドで現在位置のレコードデータをクラスのフィールドにセットする。
  4. INSERT クエリー等の場合、SetParams メソッドでクラスのフィールドの値をパラメータにセットする。

こうなります。メリットはスライドの通りです。TCustomEdit 用のクラスヘルパーと併用すれば入れポン出しポンが簡単になり、かつコンパイル時にそれなりにエラーで止まります。

uClassBaseClass.pas は BDE / dbGo / IBX / DBX/ FireDAC に対応しているハズですが、完全なテストができていません...が、それなりには動作します。

ライナタン・カクチョウ!

ちょっとセッションの趣旨からは外れるので Extras にしましたが単純に楽しいですよね、わはー!

一覧にしたのは以下の機能:

• 16進数表示プラグイン [詳細]
ツールチップで表示される数値を16進数で表示する
• Clipboard-History-Disabler [詳細]
クリップボード履歴を無効にする
• Component Initializer [詳細]
コンポーネントの初期値を設定する
• Component Tray [詳細]
非ビジュアルコンポーネントを置けるトレイを追加する
• DisableStat [詳細]
stat ファイルの生成を止める
• DLight [詳細]
ツールチップ式評価の内容や監視式の内容をインライン表示する。ツールチップ式評価の使えない Starter Edition でも動作する
• dNotes plugin [詳細]
プロジェクトマネージャで、ユニットに説明を記入できる。すっごく便利
• Jpfix plugin [詳細]
キャレット位置がズレる問題を修正
• Lock on Load plugin [詳細]
プロジェクトロード時に「コントロールのロック」を自動でオンにする
• New Edit Window for Embedded Designer [詳細]
埋め込みデザイナでフォームユニットを複数表示する
• LIB フォルダを読取専用で開く [詳細]
SOURCE フォルダにある Delphi のライブラリソースは読取専用で開くようにする
• Quick Quick Edit [詳細]
QuickEdit を〔F2〕で開けるようにする
• Sort Projects plugin [詳細]
プロジェクトグループ内のプロジェクトをソートする
• Template Replacer [詳細]
ユニットのテンプレートをカスタマイズ可能にする
• UTF8ize plugin [詳細]
新規に作成したり開いたユニットのファイルフォーマットを自動でUTF-8にセットする
• 凹ンパイルプラグイン [詳細]
10 Seattle 以降ではコンパイル進行状況ウィンドウがフラットになってしまって大変見づらいので、以前のように凹ませる
• 痛IDEプラグイン [詳細]
コードエディタの背景に任意の画像を表示する。忘れがちなキーボードショートカットの画像を作って背景にするといった、マジメな (?) 使い方もできる

一部直リンクがあるので注意 (リンクの右にあるアイコンで判別可能)。

まとめ

内容薄いように見えて、1時間で喋るにはこれでも多すぎるんですよね...orz


この雑談に対するご意見ご感想等ありましたら Delphi Forum までどうぞ。

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