戻る

Delphi2006 で .NET Compact Framework を作る

 「.NET Compact Framework」のソフトを作るDelphi2006ユーザーが増えてくれること願いつつ、私が試行錯誤している事をここに書いていきます。
 ただいま「コンポ同士の繋がりが消える」という致命的なバグにより試行錯誤を休止中です(泣)。



ソフト公開

PhotoToMiniSD

  • 作った理由
    カメラの設定で撮った写真を直接MiniSDに保存する事も出来ますが、それをやると撮る度にちょっと長い待ち時間が発生します。
    そのため私は本体(「マイピクチャー」フォルダ)に入れるように設定していました。
    ですが、それだとある程度枚数を撮ると本体の容量が溢れてしまうので、その度に手動でMiniSDに写真を移動する事になります。
    それがまた面倒臭い…というわけで、今回このようなソフトを作ってみました。
     
  • 使い方と特徴
    [写真をMiniSDに移動]ボタンを押すか、テンキの左上[-]又は、右上[-]ボタンを押すと、マイピクチャーにある写真と動画を、MiniSDに移動します。
     
     内部的な動きとしては
     (1)MiniSDに「PhotoToMiniSD」というフォルダを作る
     (2)さらにその中に年月日のフォルダを作り、振り分けてファイルを移動します。
     
     例1:2007/2/21のタイムスタンプのファイル「img227.jpg」をMiniSDに移動した状態
    「\MiniSDカード\PhotoToMiniSD\20070221\img227.jpg」
     
     例2:例1の条件で、既にコピー先に同じファイル名のファイルがあった場合
    「\MiniSDカード\PhotoToMiniSD\20070221\移動(1)~img227.jpg」
     
     レジストリをいじって、MiniSDのフォルダが「MiniSDカード」になっていない場合も自動的に認識しますので安心して下さい。
     例:MiniSDのフォルダが「MiniSD」になるようにレジストリをいじってる場合
     「\MiniSD\PhotoToMiniSD\20070221\img227.jpg」
     
    ダウンロード

ダウンロードはこちらのサイトでも行えます、こちらが正式ページなのでよろしくです^^
●ドルドのゲームアイランド(ドルドマイページ本家)
http://www.geocities.jp/doldomn/

初期設定はまり雑記

Delphi2006のバグFIX・バージョンアップ

 先にしときましょう、そうしないと以後に入れる事になるビルドヘルパーが誤動作します。

参考ページ

Compact Framework ビルドヘルパーの設定ではまり

cfmh_option1.jpg

ここは特に問題なし。

cfmh_option2.jpg

あれ?

-DCF_Oosterkamp

-DCF_Pluimers

に変わってる!

.NET CF 1.0 アセンブリのインストール

「ConvertCAB.bat」を使ってやる方法は.NET Compact Framework 1.0 SP3 インストール パッケージ のページでダウンロードできる中から「netcf.core.ppc3.ARM.cab」 (=.NET CF のインストレーションファイル) に含まれるすべてのファイルを解凍してバッチを実行するのだが、見事にファイル名が違っていて失敗!!

仕方ないので「ConvertGAC.bat」を使う方法を行う。 まずはPoketPC(私はW-ZERO3[es]から)のWindowsフォルダにある「GAC_」が付いている すべてのDLLを、PC上の適当なフォルダにコピーして、いざバッチを実行すると「ファイルがありません」と出る…??? う、このファイル、システム属性と非表示属性が付いてる(;;)

attrib -h -s (ファイル名)

で解除できるみたいなので「Setattrib.bat」というバッチファイルを作る

ついでに「ConvertCAB.bat」も置いておきます

cfmh_option3.jpg

CEエミュレータよくわかんないよ…

 CEエミュレータなるものがあって、それが使えるらしいんだけどいまいちピンとこない。
 まぁ設定で「ActiveSync」選んでおけば実機(W-ZERO3[es])の直下にコピーされて勝手に動くから、これでいいかな。

プログラムはまり雑記

なんだかたまに不安定

 .NET Compact Frameworkで使えないコンポーネントを貼ったり、使えないプロパティを設定したりするとたちどころに不安定。  何度もトライ&エラーしてても不安定になる、突然コンパイル通らなくなるとか(;;)  Delphiの再起動で直ったり、Windowsの再起動しないと直らなかったり、わけわからんのです。

突然プロジェクトが.NET Compact Frameworkとして認識しなくなった!

「プロジェクト名.bdsproj」のファイル内の下でFalseになっている2箇所を両方Trueにします
※突然なるので詳細は不明…

	<CompactFramework_UseDefaultDeploy>False</CompactFramework_UseDefaultDeploy>
	<CompactFramework>False</CompactFramework>

	<CompactFramework_UseDefaultDeploy>True</CompactFramework_UseDefaultDeploy>
	<CompactFramework>True</CompactFramework>

