Home New Help Edit

Delphi FireMonkey memo

Suns & Moon Laboratory
DelphiのFireMonkeyネタです。

Delphi memo FireMonkey以外のネタはこっち


印刷

FireMonkey アプリケーションからの印刷

1.FMX.Printerの追加
uses FMX.Printer;
2.BeginScene,EndScene使用fmac
ちょっと意味わかんない

3.DPI選択
Printer.ActivePrinter.SelectDPI(600,600);
あくまで選択なので、一致するDPIが無い場合は、プリンターが持つDPIが設定される。
例えば300DPI,600DPIをプリンタがサポートしている場合
SelectDPI(350,350) -> 300DPIが選択される
SelectDPI(550,550) -> 600DPIが選択される
※プリンタドライバによって、何が選択されるかは挙動違う事がありそう。
なので、SelectDPIで選択したら、選択されたDPIを利用して描画する必要が有る。
Printer.ActivePrinter.DPI[Printer.ActivePrinter.ActiveDPIIndex].X Printer.ActivePrinter.DPI[Printer.ActivePrinter.ActiveDPIIndex].Y
手持ちのプリンタBrother MFC-J827DNの場合、SelectDPI設定してもActiveDPIIndex=-1のままで変わらない。
従ってDPIの読み出しも不可。
...DPI無視して描画するしかないのか。


4.印刷ジョブ開始
Printer.BeginDoc;
5.印刷ジョブ終了
Printer.EndDoc;

スレッド

(iOSのバグで)メモリリークがあるため、対策必要。
http://www.s-m-l.org/dev/delphi.html#TAnonymousThread

サンプル

http://docwiki.embarcadero.com/RADStudio/XE6/ja/%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AE%E8%AA%AC%E6%98%8E

モバイルアプリの注意点

文字列のインデックスが0→TStringHelperを使う
System.Pos→TStringHelper.IndexOf
System.Copy→TStringHelper.Substring
System.Delete→TStringHelper.Remove
System.SysUtils.Trim→TStringHelper.Trim
TStringHelper.Chars[](読み取り専用)プロパティを利用すると、インデックス0からアクセス出来る
for i=1 to Length(s) do→for Low(s) to High(s) do
静的配列 array [10] of integer→動的配列 array of integer,TArray


デスクトップ アプリケーションからモバイル アプリケーションへの Delphi コードの移行

ジェスチャ

FireMonkey でのジェスチャ

ActionのUnsupportedPlatforms

XE5
チェックしておくと、チェックしたプラットフォームではコントロールが非表示になる。便利。

多重解像度ビットマップ

XE5
MultiResBitmap エディタ
多重解像度ビットマップの使用
12 多重解像度のアイコンおよび画像の使用


いろいろ

uses System.Types; RectF()


フォント

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した時に自動スクロールしないので、コード追加して対処。
ログを垂れ流すとかなら、これで良いかなと。

Delphi11.3でOK
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.1 OK
Delphi11.3 NG EArgumentOutOfRangeExceptionでそのうち死ぬ
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に描画されているっぽい)

★BeginScene〜EndSceneの数が合わないと、変な事が起きます...

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;

OnPaintint,Invalidate,InvalidateRectFで描画範囲を限定する

OnPaintじゃなくてOnPaintingを使うと、描画矩形を取得できる。
★とおもったが、取得できてないのでダメ
★だめだけど残しておく
var rct, rct1, rct2, rct3: TRectF; count: integer; procedure TForm1.FormCreate(Sender: TObject); begin rct1 := RectF(0, 0, 100, 99); rct2 := RectF(0, 100, 100, 199); rct3 := RectF(0, 200, 100, 299); end; procedure TForm1.Button1Click(Sender: TObject); begin PaintBox1.InvalidateRect(rct1); end; procedure TForm1.Button2Click(Sender: TObject); begin PaintBox1.InvalidateRect(rct2); end; procedure TForm1.Button3Click(Sender: TObject); begin PaintBox1.InvalidateRect(rct3); end; procedure TForm1.Button4Click(Sender: TObject); begin Invalidate; end; procedure TForm1.PaintBox1Painting(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin Canvas.BeginScene; if IntersectRectF(rct, ARect, rct1) then begin Canvas.Fill.Color := claRed; // 塗りつぶし色 Canvas.FillRect(rct1, 1.0); Canvas.Fill.Color := claWhite; // 文字色 Canvas.FillText(rct1, count.ToString, true, 1.0, [], TTextAlign.Center, TTextAlign.Center); inc(count); end; if IntersectRectF(rct, ARect, rct2) then begin Canvas.Fill.Color := claGreen; // 塗りつぶし色 Canvas.FillRect(rct2, 1.0); Canvas.Fill.Color := claWhite; // 文字色 Canvas.FillText(rct2, count.ToString, true, 1.0, [], TTextAlign.Center, TTextAlign.Center); inc(count); end; if IntersectRectF(rct, ARect, rct3) then begin Canvas.Fill.Color := claBlue; // 塗りつぶし色 Canvas.FillRect(rct3, 1.0); Canvas.Fill.Color := claWhite; // 文字色 Canvas.FillText(rct3, count.ToString, true, 1.0, [], TTextAlign.Center, TTextAlign.Center); inc(count); end; Canvas.EndScene; 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, [], TTextAlign.Center, TTextAlign.Center);
ちなみに[]のところ[TFillTextFlag.RightToLeft]にすると、単語が右から左に配置される...

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;

DrawPathで矩形描画

Delphi11
procedure TForm1.PaintBox1Painting(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var pd: TPathData; begin Canvas.BeginScene; try Canvas.Stroke.Kind := TBrushKind.Solid; Canvas.Stroke.Color := claBlack; Canvas.Stroke.Thickness := 1.0; pd := TPathData.Create; pd.MoveTo(PointF(10, 10)); pd.LineTo(PointF(100, 100)); pd.LineTo(PointF(110, 100)); pd.LineTo(PointF(120, 120)); pd.LineTo(PointF(130, 120)); Canvas.DrawPath(pd, 1.0); pd.Free; finally Canvas.EndScene; end; end;

マルチディスプレイ

Delphi 11.3

procedure TForm1.PaintBox1Painting(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin Canvas.BeginScene; try Canvas.Stroke.Kind := TBrushKind.Solid; Canvas.Stroke.Color := claBlack; Canvas.Stroke.Thickness := 1.0; Canvas.DrawLine(PointF(0, 0), PointF(100, 100), 1.0); finally Canvas.EndScene; end; end; // マルチディスプレイの情報を表示 procedure TForm1.Button1Click(Sender: TObject); begin Screen.UpdateDisplayInformation; UpdateMemo; end; // ウィンドウを指定位置へ移動 procedure TForm1.Button2Click(Sender: TObject); begin Left := 3840; Top := 1520; end; // ウィンドウを指定したサイズのディスプレイへ移動 procedure TForm1.Button3Click(Sender: TObject); begin Screen.UpdateDisplayInformation; move_win(1024, 600); end; // w,hが一致するDisplayへウィンドウを移動する procedure TForm1.move_win(w, h: integer); begin for var I := 0 to Screen.DisplayCount - 1 do begin if (Screen.Displays[I].BoundsRect.Width = w) and (Screen.Displays[I].BoundsRect.Height = h) then begin Left := Round(Screen.Displays[I].BoundsRect.Left); Top := Round(Screen.Displays[I].BoundsRect.Top); break; end; end; end; function TForm1.RectfToStr(R: TRectF): String; begin Result := '(Left,Top=' + Floattostr(R.Left) + ',' + Floattostr(R.Top) + ' W,H=' + Floattostr(R.Width) + ',' + Floattostr(R.Height) + ')'; end; function TForm1.DispToStr(Disp: TDisplay): String; begin Result := Inttostr(Disp.Index) + '. '; if Disp.Primary then Result := Result + ' Primary '; Result := Result + SLineBreak; Result := Result + 'WorkAreaRect : ' + RectfToStr(Disp.WorkareaRect) + '; '; // タスクバーの領域除外 Result := Result + SLineBreak; Result := Result + 'BoundsRect : ' + RectfToStr(Disp.BoundsRect) + '; '; // タスクバー含めた画面サイズ end; procedure TForm1.UpdateMemo; var I: integer; P: TPoint; begin Memo1.Lines.Clear; P := TPoint.Create(Round(Screen.MousePos.X), Round(Screen.MousePos.Y)); Memo1.Lines.Add('Screen'); Memo1.Lines.Add('MousePos: ' + Floattostr(P.X) + ' ' + Floattostr(P.Y)); Memo1.Lines.Add('DisplayFromForm(Self).Index: ' + Inttostr(Screen.DisplayFromForm(Self).Index)); Memo1.Lines.Add('Size.cx: ' + Floattostr(Screen.Size.cx)); Memo1.Lines.Add('Size.cy: ' + Floattostr(Screen.Size.cy)); Memo1.Lines.Add('DisplayCount: ' + Inttostr(Screen.DisplayCount)); Memo1.Lines.Add('WorkAreaRect: ' + RectfToStr(Screen.WorkareaRect)); Memo1.Lines.Add('DesktopRect: ' + RectfToStr(Screen.DesktopRect)); Memo1.Lines.Add('Displays'); for I := 0 to Screen.DisplayCount - 1 do Memo1.Lines.Add(DispToStr(Screen.Displays[I])); Memo1.Lines.Add('Form'); Memo1.Lines.Add('BoundsRect: ' + RectfToStr(TRect.Create(TPoint.Create(Left, Top), Width, Height))); 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)

ダイアログのフィルター

FMXと違ってIDEで設定できない?
FMX.Dialogs.TOpenDialog.Filter

Delph11.3
OpenDialog1.Filter:='WAV file (*.wav)|*.wav';

ディレクトリ選択ダイアログ

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

Delphi10.1,Delphi11.3

TDropTargetをフォーム上に配置

Fileterに任意のフィルターを設定
*.txt
OnDragDropイベント記述
procedure TForm1.DropTarget1DragDrop(Sender: TObject; const Data: TDragObject; const Point: TPointF); begin Memo1.Lines.Add(Data.Files[0]); //for var str in Data.Files do // Memo1.Lines.Add(str) end;

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.3
procedure TForm1.Grid1_Init; begin // 行数指定 StringGrid1.RowCount := ROW_COUNT; //桁追加 for var i := 0 to COL_COUNT - 1 do begin StringGrid1.AddObject(TStringColumn.Create(StringGrid1)); end; //桁の幅指定 for var i := 0 to COL_COUNT - 1 do begin StringGrid1.Columns[i].Width := Floor(StringGrid1.Width / StringGrid1.ColumnCount); end; end;

表の自前描画

Delphi11.3
procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates); var val: Integer; begin // 背景色を設定 if TryStrToInt(Value.ToString, val) then begin if (val mod 33) = 0 then Canvas.Fill.Color := TAlphaColors.Red else Canvas.Fill.Color := TAlphaColors.White; end; // 背景描画 Canvas.FillRect(Bounds, 0, 0, [], 1); // テキストを描画(テキストの色や位置を調整することもできます) Canvas.Fill.Color := TAlphaColors.Red; Canvas.Fill.Color := TAlphaColors.White; // テキストの色 Canvas.FillText(Bounds, Value.ToString, False, 1, [], TTextAlign.Leading, TTextAlign.Leading); end;

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;

IDEで表を作る

VCLならColumnCount,RowCount使えばよいが、FMXには無い。
TStringGridを右クリックして「TStringColumnの追加」を行うと、桁を増やせる

証明書

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ってこんなの。

Home New Help Edit
2024-08-14 11:00:24 32400