Delphi Tips
>> 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
Osamu Takeuchi osamu@big.or.jp
Tips
Delphi
Home