FireMonkey/Delphi XE2

2011年10月21日 (金)

FireMonkeyでのショートカット(Windows)

以前の記事でWindowsのショートカットの動作にも問題があると書きましたが、解決法を上げるのを忘れてました。

私の見逃しかもしれませんが、FireMonkey/Winのコード中にはショートカットキー処理するコードがありません。
実際にショートカットを設定しても動作しないので、間違ってはいないと思います。おそらくまだ作りかけなんでしょう。
この件に関しては、そのうちアップデートで治ると思いますので正式対応を待ってもいいと思っていますが、 エンバカの公式フォーラムで困っている人がいるのを見つけたので(無理やりな)解決方法を書いておきます。

まず次のようなクラスを作ります:
interface
{$IFDEF MSWINDOWS}
uses
  System.Classes, Winapi.Windows, Winapi.Messages, FMX.Menus;

type
  TAccelkeyTable = class
  private
    var FTable : array of TMenuItem;
  protected

  public
    procedure Init;
    procedure Add(menuitem : TMenuItem);
    procedure Remove(menuitem : TMenuItem);
    function  Translate(var msg : TMsg) : Boolean;
    function  CheckShortCut(Handle : HWND; var Key: Word; var KeyChar: System.WideChar;  Shift: TShiftState): Boolean;
  end;

var
  AccelKeyTable : TAccelKeyTable = nil;


{$ENDIF}
implementation
{$IFDEF MSWINDOWS}

{ TAccelkeyTable }

procedure TAccelkeyTable.Add(menuitem: TMenuItem);
var
  i : integer;
begin
  i := Length(FTable);
  SetLength(FTable, i+1);
  FTable[i] := menuitem;
end;

procedure TAccelkeyTable.Init;
begin
  Initialize(FTable);
end;

procedure TAccelkeyTable.Remove(menuitem: TMenuItem);
var
  i, cnt : integer;
begin
  cnt := Length(FTable);
  for i := 0 to cnt-1 do
  begin
    if FTable[i] = menuitem then
    begin
      FTable[i] := nil;
      break;
    end;
  end;
end;

function TAccelkeyTable.Translate(var msg: TMsg): Boolean;
var
  Shift : TShiftState;
  Key : Word;
  KeyChar : System.WideChar;
begin
  result := false;
  if msg.message = WM_KEYDOWN then
  begin
    Shift := [];
    if (GetKeyState(VK_SHIFT) and $80) <> 0 then Shift := Shift + [ssShift]
    else if (GetKeyState(VK_CONTROL) and $80) <> 0 then Shift := Shift + [ssCtrl]
    else if (GetKeyState(VK_MENU) and $80) <> 0 then Shift := Shift + [ssAlt];

    Key := LOWORD(msg.wparam);
    KeyChar := System.WideChar(LOWORD(msg.lParam));
    result := CheckShortCut(msg.hwnd, Key, KeyChar, Shift);
  end;
end;

function TAccelkeyTable.CheckShortCut(Handle : HWND; var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState) : Boolean;
var
  i, cnt : integer;
  sc : TShortCut;
begin
  result := false;

  sc := scNone;
  if ssShift in Shift then sc := sc or scShift
  else if ssCtrl in Shift then sc := sc or scCtrl
  else if ssAlt in Shift then sc := sc or scAlt;

  if Key > 32 then
  begin
    sc := sc or Key;
    //Application.MainForm.Caption := ShortCutToText(sc); // debug
    cnt := Length(FTable);
    for i := 0 to cnt-1 do
    begin
      if (FTable[i] <> nil) and (FTable[i].ShortCut = sc) then
      begin
        SendMessage(Handle, WM_COMMAND, NativeUInt( FTable[i] ), 0);
        result := true;
        break;
      end;
    end;
  end;
end;

initialization

{$ENDIF}
end.
このクラスのインスタンスを作り、ショートカットを設定したTMenuItemをすべて登録してください:
  AccelKeyTable.Add( mnuSaveAs );
  AccelKeyTable.Add( mnuCopy );
    ....
みたいな感じ
個人的にはTMainMenu/TMenuItemを派生したクラスを作って自動で登録するようにしてます。

次に、ショートカットキーが押された時にコマンドを実行するための処理を呼び出します。FireMonkeyのソースコードを見るとWM_COMMANDのwparamにTMenuItemのインスタンスを渡してメッセージを送ることでTMenuItem.Clickが実行されるようなので、キーイベントでWM_COMMANDをSendMessage()してやるようにします。

これも個人的にはFMX.Platform.Winのメッセージループを書き換えたりして実験してますが、もう少し単純にフォームのKeyDown()メソッドをoverrideして呼び出す方法を記載しておきます。


interface
  ・・・
type
  TForm1 = class(TForm)
  ・・・
 protected
  ・・・
     procedure KeyDown(var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState); override;
  ・・・
  ・・・
  end;

implementation

  ・・・

procedure TForm1.KeyDown(var Key: Word; var KeyChar: System.WideChar;  Shift: TShiftState);
begin
{$ifdef MSWINDOWS}
  if not AccelKeyTable.CheckShortCut(FmxHandleToHWND(Handle), Key, KeyChar, Shift) then
    inherited;
{$else}
  inherited;
{$endif}
end;

  ・・・

| | コメント (2) | トラックバック (0)

2011年10月15日 (土)

FireMonkey小ネタ その2

昨日の記事、一つ問題が解決したので更新しました

昨日書こうと思ってたのに忘れてた小ネタを2つ追加。
調べればすぐにわかる情報ですが、FireMonkey向けの情報として一か所にまとまっていることにも意味があると思うので掲載。

6.TControl.ClientToScreen(), TControl.ScreenToClient()の代わり
FireMonkeyの場合、LocalToScreen()とScreenToLocal()が該当の機能です。・・・が、なぜかprotectedメンバーなので外部からアクセスできません。
・・・ですが、IControlのメソッドなのでコントロールをIControlでキャストすればアクセスできます。
screen := (ctrl as IControl).localToScreen(local);
や
local := (ctrl as IControl).ScreenToLocal(screen);
みたいな感じ
こういうVCLと同じ機能は名前もアクセス指定子もVCL準拠にして欲しかった。
何か意図するところがあるんでしょうけど。


7.マウスカーソル位置の取得・変更
マウス位置はPlatform.GetMousePos()で取得可能ですが、マウス位置を変更する方法が用意されていません。
マウス位置を変更するアプリは行儀が悪いってのは置いておいて、たまにやりたくなるのでこんなクラスを作りました。
unit FMXMouse;

interface
uses
  System.Types, FMX.Platform
{$ifdef MSWINDOWS}
  ,Winapi.Windows
{$endif}
{$ifdef MACOS}
  ,Macapi.CoreGraphics, Macapi.CocoaTypes
{$endif}
  ;

type
  TMouse = class
  public
    procedure SetCursorPos(const point : TPointF);
    function  GetCursorPos: TPointF;

    property CursorPos : TPointF read GetCursorPos write SetCursorPos;
  end;

var
  Mouse : TMouse = nil;

implementation


{ TMouse }

{$ifdef MACOS}
procedure TMouse.SetCursorPos(const point: TPointF);
var
  cgpoint : NSPoint;
begin
  cgpoint.x := point.X;
  cgpoint.y := point.Y;
  CGWarpMouseCursorPosition(cgpoint);
end;
{$endif}

{$ifdef MSWINDOWS}
procedure TMouse.SetCursorPos(const point: TPointF);
begin
  Winapi.Windows.SetCursorPos(round(point.X), round(point.Y));
end;
{$endif}

function TMouse.GetCursorPos: TPointF;
begin
  result := Platform.GetMousePos;
end;

initialization

  Mouse := TMouse.Create;

finalization

  Mouse.Free;

end.
ユニット名、クラス名などはお好きにどうぞ。
マウス座標なのでTPointでも良いのですが、FireMonkey内ではTPointFが使われることが多いのでTPointFで座標を返すようにしました

| | コメント (0) | トラックバック (0)

2011年10月14日 (金)

FireMonkey小ネタ5つ(未解決ネタも含む)

1.WinとOSXでMouseUpイベントの引数の値が違う
VCLやWinのFMXだとMouseUpイベントのShiftにはUpしたボタンの情報が含まれませんがOSXでは含まれます。
(例えば左ボタンのUPイベントなのにssLeftがShiftに含まれる)

なので以下のようなコードでMouseUp時に他のマウスボタンが押されていないことを確認する処理があるとWin/OSXで異なった結果になります

  if Shift*[ssLeft,ssMiddle,ssRight] = [] then
    ...

仕方ないので、こう書いて回避

  case Button of
    TMouseButton.mbLeft  : Shift := Shift - [ssLeft];
    TMouseButton.mbRight : Shift := Shift - [ssRight];
    TMouseButton.mbMiddle: Shift := Shift - [ssMiddle] ;
  end;

  if Shift * [ssLeft, ssMiddle, ssRight] = [] then
    ...


2.自作コンポーネントにTBitmap型のプロパティを持たせて、画像をシリアライズしようとすると画像がだんだんと劣化する

どうやらα値が無いBitmapの場合はjpegで格納するようです。

jpegで格納されても全然うれしくないのでTBitmapを派生した次のようなクラスのインスタンスをTBitmap型のプロパティに突っ込んで回避。必ずPNGでシリアライズされるようになります
interface
  TESXBitmap = class(TBitmap)
  protected
    procedure DefineProperties(Filer: TFiler); override;
    procedure ReadBitmap(Stream: TStream);
    procedure WriteBitmap(Stream: TStream);
  end;
  
implementation
{ TESXBitmap }

procedure TESXBitmap.DefineProperties(Filer: TFiler);
begin
  Filer.DefineBinaryProperty('PNG', ReadBitmap, WriteBitmap, Width * Height > 0);
end;

procedure TESXBitmap.ReadBitmap(Stream: TStream);
begin
  LoadFromStream(Stream);
end;

procedure TESXBitmap.WriteBitmap(Stream: TStream);
var
  Filter: TBitmapCodec;
  this : TBitmap;
begin
  filter := DefaultBitmapCodecClass.Create;
  this := self;
  filter.SaveToStream(Stream, this, 'png');
  filter.Free;
end;

3.自作コンポーネント内部で動的に生成したサブコンポーネントもシリアライズされてしまう

内部で生成したサブコンポーネントのParentに自作コンポーネントを指定すると、.fmxにシリアライズされます。シリアライズされる前提で設計すれば問題ないかもしれないですが、interface部に公開したくないワンオフのサブコンポーネントまで シリアライズしようとするので困りもの。

今の所回避方法がわかってないので、デザイン時はサブコンポーネントを生成しないようにして回避してます。
回避方法について情報をお持ちの方、教えてください。

20111015: @onimaro2010さんから情報をいただきました。サブコンポーネントを生成した後に、Storedプロパティをfalseにすれば良いようです。ありがとうございます。


4.非VisualコンポーネントはTComponentから派生しないと、TDataModuleに置けない

例えばFireMonkeyアプリでしか使わないからと、TFmxObjectを派生してコンポーネントをつくると、フォームには配置できるのにDataModuleには配置できなくなります。

20111018: @lynatanさんから情報をいただきました。DelphiQ&Aに投稿されていた記事によると、DataModuleのClassGroupプロパティを変更すればようようです。上の例だとFMX.Types.TFmxObjectにすればOK


5.自作コンポーネント用のstyleをパッケージに含ませる方法がわからない
styleファイルをrcdataにしてリソースに含ませるのかなと思いますが方法がわからない。ご存じの方教えてください。

| | コメント (0) | トラックバック (0)

2011年10月11日 (火)

FireMonkey TPopupを使いやすくする

Delphiの補完ウインドウのようなもの(親ウインドウの外観はアクティブのまま子ウインドウをポップアップする)を作りたくなりました。

VCLだとこの手のウインドウに非常に苦労したのでFireMonkeyでも苦労するかと思いきや、TPopupを使うと簡単に実現できました。(キー操作等に難があるので、要改良ですが、ちゃんとリージョン切り抜きもできるし便利です)

2011_1011_popuppanel

ただし、現状のFireMonkeyだとTPopup周りのコードはすべて手書きで書く必要があるようなので簡単にコンポーネント化してみました:(コンポーネントとして登録するだけで、ほとんど何もしてないですが)
unit FMX.ESXPopupPanel;

interface
uses
  System.Classes, System.Types, FMX.Types;

type
  TESXPopupPanel = class(TPopup)
  private
  protected
  public
    procedure Popup; override;
  end;

{$ifdef WIN32}
procedure Register;
{$endif}

implementation

{$ifdef WIN32}
procedure Register;
begin
  RegisterComponents('ESX', [TESXPopupPanel]);
end;
{$endif}


{ TESXPopupPanel }

procedure TESXPopupPanel.Popup;
begin
  Position.X := 0;
  Position.Y := 0;
  inherited;
end;

end.
上記ソースを保存し、適当なパッケージに含めてインストールしてください。
(ユニット名やクラス名はお好きにどうぞ)

インストールしたら、適当なプロジェクトを作成して、
1.フォームにTESXPopupPanelを配置
2.ボタンも配置
3.Visible=false、PlacementTarget=ボタン、Placement=plBottomCenterにする
4.PopupPanelの上に適当な部品を配置(ここではCalloutPanel&Calemdar)
5.ボタンのOnClickイベントに ESXPopupPanel1.Popup() を記述
6.実行してボタンを押すとPopupPanelが表示されます

| | コメント (0) | トラックバック (0)

2011年10月 2日 (日)

FireMonkey/OSX メニューアイテムのショートカット

FireMonkey/OSX メニューアイテムの話題その3

FireMonkeyのメニューアイテム等にもVCLと同じShortCutを設定するプロパティがあるんですが、まだ色々と未完成です。(今回はOSXの話ですが、Winでもショートカットには不具合があります回避方法はまた別の機会に)
まず、ShortCutプロパティにプロパティエディタが適切に設定されていないので、Ctrl+A 等の文字列で設定できず数値を入れる必要があります。

次に、VCLの時と同じように修飾キー(scShiftなど)のコードがd15..12ビットに割り当てられていますが、OSXの場合は特殊キーの表現まで含めるとキーコードだけで16ビット必要になるためビットが重複してしまっています。 おかげでカーソルキー等をショートカットに設定することができません。

TShortCutのフォーマット自体を変えるか、TShortCutからOSX依存のコードに変換する部分(FMX.Platform.Mac.pasのShortCutToKey())を適切なものに変える必要があると思いますが、どちらもライブラリソースコードの修正なしで対応するのは難しいです。ShortCutToKey()がTPlatformMacのメンバーならRTTIでなんとかなったかも
追記:全力わはーの@lynatan さんがShortCutToKey()を置き換える方法を編み出してくださいました。http://d.hatena.ne.jp/tales/20111002/1317525163

なのでとりあえず自前のShortCutToKey()を作って、メニューを作った後でメニューアイテムのショートカットを置き換えていく方法をとりました。

以下、コード
procedure ShortCutToKey(ShortCut: TShortCut; var Key: Char; var ModifierMask: NSUInteger);
begin
  Key := Chr(Lo(ShortCut));
  ModifierMask := 0;
  case Key of
  'A'..'Z' : Key := Char(Ord(Key)+$20);
  #$08 : Key := Char(NSBackspaceCharacter);
  #$09 : Key := Char(NSTabCharacter);
  #$0d : Key := Char(NSEnterCharacter);
  #$21 : Key := Char(NSPageUpFunctionKey);
  #$22 : Key := Char(NSPageDownFunctionKey);
  #$23 : Key := Char(NSEndFunctionKey);
  #$24 : Key := Char(NSHomeFunctionKey);
  #$25 : Key := Char(NSLeftArrowFunctionKey);
  #$26 : Key := Char(NSUpArrowFunctionKey);
  #$27 : Key := Char(NSRightArrowFunctionKey);
  #$28 : Key := Char(NSDownArrowFunctionKey);
  #$2e : Key := Char(NSDeleteCharacter);
  #$70..#$87 : Key := Char(NSF1FunctionKey+Ord(Key)-$70);
  end;

  if ShortCut and scCommand <> 0 then ModifierMask := ModifierMask or NSCommandKeyMask;
  if ShortCut and scShift <> 0 then ModifierMask := ModifierMask or NSShiftKeyMask;
  if ShortCut and scCtrl <> 0 then ModifierMask := ModifierMask or NSControlKeyMask;
  if ShortCut and scAlt <> 0 then ModifierMask := ModifierMask or NSAlternateKeyMask;
end;


class procedure TMacHelper.UpdateMenuShortCut(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  Key: Char;
  ModMask: NSUInteger;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsmnuitem := GetNSMenuItem(menuitem);

      ShortCutToKey(menuitem.ShortCut, Key, ModMask);
      nsmnuitem.setKeyEquivalent(NSSTR(Key));
      nsmnuitem.setKeyEquivalentModifierMask(ModMask);
    end;
  end;
end;
※前回の記事に書いた GetNSMenuItem()も必要です。
ショートカット設定が必要なMenuItemすべてに対してUpdateMenuShortCut()を呼び出すとショートカットが修正されます。(ただしすべてのショートカットの組み合わせが上手く行くかはテストしてません)

| | コメント (0) | トラックバック (0)

2011年10月 1日 (土)

FireMonkey/OSX メニューアイテムのEnabled制御

FireMonkey/OSXのTMainMenuについて。その2

以前、文字列の動的変更についての記事を書きましたが、あの方法を応用すればチェックマーク等も同じようにして動的変更できます。

ただし、Enabledについては上手くいきません。正確にはEnabledプロパティの変更そのものは出来るものの、Enabledをfalseにしてもメニューがグレーアウトしてくれません。

これについて検索してみるとよくある話題らしく、(XCode/ObjCでの)解決方法はすぐに見つかりました。
どうやらNSMenuItemのターゲットオブジェクトにvalidateMenuIte:というメソッドを実装してやる必要があるようです。

ただ、この方法をFireMonkey/Delphiで実現する手段がすぐには思いつかず、いったんはDelphiのUpdateを待とうかと思ってたんですが、ちょっと基本に立ち返ってAppleのObjectiveCについての資料を読み漁り、試してみたところ以外とシンプルにできました。

以下サンプルコード:

// TMenuItemからNSMenuItemを取り出す
type
  TDummyOCLocal = class(TOCLocal)
    property Super;
  end;

class function TMacHelper.GetNSMenuItem(menuitem : TMenuItem) : NSMenuItem;
var
  nsmnuitem: NSMenuItem;
  nsobj : TDummyOCLocal;
begin
  result := nil;
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsobj := TDummyOCLocal(TOCLocal(FmxHandleToObjC(menuitem.Handle)));
      result := NSMenuItem(nsobj.Super);
    end else begin
      result := NSMenuItem(FmxHandleToObjC(menuitem.Handle));
    end;
  end;
end;

// NSMenuItemのターゲットオブジェクトに追加実装するメソッドの本体
// とりあえず NSMenuItemのisEnabledをそのまま返す。
// これで一応目的は果たせる。
function validateMenuItem(this : Pointer; cmd : SEL; sender : Pointer) : Byte; cdecl;
var
  menuitem : NSMenuItem;
begin
  menuitem := TNSMenuItem.Wrap(sender);
  if menuitem.isEnabled then
  begin
    result := 1;
  end else begin
    result := 0;
  end;
end;

// (1)TMainMenuが生成された後、適当なTMenuItem(トップ項目以外)をこの手続きに渡すと
// NSMenuItemのターゲットオブジェクトに validateMenuItem が実装される
class procedure TMacHelper.AddMenuValidator(sample_menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  objid : Pointer;
  cls : Pointer;
begin
  nsmnuitem := GetNSMenuItem(sample_menuitem);
  if nsmnuitem <> nil then
  begin
    objid := nsmnuitem.target;
    cls := object_getClass(objid);
    // Appleの"ObjCRuntimeRef.pdf" "ObhCRuntimeGuide.pdf" 参照
    class_addMethod(cls, sel_getUid(PAnsiChar('validateMenuItem:')), Pointer(@validateMenuItem), 'C@:@');
  end;
end;
// (2) TMenuItemのEnabledプロパティをNSMenuItemのEnabledに反映させる
class procedure TMacHelper.UpdateMenuEnabled(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsmnuitem := GetNSMenuItem(menuitem);

      nsmnuitem.setEnabled(menuitem.Enabled);
    end;
  end;
end;

(1)TMainMenuが生成された後、適当なTMenuItem(トップ項目以外ならなんでもOK)を.AddMenuValidator(sample_menuitem : TMenuItem) に渡す

(2)TMenuItemのEnabledプロパティが変更されたらUpdateMenuEnabled()でNSMenuItemのEnabledプロパティに反映させる。(個人的にはTMenuItemを継承したクラスを作って連動させてます)

(3)対応するメニュー項目がEnabledに応じてグレイアウトします

| | コメント (0) | トラックバック (0)

2011年9月20日 (火)

FireMonkey/OSX フォームのTCanvasへの直接描画(修正)

20110922 追記:案の定間違えていました。ソースコード修正しています

以前の記事でOSXとWindowsXP(もしくはDirect2Dが使えない環境)ではフォームのCanvasへの直接描画がOnPaint()以外ではできないと書きましたが、OSXについては無理やり描画することができました。
(FireMonkey HDアプリ。FireMonkey 3Dアプリでは試してませんが、コードを見る限り3Dアプリでは小細工なしに描画できそう)

ただ、副作用なども含めあまり自身が無いので詳しい方の意見が聞きたいのでソースを下記に書きます。

{$ifdef MACOS}
var
  win : NSWindow;
  view : NSView;
{$endif}
begin
{$ifdef MACOS}
 win := TNSWindow.Wrap((FmxHandleToObjC(Handle) as ILocalObject).GetObjectID);
 view := TNSView.Wrap(win.contentView);
 ContextHandle := THandle(win.graphicsContext.graphicsPort);
{$endif}
  with Canvas do
  begin
    BeginScene;
   // painting  //
    EndScene;
  end;
 {$ifdef MACOS}
  view.displayIfNeeded;
{$endif}
end;

やってるのは、Canvasへの描画の前に、フォームのContextHandleに無理やりCGContextRef を割り当て、
描画が終わったらviewに対して displayIfNeededを送っているだけです。
特にContextHandleに無理やり代入しているあたりが自信無し。

20110922 追記:元のソースではNSGraphicsContextのcurrentContextでGCを得ていましたが、懸念通り複数のフォームがある場合に正しく動作しませんでした。もっと単純にNSWindowのGCを得る方法に修正しています

| | コメント (0) | トラックバック (0)

2011年9月19日 (月)

FireMonkey/OSXでメニューの文字列を動的変更

FireMonkey/OSXのTMainMenuについて。

OSX上でTMainMenuを操作する場合、VCLでやってきたように、動的に文字列を書いたり動的にメニューを追加したりすることができません。
(動的にメニュー追加は一応可能ですが、MainMenuに追加する前にすべてのサブメニューを構築しておく必要があるようです)

今まで作ってきたアプリでは、起動後にメニュー文字列を書き換えて日本語モードにしたり英語モードにしたりしてきていたので、FireMonkeyアプリでも同じようにメニュー操作したいと思い調べてみました。

下記がメニューのテキストを変更(TMenuItem.Textの内容を反映する)するサンプルコード。
ひょっとしたらLionでは動かないかもしれません。snowleopardで動作確認しました。

{$ifdef MACOS}
type
  TDummyOCLocal = class(TOCLocal)
    property Super;
  end;
procedure UpdateMenuText(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  nsobj : TDummyOCLocal;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsobj := TDummyOCLocal(TOCLocal(FmxHandleToObjC(menuitem.Handle)));
      nsmnuitem := NSMenuItem(nsobj.Super);
      nsmnuitem.setTitle(NSSTR(menuitem.Text));
    end else begin
      nsmnuitem := NSMenuItem(FmxHandleToObjC(menuitem.Handle));
      nsmnuitem.setTitle(NSSTR(menuitem.Text));
    end;
  end;
end;
{$endif}

| | コメント (0) | トラックバック (0)

2011年9月12日 (月)

Delphi XE2のTCanvas

XE2関連でもう一つ投稿。
FireMonkeyがらみで遊んでいて、最初に躓いたのがTCanvasの扱いです。
とにかく、従来の使い方とは全く違う動きをするので、最初は誰しも戸惑うのでは?

続きを読む "Delphi XE2のTCanvas"

| | コメント (0) | トラックバック (0)

Delphi XE2でOpenGL

9/1にRAD Studio XE2が届いて遊んでいます。元々は64bit化が気になってたんですが、FireMonkeyというクロスプラットフォーム向けのライブラリが面白くて、まず最初はこっちから手を付けています。

FireMonekyはまだバグがあり、いきなり実用アプリを作るのはおすすめしませんが、今から遊んでいればそのうちWindowsとMacOSX向けに簡単にアプリケーションが作れるようになるのではと期待してます。(iOS向けも作れますが、UIの違いが大きいのでどこまで実用的になるかは未知数)

FireMonkeyはもともとDelphi向けのDirectX用のシーングラフライブラリが元になっているらしくて3D機能が豊富です。しかし、個人的にはお仕着せのシーングラフライブラリを使うよりもDirectXなりOpenGLを生の状態で使いたいので、ちょっとサンプルを作ってみました。

続きでグダグダ説明を書きますが、サンプルソースを書いたので基本的にはこれを読んでもらえればOKです。
Download:SimpleSampleOpenGL_FMX.pas

<実行イメージ>
20110912_simplesampleopengl

続きを読む "Delphi XE2でOpenGL"

| | コメント (1) | トラックバック (0)