Delphi Tips 
-----------------------------

キーワード:System

>> Index

06/25 自己実行形式の動画
09/27 入力された漢字のひらがなを取り出す
09/27 アプリケーションを常駐させてタスクトレイに登録したい
05/28 TFileListBox にファイル名が重複して表示されてしまう
02/08 TDDEClientConvで最初の行しか実行されない?
02/08 超高速タイマーコンポーネント(サブミリ秒)
02/08 TDriveComboBoxの内容の更新

最終更新: 7820 日前

0340  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2003/06/25 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/25 osamu 編集
自己実行形式の動画

Exe 内部に動画データをバイナリデータのリソースにしてコンパイルします。D5でのリソースファイルの作り方について:

http://halbow.cool.ne.jp/Notes/N008.html

例えば、'clock.avi' をリソースにする場合、リソーススクリプトファイル(MyRes.rc) は以下のようになります。

MyAVI AVI "c:\WINNT\clock.avi"

このリソースを使って以下のようにして、うまくいきました。

procedure TForm1.Button1Click(Sender: TObject);
var
  RS:TResourceStream;
begin
  RS := TResourceStream.Create(hInstance,'MyAVI','AVI');
  try
    RS.SaveToFile(ExtractFilePath(ParamStr(0))+'MyAVI.avi');
  finally
    RS.Free;
  end;
  if FileExists(ExtractFilePath(ParamStr(0))+'MyAVI.avi') then
    with MediaPlayer1 do begin
      Filename := ExtractFilePath(ParamStr(0))+'MyAVI.avi';
      DeviceType := dtAVIVideo;
      Notify := false;
      Open;
      Notify := true;
      Play;
    end;
end;

procedure TForm1.MediaPlayer1Notify(Sender: TObject);
begin
  MediaPlayer1.Close;
  if FileExists(ExtractFilePath(ParamStr(0))+'MyAVI.avi') then
  begin
    DeleteFile(ExtractFilePath(ParamStr(0))+'MyAVI.avi');
    ShowMessage('AviFile has Deleted!');
  end;
end;
参照: [Delphi-ML:76119] <その他Windows関連> <Windows> <コンポーネント >

0201  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/13 西坂良幸 rev 1.4
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/27 K.Takaoka 編集
入力された漢字のひらがなを取り出す

WM_IME_COMPOSITIONメッセージをとらえて、ImmGetCompositionString関数を処理するのですが、受け取るのはコントロールの場合が多いので、少し工夫が必要です。

この例は、フォームに2つのTEditがあり、
TEdit1で漢字入力すると、TEdit2で入力に利用した平仮名がとれます。
ふりがなを取得するには別の方法を利用します.
// interface
type
  TForm1 = class(TForm)
    Edit1: TEdit;        // 漢字変換を行う
    Edit2: TEdit;        // フリガナを受け取る
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    FDefEditProc: TWndMethod;
    procedure EditWndProc(var Message: TMessage);
  public
  end;

// implementation
uses imm;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // 本来のWndProcを待避する
  FDefEditProc := Edit1.WindowProc;
  // 新しいWndProcを設定
  Edit1.WindowProc := EditWndProc;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // 恐いので元に戻す
  Edit1.WindowProc := FDefEditProc;
end;

// 新しいEdit1のWndProc--ここでメッセーージを捕らえる
procedure TForm1.EditWndProc(var Message: TMessage);
var
  IMC: HIMC;
  Len: integer;
  Str: string;
begin
  with Message do
  begin
    if (Msg = WM_IME_COMPOSITION)
      and ((LParam and GCS_RESULTREADSTR) <> 0) then
    begin
      IMC := ImmGetContext(Edit1.Handle);
      Len := ImmGetCompositionString(IMC, GCS_RESULTREADSTR, nil, 0);
      SetLength(Str, Len + 1);
      ImmGetCompositionString(IMC, GCS_RESULTREADSTR, PChar(Str), Len + 1);
      ImmReleaseContext(Edit1.Handle, IMC);
      SetLength(Str, Len);
      Edit2.Text := Str;
      // Edit2.Text := Edit2.Text + Str; // でもよい
      // イベントを作成してもよい
    end;
    FDefEditProc(Message);
  end;
