デスクトップ アプリケーションからモバイル アプリケーションへの Delphi コードの移行
ジェスチャ
FireMonkey でのジェスチャ
ActionのUnsupportedPlatforms
XE5
チェックしておくと、チェックしたプラットフォームではコントロールが非表示になる。便利。
多重解像度ビットマップ
XE5
MultiResBitmap エディタ
多重解像度ビットマップの使用
12 多重解像度のアイコンおよび画像の使用
フォント
Android アプリケーションでのカスタム フォントの使用 iOS5,iOS6,Androidのフォント情報へのリンク
ログ
iOS simulatorは、OSXの場合Application->その他→コンソール.appを起動して、Library/Logs -> iOS Simulator -> system.log に表示される。
iOS実機は、Xcode -> Window -> Organizer -> DEVICES -> (実機を選択) -> Console
Androidは、Android SDK -> monitor
uses FMX.Platform;
var
log: IFMXLoggingService;
begin
log := TPlatformServices.Current.GetPlatformService(IFMXLoggingService) as IFMXLoggingService;
log.Log('%s', [str]);
条件コンパイル
iOSとかANDROIDで条件コンパイル
{$IF DEFINED(iOS) or DEFINED(ANDROID)}
{$ENDIF}
Windows(32,64問わず)で条件コンパイル
{$IFDEF MSWINDOWS}
{$ENDIF}
XE6 docwiki 条件付きコンパイル(Delphi)
イベントいろいろ
iOSとWindows8のイベント対応
iOS 開発者のためのアプリのライフサイクル
iOSのイベント対応方法
Thread: How to trigger OnClose, OnCloseQuery or OnDestroy events on iOS?
FMX.Platform.TApplicationEvent
で、iPadで試してみる
iPadのスリープボタンを押して、スリープすると
aeEnteredBackground
スリープ解除すると
aeWillBecomeForeground
aeBecameActiveが来る。
ちなみに、FormのOnActiveは起動時来るけどスリープの時とかは来ないので、この方法で取得しないとダメっぽい。
ListBoxでいろいろ表示
XE4
http://worktoolsmith.com/2013/05/delphi-xe4-listview/
XE5 モバイルアプリだと、スタイルいじれない?
モバイル チュートリアル:リスト ボックス コンポーネントを使用してテーブル ビューを表示する(iOS および Android)
TListViewで検索
Textに対して検索
Delphi XE5の新機能「TListViewのビルトイン検索フィルタリング」を試してみた
TListBoxのTSearchBoxみたいにするには、EditboxのOnChangeTrackingで検索をかける。
TListBoxで検索
TextとDetailを検索
TListBoxはListBoxを右クリックして、項目の追加から「TSearchBox」を追加すると検索機能が追加される。コード不要。
TComboBox
アイテムが多い時,ドロップダウンしたリストが、現在選択している項目を表示しない。
(10.2Tokyo)
DropDownKindをCustomに変更する。
TScrollBar
Max変更しても変わらない
(10.2Tokyo)
Max > ViewPortSize > new_max ※ここの条件詳細に確認してないけど大体こんな感じ
の時
Max := new_max
とやると、Maxが変わらない。
Max代入前にViewPortSize:=0にしておくとMaxが変更
ViewPortSize
(10.2Tokyo)
http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.StdCtrls.TScrollBar.ViewportSize
ヘルプ見てもよくわからないのですが、実際はこう。
Min,Max : スクロールバーのスクロール範囲
ViewPortSize : スクロールバーのトラックバー(掴んでスクロール出来るバー)の範囲
例えば
Min=0,Max=100で、ViewPortSize=50とすれば、スクロールバーの半分のサイズのトラックバーが表示される。
ViewPortSize=20とすれば、1/5サイズのトラックバーが表示される。
トラックバー以外をクリックした時の動作
(10.2Tokyo)
トラックバー以外をクリックした時のスクロール量が少なすぎるのだが、どうにもならない...
メモを自動でスクロール
VCL版TMemoと違って、Lines.Addした時に自動スクロールしないので、コード追加して対処。
ログを垂れ流すとかなら、これで良いかなと。
Memo1.Lines.Add(str);
Memo1.ScrollTo(0, Memo1.Font.Size * 2 * Memo1.Lines.Count);
ちなみに、細かくスクロールする方法はこれ。
Memo1.ScrollTo(0, -1);
これだとなんかダメだった。場合によって変な位置になる。
Memo1.Lines.Add(str);
Memo1.GoToTextEnd;
Memo1.GoToLineBegin;
Delphi10.1Seatle
現状これでうまくいってる。
Memo1.Lines.Add(str);
Memo1.GoToTextEnd;
VideoCapture
DelphiXE3_FireMonkey_VideoCapture
サンプルフォルダ
C:\Users\Public\Documents\RAD Studio\10.0\Samples\FireMonkey
画像描画
基本
TPaintBoxのOnPaintで、BeginScene〜EndSceneの間に描画処理を書く。
(Delphi10.1で、TImage使うとなんかFormのCanvasに描画されているっぽい)
Formへの直接描画
XPはだめ。Direct2Dがデスクトップでサポートされていないかららしい。ええぇぇ。
描画タイミング
OnPaintにて、BeginScene〜EndSceneの間に描画処理を書く。
XPがダメなのとは話違うのだが、たとえばButtonクリックイベントで描画しようとするのは書けない。
OnPaintに書くのが良い。
XE7upd1+Win7 Form1.Canvasで書ける。
XE7upd1+Nexus7(5.0.2) Form1.Canvasでは書けない。OnPaintのCanvasなら書ける。
XE7upd1+iPad(8.1.3) Form1.Canvasでは書けない。OnPaintのCanvasなら書ける。
OnPaintで書けばOKという事で。
色・色定数
TAlphaColor を使う(VCLはTColor)
clXXじゃなくてclaXX。
uses System.UIConsts
claRed
claGreen
claBlue
claBlack
claWhite
http://docwiki.embarcadero.com/RADStudio/XE3/ja/VCL_%E3%81%8B%E3%82%89_FireMonkey_%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B
http://delphimaniacs.blogspot.jp/2012/10/vcl-fmx-color-2.html
クリッピング
Clipping Rectangles in FireMonkey
Canvas.IntersectClipRectを使用する
SaveState,RestoreState使わないと他の描画に影響でるので、使った方が良い
procedure TIxBG.Draw(Canvas: TCanvas);
var
src_rct: TRectF;
dst_rct: TRectF;
clip_rct: TRectF;
wd2, hd2: Single;
w, h: Single;
save: TCanvasSaveState;
begin
if Bitmap = nil then
Exit;
wd2 := (Bitmap.Width / 2) * DrawParams.Scale * Scale;
hd2 := (Bitmap.Height / 2) * DrawParams.Scale * Scale;
w := (DrawParams.Width / 2) * DrawParams.Scale * Scale;
h := (DrawParams.Height / 2) * DrawParams.Scale * Scale;
src_rct := RectF(0, 0, Bitmap.Width - 1, Bitmap.Height - 1);
dst_rct := RectF(X - wd2, Y - hd2, X + wd2 - 1, Y + hd2 - 1);
clip_rct := RectF(X - w, Y - h, X + w - 1, Y + h - 1);
save := Canvas.SaveState;
try
Canvas.IntersectClipRect(clip_rct);
Canvas.DrawBitmap(Bitmap, src_rct, dst_rct, 1.0);
finally
Canvas.RestoreState(save);
end;
end;
DrawLine
10.1
procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
Canvas.BeginScene;
Canvas.Stroke.Kind:=TBrushKind.Solid;
Canvas.Stroke.Color := claBlack;
Canvas.Stroke.Thickness := 1.0;
Canvas.DrawLine(PointF(0, 0), PointF(100, 100), 1.0);
Canvas.EndScene;
end;
古い
ImageControl1.Bitmap.Create(Trunc(ImageControl1.Width), Trunc(ImageControl1.Height));
ImageControl1.Bitmap.Canvas.BeginScene;
try
ImageControl1.Bitmap.Clear($FFFFFFFF);
ImageControl1.Bitmap.Canvas.Stroke.Color := $FF000000;
ImageControl1.Bitmap.Canvas.DrawLine(PointF(10, 10), PointF(100, 100), 100);
ImageControl1.Bitmap.Canvas.Stroke.Color := $FF0000FF;
ImageControl1.Bitmap.Canvas.DrawLine(PointF(10, 10), PointF(100, 120), 100);
ImageControl1.Bitmap.Canvas.Stroke.Color := $FF00FF00;
ImageControl1.Bitmap.Canvas.DrawLine(PointF(10, 10), PointF(100, 130), 100);
ImageControl1.Bitmap.Canvas.Stroke.Color := $FFFF0000;
ImageControl1.Bitmap.Canvas.DrawLine(PointF(10, 10), PointF(100, 140), 100);
finally
ImageControl1.Bitmap.Canvas.EndScene;
end;
http://www.freeml.com/delphi-users/2185
FillRect
全部塗りつぶすならClearが良い。
bmp.Canvas.BeginScene;
try
bmp.Canvas.Fill.Color := claBlack;
bmp.Canvas.Fill.Kind := TBrushKind.Solid;
bmp.Canvas.FillRect(ARect, 0, 0, AllCorners, 1.0);
finally
bmp.Canvas.EndScene;
end;
FillText
10.2Tokyo
例では背景をFillRectで塗りつぶしている
Canvas.Fill.Kind := TBrushKind.Solid;
Canvas.Fill.Color := fill_color;
Canvas.FillRect(rct, 0, 0, AllCorners, 1.0);
Canvas.Fill.Color := font_color;
Canvas.FillText(rct, text, true, 1.0, [TFillTextFlag.RightToLeft], TTextAlign.Center, TTextAlign.Center);
DrawRect
XE10.1
枠を描画する。
Canvas.Stroke.Kind := TBrushKind.Solid; //※これ指定しないと描画されない時あるので注意。
Clear
全部塗りつぶし
bmp.Clear(claBlack);
GetPixel,SetPixel
Delphi10.1
BitmapにGetPixel,SetPixel無いが、BitmapDataにはある。
procedure TForm1.Button1Click(Sender: TObject);
var
bmp: TBitmap;
bmp_data: TBitmapData;
begin
bmp := Image1.Bitmap;
if bmp.Map(TMapAccess.maReadWrite, bmp_data) then
begin
ColorBox1.Color := bmp_data.GetPixel(Round(Image1.Width / 2), Round(Image1.Height / 2));
bmp.Unmap(bmp_data);
end;
end;
http://www.synaptica.info/it/2016/04/11/firemonkey-bitmap-scaling-without-aliasing-android/
BitmapChanged無い
XE4
TBitmap.BitmapChangedがPrivateメソッドになっているので、BitmapChanged呼び出せない。
ソース読むと、Canvas.EndSceneで呼び出している。
Canvas.Scaleの変更
Canvas.Scaleは読み込みようなので変更出来ない...のだが、SetMatrixでの変更は可能
https://stackoverflow.com/questions/23609523/firemonkey-xe6how-to-use-the-full-resolution-on-my-adroiddevice
bg_bitmap.Canvas.SetMatrix(TMatrix.CreateScaling(XScale, YScale));
SetMatrixを使うには
TMatrixを使って、Matrixを生成する
http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Math.Vectors.TMatrix
TPathDataでテキストの描画
一旦TextToPathでTPathDataに変換してからTPathDataを描画する。
procedure TForm1.draw_text(txt: string);
var
pd: TPathData;
txt_width: Single;
draw_width: Single;
begin
txt := Edit1.Text;
pd := TPathData.Create;
try
// 背景塗りつぶし
bmp.Canvas.BeginScene;
bmp.Canvas.Fill.Color := claBlack;
bmp.Canvas.FillRect(RectF(0, 0, bmp.Width, bmp.Height), 1.0);
// フォント外形線
bmp.Canvas.Font.Size := bmp.Height;
bmp.Canvas.TextToPath(pd, Rect(0, 0, bmp.Width, bmp.Height), txt, false, TTextAlign.Leading);
bmp.Canvas.Stroke.Kind := TBrushKind.Solid;
bmp.Canvas.Stroke.Color := $FFFF8000;;
// フォント塗りつぶし
bmp.Canvas.Fill.Color := $FFFF8000;
// 横幅変更
txt_width := bmp.Canvas.TextWidth(txt);
if txt_width > bmp.Width then
draw_width := bmp.Width / txt_width
else
draw_width := 1.0;
// 描画
pd.Scale(draw_width, 1.0);
bmp.Canvas.FillPath(pd, 1.0);
bmp.Canvas.DrawPath(pd, 1.0);
bmp.Canvas.EndScene;
ImageViewer1.Bitmap := bmp;
finally
pd.Free;
end;
end;
Styleの摘要
Styleを適用する
StyleBooxをFormにドロップ
StyleBook1ダブルクリック
スタイルデザイナ→開くアイコンクリック
スタイルを開く
スタイルデザイナ閉じる
Form->リンク→StyleBookにStyleBook1を指定
Retinaスタイル
FireMonkey アプリケーションでの Retina スタイルと非 Retina スタイル
Styleを外部ファイルから読み込み
usesにFMX.Styles追加して、下記実行
TStyleManager.SetStyleFromFile(fname);
適用するスタイルによっては、コンポーネントのサイズが変わったり変わらなかったりするので注意。
Touch系のスタイルはコンポーネントサイズが大きい。
アプリ起動→適用は1回のみが安全ぽい。(適用するスタイルによる)
(Delphi10.1)
ダイアログ
MessageDlgの代替
uses FMX.DialogService.Sync;
//FMXではこれ使う
//注意:10.2で実行した所、ダイアログでエンター押すと、メインフォームにもキーイベントが発生します。
if TDialogServiceSync.MessageDialog('ファイルの先頭から検索を始めますか', TmsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo],
TMsgDlgBtn.mbYes, 0) = mrYes then
begin
//
end;
//こっちはFMX非推奨
if MessageDlg('ファイルの先頭から検索を始めますか?', TmsgDlgType.mtConfirmation, [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) = mrYes then
begin
//
end;
(Delphi10.1)
ディレクトリ選択ダイアログ
VCLと違ってコンポーネントは無いけど関数で有る。
uses FMX.Dialogs
SelectDirectory(Caption,Root,var Directory)
(Delphi10.2)
時間を計る
GetTick
http://ht-deko.minim.ne.jp/techf021.html
FM3でPlatform変数は廃止されたようで、こう書かないと動かない...
var
tick: Double;
TimerService: IFMXTimerService;
begin
TimerService := IFMXTimerService(TPlatformServices.Current.GetPlatformService(IFMXTimerService));
tick := TimerService.GetTick;
Sleep(500);
Memo(FloatToStr(TimerService.GetTick - tick));
end;
Stopwatch
uses System.Diagnostics;
var
sw: TStopwatch;
tick: integer;
begin
sw := TStopwatch.StartNew;
tick := sw.ElapsedMilliseconds;
Sleep(500);
Memo(IntToStr(sw.ElapsedMilliseconds - tick));
end;
ファイル操作
ディスクおよびディレクトリ サポート ルーチン
クロスプラットフォームの為に、IOUtilsかSysUtilsを使う。
ファイルコピー
System.IOUtils.pas
Copy
ディレクトリ作成(親も作成)
System.SysUtils.pas
ForceDirectories
ディレクトリ存在判断
System.SysUtils.pas
DirectoryExists
ファイルパス取得
こっちにも http://www.s-m-l.org/dev/delphi.html#パス取得
サポートされているターゲット プラットフォームに適した標準の RTL パス関数
マルチユーザ対応 Android 4.2以降の内部ストレージと外部ストレージ (4.4対応を追記)
Win7+GalaxyNexus(Android4.2.2)の組み合わせで、PCを再起動しないと内部ストレージが見えない時がある。不便。
XE6 + Galaxy Nexus(Android 4.2.2)の例
Memo1.Lines.Add(TPath.GetHomePath); // '/data/data/com.embarcadero.test_app/files
Memo1.Lines.Add(TPath.GetDocumentsPath); // 同上
Memo1.Lines.Add(TPath.GetSharedDocumentsPath); // '/storage/emulated/0/Android/data/com.embarcadero.test_app/files
Memo1.Lines.Add(TPath.GetPublicPath); // 同上
Memo1.Lines.Add(TPath.GetTempPath); // '/storage/emulated/0/Android/data/com.embarcadero.test_app/files/tmp
上記をPC(Windows7)から内部ストレージとして見ると、こう見える
コンピューター\Galaxy Nexus\内部ストレージ\Android\data\com.embarcadero.test_app\files
Windows7の例
uses System.IOUtils;
GetHomePath
TPath.GetTempPath
TPath.GetDocumentsPath
TPath.GetLibraryPath
TPath.GetTempFileName
TPath.GetTempFileName
ParamStr(0) //従来のApplication.Exenameの代わりに使う
C:\Users\ユーザー名\AppData\Roaming
C:\Users\ユーザー名\AppData\Local\Temp\
C:\Users\ユーザー名\Documents
C:\app_path\Win32\Debug\
C:\Users\ユーザー名\AppData\Local\Temp\tmpA031.tmp
C:\Users\ユーザー名\AppData\Local\Temp\tmpA032.tmp
C:\app_path\Win32\Debug\test_path.exe
iOS,Androidはこんな感じ。
配置でとかする。
Androidはリモートパスを「.\assets\internal\」にして配置。
iOSはリモートパスを「StartUp\Documents」にして配置。
uses System.IOUtils;
TPath.Combine(TPath.GetDocumentsPath, 'dbdemos.gdb');
Android アプリケーションの作成 ファイルの読み込みと配置
実際の配置先は、これの下の方
How to Develop Android Database Applications in RAD Studio XE5
エクスプローラからドラッグドロップ
FMXコンポーネントのTDropTarget
TDropTargetをフォーム上に配置
Fileterに任意のフィルターを設定
*.txt
OnDragDropイベント記述
procedure TForm1.DropTarget1DragDrop(Sender: TObject; const Data: TDragObject; const Point: TPointF);
begin
memo(Data.Files[0]);
end;
Delphi10.1
WindowHandle(Windows)
どうしてもWindowsのAPI呼びたい時
uses FMX.Platform.Win, Winapi.Windows;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
hw: HWND;
begin
hw := FmxHandleToHWND(Form2.Handle);
end;
LoadFromFile
XE5
stringsで使えるLoadFromFile。
iOSとAndroidはSJISだと読めないっぽい。UNICODEにして読み込めた。
クリップボード
コピーペーストのやり方
10.2Tokyo
IFMXExtendedClipboardService を使う
http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Clipboard.IFMXExtendedClipboardService
サンプル
https://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RADStudio_Tokyo/Object%20Pascal/Multi-Device%20Samples/User%20Interface/CopyPaste/fmMain.pas
パス(画像、アニメーション)
InkScapeで作って、SVGからパスデータをコピー、RAD Studioのパスデザイナにペースト。
TStringGridのヘッダーカスタム描画
Delphi11.2
https://stackoverflow.com/questions/72892940/fmx-grid-header-lines-color
上記サイトからコピペ
procedure TForm4.StringGrid1DrawColumnHeader(Sender: TObject;
const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF);
var
ABrush: TStrokeBrush;
ARectF: TRectF;
begin
// fill
Canvas.Fill.Color := TAlphaColorRec.Lavender;
Canvas.FillRect(Bounds, 0, 0, [], 1);
// draw rect, actually only bottom and right side of current header cell
ABrush := TStrokeBrush.Create( TBrushKind.Solid , TAlphaColorRec.Red);
try
Canvas.DrawRectSides(Bounds, 0, 0, [], 1, [TSide.Bottom, TSide.Right], ABrush, TCornerType.Round);
// Draw header text
ARectF := Bounds;
ARectF.Left := ARectF.Left + 4;
Canvas.Font.Size := 15;
Canvas.Fill.Color := TAlphaColorRec.Black;
Canvas.FillText(ARectF, Column.Header , False, 1, [] , TTextAlign.Leading);
finally
ABrush.Free;
end;
end;
証明書
XE5
認証したmacと、別のmacで開発しようとすると、XcodeのOrganizerで、こんなエラーが出る。
Organizer -> Provisioning Profiles -> Status
Valid signing identity not found
証明書を持ってこないとダメらしい。
2台目のMacのXcode:「Valid signing identity not found」
証明書が複数ある場合
"iPhone Developer: ambiguous"とか出た場合は、複数の証明書があって名前解決出来なかった時
指定された証明書名があいまい
ツール→オプション→環境オプション→プロビジョニング→デベロッパ証明書を、キーチェーンの名前にする。(十分一致する長さがあればいい)
iOS Developer
アクティベーションに失敗した時の話
日本のApple StoreでiOS Developer Programを購入しActivateするまでの全スクリーンショット
MacとWin
Delphiを使ってMacOSX用アプリを作る
Macアプリ開発
2020-01-15
Win10 Delphi10.3
macOS Sierra 10.12.6
MacでPAServer20.0を起動
Delphi
ターゲットプラットフォームをmacOS 64ビット選択
接続先は、マシン名よりもIPアドレス指定した方が安心。
接続テストはマシン名でいけても、実際の配置はIPアドレスじゃないとダメな時があった。
Mac Retina
ネイティブおよびカスタム FireMonkey スタイルの取り扱い
D: 30491, FireMonkey Premium Styles Pack for RAD Studio 10.1 and 10.2
メモ
Delphi10.3.3+Firemonkeyの描画おかしかったの、macOS10.12.6→10.15.2にあげたらちゃんと描画するようになった!
フォーム(デバイス)の向き(XE5)
プロジェクト→オプション→アプリケーション→向き→カスタムの向き で指定する
デベロッパーキャンプ・アーカイブ
デベロッパーキャンプ・アーカイブ
Delphi for iOS開発ファーストステップ 必読
Windows開発者のためのFireMonkeyモバイル開発入門 必読,iOS or ANDROID?,画面サイズと画面密度
モバイル開発始めるなら今でしょ!Delphi iOSアプリ開発講座 iOS配置マネージャ
FireMonkeyファーストインプレッション パスの作成方法。VCLコンポーネントとの相違点とか、3Dとか色々書いてあるので一読お勧め
基礎から学ぶビジュアルAndroidアプリ開発今日からあなたもAndroidデベロッパー 基礎から丁寧に解説。必読
classes.dexの配置
10.1update2
昔作ったソフトが動かなかった
エラーは下記
com/embarcadero/rtl/ProxyInterface が見つかりません。
で、ここらへんとか経由して
XE10 - Java class com/embarcadero/rtl/ProxyInterface could not be found
ここ
Delphi XE8 and Seattle: Android App didn't start
からのここ
手動での classes.dex ファイルの作成と配置
最終的にプロジェクト→配置でclasses.dexをプロジェクト下にある物を配置するように変更。

チュートリアル
モバイル チュートリアル:Delphi モバイル アプリケーション開発(iOS および Android)
モバイル チュートリアル:リスト ボックス コンポーネントを使用してテーブル ビューを表示する(iOS および Android)
Androidログビューア
シリアルゲームズ製
android log viewer
リンク
Delphi XE3 FireMonkey変更点
delphi maniacs FireMonkey
全力わはー TMessageManagerってこんなの。
Delphi (FireMonkey) によるテクニック&アルゴリズム
想いが星空を巡る頃 Delphi XE2、FireMonkeyのCanvas描画サンプル
VCL 利用者が FireMonkey を使う時に陥る罠5選
FireMonkey: 設計時、スタイルにアニメーション効果を適用する
FireMonkey - Androidアプリの[Back]キーとライフサイクル
FireMonkey Premium Style Pack 3 for RAD Studio XE5 が公開されました
Delphi モバイル コンパイラでの自動参照カウント うーむ、どうなんだろ
http://ht-deko.minim.ne.jp/Delphi/index.html dekoさんがまとめている情報。便利〜
全力わはー TMessageManagerってこんなの。
2023-06-01 14:22:45 32400