FindFirstがおかしい

procedure frmMain.Button2_Click(sender: System.Object; e: System.EventArgs);
var
  sr: TSearchRec;
  WkMasterFileName: string;
  WkCopyFileName: string;
begin
  if Borland.Vcl.SysUtils.FindFirst('\My Documents\マイ ピクチャ\*.jpg',
    FaAnyFile, sr) = 0 then
  begin
    repeat
      ListBox1.Items.Add(sr.Name);
    until Borland.Vcl.SysUtils.FindNext(sr) <> 0;
    Borland.Vcl.SysUtils.FindClose(sr);
  end;
end;

 「\My Documents\マイ ピクチャ\」フォルダには「img227.jpg」「img228.jpg」「img229.jpg」のファイルがあるのですが、ListBoxに表示された内容はなんと「g227.jpg」「g228.jpg」「g229.jpg」となぜか前2バイトが抜けたものが並びます。
 調べていくと、さらに内部の関数「FildFirstFile」まで同じくファイル名の頭2バイトが無い状態で取り出されてしまう模様。
 そもそも、Delphi2006が、.NET Compact Frameworkに対してのVCLが未サポートらしいです…偶然動いただけらしい(汗)
 
 結局、.NETライブラリである「Directory.GetFiles」関数を使って解決しました。  

レジストリってどうやって読めばいいのかな?

 「.NET Compact Framework 1.0」ではレジストリはAPI使わないと駄目らしい。
 「.NET Compact Framework 2.0」はクラスあるのに~…って愚痴っても仕方ないので、どれをUSESすればAPI使えるか調べる。
 されどWebページを検索しても何処にも見つからず(;;)シクシク
 仕方ないので「C:\Program Files\Borland\BDS\4.0\lib\cf」のファイルを見て、カンで「Borland.VclCF.Windows」をUSESに入れる。
 APIである「RegOpenKeyEx」が使えるようになった…当たり・・・かな???
 一応コンパイルは通るけど、正しいっていう根拠がどこにも無いのが恐ろしい…。
 
 とりあえずやりたい事は「HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory」の「Folder」キーの文字列を取りたいだけなのだが…値は「miniSDカード」と返ってくるはず。
 ところが、返ってくる文字列がしこたまおかしい!!1バイトごとに途中でNULLが入ってる文字列になってる。
 これじゃあ文字途中で切れじゃうじゃない~なんだろなこれ…
 色々調べるとこういう場合は「PlatformStringOf関数」を通さないと駄目らしい。
 さらにこの関数、ヘルプを見ると「末尾の NULL 文字を追加したり削除しないことに注意してください」との事で、何故か後にNULL文字が2つ付いている状態で渡してくるものだから、それを削る処理も入れないと以後文字連結できなくなるというさらにハマリが(;;)

procedure frmMain.Button1_Click(sender: System.Object; e: System.EventArgs);
var
  WkHKEY: HKEY;
  WkType, WkSize: Cardinal;
  WkGetValue: array of Byte;
  WkValue: string;
begin
  try
    if RegOpenKeyEx(HKEY_LOCAL_MACHINE,
      'System\StorageManager\Profiles\SDMemory',
      0, KEY_EXECUTE, WkHKEY) <> ERROR_SUCCESS then
    begin
      //キーが無いので終了
      Exit;
    end;
    try
      WkSize := 256;
      SetLength(WkGetValue, WkSize);
      RegQueryValueExW(WkHKEY, 'Folder', nil, WkType, WkGetValue, WkSize);
      SetLength(WkGetValue, WkSize);

      WkValue := '';
      if WkType = REG_SZ then
      begin
        //PlatformStringOf関数を通さないと
        //まともな文字列に変換されない
        WkValue := PlatformStringOf(WkGetValue);

        //後に何故か#0が2つ付いているため、
        //以後の文字列連結がおかしなるのを防ぐのに後1バイト削除
        WkValue := Copy(WkValue, 1, Length(WkValue) - 1);
      end;

      //デバッグ
      System.Windows.Forms.MessageBox.Show(WkValue);
    finally
      RegCloseKey(WkHKEY);
    end;
  except
    //SDメモリのフォルダ名取得失敗
    Exit;
  end;
end;

以上でなんとかメッセージボックスで表示するサンプルコードが完成しました。