end;


実際は、メッセージを捕まえるコンポーネントのイベントなどで、必要なコントロールに渡すのがいいでしょうか。

参照: [Delphi-ML:41353] [Delphi-ML:41355] <その他コンポーネント関連> <コンポーネント >

0207  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/19 西坂良幸 rev 1.10
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/27 西坂良幸 編集
アプリケーションを常駐させてタスクトレイに登録したい

コンポーネントをつかう人が多いんでしょうね。MLでは少ない話題です。このようなAPLを何十本も作るんでなければ、直接コーディングしてみませんか。
要領は、APIのShell_NotifyIcon関数を使うことです。TaskTrayへの登録と削除は簡単にできます。
頭を悩ますのは、どんなアイコンを使うのかと、TaskTrayに送られてくるメッセージを自分で決めなければならないことです。

const
  WM_MY_TRAYICON = WM_APP + $300; // 適当です

// ProcessMesageに配慮−−無くても良い
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // WM_QUIT メッセージを受け取る時
  if Application.Terminated then
  begin
    ShowWindow(Application.Handle, SW_HIDE);
    Visible := False;
    Action := caNone;
  end;
end;

// アイコンをトレイに登録−−ここではメインアイコンを使用
procedure TForm1.CreateTaskBarIcon;
var
  NotifyData: TNotifyIconData;
begin
  with NotifyData do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd    := hWndTrayIcon;
    uID    := 0;
    uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
    szTip  := 'Traybar Tip';
    hIcon  := Application.Icon.Handle;
    uCallbackMessage := WM_MY_TRAYICON;// 独自に定義
  end;
  Shell_NotifyIcon( NIM_ADD, @NotifyData );
end;

// アイコンを削除
procedure TForm1.DeleteTaskBarIcon;
var
  NotifyData: TNotifyIconData;
begin
  with NotifyData do
  begin
    cbSize := SizeOf(TNotifyIconData);
    Wnd    := hWndTrayIcon;
    uID    := 0;
  end;
  Shell_NotifyIcon( NIM_DELETE, @NotifyData );
end;

// 起動直後はトレイにアイコン表示のみ
procedure TForm1.FormCreate(Sender: TObject);
begin
  // uTaskBarRecrate は TForm1 の private に UINT 型で宣言
  // 新しい UtilWindow を作成し、ブロードキャストメッセージのみを受け取らせる
  uTaskBarRecreate := RegisterWindowMessage('TaskbarCreated');
  // hWndTrayIcon は TForm1 の private に HWND 型で宣言
  // メッセージ送信先を指定
  hWndTrayIcon := AllocateHWnd(TaskTrayWndProc);

  CreateTaskBarIcon;
  ShowWindow(Application.Handle,SW_HIDE);
  Application.ShowMainForm := False;
end;

// 終了した時にトレイのアイコンを削除
procedure TForm1.FormDestroy(Sender: TObject);
begin
  DeleteTaskBarIcon;
  DeallocateHWnd(hWndTrayIcon);
end;

// タスクトレイに来るWM_MY_TRAYICONメッセージを受信
procedure TForm1.TaskTrayWndProc(var Msg: TMessage);
var
  ps: TPoint;
