プレゼンテーション資料 TRACK B 第23回 エンバカデロ・デベロッパーキャンプ 2012年 9月 4日 (火 ) UDX GALLELY NEXT(東 京 /秋 葉 原 ) Program 10:00~11:00 【A1】 Delphi テクニカルセッション 【B1】 C++テクニカルセッション 「Delphi 2009 Handbook 以降の Delphi 言語 新機能」 配布資料あり 「業務で使える!C++実践ワンポイントテクニック」 スピーカー: スピーカー: 配布資料あり 福士 光 服部 励起 東洋テクニカルシステム株式会社 システム開発部 アナハイムエンジニアリング株式会社 代表取締役 15 年来の Delphi ユーザ。 Delphi-ML(http://www.freeml.com/delphi-users)や公式フォーラム に生息しています。 Delphi 1.0γ 版(Windows 3.1) や Borland C++(MS-DOS)を使って業 務系システム開発を始め、1990 年代はメーリングリスト等で積 極的に普及活動を行なっていました。最近では株式会社フ ルネ スの専属講師として、Delphi や C++ Builder の研修講師を務めつ つ、iOS や Android のアプリ開発も行っています。 11:15~12:15 【A2】 HTML5 テクニカルセッション 【B2】 Delphi テクニカルセッション 「HTML5 アプリ開発入門」 「見た目で楽しい Delphi プログラミング」 配布資料あり スピーカー: 配布資料あり スピーカー: 高橋 智宏 細川 淳 エンバカデロ・テクノロジーズ エヴァンジェリスト 株式会社シリアルゲームズ 取締役・シニアエンジニア Java、 Delphi、 C++など幅広いプログラミング言語の知識と CORBA や J2EE をはじめとするシステム開発に関するコンサル ティングサービス提供の豊富な経験を持つ。技術力に裏付けら れたそのサービスには定評がある PostPet V3 Windows 版の開発に関わるなど、主にエンターテイン メント/コミュニケーション系ソフトウェアの開発を行う。高 校時代に Turbo Pascal に触れたばっかりに、今では立派な? Delphi 使いに。VM やスクリプト言語全盛の中、ネイティブ・ア プリケーションの復権を目指し活動し つつも、最近は Android のプログラムを書いたりもしています。 13:30~14:30 【G3】 Delphi/C++Builder テクニカルセッション 「RAD Studio XE3 の概要」 スピーカー: デビッド・インターシモーネ エンバカデロ・テクノロジーズ チーフエヴァンジェリスト David I (デビッドアイ)の愛称で知られるデビッド・インターシモーネは、エンバカデロ・テクノ ロジーズのチーフエヴァンジェリストとして、エンバカデロ・テクノロジーズをリードしています。 1985 年プロダクト・サービス・ディレクターとしてボーランドに参画以来、言語・ツールの研究お よび開発に従事。ボーランド入社以前は、Softsel Computer Products Inc.(現 Merisel)のプロダクト・ サービス・ディレクターとして活躍していました。2008 年、エンバカデロ・テクノロジーズによる CodeGear 事業本部の買収により、同社に移籍し、現在に至ります。カリフォルニア州立ポリテクニ ック大学サン・ルイス・オビスポ校でコンピュータサイエンス学士号を取得しています。 14:45~15:45 【A4】 Delphi テクニカルセッション 【B4】 C++Builder テクニカルセッション 「Delphi+IntraWeb+FastReport による Web、モバ イル、タブレットアプリ開発」 「 FireMonkey クロス開発テクニカルエッセンス アニメーションデータ作成ツール開発事例から」 配布資料あり スピーカー: 配布資料あり スピーカー: 山本 悟 橋本 孔明 株式会社ドリームハイブ 代表取締役 IT コンサルタント 株式会社ウェブテクノロジ R&D 1 部 職業、IT コンサルタント。メンドウクサイを IT の力でラクチンに 変えるプロフェッショナルです。 1978 年東京都目黒区生まれ。 母はデザイナー、父は写真家。大学卒業後、就職せずに株式会社 ドリームハイブを設立、今年 11 期目を迎えました。多くの企業様 から 相談を受ける「課題を IT で解決するプロ」として、700 回 を超えるセミナー講演や、多数のサービスを提供しています。 弊社デスクトップアプリケーション全般の開発に携わっている ほか、さまざまなプラットフォームおよび開発環境の技術検証 の担当も行っています。 16:00~17:00 【A5】 Delphi/C++Builder テクニカルセッション 【B5】 Delphi/C++Builder テクニカルセッション 「RAD Studio XE3 の新機能」 「 FireMonkey モバイル/タブレットアプリ開発」 配布資料あり スピーカー: スピーカー: デビッド・インターシモーネ 高橋 智宏 エンバカデロ・テクノロジーズ チーフエヴァンジェリスト エンバカデロ・テクノロジーズ エヴァンジェリスト J 17:15~18:15 【G6】 ライトニングトーク 「共有!みんなの開発事例、開発経験、テクニック」 司会: はやし つとむ アナハイムテクノロジー株式会社 代表取締役 本日のセッション資料の最新版ならびに配布資料に含まれないプレゼンテーション資料については、 後日 Embarcadero Developer Network 日本語版(http://edn.embarcadero.com/jp) からダウンロードいただけます。 17Th Developer Camp 【B1】テクニカルセッション 「業務で使える! C++実践ワンポイントテクニック」 アナハイムエンジニアリング株式会社 代表取締役 服部励起 1 17Th Developer Camp 1 エンジニアとして 「都市伝説!?」 2 4 「業務で使える!C++実践ワンポイントテクニック」 近頃!?の見たり聞いたり • • • • • • • • 「周りの技術レベルが低い」 「改修よりスクラップアンドビルドが効率的」 「オブジェクト指向だから開発工数が削減できる」 「アジャイル開発なので各種標準化は不要」 「ソースコードレビューは不要(出来ない)」 「ドキュメントよりもソースコードが重要」 「インデントが無いソースコードの方が読み易い」 「コピペしただけなので、バグは作成元に責任があり私 では無い」 プロフェッショナルの仕事では無い それなら私がやるしか・・・ B1 3 (;´∀`) • 技術指向より業務指向 – ハイテクニック依存は属人的になりやすい – 組織全体としての効率化とそのテクニック中心 • プロフェッショナルとは何か? – ソフトウェア品質特性 – 特に保守について • C++言語特性を再確認 – 業務的視点から見たメリットとデメリット 4 5 17Th Developer Camp 2 集団開発技術として 「業務指向開発!?」 5 技術指向と業務指向 • 技術指向とは – – – – 理解できる人のみ理解できれば良い 華麗なテクニックや最新ライブラリ等を駆使 自分が頑張って勉強したので、他人も同様の努力を要求 コメントは極力少ない傾向 • 業務指向とは – – – – 組織としての最大の効果を常に考える 技術レベルは、8割が理解できるレベルで統一 他人がソースを読むことを常に念頭に 仕様変更を念頭にクラス設計を 6 6 「業務で使える!C++実践ワンポイントテクニック」 業務指向の効果とは • 技術指向の罠は、属人化 B1 – 担当した仕事の保守は、概ね元担当者へ (会社側は新たな仕事を担当させられない事に) – 属人的ソースコードの行方はスクラップアンドビルド (スクラップアンドビルドの非効率工数は誰が支払う?) – 但し、ソフトウェア寿命がワンオフなら話は別 • 業務指向では他人に任せられる点 – 面倒な保守は新人等に担当させたい – 転職時にも面倒な引き継ぎ期間の短縮 – 特に複雑な部分をブラックボックス化する等の柔軟性も 7 17Th Developer Camp 3 プロフェッショナルとして 「期待される特性」 8 7 ソフトウェア品質特性(ISO9126) • • • • • • • 機能性:要求通り実装されている等 信頼性:バグが少ない等 使用性:使い易い等のUX 効率性:レスポンス等 保守性:保守する場合の対応等 移植性:環境変更時の対応等 セキュリティ:機能性の一部 要件定義に記載 非機能要件と呼ばれる内容! 9 Note. 移植性の補足 • 移植性の構成要素 – 環境適応性 • インストール先変更しても問題が発生しない – 設置性 • インストールのしやすさ等 – 共存性 • 複数のソフトウェア同士で、共存することによる問題点回避 – 置換性 • ソフトウェアの依存度や他ライブラリバージョン依存の回避 ソフトウェアアーキテクチャでの対応 10 8 「業務で使える!C++実践ワンポイントテクニック」 Note. 保守の重要性 • ソフトウェア目標寿命まで運用できること • 保守工数がソフトウェアライフサイクルの大半を占める B1 – 氷山に例えられることも • 氷山は海上は全体の10% 海面下は90% • 初期開発工数は10%で、 保守工数は90% – 保守工数を削減し利益へ貢献 • 経営環境が迅速に変化している ため、ソフトウェア保守に時間を 割くことが難しくなっている 11 参照: http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Iceberg.jpg Created by Uwe Kils (iceberg) and User:Wiska Bodo (sky). Note. 保守の重要性 • オブジェクト指向技術 – 保守工数の削減に利用を主眼に置き、開発工数削減を 狙うと失敗する危険性が高い • クラス設計や構成等は十二分に検討 • ソースコードに対する技術不足 – 他人のソースコードを読み、理解し、推測できる技術が特 に重要 – 優れたオープンソースを読む訓練は役に立つ 12 9 保守性の構成要素に対応するテクニック • 解析性 – コーディング規約全般、命名規約、コメント規約 – 標準化運用ルール ※リバースエンジニアリングツールを過信してはダメ • 変更容易性 – コーディング規約全般、クラス設計標準 – 各種ドキュメント • 試験性 – ソフトウェア変更標準 – ユニットテスト 13 17Th Developer Camp 4 C++の言語特性 14 10 「業務で使える!C++実践ワンポイントテクニック」 マルチパラダイムプログラミング言語 • 構造化プログラミング B1 – 階層的に抽象化されたプログラム記述形式 • 命令型(手続き型)プログラミング – プロシージャ、ルーチン、サブルーチン、メソッド (グローバル関数・変数) • オブジェクト指向プログラミング – オブジェクトの集まりとしてプログラムを構成 (C++標準) • ジェネリックプログラミング – データ形式に依存しないプログラミング方式 (C++テンプレート機能) 15 マルチパラダイムプログラミング言語 • マクロ – テンプレートはマクロの発展系 – C++では問題点も多いと指摘されることも • 演算子のオーバーロード – 演算子を別の処理にコンパイル時に置き換える – iostreamでは普通に使われている「<<」等 16 11 C++の歴史 規格制定日 C++ 標準規格 非公式名称 1998年9月1日 ISO/IEC 14882:1998 C++98 2003年10月16日 ISO/IEC 14882:2003 C++03 2007年11月15日 ISO/IEC TR 19768:2007 C++TR1 2011年9月1日 ISO/IEC 14882:2011 C++11 • 言語仕様が変遷しており、今後も変更される • 関数型プログラミングも今後取り込む予定 • 恐らく前方互換性を持たせるため、旧規格で作成しても 問題は無い • 保守業務を考えると最新技術仕様を取り込む場合には 注意が必要 17 17Th Developer Camp 5 実践ワンポイント 「標準化編」 18 12 「業務で使える!C++実践ワンポイントテクニック」 【コーディング標準】 1.クラス定義 • 1つの物理ソースファイルに、複数のクラス定義を実装 するのを是か非か B1 – 関連性が維持できるクラス定義は統合するべき。 但し、担当者が分散するケースが散見されるなら敢えて1 ファイルを1クラスにするのも一考 class HogeBase { protected: virtual int Get() = 0; virtual void Set(int st) = 0; public: HogeBase(); ~HogeBase(); }; 仮想クラスを多用する場合に は1クラスの方が見通しが良い class HogeData : private HogeBase { public: int Get(); void Set(int st); }; 19 2.メソッド行数制限と行内桁数制限 【コーディング標準】 • メンバ関数行数制限 – 最大でも200~250行 – それ以上は分割する。 但し、初期化処理は例外とする • 1行内の桁数制限 – ディスプレイサイズで決定すれば良いのかなと・・・ – 個人的には160~180桁 ※昔は80桁以内か以上で論争がありましたねぇ。 20 13 【コーディング標準】 3.カプセル化方針 • 内部変数のpublic公開について – – – – 異論はあるが、内部変数をpublic公開は禁止 getter/setterメンバ関数(アクセッサ)を利用するべき 全てのクラス内定義は、privateで作成すると便利 クラスデフォルトはprivateだが全て記述するべき class HogeBase { private: int st; protected: virtual int Get() = 0; virtual void Set(int st) = 0; public: HogeBase(); ~HogeBase(); }; DBデータを扱うクラスも、継承 してメソッドをpublicで公開する と、仕様変更時の柔軟性が上 がる。 21 【コーディング標準】 4.継承方針 • 多重継承の禁止 – 混乱と仕様変更時の柔軟性に影響 • 基底クラスを使い、継承を利用して公開する仕様も検討 してはどうでしょう? //基底クラス定義 class Calc_Base { public: Calc_Base(); ~Calc_Base(); }; // 計算クラスを継承して加算クラスを作成 class Calc_Add : private Calc_Base public: int Opereation(int data1, }; // 計算クラスを継承して減算クラスを作成 class Calc_Sub : private Calc_Base public: int Opereation(int data1, }; 14 「業務で使える!C++実践ワンポイントテクニック」 継承階層が深くなり過ぎないよ うに注意する必要はあります。 { int data2); { int data2); 22 5.コンストラクタとデストラクタ 【コーディング標準】 • 使用しない場合でも定義だけはコーディング B1 – 修正が必要となった場合に楽 • 継承時の実行順番は重要! – ①スーパークラスのコンストラクタ ②サブクラスのコンストラクタ ③サブクラスのデストラクタ ④スーパークラスのデストラクタ 23 6.パラメタ設計方針 【コーディング標準】 • 大きく分類して2種類 – getter/setterメンバ関数は欲しい結果をreturnで受け取る – returnで受け取るのは、メンバ関数が動作したbool情報と し、結果値は別メンバ関数経由で返却 • getter/setter系メンバ関数 – 結果情報を直接returnで返却する方式 class CalcAdd : private CalcBase { public: int Opereation(int data1, int data2); }; int CalcAdd::Opereation(int data1, int data2) { return data1 + data2; } 24 15 6.パラメタ設計方針 【コーディング標準】 • returnでbool値(int値も可)で動作状態判別系 – メンバ関数が正常に動作したのかをreturnで通知し、その 時メンバ関数が行なったデータは別メンバ関数(getter)で 行う class hoge { private: DB_EmpData data; public: hoge(); ~hoge(); bool getEmployee(int empNumber); //社員情報の取得メンバ関数 DB_EmpData getEmpData(); //取得した社員データ提供メンバ関数 }; 25 7.構造体・共用体 【コーディング標準】 • C++ではクラスで代用できるため、コーディング標準的 には積極的には使用しない方向で • C言語開発経験者が多いプロジェクト等ではC++でも利 用されている可能性も struct hoge { protected: int a; public: hoge(); int getA() {return a;} }; struct hoge2 : public hoge { private: int b; public: hoge2(); int getB() {return b;} }; 26 16 「業務で使える!C++実践ワンポイントテクニック」 8.演算子のオーバーロード 【コーディング標準】 • 一般的には極力控えた方が、保守性に貢献するものと 想定します。 B1 – 演算子のオーバーロードを自由自在に操れる人は少数 – 属人的になりやすいため敬遠することが賢明 • 演算子としか見えないため、オーバーロードされている と気が付きにくい。 – きちんと管理されていれば、利用することは吝かではない 27 9.マクロの扱い 【コーディング標準】 • マクロとは – コンパイラがソースコードをコンパイルする直前に、プリプ ロセッサで実行される命令群 – スコープがプロジェクト全体 – コンパイラに近い言語と言え、習熟している人は少ない • 基本的にマクロ使用は最低限度に抑え、保守性を向上 させる方針を推奨 – 関数形式マクロを使うならテンプレート化を検討 オブジェクト形式マクロ文法 #define [マクロ名] [置換文字列] 関数形式マクロ文法 #define [マクロ名](引数リスト) [置換文字列] 28 17 10.テンプレート 【コーディング標準】 • テンプレートのメリット – マクロより型安全 • テンプレートのデメリット – 移植性が低い – エラーメッセージが分かり辛い – 実行ファイルが大きくなる危険性もある • テンプレートの使用は、テンプレート関数までとし複雑に なりやすいテンプレートクラスは避ける • 特に実行時デバッグでは分かり辛いため、デバッグ効 率性かも極単機能で分り易いものだけに限定 29 10.テンプレート 【コーディング標準】 例) template <class X> int operation(X *obj, int data1, int data2) { return obj->Operation(data1, data2); } void __fastcall TMyCalc::bt_equClick(TObject *Sender) { int ans; switch(calc_kind) { case C_add: { CalcOpe_Add obj; ans = operation(obj, data1.Get(), data2.Get()); break; } case C_sub: { CalcOpe_Sub obj; ans = operation(obj, data1.Get(), data2.Get()); break; } } Panel1->Caption = IntToStr(ans); 30 18 「業務で使える!C++実践ワンポイントテクニック」 11.define, const, typedef 【コーディング標準】 • defineはマクロのため、コンパイル時に置き換え • constは修飾子のため、全てに使用可 • typedefは変数の型を独自に定義 B1 • マジックナンバーはdefineかconstで定義しておく – constは型を指定できるため、こちらを推奨 – スコープはdefineは全体。constはソース定義範囲。 const int MAX_ARRAY_SIZE = 3000; #define MAX_ARRAY_SIZE 3000 typedef int myInt16; #define myInt16 int //myInt16という型を定義 //typedefと同じ効果を持つ 31 12.constメンバ関数 【コーディング標準】 • メンバ関数に付与することで、その関数内でメンバ変数 の値を変更しない – getterメンバ関数等で使うと非常に便利 class constClass { int i_test; const int MAX_SIZE; mutable int m_test; //mutableを使うとconst中でも変更可だが・・・ public: constClass() : MAX_SIZE(10) {} //コンストラクタで初期化 int getMaxSize() const { //constメンバ関数 m_test = 3; // i_test = 10; コンパイルエラー // MAX_SIZE = 20; コンパイルエラー return(MAX_SIZE); } }; 32 19 12.各種命名規約 • 組織等で分り易い記述形式にし、変数からメソッド、クラ ス名、例外エラークラス等ざっくりとでも決定 • ハンガリアン記法 – データ属性を小文字の接頭語として使用 • キャメル記法 – 単語の区切りを大文字を利用する // ハンガリアン記法 int iCount; char cName[10]; // キャメル記法 std::string lastName; //ローワーキャメルケース std::string FirstName; //アッパーキャメルケース 33 13.コメント規約 • ファイルコメント – .cppや.hファイルの先頭に、作成者やファイルの概要や 名前、修正履歴等を記入 (ドキュメントの不備等に対応させる目的) • クラス・メソッドコメント – クラス定義部と各メソッド実装部に、簡単でも目的 – 実装でトラブルがあった場合、トラブル内容等を簡易に記 述する • 実装コメント – 例外処理や、規約違反している場合の詳細説明、実装に 苦労した内容等を詳細に記載 34 20 「業務で使える!C++実践ワンポイントテクニック」 17Th Developer Camp B1 6 実践ワンポイント 「ツール編」 35 1.ユニットテストの活用 • テストプロジェクトの追加 36 21 1.ユニットテストの活用 • テストケースの追加 37 2.GExpertsの活用 • GExperts – 機能が多すぎで分かりません。 (^^;; – Editor Experts • エディタの補完を行ってくれます – Grep Results/Grep Search • プロジェクト全体のGrepも出来ます – Procedure List • 今開いているファイル内の関数一覧 http://www.gexperts.org/ 38 22 「業務で使える!C++実践ワンポイントテクニック」 17Th Developer Camp 【B2】Delphi テクニカルセッション 「見た目で楽しい Delphi プログラ ミング」 B2 会社名 株式会社シリアルゲームズ 名前 細川 淳 1 アジェンダ • VCL / FireMonkey のスタイルの触りを紹介します • VCL スタイル – TStyleManager • FireMonkey スタイル – TStyleBook 2 23 17Th Developer Camp VCL スタイル 1 3 VCL スタイル • Delphi XE 以前 – TThemeServices • OS が提供する「テーマ」を利用するクラス • Windows XP Style (Luna など)に対応するために追加されました • ※XE2 以降でも依然として利用可能 • Delphi XE2 以降 – TStyleManager • VCL / FireMoneky に新しく追加された「スタイル」を利用するクラス • スタイルを利用すると、OS のビジュアル(見た目)から解放されます →特にマルチプラットフォームである FireMonkey において重要 4 24 「見た目で楽しい Delphi プログラミング」 VCL スタイルの一番簡単な使い方 好きなスタイルにチェックを入れる ※スタイルを1個でも追加すると120[KB]程 ファイルサイズが増加し、スタイル一個につき ファイルサイズが40~60[KB]増加する B2 デフォルトのスタイルを選ぶ たったこれだけ! 5 17Th Developer Camp VCL スタイルを 適用する デモンストレーション 6 25 17Th Developer Camp 1 VCL スタイルを プログラムから使う 7 VCL スタイル - TStyleManager • TStyleManager.TrySetStyle – スタイルを設定するメソッド – とりあえずこのメソッドさえ知っていればスタイルの適用は 可能 procedure TForm1.Button1Click(Sender: TObject); begin TStyleManager.TrySetStyle('Amakrits'); // スタイルの名前 end; 8 26 「見た目で楽しい Delphi プログラミング」 VCL スタイル - TStyleManager • TStyleManager.StyleNames – 使用可能なスタイルを返すメソッド procedure TForm1.Button2Click(Sender: TObject); var StyleName: String; begin for StyleName in TStyleManager.StyleNames do ListBox1.Items.Add(StyleName); end; B2 名前をリストアップして、それを適用します procedure TForm1.Button3Click(Sender: TObject); begin // SetStyle は内部で TrySetStyle を呼び出し、失敗すると例外をあげる if (ListBox1.ItemIndex > -1) then TStyleManager.SetStyle(ListBox1.Items[ListBox1.ItemIndex]); end; 9 17Th Developer Camp VCL スタイルを プログラムから 適用する デモンストレーション 10 27 17Th Developer Camp 1 VCL スタイルを自分で 作ってみる 11 VCL スタイル - VCL スタイルデザイナ 自分でスタイルを作成する場合、VCL スタイルデザイナを使います。 12 28 「見た目で楽しい Delphi プログラミング」 VCL スタイル - VCL スタイルデザイナ • スタイルは基本的に各部分部分を表す画像で提供され ます – ゲームのように一枚の画像からパーツを切り出して使い ます B2 • 設定項目が多い! – 自分のスタイルをゼロから作ろうと思っても挫折します – 既存のスタイルを修正していくと良いでしょう 13 VCL スタイル - VCL スタイルデザイナ 一枚の画像に全ての構成要素をいれます 選択部分が 反映されています 14 29 VCL スタイル - VCL スタイルデザイナ スタイルデザイナ上 で確認できます 15 17Th Developer Camp VCL スタイル スタイルデザイナの デモ 16 30 「見た目で楽しい Delphi プログラミング」 VCL スタイル - 自作スタイルの使い方 まず Object のトップのプロパティを 設定しておきます Name プロパティがスタイルの名前になります B2 17 VCL スタイル - 自作スタイルの使い方 • TStyleManager.LoadFromFile – スタイルファイルを読み込むメソッド procedure TForm1.Button2Click(Sender: TObject); begin TStyleManager.LoadFromFile('C:¥Temp¥TestStyle.vsf'); TStyleManager.TrySetStyle('TestStyle'); //スタイルデザイナで設定した名前 end; 18 31 VCL スタイル - 自作スタイルの使い方 • TStyleManager.IsValidStyle – スタイルファイルの正当性チェック&スタイル情報取得 procedure TForm1.Button2Click(Sender: TObject); var StyleInfo: TStyleInfo; begin if (TStyleManager.IsValidStyle('C:¥Temp¥TestStyle.vsf', StyleInfo)) then with StyleInfo do 実行結果 ShowMessage( Name + sLineBreak + Author + sLineBreak + AuthorEMail + sLineBreak + AuthorURL + sLineBreak + Version ); end; 19 17Th Developer Camp VCL スタイル スタイルファイル 読み込み デモ 20 32 「見た目で楽しい Delphi プログラミング」 17Th Developer Camp 1 VCL スタイルを使用する コントロールの作成 B2 21 VCL スタイル - コントロールの作成 一番単純な方法は Paint メソッドや WM_NCPAINT, WM_PAINT に応えて自分で実装 します。 procedure TForm1.PaintBox1Paint(Sender: TObject); var DC: HDC; R: TRect; begin DC := PaintBox1.Canvas.Handle; R := PaintBox1.ClientRect; ノーマル状態のボタンを描画する例 StyleServices.DrawElement( DC, StyleServices.GetElementDetails(tbPushButtonNormal), R); StyleServices.DrawText( DC, StyleServices.GetElementDetails(tbPushButtonNormal), 'TEST CAPTION', R, TTextFormatFlags(DT_CENTER or DT_VCENTER or DT_SINGLELINE), StyleServices.GetStyleFontColor(sfButtonTextNormal)); end; 22 33 VCL スタイル - コントロールの作成 • 一般的に、VCLスタイルの描画は TStyleHook を使い ます。 – TStyleHook とは TStyleManager から呼び出されコント ロールの描画を担います。 – WM_PAINT や WM_NCPAINT などを「フック」して、それ らの応答をコントロールに変わって実行します。 – ただし、OS 標準スタイル時の描画には使われません • 標準のスタイル時は、従来と同様に、コンポーネントの Paint メソッドなどで処理されます。 23 VCL スタイル - TStyleHook の実例 unit uTestControl; interface uses Winapi.Windows, Vcl.Controls, Vcl.ExtCtrls, Vcl.Graphics, Vcl.Themes; type TTestControl = class(TPanel) private class constructor Create; // クラスコンストラクタは initialization に追加するのと同じ end; implementation type TTestControlStyleHook = class(TStyleHook) protected procedure Paint(Canvas: TCanvas); override; public constructor Create(iWinControl: TWinControl); override; end; 24 34 「見た目で楽しい Delphi プログラミング」 VCL スタイル - TStyleHook の実例 { TTestControl } class constructor TTestControl.Create; begin // StyleHook とコントロールを結び付けます TCustomStyleEngine.RegisterStyleHook(TTestControl, TTestControlStyleHook); end; B2 { TTestControlStyleHook } constructor TTestControlStyleHook.Create(iWinControl: TWinControl); begin inherited; OverridePaint := True; // Paint メソッドをフックしますよ、という意味 end; procedure TTestControlStyleHook.Paint(Canvas: TCanvas); begin // TTestControl の Paint の代わりにこちらが呼ばれる (ノーマル状態のボタンを描画する例と同様のため中略) end; end. 25 VCL スタイル - TStyleHook の実例 Windows 標準時 TTestControl が継承している TPanel の標準の見た目が描画 される VCL スタイル適用時 TTestControlStyleHook がスタイルに応じた見た目を描画する 26 35 17Th Developer Camp VCL スタイル TStyleHook デモ 27 17Th Developer Camp 1 FireMonkey スタイル 28 36 「見た目で楽しい Delphi プログラミング」 FireMonkey スタイル • FireMonkey のスタイルは VCL スタイルとはまったく異 なります。 – 個々のコントロールがスタイルを持っている B2 • TStyledControl を継承したコントロール • 個別に設定できる – スタイルは TStyleBook で管理される • TStyleBook で定義済みのスタイルリソースを読み込むと スタイルを一括で変更できる 29 FireMonkey スタイル • 一番簡単な使用方法は… – Form に TStyleBook コンポーネントを貼る – TStyleBook コンポーネントの「Resource」プロパティをク リックしてスタイルエディタを開く – スタイルエディタから定義済みスタイルを読み込む – 「適用して終了」を押す 30 37 FireMonkey スタイル 簡単な設定方法 スタイルエディタを開く 定義済みスタイルを開く 31 FireMonkey スタイル - コンポーネント毎 • 個々のコンポーネントごとに編集する方法は… – コンポーネントを右クリックして – 「カスタムスタイルの編集」「デフォルトスタイルの編集」の どちらかを選ぶ – スタイルエディタが開く – 「適用して終了」を押す ※個々のコンポーネントのスタイルを編集すると、自動的に TStyleBook コンポーネントのインスタンスが生成される 32 38 「見た目で楽しい Delphi プログラミング」 FireMonkey スタイル - コンポーネント毎 スタイルエディタを開く B2 スタイルの要素のプロパティは オブジェクトインスペクタに表示され 編集可能 33 FireMonkey スタイル - コンポーネント毎の例 • フォーカス時に使われる TGlowEffect の色を変えてみる GlowEffect の色 GlowEffect が発動するトリガー ほかにも IsMouseOver などがある GlowColor を「Crimson」($DC143C) に変更 34 39 FireMonkey スタイル - StyleLookup • コンポーネントの StyleLookup プロパティを設定すると デフォルトのスタイルを変更できます。 – StyleLookup プロパティは、このコントロールが使うスタイ ルの名前です。 – このプロパティが設定されると FindStyleResource メソッ ドによって適切なスタイルが設定されます。 35 FireMonkey スタイル - StyleLookup • TPanel の StyleLookup を変更して見た目をボタンのようにしてみます。 36 40 「見た目で楽しい Delphi プログラミング」 17Th Developer Camp FireMonkey スタイル デモ B2 37 17Th Developer Camp 1 FireMonkey スタイル そのほか 38 41 FireMonkey スタイル • スタイルの個々の要素をプログラムから変更することができます(本当は) • 現状では小細工しないと変更できません – Delphi XE2 Update4 で確認(QC100275 既に Closed) – これについては、EDN TeamJapan の高橋さんのブログ記事が詳しい です • http://blogs.embarcadero.com/teamj/2011/11/11/2589/ 上記記事より引用 FireMonkeyのコンポーネントのFindStyleResourceメソッドを呼び出して、スタイルにア クセスしようとしますが、なぜかnil(見つからなかったということ)が返ってきてしまいま す。 この問題(現象)はQualityCentralにも報告されたのですが、トップレベルのスタイルの 場合、親クラスである「TStyleControlクラスのprotectedなメンバであるFResourceLink」 にアクセスする必要がある(As Designed, 仕様)という結果になりました。 39 17Th Developer Camp 1 付録:UI 設計の指針 40 42 「見た目で楽しい Delphi プログラミング」 UI 設計の指針 • VCL / FireMonkey スタイルを利用することで OS の見た目から解放さ れます。 • しかし、OS の UI から解放されるわけでありません。そのため OS で提 供されている一般的な操作が犠牲になる場合があります。 – 例として • Flash (Air) B2 – Win / Mac / Linux で動作するが、一般化のためにコンテキストメニューが廃 止されている • Unitiy – Android / iOS などで動作するが、一般化のために「戻るボタン」による Activity 遷移がサポートされていない • FireMonkey の場合は特に OS の提供する UX の犠牲を最小限にとど める必要があります。 • VCL は Windows アプリケーションとなりますが、見た目が自由になった からといって、独自すぎる UI を提供すべきではありません。 41 UI 設計の指針 - 一般的論としての UI • 視線は左から右、上から下に流れる 視線の流れ このコンテキストで一般的な動作は右側に イリーガルな操作は左側に。 ←ここには視線が最後にたどり着く 左上から見ていって、途中に問題がない事を確認していくので、 UI の右下に「OK」や「確認」といったボタンがある 上記原則に反するが、Windows は MacOS との類似を避けるためにOK ボタンを左にした FireMonkey の場合は、MacOS に合わせるか、Windows に合わせるかはメインターゲットによる。 もしくは、プログラムで動的に変更する 参考として Android は 2.x までは左側、3.x からは右側に変更されている 42 43 UI 設計の指針 - 一般的論としての UI • 視覚効果は感覚に合わせる – グレーアウトされていれば押せない • MouseOver で凹むボタンなど言語道断 – 感覚としてボタンは押されると凹むもの – 曖昧なアイコンは使わない グレーアウトされているボタンは押せない。 マウスオーバーするとグレーが解除されたり、 ポップアップしたりして押せる事をアピールする 変な動作がウェブにあふれていますが、間違い。 このアイコンをクリックすると起きるアクションは? ・音がOFFになる ・音がONになる どっち? 43 UI 設計の指針 - 一般的論としての UI • その UI で正しいかどうか考慮する – – – – TComboBox と ListBox TLabel と TImage TMainMenu と TPopupMenu etc. 都道府県の選択の場合、 どの UI が正解だと思いますか? 44 44 「見た目で楽しい Delphi プログラミング」 UI 設計の指針 - その他の事 ターゲット UI はターゲット層で決まる ターゲット層 ターゲットデバイス ターゲット UI B2 色覚異常への対応 それぞれが判別可能か? ユーザビリティテスト 独りよがりな UI になっていないか? 45 17Th Developer Camp 1 質疑応答 46 45 17Th Developer Camp 【B4】 C++Builderテクニカルセッション 「FireMonkeyクロス開発テクニカ ルエッセンス - アニメーションデー タ作成ツール開発事例から」 株式会社ウェブテクノロジ R&Dグループ 橋本 孔明(Yoshiaki Hashimoto) 1 はじめに 本日は ご来場いただき ありがとう ございます 2 46 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 自己紹介 橋本 孔明(はしもと よしあき) hashimoto@webtech.co.jp ‒ 経歴 • 勘違いからPC入門と同時にプログラミング入門 • 中高生時代、VC++、Delphiなどいろいろな環境で オンラインソフトを作っていたことがきっかけで入社 ‒ 現在 • Windows・Mac・スマートフォンなどなんでも手がける • プロダクト開発のほか、各種プラットフォームおよび 開発環境の調査や導入決定などにも携わる • 基本的にC++屋(STL/Boost/C++11などを多用) B4 ‒ その他 • 趣味人間(鉄道、釣り、アクアリウムとか) 3 会社紹介 - 株式会社ウェブテクノロジ 各種製品・サービスの企画・開発・販売・サポート – 画像最適化ツール『OPTPiX imésta』 ゲーム業界国内シェア100% – スプライトアニメーション作成ツール『SpriteStudio』 – 携帯電話向け画像最適化ASP『OPTPicture』 – 絵を描かずにマンガが作成できる『コミPo!』 受託開発 – 大手電機メーカー向け データ放送用画像変換モジュール – 大手コンテンツプロバイダ向け 高機能画像変換システムの提供 – 大手光学機器メーカー 複合機内蔵PDF生成用減色モジュールの提 供 4 47 アジェンダ 1. 2. 3. 4. 5. 6. ソーシャル開発におけるプラットフォームの変遷 「SpriteStudio」の紹介 クロスプラットフォーム開発環境の模索 C++Builder XE2&FireMonkeyとの出会い FireMonkey苦労話(今回のメイン) まとめ 5 17Th Developer Camp 1 ソーシャル開発における プラットフォームの変遷 6 48 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 ソーシャル開発環境の変遷 ‒ ソーシャルゲーム:iOSデバイス、Androidデバイス などで動作するゲームの呼称 • 必ずしもネットワーク要素を含まない ‒ 従来、ゲームプログラム開発はWindows環境が 主流 ‒ iOSの台頭により、MacOS X上での開発が必須に ‒ MacOS X上ではAndroid開発(Eclipse)も行える B4 ‒ すべてをMac上で済ませるベンダーが増えた ‒ 開発ツール類のMac対応要望が増加 7 17Th Developer Camp 2 「SpriteStudio」の紹介 8 49 SpriteStudioとは(1) SpriteStudio(スプライトスタジオ)は、汎用的なアニメーションデータ作成ツールです。 「イベントデータ」の 編集と管理 ドラッグ&ドロップなど の簡単な操作 キーフレーム方式で 楽に編集 トラッキングモードに よるキーフレーム化 タイムチャートによる 視覚的な管理 動きを組み合わせる シーン編集モード SpriteStudio SDK ソフトがなくても 確認できるビューア for Designers •ドラッグ&ドロップなど直感的な操作で、 アニメーションデータの作成が可能に •タイムチャートとグラフでアニメーション データを視覚的に管理 for Programmers •動きを付ける作業をデザイナに任せる ことにより、負担が軽減 •SDKを使って、アニメーションデータの コンバータにも簡単に作成可能 for All Developers •SpriteStudioが、アニメーションの 開発効率を向上させる! http://www.webtech.co.jp/spritestudio/ 9 SpriteStudioとは(2) ‒ スプライトアニメーション編集ツール ‒ 著名コンシューマーゲーム、ソーシャルゲーム等 での採用事例多数 10 50 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 SpriteStudioとは(3) ‒ リリース中のバージョンはWindows専用 • VC++、ネイティブC++およびWin32 APIで開発 ‒ MacOS Xにて、仮想環境上のWindowsによる 動作も可能だが… ‒ Mac版の要望を多数頂戴 ‒ 開発決定 B4 11 17Th Developer Camp デモンストレーション SpriteStudio 開発途上版 12 51 17Th Developer Camp 3 クロスプラットフォーム 開発環境の模索 13 要件定義 ‒ MacOS XとWindowsのGUIの違いを吸収したい • メニューバー位置などはOSネイティブに合わせたい ‒ OSネイティブではなく、ダークグレーベースの外観 としたい • 他のデザイナー向けプロフェッショナルツールでも導入事 例が多い(Adobe CS6、3Dツールなど) • 見た目が良いというだけではなく、デザイナーの長時間利 用に耐え、目に優しい色遣いとなっている ‒ プロフェッショナルユースに耐えうるUX設計 ‒ 社内ツールや簡単なフリーソフトなどとは違います 14 52 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 クロスプラットフォーム開発環境の模索 いくつかの候補を調査 ‒ C/C++&ネイティブAPI ‒ Mono ‒ Qt ‒ wxWidgets ‒ C++Builder XE2 ※主観がかなり入っています B4 15 C/C++&ネイティブAPI ○ UIはそれぞれのプラットフォームに合わせて細かく 設計可能 ○ 確実な開発環境(VC++/Xcode)の存在 × 標準コントロールのみを使用していると「古くさい」UI になる(特にWindows) × 標準コントロールのカスタマイズが難しく、なんでも かんでも自作していく羽目に • 昔は実際にやっていましたが… × MacOS Xネイティブ開発技術の習得 • ただしiOS学習である程度のObjective-Cの知識有り 16 53 Mono C#および.NETを用いたクロス対応開発環境 IDEとしてMonoDevelopを使用 ○ ○ × × × C#でRAD風の開発が可能(Windows Forms) .NET(Windows Forms)開発知識が転用可能 .NETの最新潮流であるWPFは使用できない UIがOSネイティブに準じてカスタマイズしにくい 中間コードで出力されることによるソフトウェア プロテクトへの不安 17 クロス対応GUIフレームワーク C++で記述可能なGUIフレームワーク (Qt、wxWidgetsなど) ○ C++やネイティブAPIが使用できる × 商用サポートを受けるためにはライセンス料金が 高額だったり、そもそもサポートが無かったり × 他はネイティブと同じデメリット × 日本語情報の不足(微妙に不安) × 試そうとしたがビルド環境構築(OSX)で挫折 18 54 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 C++Builder XE2 実は当初候補に入っておらず、他のダメ出しをした 後で存在を思い出し、検討を開始 ○ C++で開発可能 ○ 昔のVCLの知識が役立つ? ○ Windows上で同時開発し、MacOS Xプログラム のデバッグがリモートで可能 ○ 柔軟なGUI設計が可能 × Mac開発の実績がいまいち不明 B4 19 17Th Developer Camp 4 C++Builder XE2& FireMonkey との出会い 20 55 試用版でFireMonkeyプラットフォームを学習 ‒ Delphi/C++Builderの知識はVer6くらいで 止まっていた&かなり忘れていた ‒ 久々に起動したC++Builderはすっかり変わって… ‒ FireMonkeyプラットフォームはVCLの面影がなんと なく残っていた ‒ スタイル編集により、GUI要素の外観カスタマイズ が自在→これはいけそう 21 早速開発に着手 ‒ アプリケーションの性格上、いきなりOpenGLの 導入など高度な要素から挑戦 • 後から「無理」と判明すると困る ‒ 買って数日でランタイムライブラリの内部を覗いたり する羽目に… • C++Builder単体より、ランタイムソースの付いている RAD Studioを持っていた方がよさそう ‒ ランタイムはDelphi製 ‒ 忘れかけていたDelphi言語知識をなんとか思い出す 22 56 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 17Th Developer Camp 5 FireMonkey 苦労話 (今回のメイン) B4 23 注意事項 ‒ ‒ ‒ ‒ 基礎知識的なものは省略します 独自調査に基づく項目が多く含まれます 他開発環境(VC++)からの移行も重視しています 弊社の開発スタイルの都合に合わせるための対策 も含まれます • 実際には別の解決策があったり、公式には他の方法が 推奨されている可能性があります ‒ XE3になると解消する問題もありそうです ‒ WindowsをWin、MacOS XをOSXと省略 24 57 17Th Developer Camp C++環境レベルでの 違い 25 C++環境レベルでの違い(1) • ビルド分けしたい場合 – #ifdef __APPLE__ でOSXを識別 – #ifdef _WIN32(#ifdef _WINDOWS) でWinを識別 – Winのx64では_WIN64が加わります(_WIN32も存在) • CRT関数の違い – Windowsで使われるwcscpy_s()などがOSXには無い • OSXはPOSIX準拠+α 程度のCRT関数しか無い • VC++などで書いたコードの移植時に注意 • 汎用処理はRTLの機能か、STL・Boostに頼る 26 58 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 C++環境レベルでの違い(2) • Win32構造化例外はOSXにはありません – アクセス違反などはシグナルハンドラで捕まえます – 他コンパイラでtry-catchを流用していたコードも注意 • Boostの一部機能が使えない(XE3で解消?) – OSXではスタティックライブラリを要するBoostコンポーネ ントの大半が使用不可能(ヘルプに記載はあったが…) – serialization、filesystemなど B4 • 文字列リテラルの文字コード – Windowsはシステム依存、OSXは基本的にUTF-8 – この問題は深いので各自研究してください 27 C++環境レベルでの違い(3) wchar_tの違い(公式でも解説されている) ‒ Winでは2bytes、OSXでは4bytes ‒ UnicodeString(String)型、WideChar型はどちらのOSでも 2bytesベース ‒ このためOSXではwchar_tを使用するCRT関数・ std::wstring・Boostなどへのアクセスが不便 ‒ UnicodeStringからstd::wstringへの変換関数を自前で用意 しました(ただし重そう) ‒ テンプレートにWideCharを適用した型を自分で定義して使う 方法もある ‒ std::basic_string、boost::basic_formatなど 28 59 コードサンプル inline std::wstring wstring_from_UnicodeString( const UnicodeString& str) { #ifdef __APPLE__ return (wchar_t*)PUCS4Chars( UnicodeStringToUCS4String(str)); #else // 手抜き。将来のiOSやAndroidを考えると非推奨 return str.w_str(); #endif } 29 C++環境レベルでの違い(4) L”hello” と u”hello” と _D(”hello”) ‒ L”hello”はWinで2バイト文字、OSXでは4バイト文字 • 厳密にはwchar_tの配列(環境ごとにサイズ可変) ‒ u”hello”はOSXでも2バイト • 厳密にはchar16_tの配列(C++11で導入) • char16の名の通り、どんな環境でも「最低」2バイト • 大文字のU””にするとchar32_t ‒ _D(”hello”)にするとどちらでも2バイト • UnicodeStringに渡すならとりあえずこれがいいらしい • マクロなので何かあっても後で再定義すればいい 30 60 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 17Th Developer Camp OSネイティブAPI の 呼び出し B4 31 OSネイティブAPIの呼び出し ‒ FireMonkeyだけでも結構なものは作れる ‒ 細かいユーザーインターフェースの改良にはどうし てもネイティブAPIのサポートが必要となる ‒ SpriteStudioの場合、アニメーション再生に OpenGLが必要となった ‒ OSXのネイティブAPIはObjective-Cだが…? 32 61 OSネイティブAPIの呼び出し:Windows ‒ 大半がただの関数なのであまり難しくない (必要なヘッダをincludeして呼ぶだけ) ‒ ハンドルの取得方法さえわかれば大丈夫 #include <FMX.Platform.Win.hpp> FmxHandleToHWND(this->Handle); (HMENU)(pMenu->Handle); // TForm*からHWND // TMenuItem*からHMENU 33 OSネイティブAPIの呼び出し:MacOS X ‒ Cocoa API:Objective-Cの知識が必要 ‒ ランタイムが、Objective-CクラスをC++クラス(イン ターフェース)として呼び出せる高度なラッパーを提 供している ‒ Delphi向けのためC++での記述方法がかなり特殊 ‒ 私もまだ完全理解には至っていません ‒ 公式の説明が見あたらない… ‒ Carbon APIなら簡単です • Win32 APIと同じくC関数呼び出し方式 • 最新のOS機能には非対応 34 62 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 コードサンプル // 必要となるヘッダ #include <FMX.Platform.Mac.hpp> #include <Macapi.Foundation.hpp> #include <Macapi.AppKit.hpp> // TForm*からNSWindowを得る // Cocoaクラス名に接頭辞_di_が付くものとTが付くものがあり役割も分かれる _di_NSWindow wnd = TNSWindow::Wrap(_di_ILocalObject( FmxHandleToObjC(pForm->Handle))->GetObjectID()); // 自アプリのNSBundleを得る(クラスメソッド呼び出し) // 生のObjCクラスポインタはWrapしてラッパクラス(スマートポインタ)化する Void* pMainBundle = TNSBundle::OCClass->mainBundle(); _di_NSBundle bundle = TNSBundle::Wrap(pMainBundle); B4 // 得られたNSWindowインスタンスのメソッドを呼んでみる // NSString生成にはRTL提供のNSSTR関数が利用可能 // [wnd setTitle: @”Hello World”]; ObjCの記法 wnd->setTitle(NSSTR(_D(”Hello World”))); // C++同等に呼べる 35 コードサンプル // TForm*からNSViewを得る TObject* pObj = _interfaceToObjectCast<TObject>(FmxHandleToObjC(this->Handle)); if(pObj) { boost::scoped_ptr<TRttiContext> pRttiContext(new TRttiContext); TRttiType* pRttiType = pRttiContext->GetType(pObj->ClassType()); if(pRttiType) { TRttiProperty* pRttiProperty = pRttiType->GetProperty("View"); if(pRttiProperty) { _di_NSView view = pRttiProperty->GetValue(pObj).AsInterface(); return view; } } } 36 63 17Th Developer Camp OSごとの メニューの違い 37 OSごとのメニューの違い ‒ 結構マニアックな内容に ‒ しかし、メニューはアプリケーションGUIの基本中 の基本 ‒ 中規模以上のアプリケーションを開発するには、 メニューを柔軟に制御する必要はどうしても 出てくる ‒ GUI要素でOSネイティブなのは基本的にメニュー だけ(それ以外のコントロールはFireMonkey経由) ‒ 以上の理由により、複雑になりがちですが、ちょっと 詳しくまとめてみました 38 64 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 OSごとのメニューの違い - Windows ショートカットキーとアクセラレータが別の概念 となっている B4 39 OSごとのメニューの違い – MacOS X(1/2) Windowsでいう「ショートカットキー」が無く、 「アクセラレータ」相当を「ショートカット」と呼称 40 65 OSごとのメニューの違い – MacOS X(2/2) 「アプリケーションメニュー」の存在 Windowsでいうところの「システムメニュー」 「ツール」「ヘルプ」などの内容に相当 41 OSごとのメニューの違い – その他 ‒ メニュー配置の「常識」の違い • OSXでは「終了」は「ファイル」の中ではない • バージョン情報や環境設定はアプリケーションメニューに 入っている ‒ 同じ内容でも微妙に表現が違う • Win:切り取り・コピー・貼り付け • OSX:カット・コピー・ペースト ‒ ショートカット文字列の有無 ‒ Ctrlキー vs. Commandキー 42 66 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 OSごとのメニューの違い – 解決策 ‒ フォーム上に別々のTMenuBarを作っておき、OSご とに割り付けすることで、ある程度解決可能 ‒ しかし、今後の変更やローカライズを考えるとフォー ム上のアイテムでの個別管理はわずらわしい ‒ そこで、メニュー内容をXML化しリソースに格納 • 属性としてWindows用・MacOS X用などのフラグを追加 • ショートカットもOS別に指定可能とした • これをRTLのTXMLDocumentで読み込み、 TMenuBar/TMenuItemを構築するライブラリを開発 B4 43 メニュー定義用XMLサンプル(抜粋) <!-- Commandにコマンド文字列(イベントハンドラ関数に渡される)を指定する --> <!-- WinShortcutでWindowsショートカットキーのアルファベットを指定する --> <!-- Accelにアクセラレータキーのキーコンビネーションを文字列で指定する --> <!-- 一般的な流儀に沿い、WinでCtrl+●、MacでCmd+●をアクセラレータにする(核キーが同じ)場合、 Accelアトリビュートに「Def+」と書いて共通化できる --> <Item Name="新規作成" Command="New" WinShortcut="N" Accel="Def+N" /> <!-- セパレータを作る場合はこのように指定する --> <Item Name="-" /> <!-- WinとMacで名称を分けることもできる。Win用にショートカット文字列を入れてしまう (WinShortcut省略)ことも可能 --> <!-- アクセラレータキーをWinとMacで別々に定義(または片方だけ定義)したい場合、WinAccelと MacAccelを両方定義することで分けられる --> <!-- OpenDlg=1とすると項目名の後に「...」を付与する --> <Item WinName="開く(&O)" MacName="開く" Command="Open" WinAccel="Ctrl+O" MacAccel="Cmd+O" OpenDlg="1" /> <Item Name="上書き保存" Command="Save" WinShortcut="S" Accel="Def+S" /> <!-- Winのみで表示したい場合はMacHide=1、逆はWinHide=1とする --> <Item Name="-" MacHide="1" /> <Item Name="Applicationの終了" Command="Exit" WinShortcut="X“ MacHide="1" /> 44 67 OSネイティブメニューへの対応 • 作ったTMenuBarをOSネイティブのメニューに設定 する方法 – 構築完了してから UseOSMenu() メソッドを呼べばOK – UseOSMenu()してからアイテム追加しても反映されない • OSXアプリケーションメニューに設定する方法 – 別のTMenuBarを構築し、 Application->ApplicationMenuItems に代入する 45 OSごとのメニューの違い – 実装してみたが ‒ Winでは特に問題無く動作…した?(後述) ‒ OSXでトラブル発生 • XMLのCommandの内容をTMenuItemのTagStringに格 納し、共通のOnClickハンドラから読み取って識別しようと した • TMenuItemのOnClickに指定したメソッドで、Sender引数 をTMenuItem*にキャストして使用したところアクセス違反 • ランタイムライブラリのソースコードを漁ったり検索したり • QCにて既知不具合と判明 • http://qc.embarcadero.com/wc/qcmain.aspx?d=105091 46 68 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 コードサンプル void __fastcall MenuLoader::MenuItemClick ( TObject *Sender) { pMenuItem = (TMenuItem*)(Sender); ProcessCommand(pMenuItem->TagString); // Error on OSX } B4 47 コードサンプル #include <FMX.Platform.Mac.hpp> #include <Macapi.Foundation.hpp> #include <Macapi.AppKit.hpp> TMenuItem* pMenuItem; #ifdef __APPLE__ // パラメータクラスが誤って渡されているので、同じメモリモデルのクラスに // 無理矢理キャストして中身を取り出す(暫定対応) class TFMXOSMenuItem : public TOCLocal { public: TMenuItem* FMXMenuItem; }; TFMXOSMenuItem* pOSXMenuItem = (TFMXOSMenuItem*)Sender; pMenuItem = pOSXMenuItem->FMXMenuItem; #else pMenuItem = static_cast<TMenuItem*>(Sender); #endif 48 69 OSXショートカットキーの対応 「環境設定」に[Cmd+,]を指定したい ‒ TextToShortcut("Cmd+,"); が動かない ‒ TextToShortcutはアルファベット程度しか対応していな いらしい ‒ TextToShortcut同等品を自作して差し替え (今回のプロジェクトに対応できる程度の簡素なもの) 49 メニュー項目の有効無効・チェック対応 ‒ TMenuItemのEnabledやIsCheckedを変更しても正常 に反映されない場合がある (Win・OSXとも) ‒ さらに、はっきり確認できていないが、OSXで IsCheckedを変更すると、メモリ破壊か何かが起こって 他のところにトラブルを招く模様? ‒ これらに対応するにはOSネイティブ処理を呼ぶ必要が ある ‒ このほかツールバーボタンとの共用などもあり、総合的 な管理クラスを設計して使っています 50 70 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 メニュー項目の有効無効・チェック対応:OSX ‒ チェック対応 • TMenuItemからCocoaのNSMenuItemオブジェクトを得 て、setState(NSOnState または NSOffState)メソッドを 呼ぶ ‒ 無効化対応 B4 • 次のコードサンプル参照 • ややこしいです • 今覚えなくても「なんとかなる」と記憶しておいてください 51 コードサンプル // TMenuItemからNSMenuItemを得る static _di_NSMenuItem GetNSMenuItem(TMenuItem* pMenuItem) { _di_NSMenuItem item; if(pMenuItem->Handle) { item = TNSMenuItem::Wrap(_di_ILocalObject( FmxHandleToObjC(pMenuItem->Handle)) ->GetObjectID()); } return item; } 52 71 コードサンプル(続き) // メニューアイテムを無効にする場合 TMenuItem* pMenuItem = (TMenuItem取得); _di_NSMenuItem item = GetNSMenuItem(pMenuItem); class_addMethod(object_getClass(item->target()), sel_getUid("validateMenuItem:"), &validateMenuItem, "C@:@"); item->setEnabled(false); // 無効化対応のためのチェックメソッド用関数 static BYTE validateMenuItem(void* pthis, SEL cmdsel, void* sender) { _di_NSMenuItem item = TNSMenuItem::Wrap(sender); return item->isEnabled() ? 1 : 0; } 53 メニュー項目の有効無効・チェック対応:Win ‒ チェック対応 • TMenuItemのIsCheckedを変更するだけで対応可 能(ネイティブ対応不要) ‒ 無効化対応 • 次のコードサンプル参照 • Windows APIを直接使用します • OSXほどややこしくないです 54 72 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 コードサンプル // メニューアイテムを無効にする場合 TMenuItem* pMenuItem = (TMenuItem取得); MENUITEMINFO mii; ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE; mii.fState = MFS_GRAYED; //有効化ならMFS_ENABLED B4 SetMenuItemInfo((HMENU)pMenuItem->Handle, (UINT_PTR)pMenuItem, FALSE, &mii); 55 メニュー:その他 ‒ ツールバー等とも連携できる、アクションリストが欲 しい • XE3でサポート予定らしい? • 現状では自作した • 前述の不具合なども治っているといいのですが ‒ メニュー項目へのビットマップ表示ができない • OSXでは使わないがWindowsでは標準的 • これもネイティブコードを使えば可能 • XP以前とVista(+AeroGlass)以降で扱いが異なる 56 73 17Th Developer Camp その他Tips 57 その他Tips(1) GPUアクセラレーションをオフにする ‒ SpriteStudioのようにフォーム内のコントロールが多 いとかえって遅くなるようです ‒ OpenGLとも動作が衝突するのでオフにします ‒ FMXMain()の最初で GlobalUseDirect2D = false; とすればオフにできます(Winのみ) ‒ OSXでは方法が無いようです(けっこう重い) 58 74 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 その他Tips(2) コントロールフォーカスエフェクトをオフにする ‒ デフォルトではフォーカスを得たコントロールの周囲 にぼかしエフェクトが付きます ‒ これがかなり重い ‒ FMXMain()の最初で GlobalDisableFocusEffect = true; とすればオフにできます B4 59 その他Tips(3) OSXでdynamic_castがおかしい ‒ 複数のコントロールからイベントハンドラを共有 している場合など、Senderを当該コントロール の型にdynamic_castして判定したいことがある ‒ OSXで使ったら落ちた ‒ 自分でnewしたもの同士だと問題ない ‒ ランタイムが生成したインスタンスがRTTIに 対応できていない? ‒ static_castし、Tagで識別するなどして対応 60 75 コードサンプル void __fastcall TForm1::FormCreate(TObject *Sender) { TForm* pForm = dynamic_cast<TForm*>(Sender); if(pForm) { pForm->Caption = _D("Hello World"); } } void __fastcall TForm1::ItemClick(TObject *Sender) { if(dynamic_cast<TButton*>(Sender)) { // ボタンだった場合の処理 } else if(dynamic_cast<TMenuItem*>(Sender)) { // メニュー項目だった場合の処理 } } 61 その他Tips(4) OSXでのアプリケーション終了の挙動 ‒ OSXアプリはウィンドウを閉じただけでは終了しな い ‒ OnCloseイベントでメインウィンドウを隠しておき、 OSから通知を受けたら再表示する ‒ アプリケーションメニューの「終了」で完全終了 ‒ 詳しくは前回のDevCamp資料にあった、ような… 62 76 「FireMonkey クロス開発テクニカルエッセンス - アニメーションデータ作成ツール開発事例から」 その他Tips(5) その他 ‒ ダイアログボックスでのボタンの順序 • GUIデザインはオリジナルで作っても、こういうところは 慣れが出るので標準からあまり弄らないほうがいい B4 ‒ IDEおよびエディタの動作 • 謎のコンパイルエラー・リンクエラーが出たら再起動 • 外部でソース編集する場合は齟齬に注意 63 まとめ ‒ 一部愚痴っぽくなってしまった感もありますが、 C++Builder XE2のクロスプラットフォーム対応は 間違いなくすばらしいものです ‒ クロス開発で「一番大変な部分」の大半が FireMonkeyによって片付けられます ‒ プロフェッショナルユースに耐えるアプリケーション 開発を行うためには、デベロッパー側での工夫や 調整も必要です ‒ XE3での改良にも期待します 65 77 【B5】 Delphi/C++Builderテクニカルセッション FireMonkey モバイル/タブレットアプリ開発 エンバカデロ・テクノロジーズ エヴァンジェリスト 高橋智宏 ttakahashi@embarcadero.com 1 アジェンダ • • • • • • FireMonkeyカスタムコンポーネントの基礎 TMS Pack for FireMonkey FireMonkey iOSアプリ開発テクニック DataSnapモバイルコネクタ モバイル/タブレット向けWebアプリ Delphi XE3, C++Builder XE3 2 78 「FireMonkey モバイル/タブレットアプリ開発」 FireMonkeyカスタムコンポーネントの基礎 • Delphi XE2 • C++Builder XE2 • FireMonkey iOS – Xcode 側に.pasをコピー B5 3 TMS Pack for FireMonkey • http://www.tmssoftware.com/site/tmsfmxpack.asp • Delphi XE2, C++Builder XE2, FireMonkey iOS をサポート • 注意:トライアル版には FireMonkey iOS は含まれない 4 79 FireMonkey iOSアプリ開発 • 現時点で必要な環境 – Delphi XE2 Update 4 Hotfix 1 • Windows OS上で開発 – OS X SnowLeopard(10.6) • Xcode 3.2.6 ~ Xcode 4.2 – OS X Lion(10.7) • Xcode 4.2.1 + Xcode 4.4.1 – OS X Mountain Lion(10.8) は 不可 • ただし… 5 FireMonkey iOSアプリ開発テクニック • iPhone,iPadの種類&バージョン判別 – シミュレータ or 実機 • キーボードの表示・非表示に適応させる • 画面の回転を検知 • TCP/IPクライアント – CFSocket – コールバック関数の呼び出し規約は mwpascal (MetroWerks Pascal Calling Convention) • NSThreadの利用とGUIの更新 • iOSアプリのフォルダ(パス)は? – ExtractFilePath(ParamStr(0)) 6 80 「FireMonkey モバイル/タブレットアプリ開発」 DataSnapモバイルコネクタ • DataSnapサーバー – Delphi XE2 Enterprise Edition以上が必要 • FireMonkey iOS向けモバイルコネクタ – freepascal_ios42 – freepascal_ios50 – 3点ほど不具合がありますので、.pasの修正が必要 • 日本語パラメータの文字化け – http://qc.embarcadero.com/wc/qcmain.aspx?d=103021 • メモリ(参照カウント)エラー – http://qc.embarcadero.com/wc/qcmain.aspx?d=104296 B5 • NSURLConnectionの使用法の誤り – http://qc.embarcadero.com/wc/qcmain.aspx?d=104368 7 iPhoneシミュレータの注意点 • 予め、ターミナルからiPhoneシミュレータのプロセスを UTF-8で起動しておく(日本語などの文字化け対策) – QC#101418 • http://qc.embarcadero.com/wc/qcmain.aspx?d=101418 $ export LANG=ja_JP.UTF-8 $ cd /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone¥ Simulator.app/Contents/MacOS $ ./iPhone¥ Simulator • Xcodeでビルドして起動!! 8 81 モバイル/タブレット向けWebアプリ • FireMonkeyとは直接関係ないですが… – Webアプリのほうが良い(楽だ)と考えている開発者向け – Windows 8, iPhone, iPad, Android, BlackBerry, WP etc… • IWCGjQuery が凄い!! – ポルトガルのCentralGest社が最近リリースしました • http://www.cgdevtools.com/ – IWCGjQuery Suite for IntraWeb • 主にデスクトップWebブラウザ向け • http://www.cgdevtools.com/?skill=iwcgjquery-suite – IWCGjQuery Mobile Suite for IntraWeb • スマホ & タブレットWebブラウザ向け • http://www.cgdevtools.com/skill/iwcgjquery-mobile-suite/ – Delphi 2007 ~ Delphi XE2 – C++Builder 2007 ~ C++Builder XE2 – IntraWeb 10.0.23 ~ IntraWeb 12.2.4 9 Delphi XE3, C++Builder XE3 • • • • FireMonkey 2.0 で Metropolis UI スタイル FireMonkey 2.0 で タッチ&ジェスチャー InterBase XE3 ToGo Edition dbExpress driver for SQLite3 10 82 「FireMonkey モバイル/タブレットアプリ開発」 Thank You B5 11 83 www.embarcadero.com/jp 〒102-0072 東京都千代田区飯田橋 4-7-1 ロックビレイビル 8F TEL 03-4577-4520 FAX 03-6843-0961
© Copyright 2024 Paperzz