.NET Compact Framework用じゃないですが、APIによるレジストリの取得方法の参考にしたページです。
●Tips: レジストリの使い方
[http://www.kt.rim.or.jp/~yuta/prog/win32/Registry/index.html]

下のバーの右ボタン・左ボタン

 「ToolBar」を使うのは罠で、これだとボタン名が付けられません。
 「MainMenu」を使うのが正解、ただし他のオブジェクトを移動したりすると「MainManu」に繋がっているはずの「MenuItem」郡のリンクが全て外れてしまう(InitializeComponentからその記述が消える)という現象が起きる為、その部分だけ自分で書いておく必要がある。

//フォームのLoadイベントに書いておくと良い
procedure frmMain.frmMain_Load(sender: System.Object; e: System.EventArgs);
begin
  //この記述がInitializeComponentから勝手に消えるため自分で書く(;;)

  //MainMenu1の子分はMenuItem1・MenuItem2
  Self.MainMenu1.MenuItems.AddRange(
    TArrayOfSystem_Windows_Forms_MenuItem.Create(Self.MenuItem1, Self.MenuItem2));

  //MenuItem2の子分はMenuItem3・MenuItem4
  Self.MenuItem2.MenuItems.Add(Self.MenuItem3);
  Self.MenuItem2.MenuItems.Add(Self.MenuItem4);
 end;

 
 作った「MenuItem」は「MainMenu」でメニューを登録する度に無尽蔵に増えていくため、いつのまにやら余計なMenuItemを作っている可能性がある。
 以下のように「MenuItem」が増えていくため、いらない「MenuItem」はコード上から手作業で削除する必要がある。

type
  frmMain = class(System.Windows.Forms.Form)
  {$REGION 'Designer Managed Code'}
  strict private
    /// <summary>
    /// Required designer variable.
    /// </summary>
~中略~
    MenuItem1: System.Windows.Forms.MenuItem; //生成されるコード
    MenuItem2: System.Windows.Forms.MenuItem; //生成されるコード
    MenuItem3: System.Windows.Forms.MenuItem; //生成されるコード
    MenuItem4: System.Windows.Forms.MenuItem; //生成されるコード
~中略~
procedure frmMain.InitializeComponent;
begin
  Self.FileMoveButton := System.Windows.Forms.Button.Create;
  Self.FileListBox := System.Windows.Forms.ListBox.Create;
  Self.FileMoveProgressBar := System.Windows.Forms.ProgressBar.Create;
  Self.Button1 := System.Windows.Forms.Button.Create;
  Self.Label1 := System.Windows.Forms.Label.Create;
  Self.MainMenu1 := System.Windows.Forms.MainMenu.Create;
  Self.MenuItem1 := System.Windows.Forms.MenuItem.Create; //生成されるコード
  Self.MenuItem2 := System.Windows.Forms.MenuItem.Create; //生成されるコード
  Self.MenuItem3 := System.Windows.Forms.MenuItem.Create; //生成されるコード
  Self.MenuItem4 := System.Windows.Forms.MenuItem.Create; //生成されるコード
  Self.SuspendLayout;
~中略~
  //
  // MenuItem1
  //
  Self.MenuItem1.Index := -1;                           //生成されるコード
  Self.MenuItem1.Text := 'ファイル移動';                    //生成されるコード
  Include(Self.MenuItem1.Click, Self.MenuItem1_Click); //生成されるコード
  //
  // MenuItem2
  // 
  Self.MenuItem2.Index := -1;       //生成されるコード
  Self.MenuItem2.Text := 'メニュー';//生成されるコード
  // 
  // MenuItem3
  // 
  Self.MenuItem3.Index := -1;              //生成されるコード
  Self.MenuItem3.Text := 'オプション(&0)'; //生成されるコード
  // 
  // MenuItem4
  //
  Self.MenuItem4.Index := -1;                          //生成されるコード
  Self.MenuItem4.Text := '終了(&X)';                   //生成されるコード
  Include(Self.MenuItem4.Click, Self.MenuItem4_Click); //生成されるコード

コンポ同士の繋がりが消える

 例えばパネルの上にボタンとか置いたりしても、いつのまにか外れます。
 置いた直後はInitializeComponentにその記述はあるんですけどねぇ…他のオブジェクトを移動したりするだけでその記述だけ消えるんですよね。
 このバグがある限りは、もうデザインがマウスでぱぱっと出来ないことを意味するので、ちょっとやってられません(泣)致命的です。
 仕方ないので、Delphi2006で.NET Compact Frameworkを作る試みはここで一時休止しようと思います。
 Delphi2007 for .NET の.NET Compact Frameworkフル対応を期待して…。

コメント

  • アイデアソース:コピー元・コピー先が指定出来ると色々使えそうですねぇ -- ムーンドルド? 2007-05-16 (水) 12:18:39
  • FindFirstで頭2文字が消える件。その昔、C系の文字列はゼロ終端、Pascal系の文字列は頭2バイトに字数が入り終端記号は無し、という約束事があったのを思い出しました。 -- it(通りすがり)? 2007-09-18 (火) 13:59:54
  • すみません今日気が付きました(遅)、なるほど~情報ありがとうございます^^ -- ムーンドルド? 2007-12-08 (土) 15:49:09