begin
  Case Msg.LParam of
    WM_LBUTTONDBLCLK:
      begin
        Visible := true;
        ShowWindow(Application.Handle,SW_SHOW);
        //ShowWindow(Application.Handle,SW_RESTORE);
      end;
    WM_RBUTTONUP:
      begin
        GetCursorPos(ps);
        SetForegroundWindow(Handle);
        // フォームにポップアップメニューがあるとする
        PopupMenu1.Popup(ps.x,ps.y);
        PostMessage(Handle, WM_NULL, 0,0);
      end;
    else
      // タスクバーが移動・再構築された場合に消えたアイコンを再生成
      if (Msg.LParam = LongInt(uTaskBarRecreate)) then
        CreateTaskBarIcon;
  end;
end;

AllocateHWnd 関数の戻り値のウィンドウハンドルを利用すれば他のメッセージ受信先/送信先として利用できるので、TrayIcon のメッセージ送信先に利用しました。
参照: [Delphi-ML:2536] [Delphi-ML:11821] [Delphi-ML:35250] <Windows> <フォーム> <コンポーネント >

0192  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/05/28 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/05/28 osamu 編集
TFileListBox にファイル名が重複して表示されてしまう

TFileListBox.Mask に、'*.txt;*.?x?' などと入力した場合、もし複数の Mask に合致するファイル(例えば、example.txt)があると、そのファイルはダブって表示されてしまいます。これを回避する単純な方法は、TDirectoryListBox.OnChange にて、重複しているファイル名を削除してやることです。

procedure Form1.DirectoryListBox1Change(Sender: TObject);
var i: Integer;
begin
    for i:=FileListBox1.Items.Count-2 downto 0 do
        if FileListBox1.Items[i]=FileListBox1.Items[i+1] then
            FileListBox1.Items.Delete(i+1);
end;

この位のことは、TFileListBox 自身で面倒を見てもらいたいものですが。。。
参照: <コンポーネント >

0084  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
TDDEClientConvで最初の行しか実行されない?

TDDEClientConv を使って、ステップ実行を行うとちゃんとマクロは実行されるのですが、そのまま実行すると、最初のコマンドのみ実行してその後が実行されません。

これは2.0からのバグです。3.0/3.1用のパッチを当てると直ると思います。

http://www.dataweb.nl/~r.p.sterkenburg/bugsall.htmが詳しいです。
日本語版でも通用する個所が多いです。参考にしてみて下さい。

1)必要なったらTDDEClientConvをCreate
2)マクロを実行
3)用が済んだらFree
で逃げられます。
参照: [Delphi-ML:19657] <その他Windows関連> <ShellApi> <Windows> <バグ> <コンポーネント >

0111  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
超高速タイマーコンポーネント(サブミリ秒)

DSPで見つけたのは「TZTimer」コンポーネントでした。

以下 Readme からの抜粋。
----------
Similar to the vcl Ttimer component, but with a resolution of 0.1ms and accurate to 0.015ms.

(略)

Resolution could be improved considerably when the RDTSC (pentium) instruction is utilized, however I had to get this timer working on a 486 also.
It was tested on D2 and D3 for W95, it should also work on D1 and W3.1.
However it will not work in Windows NT (?).

Some observed timing measurements of Tztimer, compared with the (vcl) Ttimer
:
{ evaluation of 60 runs on W95, P133, D3}

interval    (vcl) Ttimer           Tztimer
100  ms      108 +/- 4 ms          99.3  +/- 0.14  ms
 10  ms       59 +/- 5 ms          10.1  +/- 0.07  ms
  1  ms       59 +/- 6 ms (!)       1.00 +/- 0.02  ms
  0.1ms       Not available         0.098+/- 0.015 ms
----------
参照: [Delphi-ML:21828] <コンポーネント >

0017  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
TDriveComboBoxの内容の更新

ネットワークドライブの割当てをした後、TDriveComboBoxにて割当てたドライブを反映させたいのですが、方法が解りません。

    DriveComboBox1.TextCase:=DriveComboBox1.TextCase;

たぶんこれが一番楽な方法だと思います。
非常に裏わざ臭いですが。。。
参照: [Delphi-ML:7162] <バグ> <コンポーネント > <ファイル>

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords

Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp