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

キーワード:Windows

>> Index

01/22 短いファイル名を長いファイル名に変換したい(COM版)。
12/31 リンクファイルから参照先のファイル名を得る
03/04 フォームの最小化時のアニメーション効果を出す(BCB)
11/21 子プロセス(DOS)の標準出力をパイプする
07/18 スクリーンセーバーの作り方
06/27 Delphi によるレジストリの操作方法
06/27 システムアイコンをリフレッシュする
06/27 コントロールパネルを作る
06/27 全てのウィンドウを最小化する
06/25 自己実行形式の動画
06/25 ActiveX でショートカットキーが使えない
06/25 FindFirst でアイコンを変更したディレクトリを検索できない
06/25 FindFirst による4文字以上の拡張子の判別
05/17 ActiveX 内部から自身の親ウィンドウのハンドルを得る
08/25 ComCtl32.DLL を配布するには
12/28 Windows2000の新APIを使った半透明ウィンドウ
11/30 スクリーンセーバーの名前を変更する。
11/16 INI ファイルを扱うもう1つのクラス
10/07 文字列リソースの編集ツール - 文字列テーブルエディタ
09/30 アクティブデスクトップを使って壁紙を変更
09/27 デスクトップにあるアイコンの数と位置を知りたい。
09/27 アップリケーションにサウンドリソースを埋め込んで使いたい。
09/27 エクスプローラからファイルをドラッグ&ドロップする
09/27 アプリケーションを常駐させてタスクトレイに登録したい
09/26 ファイルを削除してゴミ箱に移動させたい。
09/24 Windows 特殊フォルダの Class ID List
09/23 シェルのデスクトップやマイコンピュータをプログラムから開きたい。
09/22 長いファイル名を短いファイル名に変換したい
09/20 エクスプローラのように、アプリケーションにブラウザページをつくりたい。
09/20 MDI等で二重起動を防止して新しいファイルを開く
09/19 二重起動の判定
09/19 インターネット エクスプローラを起動したい/その情報を取得したい
09/17 起動中のブラウザからURLを取得する/ブラウザにURLをセットする方法
09/08 IME に未確定文字列を入力
09/08 フォルダのタイムスタンプを変更する
09/06 メインフォーム以外のフォームをタスクバーに入れたい。
09/06 APPのフォームを最小化して起動したい
09/02 Windowsの「ファイルの検索」ダイアログをプログラムから使いたい
09/01 フォームの最小化、最大化をアニメーションでやりたい。(DELPHI)
08/30 メインフォーム以外のフォームを最小化した時もAPP全体を最小化したい
08/26 ダイヤラを呼び出す。(TAPI32.DLLの使用)
08/26 他のアプリの起動パスを取得する
08/26 セルのテキストをドラッグイメ−ジにしてグリッド(TStringGrid)でドラッグ&ドロップを行う
08/23 デスクトップのウィンドウのタイトルとハンドルを取得する
08/23 プロセスの実行ファイル名を列挙する
08/23 Win95/98で、ウィンドゥハンドルから、実行アプリ名を知る
08/23 WinNT でウィンドウハンドルから実行アプリ名を知る
08/21 クリップボードのフォーマットを知る
08/21 クリップボードが更新された時のイベントを取得する
08/19 インターネットエクスプローラのアドレス帳を呼び出す
07/28 HTML-Help を作りたい
07/07 CapsLock の状態を変更する
05/19 独自メッセージとして自由に使える値の範囲
05/19 「送る」の 516 文字制限について
03/21 アプリケーション間でデータの送受信(WM_COPYDATAを使う)
02/11 IME 入力で読み仮名を取得する
02/11 カレントユーザのデスクトップディレクトリを得る
02/11 IniFile に書き込みを行った後にはバッファのクリアが必要
02/11 TFileStream で標準出力に表示
02/11 半角カナを確定無しで直接入力させる
02/11 CreateProcess を使うときは CloseHandle で後始末
02/11 ディスパッチインターフェイスとデュアルインターフェイスについて
02/11 マウスがクリックされた正確な時刻が知りたい
02/11 エクスプローラで使われるアイコンを取得・変更する
02/11 クリップボードにコピーされたファイル・ディレクトリ
02/11 リムーバブルドライブの種類を判別する
02/11 Bitmap のパレットに使いたい色を追加する
02/08 Delphi で DOS のアプリを書く方法
02/08 Delphi/CBuilder で作った DLL から VB に文字列を返す
02/08 コントロールパネルのスクリーンセーバの設定画面を表示させる
02/08 Windows95 のみを再起動する
02/08 他プロセスの Window を GUI で選ばせたい
02/08 実行終了後、自分自身(実行ファイル)を削除したい
02/08 メタファイルを wmf 形式でコピーするときの注意
02/08 デスクトップフォルダのパスを得る
02/08 CD-DA のデータを Wav ファイルに落としたい
02/08 複数プログラムから同一内容のメモリを参照/更新する
02/08 プログラムからWindowsのスタートメニューを表示する
02/08 SetWindowsExt/SetViewportExtを使うときの注意点
02/08 スクリーンセーバーをプログラムから停止する
02/08 Delphiアプリをマウスのホイールに対応させたい
02/08 ヘルプ作成用のホットスポットエディタ(SHED.EXE)の入手方法
02/08 「システムエラー 読み出せません ドライブ X:」ダイアログを回避する
02/08 自作コントロールで IME 入力時の変換候補をキャレット位置に表示したい
02/08 TDDEClientConvで最初の行しか実行されない?
02/08 起動したアプリケーションの終了待ち
02/08 NT のタスクマネージャにアプリケーションのアイコンが表示されない
02/08 DDeClientConv を使ってスタートメニューにアイコンを登録
02/08 スタートメニューを任意の位置にポップアップさせる
02/08 Windowsの「ファイルの検索ダイアログ」を表示させる
02/08 自作アプリで作ったオブジェクトを他のアプリに貼り付けたい
02/08 TrueTypeフォントからベクタ情報を得る
02/08 32bitアプリから16bit DLLを呼び出す
02/08 Delphi3.0でDLLにバージョン情報が入らない
02/08 Delphi 1.0 (16bit)で、物理メモリアドレスに直接アクセスする
02/08 NTで他のアプリが開いているファイルを知る

最終更新: 6641 日前

0273  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/24 西坂良幸 rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2006/01/22 <> 編集
短いファイル名を長いファイル名に変換したい(COM版)。

エクスプローラは内部的には、短い名前を使っているようです。
ということは、シェルのCOMインターフェースのメソッドが使えるということです。
[Tips:233]のCOM版を考えてみましょう。

uses ShlObj,Comobj,ActiveX;

function ShortToLongFileName(const ShortName: string): string;
var
  Desktop: IShellFolder;
  pIDList: PITEMIDLIST;
  NameS: String;
  NameW: WideString;
  Len : integer;
  Buffer: array[0..MAX_PATH] of Char;
  // 以下は値は使わない
  pDummy: PCHAR;
  pchEaten, Attributes: ULONG;
begin
  pIDList := Nil;
  // フルパス化
  Len := GetFullPathName(PChar(ShortName), 0, PChar(result), pDummy);
  SetLength(NameS, Len);
  GetFullPathName(PChar(ShortName), Len, PChar(NameS), pDummy);
  // ワイド文字列に転換
  NameW := NameS;
  // IShellFolderを生成(解放は自動)
  OleCheck(SHGetDesktopFolder(Desktop));
  // IDリストをえる
  OleCheck(Desktop.ParseDisplayName(0, Nil, PWideChar(NameW), pchEaten, pIDList, Attributes));
  if not SHGetPathFromIDList(pIDList, Buffer) then
  raise EConvertError.Create('ファイルを変換できません。');
  Result := StrPas(Buffer);
end;


WideStringを使うことを覗けば、IShellFolderのParseDisplayNameメソッドとSHGetPathFromIDList
を使うだけです。[Tips:233]よりすっきりしましたか。

※ 使用できるOS、バァージョンに注意して下さい。
参照: [Delphi-ML:7322] <その他Windows関連> <ファイル> <PASCAL>

0099  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2005/12/31 長山 編集
リンクファイルから参照先のファイル名を得る

IShellLinkを使用すれば出来ます。

    CoInitialize(NULL);

    HRESULT HR;
    IShellLink *psl;
    IPersistFile *ppf;
    WideChar wsz[MAX_PATH];
    char szGotPath[MAX_PATH];
    WIN32_FIND_DATA wfd;

    HR = CoCreateInstance(CLSID_ShellLink, NULL,
                CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
    if(SUCCEEDED(HR)){
        HR = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
        if(SUCCEEDED(HR)){
            MultiByteToWideChar(CP_ACP, 0, "ショートカット.lnk", -1,
                    wsz, MAX_PATH );
            HR = ppf->Load( wsz, STGM_READ );
                if(SUCCEEDED(HR)){
                    HR = psl->Resolve(Application->Handle, SLR_ANY_MATCH);
                    if(SUCCEEDED(HR)){
                        HR = psl->GetPath(szGotPath, MAX_PATH,
                                (WIN32_FIND_DATA *)&wfd, SLGP_SHORTPATH );
                        Edit2->Text = szGotPath;
                    }
                }
            }
            ppf->Release();
        }
        psl->Release();
    }
    CoUninitialize();



Delphi翻訳版 (関数です)

uses
  Windows, SysUtils, ShlObj, ActiveX, ComObj;
  
const IID_IPersistFile: TGUID= (D1:$0000010B;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));

function ExtractStringFromLinkFile( Target:TFileName ): String;
var
    R   : HRESULT;
    SL  : IShellLink;
    PF  : IPersistFile;
    Wrk : array[0..MAX_PATH] of WideChar;
    Path: array[0..MAX_PATH] of Char;
    WFD : WIN32_FIND_DATA;
begin
    Result := '';
    CoInitialize( NIL );

    R := CoCreateInstance( CLSID_ShellLink, NIL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, SL );
    if Succeeded( R ) then
    begin
        R := SL.QueryInterface( IID_IPersistFile, PF );
        if Succeeded( R ) then
        begin
            MultiByteToWideChar( CP_ACP, 0, PChar(Target), -1, Wrk, MAX_PATH );
            R := PF.Load( Wrk, STGM_READ );
            if Succeeded( R ) then
            begin
                R := SL.Resolve( 0{Application.Handle}, SLR_ANY_MATCH );
                if Succeeded( R ) then
                begin
                    SL.GetPath( Path, MAX_PATH, WFD, SLGP_SHORTPATH );
                    Result := Path;
                end;
            end;
        end;
    end;

    CoUninitialize;
end;
参照: [builder:5475] <ShellApi> <ファイル>

0057  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2004/03/04 osamu 編集
フォームの最小化時のアニメーション効果を出す(BCB)

BCBで作成したアプリだけは、他のアプリと異なり、Win95で「アイコン化」したときなどのタイトルバーのアニメーション(タイトルバーがひゅるるっとタスクバーに吸い込まれるようなアレ)が出ないようなのですが、これはBCBの仕様なのでしょうか?あるいは出す方法があるとか??
  Delphiでもそうですよ!!

 これは、BCB が使用しているライブラリ VCL の仕様のようです。

 アニメーションを実現するには、プログラムを組む必要がありますが、(別項でDELPHIでのコード例を見て下さい)
既にこのようなコンポーネントが発表されています。

http://www.delphianworld.com/direct.html?id=SY0042

TAnimateWindowというのがそれのようです。
参照: [Delphi-ML:34432] [builder:4884] <フォーム>

0115  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/11/21 osamu 編集
子プロセス(DOS)の標準出力をパイプする

こんなんでどうでしょう?(↓)
    CreatChildProcess('cmd.exe /c dir');
とやると、Memo1に"dir"の結果が表示されます(NT4.0では動きました)。

ただし、標準出力をリダイレクトしてしまっているので、DOS窓(コンソール)には、なにも表示されません(この例では、コンソールを表示しないようにしていますが、表示しても空のコンソールが表示されるだけです)。
どうしてもコンソールにも表示したい場合は、AllocateConnsoleAPIで自前でコンソールを作成して、Memo1に書く内容を自前で書くのかなぁ?

あとエラー処理等まるっきり省いていますのでご注意を。

function TForm1.CreatChildProcess(exec_name: AnsiString): Integer;
var
  buf: array[0..4095] of Char;
  hRead, hWrite: THandle;
  SecAttrib: TSecurityAttributes;
  StartInfo: TStartupInfo;
  dwRead: DWORD;
begin
  //
  // 名前なしパイプの作成
  //
  FillChar(SecAttrib, SizeOf(SecAttrib), 0);
  SecAttrib.nLength := SizeOf(SecAttrib);
  SecAttrib.bInheritHandle := TRUE;
  CreatePipe(hRead, hWrite, @SecAttrib, 0);

  //
  // 子プロセスを作成
  //
  FillChar(StartInfo, SizeOf(StartInfo), 0);
  StartInfo.cb := SizeOf(StartInfo);
  StartInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  StartInfo.hStdOutput := hWrite;
  StartInfo.wShowWindow := SW_HIDE;
  if not CreateProcess(Pointer(0),
              PChar(exec_name),
              Pointer(0), Pointer(0),
              TRUE,
              0,
              Pointer(0), Pointer(0),
              StartInfo, ProcInfo) then
  begin
    Result := -1;
    Exit;
  end;
  WaitForInputIdle(GetCurrentProcess(), INFINITE);
  CloseHandle(hWrite);

//
//  Windows95ではこの部分で制御を返してくれなくなります。
// もうちょっとしたら対処法を書くつもり。
// いつになることやら。。。(--;
//
  While ReadFile(hRead, buf, SizeOf(buf) - 1, dwRead, Nil) do
  begin
    if dwRead = 0 then
      Break;
    buf[dwRead] := #00;
    Memo1.Lines.Add(buf);
    Application.HandleMessage;
  end;

  CloseHandle(hRead);
  Result := 0;
end;


[追記] Autch.net さんの tips にもソースが挙げられているとの情報を得ました。[Delphi-ML:79357]

Autch.net
http://hp.vector.co.jp/authors/VA026252/

GUI アプリからコンソールアプリを実行するには
http://hp.vector.co.jp/authors/VA026252/tips/delphi_anonymous_pipe.html
参照: [Delphi-ML:21973] [Delphi-ML:79357]

0345  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2003/07/18 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/07/18 osamu 編集
スクリーンセーバーの作り方

Ryota Ando さんの、「Delphi で作るスクリーンセーバー制作講座」
http://www02.so-net.ne.jp/~rando/delphi/how2ss/index-f.html
に詳しいです。

参考として、以下の URL も紹介されています。

HowToScr - technical documentation
http://www.wischik.com/scr/resources.html
  How to write a 32bit screen saver
  http://www.wischik.com/scr/howtoscr.html

screensavergallery.com: Developers Corner
http://www.screensavergallery.com/Developers_Corner/

Borland Technical Information
http://www.borland.com/devsupport/delphi/ti_list/TI4534D.html

Microsoft Visual J++ 6.0 Developer's Workshop
http://mspress.microsoft.com/vstudio/books/sampchap/2275.htm#94
参照: [Delphi-ML:31792] <その他Windows関連>

0170  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/03/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/27 osamu 編集
Delphi によるレジストリの操作方法

ひきさんのページで詳しい解説をしてくださっているので、参考にすると良いでしょう。

[Delphi 壁の穴]-[その三:レジストリを覗く]
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabereg.htm

以下は内容:

レジストリ操作の基本を知る
レジストリにアプリケーションの設定を保存する
レジストリにファイルの関連づけを設定する
レジストリにDWORD値を記録させる
レジストリにバイナリ値を記録させる
各種のシェルフォルダを得る(レジストリ版)
REGファイルを作る
TRegistryでDeleteKeyできない
TRegIniFileでキーを丸ごと削除したい
キーの指定で「\」付きとなしではどう違うのか
参照: <その他Windows関連>

0175  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/03/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/27 osamu 編集
システムアイコンをリフレッシュする

フォルダのアイコンなど、システムで使われるアイコンを変更した後は、ちょっとしたトリックを使わないと画面に反映されません。
具体的には、一旦アイコンの大きさを変更してまた元に戻すのだそうです。ひきさんのページでサンプルコードを見ることができます。

[Delphi壁の穴]-[その二:システムを覗く]
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#refreshsysicon
参照: <バグ> <アイコン>

0176  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/03/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/27 osamu 編集
コントロールパネルを作る

コントロールパネル(*.CPL)を作るなんてさぞかし難しいように思われるかも知れませんが、案外簡単に作れてしまいます。とのことです。
ひきさんのページへGo!

[Delphi壁の穴]-[その二:システムを覗く]
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#controlpanel
参照: <その他Windows関連>

0174  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/03/08 osamu rev 1.6
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/27 osamu 編集
全てのウィンドウを最小化する

Keybd_event を使って、[WindowsKey(ミ田)]+[M] を押してやると言う手法が、ひきさんの日本Delphi振興会のページで紹介されています。

[Delphi壁の穴]-[その2:システムを覗く]
http://hp.vector.co.jp/authors/VA009712/take/delphi/kabesys.htm#allminimize

Windows+Mを押すと全起動APPが最小化するいうこと知っていましたか?
知らなかったらこのコードは書けませんね。
procedure TForm1.Button1Click(Sender: TObject);
begin
  Keybd_event(VK_LWIN,   0, 0, 0);  //Windowsキーを押す
  Keybd_event(Byte('M'), 0, 0, 0);  //Mキーを押す
  Keybd_event(Byte('M'), 0, KEYEVENTF_KEYUP, 0); //Mキーを離す{この行:必要ないかも知れない}
  Keybd_event(VK_LWIN,   0, KEYEVENTF_KEYUP, 0);  //Windowsキーを離す
end;

Byte('M')の代わりにOrd('M')を用いてもよいでしょう。

そして、この操作で最小化したAPPを元に戻すには、
Windows+Shift+Mキーを押します。
Keybd_eventの書き方は分りますね。Shiftキーの仮想キーコードはVK_SHIFTです。

また、Win98やIE4以降インストールでデスクトップ統合を行った
Windowsでは
Windows+Dキーで
『全ウィンドウの最小化』←→『元に戻す-すべて最小化』
を切りかえられます。
参照:

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関連> <System> <コンポーネント >

0334  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 編集
ActiveX でショートカットキーが使えない

ActiveXをd3・d4で取り込むと ActiveX に組み込まれているショートカットキーが使えないものがあります。

どうも、TOLEControlの親であるTWinControlでショートカットのメッセージが止まっていて、activeXに渡されてないようなのです。

ちょっとうまい対処の方法が思いつかないのですが、とりあえずApplication.OnMessage をつかってOleInPlaceActiveObject.TranslateAccelerator(Msg); で、activeXに直接伝えれば、症状を回避できるようです。

由木尾@蛸薬師倶楽部さんが具体的なコードを [Delphi-ML:32242] に示してくださっています。
参照: [Delphi-ML:32242] <その他Windows関連> <バグ>

0331  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 編集
FindFirst でアイコンを変更したディレクトリを検索できない

Delphi7, WinXPです。XPにはフォルダのアイコンイメージを変更することができるのですが、これを適用したフォルダをFindFirstは認識しません。

この投稿に簡単な解決法は投稿されませんでした。FindFirstFileEx API や Shell 関連の API を使うことで回避できるかもしれないとの意見がありました。
参照: [Delphi-ML:73372] <ファイル>

0330  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2003/06/25 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/06/25 osamu 編集
FindFirst による4文字以上の拡張子の判別

Q.FindFirst,FindNextを使用してファイル名を取得しているのですが、PATH定数を "C:\TEST\*.jpg" と指定した場合、拡張子が「.jpg」のファイルだけでなく退避用にリネームした”XXXX.Jpg_”といったファイルまでヒットしてしまいます。

A.WinXPには4文字以上の拡張子を正しく認識させるためのレジストリが用意されています。以下の方法を試してみてはいかがでしょうか。Win2000でも同じことができるかどうかはわかりません。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem の Win95TruncatedExtensions を 0 にして再起動。
参照: [Delphi-ML:73374] <ファイル>

0319  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2002/05/17 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2002/05/17 osamu 編集
ActiveX 内部から自身の親ウィンドウのハンドルを得る

Q:
ActiveXコントロールに関する事です。親ウインドウをサブクラス化しようとする時に必要なウインドウハンドルをparent等で、取得することができませんでした。(nilが返される)

A:
IE4 以降の ActiveX コントロールでは、ウィンドウハンドルを持たないことが多い ( ウィンドウレスコントロール ) ので、親ウィンドウのウィンドウハンドルは自分自身のウィンドウハンドルであることが多いです。

Internet Explorer のようなアプリケーションを見て貰えるとわかるかもしれませんが、Windows でいう「ウィンドウ」は一番親にあたるコンテナ1つ以外には一切作成されなかったりします。

それで、ActiveX コントロールが乗っかっているコンテナのウィンドウハンドルはは、InPlaceSite プロパティの GetWindow メソッドを利用すれば得られます。
参照: [Delphi-ML:67312] <その他Windows関連>

0158  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2000/08/25 ITO, Sakuya 編集
ComCtl32.DLL を配布するには

Delphi4 で作成した ComCtrl32.DLL のバージョンに依存するプログラムに ComCtl32.DLL を添付して配付すると MS の EUL に違反します。CDに入ってる 40comupd.exe を添付すれば問題はないです。

インストーラを利用する場合は /q をオプションにつけて呼び出すとMicrosoft の承諾文章が出ませんがその場合の注意点なんてのもあるので詳しくは Microsoft のサイトの EUL を読んでください。

# まあ、Win95/Win98, WinNT で ComCtl32.DLL に互換性ないし
# ComCtl32.DLL を含めて配付できたとしても面倒ですね。

//2000.08.25 by Sakuya ITO 
その時点で最新のComCtl32.DLLの配布用インストーラ ??comupd.exe は、Microsoftの次のURLからダウンロードできます。これ1本で日本語を含む各国言語に対応しています。
http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp
参照: [Delphi-ML:30766] <配布>

0289  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/12/19 Atsushi Shinoda rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/12/28 osamu 編集
Windows2000の新APIを使った半透明ウィンドウ

最近、雑誌の付録についていたWin2kRC2をインストールして「半透明ウィンドウを作ってみよう」と思い立ち、TClock(KAZUBON氏作のフリーソフト)のソースファイルを参考に作ってみたので紹介します。
ウィンドウの拡張スタイルにWS_EX_LAYEREDを指定して、SetLayeredWindowAttributesというAPIを使います。このAPIの詳細は http://msdn.microsoft.com/library/psdk/winui/windows_1p6b.htm を参照してください。(英語)
Win2kを使っている方は、ちょっとした遊びのつもりで試してみてください。(^^;;;

FormにScrollBarを1つ置いて、FormCreate, FormDestroy, ScrollBar1Changeのイベントを使っています。ScrollBarを動かすと、Formの透明度が変化します。


{API宣言}
type
  TSetLayeredWindowAttributes
    = function(wnd: HWND; crKey: DWORD;
        bAlpha: BYTE; dwFlag: DWORD): Boolean; stdcall;

const
  WS_EX_LAYERED = $80000;
  LWA_ALPHA = 2;

var
  hLibUser32: THandle;
  MySetLayeredWindowAttributes: TSetLayeredWindowAttributes;


implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  p: Pointer;
begin
  hLibUser32 := LoadLibraryA('user32.dll');
  MySetLayeredWindowAttributes := nil;
  if hLibUser32 <> 0 then begin
    p := GetProcAddress(hLibUser32, 'SetLayeredWindowAttributes');
    if p = nil then begin
      FreeLibrary(hLibUser32);
      hLibUser32 := 0;
    end else begin
      MySetLayeredWindowAttributes := TSetLayeredWindowAttributes(p);
    end;
  end;
  if hLibUser32 <> 0 then begin
    SetWindowLong(Handle, GWL_EXSTYLE,
      GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
    ScrollBar1.Position := ScrollBar1.Max;
    ScrollBar1Change(Self);
  end else begin
    ShowMessage('OSが半透明ウィンドウに対応していません!');
    Application.Terminate;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if hLibUser32 <> 0 then begin
     FreeLibrary(hLibUser32);
     hLibUser32 := 0;
  end;
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
var
  alpha: Integer;
begin
  if hLibUser32 <> 0 then begin
    alpha := ScrollBar1.Position;
    alpha := alpha * 255 div (ScrollBar1.Max - ScrollBar1.Min);
    if alpha < 8 then alpha := 8;
    if alpha > 255 then alpha := 255;
    MySetLayeredWindowAttributes(Handle, 0, Byte(alpha), LWA_ALPHA);
  end;
end;

参照: [Delphi-ML:44902] <その他Windows関連>

0252  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/09 濱野 rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/11/30 K.Takaoka 編集
スクリーンセーバーの名前を変更する。

スクリーンセーバーに名前を付ける場合、{$D }コンパイラ指令でリソース文字列を埋め込んでもコントロールパネルの画面の設定には反映されません。これはWin95/WinNT4.0からの新GUIに移行した際に、コントロールパネルで表示されるスクリーンセーバーの名前はファイル名そのものに変更されたためです。

しかし、 Delphi のプロジェクト名には日本語を使う事は出来ないので、日本語名を付けたい場合はバッチなどで変更するようにします。

COPY C:\MyProj\MySaver.exe "C:\Windows\まい せーばー.scr"

ただし、ファイル名が 8 バイトまでの場合に、先頭が SS で始まっていると、SS は削除されます。
例) sstest.scr → test

Microsoft の技術文章によると Win16/Win32 ともに、スクリーンセーバーの説明は {$D } にて 25 文字までで指定しておくことになっています。

この値を有効にするためには、ファイル名を 8 文字までにし、すべてを大文字にする必要があります。

ex) SSTEST.SCR

このようにすることで {$D} にて設定した 25 文字までの内容をコントロールパネルのスクリーンセーバーの選択肢として表示できるようになります。
参照: <その他Windows関連>

0287  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/11/16 K.Takaoka rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/11/16 K.Takaoka 編集
INI ファイルを扱うもう1つのクラス

みなさん TIniFile を利用して Windows の .ini というファイルを扱われていると思いますが、Inifiles Unit には TMemIniFile というクラスがあります。

TIniFile は Windows API をカプセル化しているので以下のような制限・仕様があります。

・ファイルサイズは 64k bytes までしか認識しない
・1つのセクションの大きさは 32k bytes までしか扱えない
・コメントの概念が存在しない(無意味なキーを使って実現)
・クオーテーションを自動除去する
・Win95/98 では TAB 文字が扱えない
・WInNT では読み書きキャッシングが行われない

最初の2つは容量の制限。
最後の2つは重要で、Win95/98 では TAB 文字を扱えないために

[Section]
Key=Value    タブで区切って Key の意味を説明書き

なんて記述ができてしまい、WinNT でヒドイ目を見ますし、 WinNT では INI ファイルへの読み書きをレジストリに読み書きするためのマッピング処理のため、キャッシュが効かずに低速です。
また、キャッシングの有無に違いがあるため、キャッシュの操作を忘れると INI ファイルを頻繁に読み書きする際に挙動不審になるという弊害もあります。

TMemIniFile は上のような点をすべて解決します。

・ファイルサイズの制限はシステムによってのみ制限される。

・セクションの大きさはファイルサイズによってのみ制限される。

・行頭が ; で開始する行をコメントとして扱う
( ';hoge' のようなキー名は扱えないということです )

・クオーテーションの自動削除は行わない

・OS に関係なく行末までを読み出すことができる

・すべての変更は常にメモリ上にキャッシュされる
( UpdateFile を呼ばずに Free すると変更は無効になります )

と、なります。
TMemIniFile の保存処理で String 型の変数を介すため、2G Bytes までということになりますが、すべての Win32 環境で利用可能な最大メモリ量が 1.995G Bytes ですので、この制限は問題にならないでしょう。
参照:

0281  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/10/07 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/10/07 osamu 編集
文字列リソースの編集ツール - 文字列テーブルエディタ

> .RCファイルは手でも書けるということですが、ツールがあれば使
> いたいと思いましたのでヘルプを探してみました。
> すると、Delphi4のヘルプに、「文字列テーブルエディタ」という
> ものがあったのですが使い方が分かりません。

これの表示の仕方ですが、

1.適当なプロジェクトを開く

     もちろん、いじりたいリソースが resourcestring で定義されている
     プロジェクトです。エラーメッセージだけ編集するなら resourcestring
     がなくても OKAY(エラーメッセージもこれでいぢれるんですね!)

2.新規作成 → リソースDLL

     対象になる dfm を追加し、リソースDLLのプロジェクトを作成して
     ください。

3.表示 → プロジェクトグループ

     プロジェクトグループの一覧が出ます。(すでに出てないなら)
     ここから、2 で作成した言語のプロジェクトを開いてください。

4.言語.rc をダブルクリック

     これでOK!
参照: [Delphi-ML:34134] <開発環境> <その他Windows関連>

0278  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/30 篠田 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/30 篠田 編集
アクティブデスクトップを使って壁紙を変更

アクティブデスクトップを使うには、IActiveDesktop を使います。
Microsoftが提供しているリファレンスはhttp://msdn.microsoft.com/library/sdkdoc/shellcc/Shell/IFaces/IActiveDesktop/IActiveDesktop.htmにあります。


uses ShlObj, ComObj;

// IActiveDesktop を使って壁紙を変更する
procedure TForm1.Button1Click(Sender: TObject);
var
  hObj : IUnknown;
  ADesktop : IActiveDesktop;
  str : String;
  wstr : PWideChar;
begin
  hObj := CreateComObject(StringToGUID('{75048700-EF1F-11D0-9888-006097DEACF9}'));
  ADesktop := hObj as IActiveDesktop;
  if OpenDialog1.Execute then begin
    wstr := AllocMem(MAX_PATH);
    StringToWideChar(OpenDialog1.FileName, wstr, MAX_PATH);
    ADesktop.SetWallpaper(wstr, 0);
    ADesktop.ApplyChanges(AD_APPLY_ALL);
    FreeMem(wstr);
  end;
end;

ここでActiveDesktopのクラスIDとして {75048700-EF1F-11D0-9888-006097DEACF9} というマジックナンバーが使われていますが、もしかしたら将来Windowsのバージョンが変わるとこの値も変わる可能性があります。
しかし[Delphi-ML:42104]に書かれているように、アクティブデスクトップはWindowsの準(?)標準コンポーネントですので、恐らく問題ないと思います。
一応、\\HKEY_CLASSES_ROOT\CLSID\{75048700-EF1F-11D0-9888-006097DEACF9}\(標準) に "ActiveDesktop" という文字列が登録されているのを見つけることができます。
参照: [Delphi-ML:42096] <デスクトップ>

0108  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/27 西坂良幸 編集
デスクトップにあるアイコンの数と位置を知りたい。

通常デスクトップには色々なアイコンがありますが、それらの数とそれらが置かれている位置(X,Y座標)をアプリケーション中で把握したいのです。

デスクトップを覆っているリストビューコントロールに対して、メッセージを投げるなりAPIを発行するなりしてください。
Commctrl.pas の ListView_XXXXXX関数は、結構豊富です。テストすることをお勧めします。

以下サンプルプログラムです。

uses Commctrl;

// デスクトップリストビューのハンドル所得
function GetDesktopListView: HWnd;
var
  Hdl:HWnd;
begin
   Hdl := FindWindow('Progman', 'Program Manager');
   if not (Hdl = 0) then
   begin
     Hdl := FindWindowEx(Hdl, 0, 'SHELLDLL_DefView', '');
     if not (Hdl = 0) then
     begin
       result := FindWindowEx(Hdl, 0, 'SysListView32', '');
       exit;
     end;
   end;
   result := 0;
end;

// アイコンの表示数をえる
procedure TForm1.Button1Click(Sender: TObject);
var
  hLView:Hwnd;
begin
  hLView := GetDesktopListView;
  if not (hLView = 0) then
    Label1.Caption := AnsiString('Count: ')
       + IntToStr(ListView_GetItemCount(hLView))
  else
    Label1.Caption := 'ハンドルの取得に失敗しました';
end;


詳細は、Win32 SDK Referenceを調べてください。
また、IE4&Active Desktopをインストールしている環境では動かないかもしれません。
参照: [builder:5968] <アイコン>

0276  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/27 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/27 西坂良幸 編集
アップリケーションにサウンドリソースを埋め込んで使いたい。

リソースファイルには、*.WAVファイルを埋め込むことが出来ます。しかし、これは手作業で行わなければなりません。

たとえば、TEST.WAV というファイルがあるとします。
・このファイルをproject1.dprと同じディレクトリに起きます。
・メニューから[ファイル|新規作成−テキスト]を選びます。
・このテキストに、

   MYSOUND WAVE TEST.WAV

と1行を書き込み、PROJTEST.rc(適当でよい)という*.rcファイルとしてセーブします。
  ※ TEST.WAVが同じディレクトリでないときはフルパスで指定
  ※ リソースは、原則、大文字です。
・binディレクトリにあるbrcc32.exeで、*.resファイルを作成します。

   brcc32.exe PROJTEST.rc

  ※ コマンドラインEXE であることに注意
・project1.dprを開き作成したリソースファイルを書き込みます

・・省略・・・
{$R *.RES}               // デフォルトである
{$R projtest.res}        // ←ここを書き加える

begin
  Application.Initialize;
・・省略・・・


以上で、プロジェクトの再構築を行えば、EXEの中にTEST.WAVのデータが埋め込まれます。
Demosディレクトリの中にあるリソースエクスプローラの見本をコンパイルして、このプロジェクトのEXEファイルを読み込むと、WAVEリソースが出来ていることがわかります。

以下は、簡単な使用方法です。

// 音を鳴らす
procedure TForm1.Button1Click(Sender: TObject);
begin
  PlaySound('MYSOUND',HInstance, SND_RESOURCE or SND_ASYNC);
end;

// 停止させる
procedure TForm1.Button2Click(Sender: TObject);
begin
  PlaySound(nil, 0, SND_RESOURCE);
end;


上記の場合、SND_RESOURCE は必ず必要です。
また、SND_ASYNCをSND_SYNCにすると終わるまで制御が戻りません。
参照: [Delphi-ML:8787] [Delphi-ML:12338] <アプリケーション> <その他Windows関連> <開発環境>

0218  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/26 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/27 西坂良幸 編集
エクスプローラからファイルをドラッグ&ドロップする

一度はやってみたいんですよね。MLでも多いスレッドです。
「Delphi2.0Q&A120選」(大野元久著)にもあります。

WM_DropFilesメッセージを捕まえて、DragQueryFile関数で処理するわけですが、受け取る側のスタイルを準備しなければなりません。
これは、一般的なフォームのOnCreateイベントで
DragAcceptFiles(Handle,True);
を使うよりも、CreateParamsをオーバーライドするのがベターだそうです。

// 定義部
 type
  TForm1 = class(TForm)
  ・・省略・・
  private
    procedure CreateParams(var Params: TCreateParams);override;
    procedure WMDropFiles(Var Msg: TWMDropFiles); Message WM_DropFiles;
  public
  end;

// 実装部
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  // 受け取れる準備をする
  Params.ExStyle := Params.EXStyle or WS_EX_ACCEPTFILES;
end;

// ファイル1個の場合−−メモに読み込ませる。
procedure TForm1.WMDropFiles(Var Msg: TWMDropFiles);
Var
  FileName: Array[0..MAX_PATH] of Char;
Begin
  Count := DragQueryFile(Msg.Drop, 0, FileName, SizeOf(FileName));
  Memo1.Lines.LoadFromFile(String(FileName));
  DragFinish(Msg.Drop);
End;

//今度は複数の場合−−リストボックスにファイル名
procedure TForm1.WMDropFiles(Var Msg: TWMDropFiles);
Var
  FileName: Array[0..MAX_PATH] of Char;
  i, Count: integer;
Begin
  ListBox1.Items.clear;
  // 第二パラメータを-1にするとドロップ数が取得できる
  Count := DragQueryFile(Msg.Drop, DWord(-1), FileName, SizeOf(FileName));
  for i := 0 to count - 1 do
  begin
    DragQueryFile(Msg.Drop, i, FileName, SizeOf(FileName));
    ListBox1.items.add(String(FileName));
  end;
  DragFinish(Msg.Drop);
End;

最後のDragFinishを忘れないように。
参照: [Delphi-ML:3137] [Delphi-ML:8536] [Delphi-ML:31274] <ShellApi> <ファイル>

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] <System> <フォーム> <コンポーネント >

0275  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/26 西坂良幸 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/26 西坂良幸 編集
ファイルを削除してゴミ箱に移動させたい。

SHFileOperation関数を使えば、ファイル単位でもフォルダーごとでもゴミ箱に移動させることができます。
注意事項としては、必ずフルパスでなければならないということです。

ちょっと変な関数名ですが・・・

Uses Shellapi;

procedure SendToRecycleBin(FileList: TStrings; Dlg: boolean);
var
  LpFileOp:TSHFILEOPSTRUCT;
  FileNames: string;
  i: integer;
begin
  if FileList.Count = 0 then exit;
  // #0をデリミタとした文字列を作る
  for i := 0 to FileList.Count - 1 do
    FileNames := FileNames + FileList[i] + #0;
  // ターミネイタにもう一度#0をつける
  FileNames := FileNames + #0;
  with LpFileOp do
  begin
    Wnd := Application.Handle;
    wFunc := FO_DELETE;
    pFrom := PChar(FileNames);
    pTo:= nil;
    fFlags := FOF_ALLOWUNDO;
    if not Dlg then fFlags := fFlags or FOF_SILENT;
    hNameMappings := nil;
    lpszProgressTitle := nil;
  end;
  SHFileOperation(LpFileOp);
end;

// テスト
procedure TForm1.Button1Click(Sender: TObject);
var
  Flist :TStrings;
begin
  Flist := TStringlist.Create;
  try
    Flist.Add('C:\Program Files\Borland\Delphi 4\Projects\*.~df');
    Flist.Add('C:\Program Files\Borland\Delphi 4\Projects\*.~pa');
    SendToRecycleBin(FList, true);
  finally
    Flist.free;
  end;
end;
参照: [Delphi-ML:3443] [Delphi-ML:5005] <ShellApi> <ファイル>

0196  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/07/07 osamu rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/24 K.Takaoka 編集
Windows 特殊フォルダの Class ID List


SHGetFolderPath, SHGetFolderLocation, SHGetSpecialFolderPath, SHGetSpecialFolderPath といった API で Windows が特別に扱うフォルダのパスを得ることができます.
これらのフォルダはユーザ環境によって異なるため, 常に API を利用して取得するようにすると問題のないアプリケーションが開発できます.

フォルダ名:CSIDL名(プログラムで利用できる定数名)
{CLSIDL}
ディレクトリ名

マイコンピュータ: CSIDL_DRIVES
{20D04FE0-3AEA-1069-A2D8-08002B30309D}
マイコンピュータはディレクトリにリンクしていません

ネットワークコンピュータ: CLSIDL_NETWORK, CSIDL_NETHOOD
{208D2C60-3AEA-1069-A2D7-08002B30309D}
ネットワークコンピュータはディレクトリにリンクしていません

マイドキュメント: CSIDL_PERSONAL
{450D8FBA-AD25-11D0-98A8-0800361B1103}
C:\My Document
C:\WinNT\Users\UserName\Personal

ごみ箱: CSIDL_BITBUCKET
{645FF040-5081-101B-9F08-00AA002F954E}
C:\Recycled.Bin

コントロールパネル: CSIDL_CONTROLS
{21EC2020-3AEA-1069-A2DD-08002B30309D}
コントロールパネルはディレクトリにリンクしていません

プリンタ: CSIDL_PRINTERS, CSIDL_PRINTHOOD
{2227A280-3AEA-1069-A2DE-08002B30309D}
プリンタフォルダはディレクトリにリンクしていません


他にも

CSIDL_COOKIES, CSIDL_DESKTOP, CSIDL_DESKTOPDIRECTORY, CSIDL_FAVORITES, CSIDL_FONTS, CSIDL_HISTORY, CSIDL_INTERNET, CSIDL_INTERNET_CACHE, CSIDL_PROGRAMS, CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU, CSIDL_STARTUP, CSIDL_TEMPLATES

などといったものが Win95/98/NT4/2K で共通に利用できます.

WinNT/2K においては CSIDL_COMMON_*** という形式で全ユーザ共通のフォルダを指定できるものが多くあり, Win2K にはさらに多くの定数が新設されています.

基本的には MSDN などの Microsoft の公式な文書を読むことになりますが, HKEY_CLASSES_ROOT\CLSID\ 以下を探すことで, アプリケーション固有のものを発見することができます.

たとえば、
「受信トレイ」
{00020D75-0000-0000-C000-000000000046}


といったものです.

これらを利用して 'プリンタ.{2227A280-3AEA-1069-A2DE-08002B30309D}' という名前のフォルダを作ることで、任意の場所にプリンタフォルダを追加できます。

参考: http://msdn.microsoft.com/library/sdkdoc/Shell/Functions/CSIDL.htm
参照: [Delphi-ML:10601] <ファイル>

0272  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/23 西坂良幸 rev 1.1.1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/23 西坂良幸 編集
シェルのデスクトップやマイコンピュータをプログラムから開きたい。

デスクトップは、
HKEY_CURRENT_USER\SoftwareMicrosoft\Windows\CurrentVersion\
Explorer\Shell Folders の Desktopを参照すればOKです。
たいていの場合 'C:\Windows\デスクトップ'(実際は半角です)

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShellExecute(Handle, 'Open', 'EXPLORER.EXE', 'C:\Windows\デスクトップ', '', SW_SHOW);
  // 'デスクトップ'は半角です。
end;


また、主要なシステムフォルダーは
HKEY_CURRENT_USER\SoftWare\Classes\CLSIDの値を使えばOKです
たとえば、マイコンピュータは。
procedure TForm1.Button4Click(Sender: TObject);
begin
  ShellExecute(Handle,'Open','EXPLORER.EXE','::{20D04FE0-3AEA-1069-A2D8-08002B30309D}','',SW_SHOW);
end;

という具合です。CLSIDについては、詳しくはCOMの知識が必要になります。
・ネットワークコンピュータ
・マイドキュメント
・ゴミ箱
などのCLSIDの値は、[Tips:196]にあります。

コントロールパネルは。アプリケーションですので。
procedure TForm1.Button2Click(Sender: TObject);
begin
  ShellExecute(Handle,'Open','Control.exe','','',SW_SHOW);
end;


// たとえばコントロールパネルの中の'アプリケーションの追加と削除'なら
procedure TForm1.Button3Click(Sender: TObject);
begin
  ShellExecute(Handle,'Open','Control.exe','Appwiz.cpl','',SW_SHOW);
end;
参照: [Delphi-ML:9689] [Delphi-ML:16991] [Delphi-ML:37909] [Delphi-ML:39661]

0068  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/22 osamu 編集
長いファイル名を短いファイル名に変換したい

GetShortPathName APIを使いましょう。

function LongToShortFileName(Const LongName: String):String;
var
  Len: integer;
begin
  Len := GetShortPathName(PChar(LongName), PChar(result), 0);
  SetLength(result, len);
  if GetShortPathName(PChar(LongName), PChar(result), Len) = 0 then
    Raise EConvertError.Create('ファイルが見つかりません。');
end;

ファイルが実在しないと例外が発生します。

逆に、短いファイル名を長いファイル名にするには [Tips:233] を見てください。
参照: [builder:5092] [Tips:233] <ファイル>

0266  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/19 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/20 西坂良幸 編集
エクスプローラのように、アプリケーションにブラウザページをつくりたい。

本来なら、DelphiにあるHRMLコンポーネント等を使うんでしょうが、これも、D4まででは、結局AktiveXなので、オフィス97をお持ちの方は、Webブラウザコントロール(WebBrowser)を使うととても簡単です。

これは、オフィス97のCD-ROM
 \VALUPACK\ACCESS\WEBHELP\Webrowse.hlpに
Web ブラウザ コントロールとして、詳しい解説があります。
この実体は、Shdocvw.dll というDLLファイルです。

メニューで[コンポーネント|ActiveXコントロールの取り込み]を開いて下さい。
ダイアログのリストに、Microsoft Internet Contorols(version 1.??) というのがあります。
無かったら、Windows\Systemディレクトリの、Shdocvw.dllを探して追加して下さい。
クラス名の欄に、TWebBrowser_V1、TWebBrowser と表示されたら、インストール実行で、パレットのActiveXページにコンポーネントがインストールされます。

ページ切り替えは省略しますが、
フォームにこのコンポーネントを貼り付け、Alignを決めます。

procedure TForm1.FormShow(Sender: TObject);
begin
  WebBrowser1.GoHome;
end;

とすれば、Web表示が出来上がりです。

URLを指定するときは、Navigate、やNavigate2 メソッドを使います

たとえば、URLがファイル(*.htm)なら、

procedure TForm1.Button1Click(Sender: TObject);
var
 url: WideString;
 flg,Tmp: OleVariant;
begin
  if OpenDialog1.Execute then
  begin
    url := OpenDialog1.FileName;
    flg := 0;
    WebBrowser1.Navigate(url, flg, Tmp, Tmp, Tmp);
  end;
end;


メソッドや、プロパティの詳細は、上記のヘルプファイルを見て下さい。
264番のインターネットエクスプローラオブジェクトと似通っているようです。
参照: [Delphi-ML:25232] [Delphi-ML:37104] <その他Windows関連> <WWW> <ShellApi> <通信>

0267  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/19 おばQ rev 1.1.1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/20 K.Takaoka 編集
MDI等で二重起動を防止して新しいファイルを開く


なんか変なタイトルですいません。
Exe本体やExeのショートカットにファイルをドラッグ&ドロップ(以下D&D)した時にアプリケーションが起動してファイルが開く処理を実現したとします。
アプリケーションが起動している最中にもう一度、Exe本体やショートカットにファイルを D&D するともう一つアプリケーションが起動しませんか?あまり素敵じゃないですよね?

貴方がお望みの動作は、たぶんアプリケーションは一つだけ立ち上がっていて MDI 子ウィンドウで新しく D&D されたファイルを開きたいというものでしょう?そこで以下のTipsを利用します。

・二重起動の判定(t269)
・簡易アプリケーション間通信(t268)

t269 のままでは Halt 手続きによってアプリケーションが終了してしまうので、引数に渡されたファイル名を t268 を利用して送信します.

halt 手続きの変わりに呼び出される CopyDataToOld 手続きを作成します.


procedure CopyDataToOld;
var
  wnd: HWND;
begin
  { 既に存在している TForm1 を探す }
  Wnd := FindWindow('TForm1', nil);  
  if Wnd<>0 then
  begin
    // SIGNATURE_FILEOPEN 定数で ParamStr の内容を送信するとする
    // SendMessage(wnd, WM_COPYDATA, ...); // t268 参照
  end;
end;

そして、送信された WM_COPYDATA を受け取るメッセージハンドラを実装します。

インターフェス部

type
  TForm1 = class(TForm)
  // …省略…
  private
    procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
  public
  end;

実装部

procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
  ArriveStr: String;
begin
  if Msg.CopyDataStruct.dwData=SIGNATURE_FILEOPEN then
  begin
    // 受信処理 : t268 参照
    // ArriveStr に受け取った文字列が入るとする

    // ※ 受け取ったファイル名で開く
    FileOpen(String(pcData));  //例です
  end;
end;

以上のソースでは※印部分では D&D されるファイルは一つだとしか考慮していません。
参照: [Delphi-ML:42587] [Tips:268] [Tips:269] <その他Windows関連> <アプリケーション>

0269  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/19 K.Takaoka rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/19 K.Takaoka 編集
二重起動の判定

該当記事で以下のようなユニットが紹介されています

unit Unique;

interface

uses
  Windows, Sysutils;

implementation

var
  UniqueName : string;
  hMutex: THandle;

initialization
  UniqueName := ExtractFileName(ParamStr(0));
  hMutex := OpenMutex(MUTEX_ALL_ACCESS, false, pchar(UniqueName));
  if hMutex <> 0 then
  begin
    CloseHandle(hMutex);
    Halt;
  end;
  hMutex := CreateMutex(nil, false, pchar(UniqueName));

finalization
  ReleaseMutex(hMutex);
end.

Mutex は同じ名前のものは 2 つ存在することはできません.
ここでは ExtractFileName(ParamStr(0)) を mutex の名前にしています.
複数のアプリケーションで(意図的な場合は除いて)同じ名前の mutex を作成しようとすると問題になる可能性が高いため、できるだけユニークな名前を割り当てるようにしなければなりません.

また、このユニットではすでに mutex が存在していた場合に Halt 手続きを実行しています.
該当部分を書きかえることによって二重起動時に任意のアクションを起こすことができるでしょう.
参照: [Delphi-ML:6240] <その他Windows関連>

0264  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/19 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/19 西坂良幸 編集
インターネット エクスプローラを起動したい/その情報を取得したい

オフィス97のCD-ROM
 \VALUPACK\ACCESS\WEBHELP\Webrowse.hlpに
InternetExPlorerオブジェクトの詳しい解説があります。
これを使うと、OLE オートメーションを利用してインターネット エクスプローラのインスタンスを作成し、操作することができます。

このオブジェクトはComObj.pas で定義されているCreateOleObject関数で使えます。
変数とメソッドを定義し、
  private
    IExp:Olevariant;
  public
    procedure ExecuteIE(Url: String = '');


uses ActiveX,ComObj;

procedure TForm1.ExecuteIE(Url: String = '');
begin
  if IUnKnown(IExp) = nil then
  begin
    IExp := CreateOleObject('InternetExplorer.Application');
    IExp.Height:=400;
    IExp.Width:=600;
    IExp.MenuBar:=1;
    IExp.StatusBar:=1;
    IExp.ToolBar:=1;
    IExp.Visible:=true;
  end;
  if Url = '' then
    IExp.Gohome
  else
    IExp.Navigate(Url);
end;

// ホームで起動
procedure TForm1.Button1Click(Sender: TObject);
begin
  ExecuteIE;
end;

// URLを指定して起動
procedure TForm1.Button2Click(Sender: TObject);
begin
  ExecuteIE('http://www2.big.or.jp/~osamu/Delphi/Tips');
end;

// インターネット エクスプローラを終了するには、Quit メソッドを使用します。
procedure TForm1.Button3Click(Sender: TObject);
begin
  if IUnKnown(IExp) <> nil then
  begin
    IExp.Quit;
    IExp:= Unassigned;
  end;
end;


便利なプロパティやメソッドがたくさんあります。
参照: <その他Windows関連> <ShellApi>

0044  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.5
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/17 おばQ 編集
起動中のブラウザからURLを取得する/ブラウザにURLをセットする方法

DDE を用いれば、ブラウザが現在表示している URL を取得したり、逆に URL をブラウザにセットすることができます。

Form1 に DdeClientConv1 を配置し、ConnectMode プロパティを ddeManual にします。

type  TBrowserType = (btIE, btNN);
const BrowserServices : array [TBrowserType] of string =
                ('Iexplore', 'netscape');

を用意して、

function TForm1.GetBrowserURL(BrowserType: TBrowserType): string;
var
  ServiceStr, TopicStr, ItemStr, UrlStr: String;
  UrlPch: PChar;
begin
  ServiceStr := BrowserServices[BrowserType];
  TopicStr   := 'WWW_GetWindowInfo';
  UrlStr     := '';

  with DdeClientConv1 do
  begin
    if SetLink(ServiceStr, TopicStr) then
      if OpenLink then
      begin
        ItemStr:= '0xFFFFFFFF';
        UrlPch := RequestData(ItemStr);
        UrlStr := UrlPch;
        StrDispose(UrlPch)
        CloseLink;
      end;
  end; {with}

  Result := copy( UrlStr, 2, Pos('",',UrlStr) - 2);
end;

GetBrowserURL(btIE) とすると起動中のインターネットエクスプローラの URL を文字列として取得出来ます。btNN とするとネットスケープから URL を取得します。
ブラウザは起動しておいてください。

URL をセットするには以下の関数を使います。

function TForm1.SetBrowserURL(BrowserType: TBrowserType; UrlStr: String): Boolean;
var
  ServiceStr, TopicStr: String;
  Pch: PChar;
begin
  Result := false;

  ServiceStr := BrowserServices[BrowserType];
  TopicStr   := 'WWW_OpenURL';

  with DdeClientConv1 do
  begin
    if SetLink(ServiceStr, TopicStr) then
      if OpenLink then
      begin
        Pch := RequestData( PChar(UrlStr) );
        CloseLink;
        StrDispose(Pch);
        Result := true; {成功すれば戻り値がTrue}
      end;
  end; {with}
end;

IE の場合は起動中のブラウザ画面にセットされた URL のページが表示されます。NN の場合は新しく Window を開いてページを表示するようです。
参照: [Delphi-ML:42589] [Delphi-ML:42621] <その他Windows関連> <WWW> <通信>

0239  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/08 osamu 編集
IME に未確定文字列を入力

> プログラム中からIMEに未変換・未確定文字列として送りたいのですが。。。
>
> 例
> プログラムで渡す文字列    へいせい10ねん
>           ↓
>          IME              「へいせい10ねん」(未変換・未確定)

方法1
  「へいせい10ねん」を「heisei10nenn」もしくは、
  「ヘイセイ10ネン」(ほんとは半角)に変換し、キーボードイベントとして
  sendkeysや、keybd_event APIでIMEに送る。
  ローマ字変換か、カナ変換かは、ImmGetConversionStatus APIで
  判断出来ます。

  Edit1.SetFocus;
  SendKeys('heisei10nenn',true);

方法2
  ImmSetCompositionString APIでIMEに直接セットする。

  var
    IMC:HIMC;
    BufLen:longint;
    Buf:string;
  begin
    Edit1.SetFocus;
    IMC:=ImmGetContext(Edit1.Handle);
    Buf:='へいせい10ねん';
    BufLen:=length(Buf);
//MS-IME98
    ImmSetCompositionStringA(IMC,SCS_SETSTR,PChar(Buf),BufLen,nil,0);

//ATOK12
    ImmSetCompositionStringW(IMC,SCS_SETSTR,PChar(Buf),BufLen,nil,0);

    ImmReleaseContext(Edit1.Handle,IMC);
  end;

MS-IME98とATOK12でテストしましたが、ATOK12の場合、UniCodeの方のAPIで実行しないとちゃんと動作しませんでした。
なぜなのかは、よくわかりません(^^;

#詳しくは、英語のヘルプやAPIの解説書等で調べてください。
参照: [Delphi-ML:32185] <その他Windows関連> <コンポーネント > <Standard>

0143  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/08 osamu 編集
フォルダのタイムスタンプを変更する

ファイルのタイムスタンプを変更するのはできるのですがフォルダのタイムスタンプはどのようにして変更したらよいのでしょうか?

procedure ChangeDirTime(DirName : String;Date : TDateTime);
var
  FHandle   : integer;

Begin
 FHandle := CreateFile(Pchar(DirName),  { ディレクトリ名最後に\はいらない }
   GENERIC_WRITE,    { 書きこみ許可しないと変えられない }
   FILE_SHARE_Read,   { 最低他からアクセスできないとハンドルがもらえない }
   nil,     { セキュリティは無視(いいのかな?) }
   OPEN_EXISTING,    { ディレクトリは存在していることを前提 }
   FILE_FLAG_BACKUP_SEMANTICS,   { APIのヘルプをみてね }
   0);
 FileSetDate(FHandle,DateTimeToFileDate(Date));
 CloseHandle(FHandle);
End;

タイムスタンプの設定にAPIのSetFileTimeを使う手もありますがフォルダならこれで十分です。

D3+Win98 では動きませんでした。NT では動くのかな???
参照: [Delphi-ML:24889] <ファイル>

0005  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/06 西坂良幸 編集
メインフォーム以外のフォームをタスクバーに入れたい。

フォームのウィンドウスタイルにWS_EX_APPWINDOWを加えます。

  TForm2 = class(TForm)
    :
    procedure FormClose(Sender: TObject; var Action: TCloseAction);  
  protected
    procedure CreateParams(var Params: TCreateParams);
  override;
    :
  end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree; // これを忘れないこと
 Form2 := nil;
end;

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

とします。[Delphi-ML:7921]

また、タスクバーにも入れたくないときは、
 Application.OnMinimize := AppMinimize;
を設定し、

procedure TForm2.AppMinimize(Sender: TObject);
begin
   ShowWindow(Form1.Handle, SW_HIDE);
end;

ですね。
参照: [Delphi-ML:3429] [Delphi-ML:6234] [Delphi-ML:17682] <タスクバー> <フォーム>

0232  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/01 西坂良幸 rev 1.4
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/06 西坂良幸 編集
APPのフォームを最小化して起動したい

メインフォームのWindowStyleをwsMinimizedに設定しておくと自分で起動するときは、最小化されタスクバーに入ります。
しかし、他のAPPから起動する時やAPIのShowWindowやショートカットやタスクトレイなどで起動する時はちょっとやっかいです。
これは、Application(変数)のフォームとメインフォームの同期がとれないからです。これはメインフォームに送られてくるスタイルフラッグに合わせて、Applicationのスタイルを合わせてやる必要があります。
この方法は、MLではいくつも紹介されています。[Delphi-ML:13173] [Delphi-ML:13185]
(混乱ということでは、古いバージョンでは、GetStartupInfoで取得できるwShowWindow値が、CmdShowと必ずしも一致しないという問題や、D2→D3で仕様が変わっているということもあります。)

以下のコードはどうでしょうか。

procedure TForm1.FormCreate(Sender: TObject);
var
  SI : TStartupInfo ;
begin
  // D4では、常にCmdShow = SI.wShowWindowですが念のため
  GetStartupInfo( SI ) ;
  CmdShow := SI.wShowWindow ;

  // 最小化に関係するスタイルフラッグにすべて対応
  case cmdShow of
    SW_SHOWMINIMIZED,
    SW_MINIMIZE,
    SW_SHOWMINNOACTIVE :
      Application.Minimize ;// 同期させる
  end ;
end;


なお、子フォームの場合をDeskTopでなく、タスクバーに入れるには、0005番「メインフォーム以外のフォームをタスクバーに入れたい。」を参照して下さい。
参照: [Delphi-ML:13173] [Delphi-ML:3426] [Delphi-ML:23218] [Delphi-ML:25557] <タスクバー> <フォーム>

0079  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/02 西坂良幸 編集
Windowsの「ファイルの検索」ダイアログをプログラムから使いたい

「ファイルの検索」ダイアログを出すには、DDEを使います。

フォームに TDdeClientConv コンポーネント(Systemタブ)を乗っけて、

procedure TForm1.Button1Click(Sender: TObject);
var
  Macro:string;
begin
  DdeClientConv1.SetLink('Folders','AppProperties');
  DdeClientConv1.ServiceApplication:='Explorer';
  DdeClientConv1.OpenLink;
  Macro := Format('[FindFolder("%S")]', ['D:\Delphi 3']);
  DdeClientConv1.ExecuteMacro(PChar(Macro),False);
  DdeClientConv1.CloseLink;
end;

てなふうにします。D:\Delphi 3 フォルダがカレントになります。
ちなみにどこで見つけたかというと、レジストリの

 HKEY_CLASSES_ROOT\Directory\shell\find\ddeexec

です。

なお、終了させる場合は

procedure TForm1.Button2Click(Sender: TObject);
var
 hDialog;
begin
 hDialog:=FindWindow('#32770',nil); {ダイヤログのハンドル}
 SendMessage(hDialog, WM_CLOSE, 0, 0);  {終了}
end;


が簡単でいいでしょう。
参照: [Delphi-ML:20377] <その他Windows関連> <ShellApi> <ダイアログ>

0228  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/29 西坂良幸 rev 1.4
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/01 西坂良幸 編集
フォームの最小化、最大化をアニメーションでやりたい。(DELPHI)


過去のMLを検索してみましたが案外少ないようです。「最小化」の話題は結構あるのに。このような機能をもつコンポーネントがたくさんあるし、あまり重要な機能でもないということですか。

これは当然ですが、SetBoundsメソッドなんかをいじっていてもダメですね。
また、WM_SYSCOMMANDメッセージをとらえて
procedure TForm1.WMSysCommand(var msg: TWMSysCommand);
begin
  if msg.CMdType = SC_MINIMIZE then
    WindowState := wsMinimized;
  inherited;
end;

としてもだめですね。[Delphi-ML:939]

結論的に言うと、MovWindowというAPIを使うんですが、このためのちょっとした工夫が、メッセージの理解やその処理の仕方について大変勉強になります。(コンポーネント貼り付けるだけが能ではない!)

ということで、今回はちょっと解説を。
・フォーム(メインも含めて)とApplicationの同期を考慮しなければならないので、双方のWindProcをオーバーライドしなければならない。
・自分のメソッドのWindProcは、オーバーライドは簡単ですよね、
・では、ApplicationのWndProcはどうすればオーバーライドのようにできるのか。
というようなことを考えて下さい。

  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;        // ボタンではなく、メニューでテストがミソ
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
  private
    NewAppWndProc: Pointer;
    OldAppWndProc: Pointer;
  protected
    procedure WndProc(var Msg: TMessage); override;
    procedure AppWndProc(var Msg: TMessage); virtual;
  public
  end;

//  途中省略

uses MMSystem;

{$R *.DFM}
// AppliCationのWndProcをすり替えている
procedure TForm1.FormCreate(Sender: TObject);
begin
  if Application.MainForm = nil then
  begin
    // WndProcのインスタンスを作成
    NewAppWndProc := MakeObjectInstance(AppWndProc);
    // 元のApplicationのWndProcアドレスを保存
    OldAppWndProc := Pointer(GetWindowLong(Application.Handle, GWL_WNDPROC));
    // ApplicationのWndProcアドレスをNewAppWndProcに変更
    SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(NewAppWndProc));
  end;
end;

// 終わる時は後始末をする
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if (Application.Handle <> 0) and (OldAppWndProc <> nil) then
  begin
    // 元のWndProcに戻す
    SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(OldAppWndProc));
    // インスタンスを解放
    FreeObjectInstance(NewAppWndProc);
  end;
end;

//ウィンドウプロシージャを書き直す
procedure TForm1.WndProc(var Msg: TMessage);
var
  SaveTitle: string;
begin
  with Msg do  // ここでメッセージを横取り
  begin
    if (Msg = WM_SYSCOMMAND) and (WParam = SC_MINIMIZE) then
      with Application do
      begin
        SaveTitle := Title;
        Title := Caption;
        // 再び手前に表示−−おまじない
        NormalizeTopMosts;
        // トップ レベルでアクティブ ウィンドウ化
        SetActiveWindow(Handle);
        // ウィンドウの位置と寸法を変更
        MoveWindow(Handle, Left, Top, Width, Height, True);
        // サウンドを再生  ふろくだから無視してください
        PlaySound('Minimize', 0, Snd_Alias or Snd_NoDefault or Snd_ASync);
        // 表示状態を設定
        ShowWindow(Handle, SW_MINIMIZE);
        Title := SaveTitle;
      end
  end;
  inherited WndProc(Msg);
end;

//アップリケーションプロシージャに置き換えられた偽のWndProc
procedure TForm1.AppWndProc(var Msg: TMessage);
begin
  with Msg do     // ここでも横取りする
  begin
    if (Msg = WM_ERASEBKGND) then
      Result := 1
    else if (Msg = WM_SYSCOMMAND) and (WParam = SC_RESTORE) then
      with Application do
      begin   // 戻す
        PlaySound('RestoreUp', 0, Snd_Alias or Snd_NoDefault or Snd_ASync);
        // トップ レベルでアクティブ ウィンドウ化
        SetActiveWindow(Handle);
        ShowWindow(Handle, SW_RESTORE);
        // わり算を大きくするとスム−ス
        MoveWindow(Handle, Screen.Width div 4, Screen.Width div 4, 0, 0, False);
        Result := 1;
      end
    else if (Msg = WM_SYSCOMMAND) and (WParam = SC_MINIMIZE) then
    begin    // 最小化
      PlaySound('Minimize', 0, Snd_Alias or Snd_NoDefault or Snd_ASync);
      // フォーム
      Perform(WM_SYSCOMMAND, SC_MINIMIZE, 0);
    end
    else
      Result := CallWindowProc(OldAppWndProc, Application.Handle, Msg, WParam, LParam);
  end;
end;


これをヒントに自分でコンポーネント化するのは簡単でしょう。
もう一つ、フォームへのメッセージを横取りするWndProcをコンポーネントで書くということです。

MLで話題になっていたので、ひとこと。ボタンやメニューで最小化する時は

procedure TForm1.N1Click(Sender: TObject);
begin
  Application.minimize;  // これはダメ アニメーションしない(当然)
end;

procedure TForm1.N2Click(Sender: TObject);
begin
  Perform(WM_SYSCOMMAND, SC_MINIMIZE, 0); // これでうまくいく
end;

逆のRestoreの場合は、
  Application.minimize;
  Perform(WM_SYSCOMMAND, SC_RESTORE, 0);
でも似たようなものになります。
なぜか?  → MLを再読されたし。
参照: [Delphi-ML:939] [Delphi-ML:34432] <フォーム>

0227  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/29 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/30 osamu 編集
メインフォーム以外のフォームを最小化した時もAPP全体を最小化したい


複数のフォームを持つAPPで、メインフォームでないフォームのMiniMizeボタンを押すとこのフォームは左下にタイトルバー形式にアイコン化され、メインフォームはそのまま残っています。これはこれで意味があるのですが、どのフォームを最小化してもAPP全体を最小化したい時があるものです。

これは、WM_SYSCOMMANDメッセージをとらえて、Appicationを最小化すればできます。

// Form2は、メインフォームでないフォームです。

type
  TForm2 = class(TForm)
    // コントロールいろいろ
  private
    procedure WMSysCommand(var Message: TWMSysCommand);message WM_SYSCOMMAND;
  public
    { Public 宣言 }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.WMSysCommand(var Message: TWMSysCommand);
begin
 if (Message.CmdType and $FFF0 = SC_MINIMIZE) then
    Application.Minimize
  else
    inherited;
end;


最小化された状態の判定は、
  IsIconic(Application.Handle); で行います

「元のサイズに戻す」のは、
  Application.Restore;    ですね。

TCustomFormのWM_SYSCOMMANDメッセージ処理は

  if (Message.CmdType and $FFF0 = SC_MINIMIZE) and
    (Application.MainForm = Self) then
    Application.Minimize
  else
    inherited;

のようになっていることからもわかるように、本来メインフォームとApplicationフォームとは別のものです。
この違いからWindowStyleプロパティの独特の仕様が生まれているのでしょうか?
左下にアイコン化するときは、WindowStyleプロパティは変化しないようです。フォームのWindowStyleプロパティは、メインフォームでないときは注意が必要です。
参照: [Delphi-ML:25286] [Delphi-ML:40312] <フォーム>

0206  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/18 西坂良幸 rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/26 西坂良幸 編集
ダイヤラを呼び出す。(TAPI32.DLLの使用)


TAPI32.DLLのtapiRequestMakeCall関数を呼び出します。


function tapiRequestMakeCall(pDestAddress,pAppName,pCalledParty,pComment: PChar): LongInt; stdcall; external 'TAPI32.DLL';

procedure CallDialar(Number, DName , Comment : string);
begin
  tapiRequestMakeCall(pChar(Number),
    PChar(Application.Title), pChar(DName), PChar(Comment));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CallDialar('06-5556-1234', '山田太郎', '');
end;


で、ダイアラが起動します。


本格的にTAPIを使う場合は、Tapi32.dll用の定義ユニットが必要です。

なお、TAPIの定義ユニットは、
外国製ですが、
 d_tapi.zip (28K)のTapi.pas
 tapid3.zip (28K)のTapih.pasなどがあります。

これらは、桜島子宮さんの ページ
http://www.kobira.co.jp/sakura/d_net_RasAPI.htm

からダウンロードできます。
参照: [Delphi-ML:6833] [Delphi-ML:17807] [Delphi-ML:41356] <ShellApi>

0182  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/05/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/26 西坂良幸 編集
他のアプリの起動パスを取得する


> (ウィンドウハンドルの場合)
> GetWindowLong(hwnd, GWL_HINSTANCE) でモジュールハンドルを取り出す。
> (モジュールハンドルの場合)
> GetModuleFileName(hModule, strBuffer, nBufferSize) でファイル名を得る。

 残念ですがこの方法では、他のアプリの起動パス は取得できません。自分自身のExe名しか取得できません。(私も最初はこれではまった。)(^.^)

 モジュールハンドルはプロセス毎に独立して管理されるので、他のアプリ(他のプロセス)のモジュールハンドルを持ってきても意味がありません。

http://www.microsoft.com/japan/support/kb/articles/J041/6/32.htm

にシステム内で稼働中のプロセスを列挙する方法がでてますから、参考にしてください。ウィンドウハンドルが判っているのでしたら、
GetWindowthreadProcessID でプロセスIDを求めて、列挙中にこれと合致するプロセスを探せばよいでしょう。

たとえば、Win95/98用(WinNTではダメ)ですが、


uses TLHelp32;

// ハンドルからファイル名を得る
function GetProcesFileNameFrom(Handle: hWnd):string;
var
  PID: DWORD;
  SnapShot: THandle;
  ProcessEntry32: TProcessEntry32;
begin
  // ハンドルから作成スレッドを調べてプロセスIDを得る
  GetWindowThreadProcessId(Handle, @PID);
  // TProcessEntry32構造体の初期化
  ProcessEntry32.dwSize := SizeOf(TProcessEntry32);
  // システム中の情報のスナップショットをとる
  SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  try
    // 最初のプロセスの検索
    if Process32First(SnapShot, ProcessEntry32) then
    begin
      repeat
        // IDが一致したら
        if ProcessEntry32.th32ProcessID = PID then
        begin
          Result := string(ProcessEntry32.szExeFile);
          break;
        end;
      // 次のプロセスの検索
      until Process32Next(SnapShot, ProcessEntry32) = False;
    end;
  finally
    CloseHandle(SnapShot);
  end;
end;

などです。
参照: [Delphi-ML:30032] <アプリケーション> <ファイル>

0219  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/26 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/26 西坂良幸 編集
セルのテキストをドラッグイメ−ジにしてグリッド(TStringGrid)でドラッグ&ドロップを行う


やり方は2つあって、Drag Object をすりかえる方法と
コントロール側で DoStartDrag, DoEndDrag, GetDragImages 等を
override する方法があります。[d40216]中村

以下は、[d40948]で須賀さんが書いたコードを若干省略したものです。
Drag&Dropのやり方として大変参考になりますね。


type
  TForm1 = class(TForm)
    //<省略>
   ・・・・・
  public
     CursorSave:TCursor;
  end;

  type

  TCustomDragObject = class(TDragControlObject)
  public
    function GetDragImages: TDragImageList; override;
    procedure HideDragImage; override;
    procedure ShowDragImage; override;
    function GetDragCursor(Accepted: Boolean; X, Y: Integer)
      : TCursor; override;
    procedure Finished(Target: TObject; X, Y: Integer;
                      Accepted: Boolean); override;
  end;

    //<省略>
   ・・・・・

var  // ローカルに宣言
  w_x,w_y:integer; // もとのcellの位置を取っておく
  Images: TImageList; // Image作成用
  drag_sizex,drag_sizey:integer;  // 作成したimageのサイズ
  drag_enter_sw:smallint;   // drag start時かどうかのsw

function TCustomDragObject.GetDragImages: TDragImageList;
begin
  Result := Images;
end;

procedure TCustomDragObject.HideDragImage;
begin
  GetDragImages.HideDragImage;
end;

procedure TCustomDragObject.ShowDragImage;
begin
  GetDragImages.ShowDragImage;
end;

procedure TCustomDragObject.Finished;
begin
  inherited;
  Free;
end;

function TCustomDragObject.GetDragCursor;
begin
  Result := crDeFault;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  drag_enter_sw := 0;   // drag start時かどうかのSwをクリア
  Grid1.ControlStyle := ControlStyle + [csDisplayDragImage];

  // 適当にセルに文字列を・・・
  Grid1.cells[1,1]:='AAA';
end;

procedure TForm1.Grid1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
var
   acol,arow:integer;
begin
  if source is TCustomDragObject then
  begin
    Accept := True;
    Grid1.mousetocell(x, y, acol, arow);
    if (acol<0) or (arow<0) then   //
    begin
      Grid1.DragCursor := crNoDrop;
      exit;
    end
    else begin
      Grid1.DragCursor := crDrag;
    end;
    if State=dsDragMove then
    begin
      if drag_enter_sw = 0 then  // start drag時以外のとき
      begin
        if (y-drag_sizey) <= Grid1.rowheights[1] then  // 上にscroll
        begin
          if Grid1.toprow > 1 then
          begin
            Grid1.toprow := Grid1.toprow - 1 ;
            Grid1.repaint;
          end;
        end;
        if (y >= (Grid1.height - 5)) then   // 下にscroll
        begin
          if (Grid1.rowcount - Grid1.visiblerowcount)>Grid1.toprow then
          begin
            Grid1.toprow := Grid1.toprow + 1;
            Grid1.repaint;
          end;
        end;
      end
      else
       drag_enter_sw := 0;
    end;
  end;
end;

procedure TForm1.Grid1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
var Size: TSize;
  bm: TBitmap;
  acol,arow:integer;
begin
  drag_enter_sw := 1;  
  // drag start時にswをたてる
  Grid1.mousetocell(Grid1.screentoclient(mouse.CursorPos).x,Grid1.screentoclient(mouse.CursorPos).y, acol, arow);
  w_x := acol;   // drag開始時のcellの位置を取っておく
  w_y := arow;   // drag開始時のcellの位置を取っておく
  // textのimageを作成
  bm := TBitmap.Create;
  bm.Canvas.Font := Font;
  Size := bm.Canvas.TextExtent(Grid1.cells[acol, arow]);
  bm.Width := Size.cx;
  bm.Height := Size.cy;
  drag_sizex := Size.cx;
  drag_sizey := Size.cy;
  bm.Canvas.TextOut(0, 0, Grid1.cells[acol, arow]);
  Images := TImageList.Create(Self);
  Images.Width := Size.cx;
  Images.Height := Size.cy;
  Images.Add(bm, Nil);
  bm.Free;
  Images.SetDragImage(0, Size.cx, Size.cy);
  Images.EndDrag;
  // カーソル処理
  CursorSave := Screen.Cursor;
  Screen.Cursor := crDefault;
  // DragImageを作成
  DragObject := TCustomDragObject.Create(Grid1);  // dragobjectの差し替え
end;

procedure TForm1.Grid1EndDrag(Sender, Target: TObject; X, Y: Integer);
begin
  Screen.Cursor := CursorSave;
  Grid1.repaint;
  images.free;   // drag終了時にTImageListの開放   これを忘れていました !!
end;

procedure TForm1.Grid1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
   acol,arow:integer;
begin
  Grid1.mousetocell(x, y, acol, arow);
  if (acol < 0) or (arow < 0) then  // scroll barや最後の行より下のところにdropしたときは何もしない
  begin
    Grid1.DragCursor := crNoDrop;
    exit;
  end;
  if (Sender = Grid1) then    //  drag開始時のcellの内容をdropしたcellにcopy
  begin
    Grid1.mousetocell(x, y, acol, arow);
    Grid1.cells[acol, arow] := Grid1.cells[w_x, w_y];
    Grid1.repaint;
  end;
end;


なお、落とし穴があります。
IDEの中では、ドラッグカーソルとドラッグイメージの合成処理の過程で(TCustomImageList.CombineDragCursor)
Win95/98 が落ちることが前は良く起きました。Video Driver の問題らしいのですが、いまだに原因が良く判らないそうです。
EXEレベルではこの障害はでません。
参照: [Delphi-ML:22670] [Delphi-ML:40662] [Delphi-ML:40977] <コンポーネント > <その他コンポーネント関連>

0214  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/23 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/23 西坂良幸 編集
デスクトップのウィンドウのタイトルとハンドルを取得する


稼働中のウィンドウのタイトルとハンドルを取得するには、
APIのENumWindows関数を使います。
第一パラメータのコールバック関数は、タイトルとハンドル
をどのように処理するかを工夫します。

次の例はListBoxに列挙し、Labelにその数を示します。

function CallBackTest(WH: HWND; LP: LParam): BOOL stdcall;
var
  Buf: array [0..255] of Char;
begin
  // スタイル ビットがセットされているもののみ
  if IsWindowVisible(hwnd) then
    // タイトル バーのテキストをBufにコピー
    if GetWindowText(WH, Buf, 255) <> 0 then
      TListBox(LP).Items.AddObject(Buff, Pointer(hwnd));
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Clear;
  EnumWindows(@CallBackTest, Longint(ListBox1));
  Label1.Caption := IntToStr(ListBox1.Items.Count);
end;

参照: [Delphi-ML:2378] [Delphi-ML:23203] <デスクトップ>

0213  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/23 西坂良幸 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/23 西坂良幸 編集
プロセスの実行ファイル名を列挙する


  Tipsの別項、[Win95/98で、ウィンドゥハンドルから、実行アプリ名を知る]および、[WinNTで、ウィンドゥハンドルから、実行アプリ名を知る]の例にある
  EnumProcesses95、EnumProcessesNTを使えば
汎用関数のようなものができます。

同名の関数がありますので、OverrLoad指定を忘れないで下さい。

procedure EnumProcesses(lpEnumFunc: TEnumProcs; lParam: longint);overload
begin
  case Win32Platform of
   VER_PLATFORM_WIN32_NT: EnumProcessesNT(lpEnumFunc, lParam);
   VER_PLATFORM_WIN32_WINDOWS: EnumProcesses95(lpEnumFunc, lParam);
  else
   raise Exception.Create('未対応のOSかバージョンです。');
  end;
end;

// 以下の例は、リストボックスに列挙しています。
function CallBackTest(ID: DWord; Str: PChar; LP: LParam):bool;stdcall;
begin
  TListBox(LP).Items.Addobject(Str,Pointer(ID));
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  EnumProcesses(@CallBackTest,Longint(ListBox1));
end;

参照: [Delphi-ML:30064] <その他Windows関連>

0212  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/23 西坂良幸 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/23 西坂良幸 編集
Win95/98で、ウィンドゥハンドルから、実行アプリ名を知る

Win95 では、ToolHelp32 を使って取得できます。WinNT ではこの方法では使えません。
  http://www.microsoft.com/japan/support/kb/articles/J041/6/32.htm

に、Win95/NT 両方で使える方法が C 言語で書かれてます。

ここでは、上記の部分的丸写しですが、ToolHelp32を使った例を示します。
コールバック関数を適切に作れば、プロセスIDとファイル名が列挙できますので、ウィンドゥハンドルからID(ProcessID)を
  GetWindowThreadProcessID(WH: hWnd; @ID); 関数
で取得し、一致するものを探せば実行アプリ名を取得できます。


uses TLHelp32;

type
  TEnumProcs = function(ID: DWord; Str: PChar; LP:  LParam):bool; stdcall;

procedure EnumProcesses95(lpEnumFunc: TEnumProcs; lParam: longint);
var
  // 関数ポインタ
  CreateToolhelp32Snapshot: TCreateToolhelp32Snapshot;
  Process32First: TProcess32First;
  Process32Next: TProcess32Next;
  // 変数
  hLib: THandle;
  Snapshot: THandle;
  ProcEntry: TProcessEntry32;
  Flag: boolean;
begin
  // Kernel32.DLL のロード
  hLib := LoadLibraryA('Kernel32.dll');
  if hLib = 0 then
   raise Exception.Create('Kernel32.dll がロードできません。');
  // API のアドレス取得(使用するのは以下の3個)
  CreateToolhelp32Snapshot := TCreateToolhelp32Snapshot(
    GetProcAddress(hLib, 'CreateToolhelp32Snapshot'));
  Process32First := TProcess32First(GetProcAddress(hLib, 'Process32First'));
  Process32Next := TProcess32Next(GetProcAddress(hLib, 'Process32Next'));
  // ロードをチェック
  if (not Assigned(CreateToolhelp32Snapshot))
     or (not Assigned(Process32First))
     or (not Assigned(Process32Next)) then
   begin
     FreeLibrary(hLib);
     raise Exception.Create('API のアドレスを取得できません。');
   end;
  // スナップショットを行う
  Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Snapshot = INVALID_HANDLE_VALUE then
   begin
     FreeLibrary(hLib);
     raise Exception.Create('Toolhelp32 スナップショットが取得できません。');
   end;
  // TProcessEntry32構造体の初期化
  ProcEntry.dwSize := SizeOf(TProcessEntry32);
  // 最初のプロセスの取得
  Flag := Process32First(Snapshot, ProcEntry);
  while Flag do
   begin
     // コールバック関数呼び出し
     if not lpEnumFunc(ProcEntry.th32ProcessID, ProcEntry.szExeFile, lParam) then
       break;
     // 次のプロセスの取得
     Flag := Process32Next(Snapshot, ProcEntry);
   end;
  // 解放
  CloseHandle(Snapshot);
  FreeLibrary(hLib);
end;

// コールバック関数の例
function CallBackTest(ID: DWord; Str: PChar; LP: LParam): bool; stdcall;
begin
  TListBox(LP).Items.Addobject(Str,Pointer(ID));
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  EnumProcesses95(@CallBackTest,Longint(ListBox1));
end;

参照: [Delphi-ML:8519] [Delphi-ML:19427]

0051  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.4
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/23 西坂良幸 編集
WinNT でウィンドウハンドルから実行アプリ名を知る

WinNT では、ToolHelp32 が使えないので、Win95 で良く知られた方法(ToolHelp32)は使えません。
  http://www.microsoft.com/japan/support/kb/articles/J041/6/32.htm

に、Win95/NT 両方で使える方法が C 言語で書かれてます。

ここでは、PSAPIを使っています。
上記の部分的丸写しですが。

uses PsApi;

type
  TEnumProcs = function(ID: DWord; Str: PChar; LP:  LParam):bool; stdcall;

procedure EnumProcessesNT(lpEnumFunc: TEnumProcs; lParam: longint);
var
  // 関数ポインタ
  EnumProcesses: TEnumProcesses;
  EnumProcessModules: TEnumProcessModules;
  GetModuleFileNameEx: TGetModuleFileNameEx;
  // 変数
  hLib: THandle;
  Process: THandle;
  hMod: DWORD;
  PIDs: array[0..2047] of DWORD; // 動的配列ポインタの扱いを簡素化(^^;
  Size, Size2, Index: DWORD;
  ProcessName: array[0..MAX_PATH] of char;
begin
  hMod := 0;
  // PSAPI.DLL のロード
  hLib := LoadLibraryA('PSAPI.DLL');
  if hLib = 0 then
   raise Exception.Create('PSAPI.DLL がロードできません。');
  // API のアドレス取得(以下の3個を使う)
  EnumProcesses := TEnumProcesses(GetProcAddress(hLib, 'EnumProcesses'));
  EnumProcessModules := TEnumProcessModules(GetProcAddress(hLib, 'EnumProcessModules'));
  GetModuleFileNameEx := TGetModuleFileNameEx(GetProcAddress(hLib, 'GetModuleFileNameExA'));
  // ロードのチェック
  if (not Assigned(EnumProcesses))
     or(not Assigned(EnumProcessModules))
     or(not Assigned(GetModuleFileNameEx)) then
   begin
     FreeLibrary(hLib);
     raise Exception.Create('API のアドレスを取得できません。');
   end;
  // プロセスの数は2048まで
  Size2 := 2048 * SizeOf(DWORD);
  if not EnumProcesses(@PIDs, Size2, Size) then
  begin
     FreeLibrary(hLib);
     raise Exception.Create(SysErrorMessage(GetLastError));
  end;
  if Size >= Size2 then
  begin
    FreeLibrary(hLib);
    raise Exception.Create('2048 個以上のプロセスがあるみたいです。');
  end;
  Size := Size div SizeOf(DWORD);
  for Index := 0 to Size - 1 do
  begin
    // プロセスを読み出す
    Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
        False, PIDs[Index]);
    if Process <> 0 then
    begin
      // プロセスのモジュールをチェック
      if EnumProcessModules(Process, PDWORD(hMod), SizeOf(hMod), Size2) then
      begin
        // ファイル名を取得
        if GetModuleFileNameEx(Process, hMod, ProcessName, SizeOf(ProcessName)) = 0 then
        begin
          ProcessName:='';
        end;
      end;
      CloseHandle(Process);
    end
    else
      ProcessName:='';
    // コールバック関数を呼び出し
    if not lpEnumFunc(PIDs[Index], ProcessName, lParam) then
    else Break;
  end;
  // 解放
  FreeLibrary(hLib);
end;

// 使用例
function CallBackTest(ID: DWord; Str: PChar; LP: LParam):bool;stdcall;
begin
  TListBox(LP).Items.Addobject(Str,Pointer(ID));
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Items.Clear;
  EnumProcessesNT(@CallBackTest,Longint(ListBox1));
  // リストボックスに列挙する
end;


参照: [Delphi-ML:19427]

0210  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/21 おばQ rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/21 おばQ 編集
クリップボードのフォーマットを知る

クリップボードのフォーマットは
ヘルプを見ると幾つか定義されています。

プロフェッショナル版以上のDelphiに付属する
VCLのソースをみると
windows.pasに定義されていることが分ります。
CF_TEXTは単に1という値で定義されています

こちらの定義を用いれば現在のクリップボードのフォーマットが分ります。
定義されていないクリップボードフォーマットもありますが
その場合には単に数値として取得してみます。

procedure ClipFormat;
    function ShowMessageCF(Value: Integer): String;
      case Value of
        CF_TEXT:
          Result := 'CF_TEXT';
        CF_BITMAP:
          Result := 'CF_BITMAP';
        CF_METAFILEPICT:
          Result := 'CF_METAFILEPICT';
        CF_SYLK:
          Result := 'CF_SYLK';
        CF_DIF:
          Result := 'CF_DIF';
        CF_TIFF:
          Result := 'CF_TIFF';
        CF_OEMTEXT:
          Result := 'CF_OEMTEXT';
        CF_DIB:
          Result := 'CF_DIB';
        CF_PALETTE:
          Result := 'CF_PALETTE';
        CF_PENDATA:
          Result := 'CF_PENDATA';
        CF_RIFF:
          Result := 'CF_RIFF';
        CF_WAVE:
          Result := 'CF_WAVE';
        CF_UNICODETEXT:
          Result := 'CF_UNICODETEXT';
        CF_ENHMETAFILE:
          Result := 'CF_ENHMETAFILE';
        CF_HDROP:
          Result := 'CF_HDROP';
        CF_LOCALE:
          Result := 'CF_LOCALE';
        CF_MAX:
          Result := 'CF_MAX';
        CF_OWNERDISPLAY:
          Result := 'CF_OWNERDISPLAY';
        CF_DSPTEXT:
          Result := 'CF_DSPTEXT';
        CF_DSPBITMAP:
          Result := 'CF_DSPBITMAP';
        CF_DSPMETAFILEPICT:
          Result := 'CF_DSPMETAFILEPICT';
        CF_DSPENHMETAFILE:
          Result := 'CF_DSPENHMETAFILE';

        CF_PRIVATEFIRST:
           Result := 'CF_PRIVATEFIRST';
        CF_PRIVATELAST:
          Result := 'CF_PRIVATELAST';

        CF_GDIOBJFIRST:
          Result := 'CF_GDIOBJFIRST';
        CF_GDIOBJLAST:
          Result := 'CF_GDIOBJLAST';
        else
          Result := IntToStr(Value);
      end;//case
      ShowMessage(Result);
    end;
var
  i: Integer;
begin
  for i := 0 to 1100 do
    if Clipboard.HasFormat(i) then
      ShowMessageCF(i);
end;

1100までループさせているのは最後のCF_GDIOBJLASTが
1023で定義されていたからです。

FormにButton1を貼り付けて以下のように実装してみてください。

procedure TForm1.Button1Click(Sender: TObject);
begin
  ClipFormat;
end;

ボタンを押すと現在のクリップボードデータのフォーマットがShowMessageで表示されます
参照: <その他Windows関連>

0209  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/21 おばQ rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/21 おばQ 編集
クリップボードが更新された時のイベントを取得する

クリップボードが更新された時、いろいろしたいことがあると思います。
少々ややこしいですが以下のようにすれば
クリップボードの更新を監視する事が出来ます。
そうするとクリップボード履歴機能を持つソフトが作れますね。

Formのメンバーに以下のように定義します

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FClipNextHandle: HWND;

    procedure WMDrawClipboard(var Msg: TWMDrawClipboard);
        message WM_DRAWCLIPBOARD;
    procedure WMChangeCBChain(var Msg: TWMChangeCBChain);
        message WM_CHANGECBCHAIN;
  public
  end;

↑適当に省略しています

implimention部に以下のように実装します。

procedure TForm1.WMDrawClipboard(var Msg: TWMDrawClipboard);
//クリップボード更新フック
//更新された後に流れてくる。
//アプリが立ち上がった瞬間も流れる
begin
  inherited;
//------------------------------


{ここにテキストバックアップ処理等を行えば。
  クリップボード履歴機能が実装できます。}
  ShowMessage('クリップボード更新されたよ');

//------------------------------
  if FClipNextHandle<>0 then
    SendMessage(FClipNextHandle,WM_DRAWCLIPBOARD, 0, 0);
end;

procedure TForm1.WMChangeCBChain(var Msg: TWMChangeCBChain);
begin
  if Msg.Remove = FClipNextHandle then
    FClipNextHandle := Msg.Next;
  if FClipNextHandle <> 0 then
    SendMessage(FClipNextHandle, WM_CHANGECBCHAIN, Msg.Remove,Msg.Next);
end;

procedure TForm1.FormCreate(Sender: TObject);
    procedure ClipboardSetHandle;//クリップボード履歴の為に必要な初期化
    begin
      FClipNextHandle := SetClipboardViewer(Form1.Handle);
      if FClipNextHandle = 0 then
        if GetLastError <> 0 then {本当にエラーだったら}
          ShowMessage('なぜかクリップボードのフックに失敗しました(T_T)');
    end;
begin
  ClipboardSetHandle;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ChangeClipboardChain(Handle, FClipNextHandle);
  //クリップボード監視処理の破棄
end;
参照: [Delphi-ML:5296] <その他Windows関連>

0208  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/19 西坂良幸 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/19 西坂良幸 編集
インターネットエクスプローラのアドレス帳を呼び出す


アドレス帳(IE4以上)の起動は、使用しているアドレスデータとともに呼び出すことが重要です。
このデータは、レジストリの
HKEY_CURRENT_USER\Software\Microsoft\WAB\WAB4\Wab File Name
に示される 拡張子 wab のファイルにあり、
これを「ファイルの関連づけ」機能(IEをインストールすれば自動設定される)をつかって呼び出すのが簡単です。

procedure TForm1.Button1Click(Sender: TObject);
var
  RegIniFile: TRegIniFile;
  Wab:String;
  Comm: array[0..128] of Char;
  Ret:Integer;
begin
  Wab := '';
  Ret := 0;
  // レジストリからwabファイルを探す。
  RegIniFile := TRegIniFile.Create('Software\Microsoft\WAB\WAB4');
  try
    Wab := RegIniFile.ReadString('Wab File Name', '', '');
  finally
    RegIniFile.Free;
  end;

  if Wab <> '' then
  if FileExists(Wab) then
  begin
    StrPCopy(Comm, Wab);
    Ret := Shellexecute(Handle, 'Open', Comm, '', '', SW_SHOWNORMAL);
  end;
  if Ret < 32 then
       ShowMessage('呼び出しに失敗しました。');
end;

参照: [Delphi-ML:39621] <その他Windows関連>

0095  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/07/28 osamu 編集
HTML-Help を作りたい

HTML-Help に関する情報ソースです。

Microsoftから
HTML Help Web site
  http://msdn.microsoft.com/workshop/author/htmlhelp/default.asp
latest version Microsoft HTML Help Workshop
  http://msdn.microsoft.com/workshop/author/htmlhelp/download.asp

国内では
  http://www.takenet.or.jp/~ryuuji/delphi/

またDelphi用のUNITが、
  http://www.mygale.org/~jlucm/
からダウンロードできます。
参照: [Delphi-ML:20899] <ヘルプ>

0195  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/07/07 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/07/07 osamu 編集
CapsLock の状態を変更する

> ある入力コントロールにフォーカスが移った時に、CapsLockを
> プログラムにて On/Off することは出来ないでしょうか?

keybd_event で CAPS キーを押したことにしてあげれば良いです。この方法は、いろいろ応用がききそうです。

// CapsLock を Off にする場合
procedure TForm1.Edit1Enter(Sender: TObject);
begin
  if GetKeyState(VK_CAPITAL) and 1 = 1 then begin
    keybd_event(VK_CAPITAL, 0, 0, 0);
    keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0);
  end;
end;

// CapsLock を On にする場合
procedure TForm1.Edit2Enter(Sender: TObject);
begin
  if GetKeyState(VK_CAPITAL) and 1 <> 1 then begin
    keybd_event(VK_CAPITAL, 0, 0, 0);
    keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0);
  end;
end;
参照: [Delphi-ML:33786]

0136  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/05/19 osamu 編集
独自メッセージとして自由に使える値の範囲

MSDN (99/01 版)をみた感じでは、

$0000          - $03FF (WM_USER-1) システム用予約領域
WM_USER ($0400)- $7FFF (WM_APP -1) WindowClass 用
WM_APP  ($8000)- $BFFF             アプリケーション用
$C000          - $FFFF             RegisterWindowMessage 用
$10000         - last              今後のために予約

で、自由に使用できるのは、WM_USER から $BFFF であると読み取れます。ただし、WM_USER 〜 $7FFF はアプリケーションの制御ではなく、その部品になっているウィンドウコントロールのために予約しておくほうがよいので、コード中から独自メッセージを PostMessage するような場合には、WM_APP〜$FFFF までを使うとよいようです。
参照: [Delphi-ML:24086] <その他Windows関連>

0189  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/05/19 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/05/19 osamu 編集
「送る」の 516 文字制限について

> エクスプローラー等の右クリックの「送る」に機能を
> 追加するソフトを開発しています。SendToフォルダに
> ショートカットを置くことで、上の機能を実現してい
> るのですが、コマンドラインからの起動(?)の516文字
> 制限に困っています。

おそらく、「送る」に頼らず自力でシェルエクステンションを登録するという解決策が一番実現しやすいかなと思っています。
言い換えれば、右クリックしたとき独自のメニューを表示させ、あとはそのメニューに関連付けられたdllがファイル名を処理するというわけです。
参照: [Delphi-ML:37241]

0090  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/03/21 osamu 編集
アプリケーション間でデータの送受信(WM_COPYDATAを使う)

BCB1で記述してます。3用に手直しがあるかもしれません。

送り側アプリ

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    HANDLE handle;
    WPARAM wParam;
    LPARAM lParam;
    char   msgbuf[]="hogehoge";
    COPYDATASTRUCT cds;
    cds.dwData = 1;
    cds.cbData = strlen(msgbuf);
    cds.lpData = (LPVOID)msgbuf;

    handle = ::FindWindow(NULL,"受けアプリ");
    wParam = (WPARAM)Application->Handle;
    lParam = (LPARAM)&cds;
    ::SendMessage(handle,WM_COPYDATA,wParam,lParam);
}
//---------------------------------------------------------------------------

受け側アプリのヘッダ

public:         // ユーザー宣言
    void __fastcall EvWmCOPYDATA( TMessage message );
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA,TMessage, EvWmCOPYDATA)
END_MESSAGE_MAP(TForm)

浮け側アプリのソース

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
    Form1->Caption = "受けアプリ";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::EvWmCOPYDATA( TMessage message )
{
    COPYDATASTRUCT *cds;
    char           buf[80];
    cds = (COPYDATASTRUCT *)message.LParam;
    ::ZeroMemory(buf,sizeof(buf));
    memmove(buf,cds->lpData,cds->cbData);
    ::MessageBox(0,buf,"Oh!",MB_OK);
}
参照: [builder:5252]

0168  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
IME 入力で読み仮名を取得する

以下のコードを含んだ関数を作成し、追跡したいところで
     Application->OnMessage = AppMessage;
と書けばよいのではないでしょうか? はずしていたらすみません。

void __fastcall TForm1::AppMessage(TMessage &Msg, bool &Handled)
{
     if (Msg.message == WM_IME_ENDCOMPOSITION)
     {
          int nRetVal;                   //APIの戻り値を格納
          HIMC hImcIMEHandle;            //IMEのコンテキストを格納
          char cBuff[256];

          hImcIMEHandle = ImmGetContext(Handle);
          //変換結果の「読み」を取得
          nRetVal = ImmGetCompositionString(hImcIMEHandle,
GCS_RESULTREADSTR,
                cBuff, sizeof(cBuff));
          cBuff[nRetVal] = '\0';
          AnsiString strTemp = cBuff;
          //IMEのコンテキストを開放する
          nRetVal = ImmReleaseContext(Handle, hImcIMEHandle);

          //cBuffに対して処理をする(入力された文字列)
     }
}

でcBuffに入力された文字が入ってきていると思います。
このコードを実行するにはimm.hが必要です。
参照: [builder:6815] <その他Windows関連> <コンポーネント > <Standard>

0163  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
カレントユーザのデスクトップディレクトリを得る

>実行中に現在の(ユーザの)「デスクトップ」ディレクトリのパスを取得したい
>のですが、どうすれば良いのでしょうか?

こんなの有ります。
uses ShellAPI, SHlObj, ComObj, ActiveX;
  :
  :
function GetDesktopFolder: string;

  function GetDispName(shi: IShellFolder; pidl: PItemIDList): string;
  var DispName: TStrRet;
  begin
    shi.GetDisplayNameOf(pidl, SHGDN_FORPARSING, DispName);

    if DispName.uType = STRRET_CSTR then
      Result := DispName.cStr
    else if DispName.uType = STRRET_OFFSET then
      Result := PCHAR(LongInt(pidl) + DispName.uOffset)
    else
      Result := WideCharToString(DispName.pOleStr);
  end;

  var Pidl: PItemIDList;
      DesktopFolderI: IShellFolder;

begin
  OleCheck(SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, Pidl));
  try
    OleCheck(SHGetDesktopFolder(DesktopFolderI));
    Result := GetDispName(DesktopFolderI, Pidl);
  finally
    CoTaskMemFree(Pidl);
  end;
end;
参照: [Delphi-ML:31606] <ファイル>

0162  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
IniFile に書き込みを行った後にはバッファのクリアが必要

Delphi4 になって追加されたメソッドに、TIniFile.UpdateFile というのがあります。

TIniFile.UpdateFile メソッドは,バッファリングされた INI ファイルのデータをディスクにフラッシュします。

function UpdateFile; override;

説明

UpdateFile メソッドを呼び出すと,バッファリングされた,INI ファイルからの読み取りや INI ファイルへの書き込みをディスクにフラッシュできます。UpdateFile は,Windows95 では便利ですが,Windows NT では INI ファイルの読み取りや書き込みをバッファリングしないので、効果がありません。

Delphi3 以前では自分で
    WritePrivateProfileString(nil, nil, nil, PChar(FileName));
などとして IniFile のキャッシュを書き込む必要があります。

>   Ini := TIniFile.Create(Filename);
>   with Ini do begin
>     WriteString(aaaa, bbbb, cccc);
>     WriteString(dddd, eeee, ffff);
>     Free;
>     //  以下の処理で、キャッシュをフラッシュ
>     WritePrivateProfileString(nil, nil, nil, PChar(Filename));
>   end;
参照: [Delphi-ML:31512] <アプリケーション> <バグ>

0161  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
TFileStream で標準出力に表示

> テキストファイルの入出力は TStringList でやると便利です。
> そこで、コンソールアプリケーションの標準出力でも使いたいなと、
> SaveToFile('con') を実行したところ例外で失敗しました。
> VCLソースを追いかけてみたところ、TFileStream.Create() で例外が起きていました。
>
> ところが、SaveToFile('nul') を実行したところ、なにも出力されないとはいえ
> 例外が発生することなく実行できました。
>
> 簡単に使えないのはしかたないのですが、この違いはなんでしょうね?

これ、'con'の代わりに'conout$'だと行けるみたいですね。

ところで、ちょっと横道にそれますけど、'con'だと仮にopen出来ても
リダイレクトした場合にまでコンソールに表示されて場合によっては
不便じゃありませんか?
その場合は以下のようにした方が良いかと。

uses
  windows, classes, sysutils;

var
  s : TStringList;
  hs : THandleStream;
begin
  s := TStringList.Create;
  try
    hs := THandleStream.Create(GetStdHandle(STD_OUTPUT_HANDLE));
    try
      s.SetText('一行目'#10'二行目'#10'三行目'#10);
      s.SaveToStream(hs);
    finally
      hs.free;
    end;
  finally
    s.free;
  end;
end.
参照: [Delphi-ML:31323] <ファイル>

0160  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
半角カナを確定無しで直接入力させる

> IMEの制御についてお聞きしたいのですが、例えばTEditのIMEMode
> プロパティを半角カナに設定した時、「アイウエオ(半角)」と打
> ちこんだ後リターンキーで確定をしなければなりませんが、ここで
> 入力される文字(半角カナ)を随時確定していきたいのですが、どの
> ようにすればよろしいでしょうか?

[スマートな解法]

Edit1の ImeMode プロパティを imSKata にして

uses Imm;

procedure TForm1.Edit1Enter(Sender: TObject);
var
  Imc: HIMC;
  Conversion, Sentence: DWORD;
begin
  Imc := ImmGetContext(Handle);
  ImmGetConversionStatus(Imc, Conversion, Sentence);
  ImmSetConversionStatus(Imc, Conversion, IME_SMODE_NONE);
  ImmReleaseContext(Handle, Imc);
end;

[スマートではないがいろいろ応用が利きそう]

procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
type
  TLetters = set of 'A'..'z';
const
  Vowels: TLetters = ['A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u'];
begin
  if (Key<>VK_RETURN) and (Chr(Key) in Vowels) then
  begin
    Keybd_event(VK_RETURN,0,0,0);
    Keybd_event(VK_RETURN,0,KEYEVENTF_KEYUP,0);
  end;
end;
参照: [Delphi-ML:31097] <その他Windows関連> <コンポーネント > <Standard>

0159  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
CreateProcess を使うときは CloseHandle で後始末

CreateProcess で Process_Infomation に返されるプロセス/スレッドハンドルは、明示的に CloseHandle でクローズしないとまずいです。

Win32 Ref. より抜粋

The created process remains in the system until all threads within the process have terminated and all handles to the process and any of its threads have been closed through calls to CloseHandle. The handles for both the process and the main thread must be closed through calls to CloseHandle. If these handles are not needed, it is best to close them immediately after the process is created.

作成されたプロセスは、プロセス内の全てのスレッドが終了し、かつ全てのプロセスとスレッドのハンドルが CloseHandle でクローズされるまでシステム内に残る。プロセスとメインスレッドのハンドルは必ず CloseHandle でクローズしなければならない。もしこれらのハンドルを使わないならばプロセスを作成した直後にクローズするのが最も良い。
参照: [Delphi-ML:30914]

0157  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
ディスパッチインターフェイスとデュアルインターフェイスについて

> さて、マニュアルを読んでみました。ですが、結構読みづらいです(@ @)。
> そこで、ちょっとほぐしてみました。
> (解釈に間違いがあればご指摘お願いいたします)

とのことですので、とりあえず覗いてみましょう。
参照: [Delphi-ML:30627] [Delphi-ML:30649] [Delphi-ML:30684] <PASCAL>

0155  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
マウスがクリックされた正確な時刻が知りたい

> 現在は、ふつうに OnMouseDown イベントから、GetCurrentTimeMillis()
> しているのですが、 Windows のイベントスプールにマウスイベントが
> たまってしまった場合、正確に マウスイベントの時間を計測しているか
> どうか、疑わしいと思います。

GetMessageTime API はいかがでしょう?  Thread Queue に置かれたときの時刻が手に入るみたいです。
参照: [Delphi-ML:30236] <その他Windows関連>

0153  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
エクスプローラで使われるアイコンを取得・変更する

> Windowsでディレクトリなどに使われるアイコンを変更するなどの
> プログラムもあるみたいですが、そういったシステムで使われる
> アイコンを取得したいと思っています。

レジストリの HKEY_LOCAL_MACHINE の下に

Software\Microsoft\Windows\CurrentVersion\explorer\Shell Icons

というキーがあり、ここに番号の文字列を作り、アイコンのファイル名とインデックスを設定することによりアイコンが設定可能です。
参照: [Delphi-ML:26403] <アイコン> <ファイル>

0147  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
クリップボードにコピーされたファイル・ディレクトリ

> クリップボードからペーストなのですが、どのようにしたらファイル名
> なのか確認できますか?その取り出し方も教えていただけないでしょうか?

プログラム上、考慮することが2点(だけかな?)、あります。

1) Explorer上で「コピー」した場合は、クリップボード内にCF_HDROPフォーマットのデータが入るようになってます。この場合、ファイルの有無はこのフォーマットの有無で判断できます。例は下のほうに置いておきます。

2) IE4が出てから、Explorerに「アドレス」なるコンボボックスが付きやがりまして、ここでディレクトリ名の「コピー」、できちまうんスよ、ったく。こいつ、テキスト形式(CF_TEXT)なんでね、これも考慮するとくりゃ、テキストがファイル名として正しいのか、白黒つけなきゃならないんスね。あ〜こりゃこりゃ。ちと面倒なコトをするハメになりそうっスよ、ったく。くぁ〜、まぃったねぇ。あっしぁ、面倒みきれませんぜ。なんせ あっし、ほれ、バカなんで。

// uses Clipbrd, ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
var
  i,
  n: integer;
  hDrop: THandle;
  szFile:  array[0..MAX_PATH-1] of Char;
begin
  if HasFormat(CF_HDROP) then
  begin
    hDrop := GetAsHandle(CF_HDROP);
    n := DragQueryFile(hDrop, $FFFFFFFF, szFile, MAX_PATH); // -1かな?(64bit用)
    Caption := Format('FileCount : %d', [n]);
    for i := 0 to n - 1 do
    begin
      DragQueryFile(hDrop, i, szFile, MAX_PATH);
      ListBox1.Items.Add(szFile);
    end;
  end;
end;
参照: [Delphi-ML:25073] <その他Windows関連> <ファイル>

0140  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
リムーバブルドライブの種類を判別する

結局結論は出たのでしょうか???
参照: [Delphi-ML:24577] <ファイル>

0138  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
Bitmap のパレットに使いたい色を追加する

>どうやれば どんなBMP にでも 画像を悪化 せずに
>自分で指定した色で文字を描画出来るようになるのでしょうか

取りあえず、こんな処理はどうでしょう?

var bm: TBitmap;
    pal: TMaxLogPalette;
    PalSize: WORD;
    i: Integer;

const Colors: array[0..15] of TColor =
  (clBlack, clMaroon, clGreen, clOlive,
   clNavy, clPurple, clTeal, clSilver,
   clGray, clRed, clLime, clYellow,
   clBlue, clFuchsia, clAqua, clWhite); // VGA Colors

    :
    :

  bm := TBitmap.Create;
  bm.LoadFromFile('c:\windows\雲.bmp');

  // パレットエントリ数を得る
  GetObject(bm.Palette, 2, @PalSize);

  // パレットの色を取得
  GetPaletteEntries(bm.Palette, 0, PalSize-1, pal.palPalEntry);

  // パレットのエントリを16色分ずらす
  for i := PalSize-1 + 16 downto 16 do
    if i < 256 then
      pal.palPalEntry[i] := pal.palPalEntry[i-16];

  // ずらして空いた部分に VGA カラーを埋め込む
  for i := 0 to 15 do begin
    pal.palPalEntry[i].peRed   := GetRValue(Colors[i]);
    pal.palPalEntry[i].peGreen := GetGValue(Colors[i]);
    pal.palPalEntry[i].peBlue  := GetBValue(Colors[i]);
    pal.palPalEntry[i].peFlags  := 0;
  end;

  if Palsize + 16 > 256 then
    pal.palNumEntries := 256
  else
    pal.palNumEntries := PalSize + 16;

  pal.palVersion := $0300;

  // VGA カラーを足したパレットをビットマップにセット
  // TBitmap は新しいパレットで色の劣化が最小限に
  // なるように自動的にカラーマッチをやり直してくれます。
  bm.Palette := CreatePalette(PLogPalette(@pal)^);

これで VGA Color が描けるビットマップになると思います。
ほとんど色は劣化しません。ただ、パレットの後半に重要な色が有ると多少劣化するかも。そこまでやるには VGA Color を挿入する前にパレットの色を明るさの降順に並べ替える処理を入れた方がいいと思います。
また、VGA Colors と同色の色が有った場合、その色を挿入しないようにすれば、より品質が向上すると思います。
参照: [Delphi-ML:24045] <その他Windows関連> <画像>

0117  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 編集
Delphi で DOS のアプリを書く方法

[A1]
http://www.geocities.com/SiliconValley/Park/4493/
にある 32 ビット DOS エクステンダで Win32 Console 実行ファイルをMS-DOS 実行ファイルに変換できます。
どの API が使用できるのかは未確認ですが・・・・

[A2]
Delphi1の場合、DOS用Turbo Pascalの最終バージョンであるBorland Pascal 7.0付属のライブラリソースを元にしてDOS用ライブラリをでっちあげ、かつコマンドラインコンパイラでオプション-cdをつけてコンパイルすれば、DOS プログラム用のコンパイラとして動かすことができます。
ライブラリの構築にBP7が必要なので、「Delphiだけで」というわけにはいきませんが、一度ライブラリを作ってしまえばOKということです。
ただ、このライブラリでっち上げが「すげー手間」なのでお勧めしません。
昔はCompuServeにライブラリソースの差分が上がってたんですけど、さすがにもう消えているはずです。
現実的には、どうせライブラリ作成過程で必要になるBP7を素直に使うのが正常な判断というものでしょう。
#私?BP7も持ってたから試しましたとも、D1日本語版すら出てない頃に(^^;
参照: [Delphi-ML:22238] [Delphi-ML:22240] <開発環境>

0118  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 編集
Delphi/CBuilder で作った DLL から VB に文字列を返す

> VB(VBA含む)は、ポインタが使えませんので、DLLで文字列を返す方法
> が知りたいです。 だれか、ご存知のかたおしえてください。

一番手軽なのは,SysAllocStringByteLen で文字列を確保して,そのまま返す方法です.

例)
  return SysAllocStringByteLen( "Hello", 5 );

内容は ShiftJIS で Ok.
ここで確保したメモリーは VB 側で開放されるそうです.
参照: [builder:6429] <DLL> <メモリ>

0120  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 編集
コントロールパネルのスクリーンセーバの設定画面を表示させる

> 画面のプロパティの設定ウィンドウを自作のアプリから
> 起動するにはどうすれば良いのでしょう?
---------------8<---------8<-------------------------------
> できれば、プロパティ設定画面の"スクリーンセーバー"のページが
> デフォルトで表示される方法をご教示頂ければ有り難いのですが。

 コマンドラインだと
  Rundll32 Shell32.dll,Control_RunDLL Desk.cpl,,1


 アプリからでは
  ::ShellExecute( Handle ,"open","Rundll.exe",
                  "Shell32.dll,Control_RunDLL Desk.cpl,,1",
                  "",SW_SHOWNORMAL);

で"スクリーンセーバー"のページが表示されます。
(コンマの前後に空白は入れないこと。)

パラメータの最後の数値が 2 なら"デザイン"、3 では"ディスプレイの詳細"が表示されます。終端の数字が 0 或いは、コンマ・数字無しだとデフォルトの"背景"です。
参照: [builder:6442] <その他Windows関連>

0121  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 編集
Windows95 のみを再起動する

> Windowsの再起動ってどうやればいいんでしょうか?
> マシンごと再起動ではなく、Windowsのみの再起動を
> したいのですが・・・。
> Windowsの終了->コンピューターを再起動する
> をシフトキーを押しながらしたときの動作がしたいのです。

これ、16BitAPIコードじゃないとできないらしいです。
だからWin95では使えても、NTでは無理なのでは?
と思いますが……どうなんでしょう?

ちょっと裏技として、RUNDLLを利用する手段があります。
 RUNDLL.EXE に
 user.exe,exitwindowsexec
というオプションをつけて起動させてみてください。
ショートカットでは正常動作したので、多分使えると思います。
プログラムでは95でもNTでも試していませんが……。

できなかったらごめんなさい。
ではまた。
参照: [builder:6513]

0125  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 編集
他プロセスの Window を GUI で選ばせたい


TImage を基本として作ったVCLを紹介します。
当該コントロール上でマウスの左ボタンを押下し、そのまま目的のウィンドウ上までドラッグ、ボタンを離す事によって、ウィンドウハンドルを得ることができます。

ThWndCapture Ver. 1.00
http://w3ma.kcom.ne.jp/~sammy/

レポートお待ちしております。
参照: [Delphi-ML:22176]

0128  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 編集
実行終了後、自分自身(実行ファイル)を削除したい

> 実行終了後、自分自身を削除したいのですが、
> なにか良い方法はありませんか?

こんなのはどうでしょう?
MoveFileEx(lpszExisting,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
NTではこれで再起動時に削除されます。

Windows95 ではこのAPIはサポートされないので
以下の方法をとるように、MoveFileEx のヘルプで示されています。

Windows 95: The MoveFileEx function is not supported on Windows 95.
To rename or delete a file at reboot on a Windows 95 system, use the following procedure.

・To Rename or Delete a File on Windows 95
Check for the existence of the WININIT.INI file in the Windows directory. If WININIT.INI exists, open it and add new entries to the existing [rename] section. If the file does not exist, create the file and create a [rename] section. Add lines of the following format to the [rename] section:
DestinationFileName=SourceFileName

Both DestinationFileName and SourceFileName must be short filenames. To delete a file, use NUL as the value for DestinationFileName.

The system processes WININIT.INI during system boot. After WININIT.INI has been processed, the system names it WININIT.BAK.

ちなみに、いずれも再起動が必要です。また私自身は、Windows95 で上記の方法は試したことがありませんが、WindowsNTで自分自身を消去するのは確認済みです。
参照: [Delphi-ML:22795]

0130  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 編集
メタファイルを wmf 形式でコピーするときの注意

Word 95 などのように旧メタファイル形式にしか対応しないアプリにメタファイルをコピーするときの注意点です。
Windows はクリップボードにエンハンストメタファイルが有って CF_METAFILEPICT 形式のメタファイルを要求されるとメタファイルを自動的に変換(emf->wmf)します。

ところが Windows がメタファイルをエンハンストから旧メタファイルに変換するとき境界枠の大きさやアスペクト比が失われてしまいます。

以下のように、はじめから wmf でクリップボードにコピーしておくといいようです。

procedure SaveToClipAsWMF(mf: TMetafile);
var
  hMetafilePict: THandle;
  pMFPict: PMetafilePict;
  DC: THandle;
  Length: Integer;
  Bits: Pointer;
  h: HMETAFILE;
begin
  DC := GetDC(0);
  try
    Length := GetWinMetaFileBits(mf.Handle, 0, nil,
                                 MM_ANISOTROPIC, DC);
    Assert(Length > 0);
    GetMem(Bits, Length);
    try
      GetWinMetaFileBits(mf.Handle, Length, Bits,
                     MM_ANISOTROPIC, DC);
      h := SetMetafileBitsEx(Length, Bits);
      Assert(h <> 0);
      try
        hMetafilePict := GlobalAlloc(GMEM_MOVEABLE or
                                     GMEM_DDESHARE,
                                     Length);
        Assert(hMetafilePict <> 0);
        try
          pMFPict := GlobalLock(hMetafilePict);
          pMFPict^.mm := MM_ANISOTROPIC;
          pMFPict^.xExt := mf.Width;
          pMfPict^.yExt := mf.Height;
          pMfPict^.hMF  := h;
          GlobalUnlock(hMetafilePict);

          Clipboard.SetAsHandle(CF_METAFILEPICT, hMetafilePict);
        except
          GlobalFree(hMetafilePict);
          raise;
        end;
      except
        DeleteObject(h);
        raise;
      end;
    finally
      FreeMem(Bits);
    end;
  finally
    ReleaseDC(0, DC);
  end;
end;

参照: [Delphi-ML:23065] <その他Windows関連> <画像>

0052  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 編集
デスクトップフォルダのパスを得る

uses Shellapi, ShlObj, ActiveX, ComObj;

function GetDesktop: string;
var pidl: PItemIDList;
    buf : array [0..MAX_PATH] of Char;
    m   : IMalloc;
const DesktopID = CSIDL_DESKTOPDIRECTORY;
begin
  OleCheck(CoGetMalloc(1, m));
  OleCheck(SHGetSpecialFolderLocation(0, DesktopID, pidl));
  try
    Assert(SHGetPathFromIDList(pidl, buf));
    Result := buf;
  finally
    m.Free(pidl);
  end;
end;

ネットワークコンピュータ、マイコンピュータは仮想フォルダなので
パスは有りません。マイコンピュータの定義は CSIDL_DRIVES です。
参照: [Delphi-ML:19392]

0060  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 編集
CD-DA のデータを Wav ファイルに落としたい

ここにあるcd2wavが大いに参考になるでしょう。ソース付きです。
http://www2s.biglobe.ne.jp/~elfin/
参照: [builder:4912]

0061  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 編集
複数プログラムから同一内容のメモリを参照/更新する

Win32用に、中村@NECさんが、File Mapping を利用して実現したクラスを [Delphi-ML:19603] で紹介されています。
ただ、添付ファイルは Web からは取れません。
どこか他からダウンロードしないと。。。
参照: [Delphi-ML:19603] <ファイル> <メモリ>

0062  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 編集
プログラムからWindowsのスタートメニューを表示する

以下の方法でメニューを出すことができるようです。

 HWND taskbar=FindWindow("Shell_TrayWnd","");
 if(taskbar) PostMessage(taskbar,WM_USER+260,0,0);
参照: [builder:4947] <メニュー>

0064  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 編集
SetWindowsExt/SetViewportExtを使うときの注意点

TCanvas.Handle に対してこれらの関数を呼んで使う際の注意点。

(1) Font.Height と Font.Size の関係はマッピングモードが MM_TEXT
    で有ることを仮定しているので SetMapMode API でマッピングモードを
    変えた場合は Font.Height のみを使った方が良いでしょう。
(2) API の効果の寿命はイベントハンドラ毎です。
    引き継がれません。
参照: [Delphi-ML:19671] <描画>

0072  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 編集
スクリーンセーバーをプログラムから停止する

API の SetCursorPos() で強制的にマウスの位置を動かしてやることでスクリーンセーバを止めることができます。
95ではちょっと動かしてやれば止まりますが、NT4ではある程度以上大きく動かさないと止まってくれないそうです。
最近の報告では、この方法でNT4のスクリーンセーバを停止すると、その後いつまで経ってもスクリーンセーバが起動してくれないとのことです。

ちなみに、スクリーンセーバを開始させるには、uses 節に Messages を加えて、

  SendMessage(Handle, WM_SYSCOMMAND, SC_SCREENSAVE, 0);

でできます。
参照: [Delphi-ML:5062] [Delphi-ML:17211] [Delphi-ML:19836] <その他Windows関連>

0078  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 編集
Delphiアプリをマウスのホイールに対応させたい

TMouseWheel コンポーネントってのがあります。
これが、参考になるのではないでしょうか。

以下、readme.txtより抜粋
---------ここから
(概要)
このコンポーネントはフォームに貼り付ける事によってそのフォー
ムに貼り付けてある全てのコントロールに対してホイールによるス
クロールを可能にする事ができます。
---------ここまで

Delphi広場にありました。ファイル名:mwheel.exe
http://www.sakaki.keiaikai.or.jp/
参照: [Delphi-ML:20365]

0080  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 編集
ヘルプ作成用のホットスポットエディタ(SHED.EXE)の入手方法

以下のURLよりダウンロードが可能です。
ftp://ftp.microsoft.com/Softlib/MSLFILES/SHED.EXE
参照: [Delphi-ML:20436] <開発環境> <ヘルプ>

0081  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 編集
「システムエラー 読み出せません ドライブ X:」ダイアログを回避する

Q:
Delphiで、フロッピーのようなリムーバブルメディアがちゃんとセットされているかを、「静かに」知る方法はないものでしょうか。FileExists関数を使っても、フロッピーの入っていないドライブを見に行くと、システムエラーダイアログが表示されてしまいます。

A:
Windows API の SetErrorMode を使用すればいいでしょう。
ここ一年使っているドライブのチェックルーチンはこんな感じです。
# WIN32の部分はまだあまり実績がないですけど...

function IsDriveReady(drive : char) : boolean;
var
  oldmode : word;
  searchrec : tSearchRec;
begin
  drive := upcase(drive);
  oldmode := SetErrorMode(SEM_FAILCRITICALERRORS);  (* ここと *)
  result := DiskSize(ord(drive)-$40) <> -1;
{$IFDEF WIN32}
  if result and (GetDriveType(pchar(drive+':\')) in [DRIVE_REMOTE, DRIVE_CDROM]) then begin
{$ELSE}
  if result and (GetDriveType(ord(drive)-$41) = DRIVE_REMOTE) then begin
{$ENDIF}
    result := FindFirst(drive+':\*.*',$3f, searchrec) = 0;
    FindClose(searchrec);
  end;
  SetErrorMode(oldmode);                            (* ここね *)
end;

http://slis.flet.mita.keio.ac.jp/~anakata/delphi/myfaq.html#Q12
にも載せてあります。
参照: [Delphi-ML:184] <ダイアログ>

0083  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 編集
自作コントロールで IME 入力時の変換候補をキャレット位置に表示したい

IMEが編集を開始する直前にWM_IMESTARTCOMPOSITION というメッセージを送って来るので、そのメッセージを捕らえて設定してやります。

class TCustom : public TCustomControl
{
  ・・・・・・・・・・・・

   void __fastcall IMEStart(TMessage& Message);

   BEGIN_MESSAGE_MAP
      MESSAGE_HANDLER( WM_IME_STARTCOMPOSITION ,TMessage,IMEStart)
   END_MESSAGE_MAP(TCustomControl)
};

void __fastcall TCustom::IMEStart(TMessage& Message)
{
  //  IMEの位置をキャレットのポジションに設定
  COMPOSITIONFORM CompForm;
  POINT pt;
  LOGFONT lf;
  HIMC hImc=ImmGetContext(Handle);

  //キャンバスのフォントと同じに設定する
  GetObject(Canvas->Font->Handle,sizeof(LOGFONT),&lf);
  ImmSetCompositionFont(hImc,&lf);

  //キャレットのポジションに設定する
  ImmGetCompositionWindow(hImc,&CompForm);
  CompForm.dwStyle=CFS_POINT;
  GetCaretPos(&pt);
  CompForm.ptCurrentPos=pt;
  ImmSetCompositionWindow(hImc,&CompForm);

  ImmReleaseContext(Handle, hImc);

  // その他の処理
  ・・・・・・・・・・・・・
}
参照: [builder:5269] <その他Windows関連> <コンポーネント開発> <コンポーネント > <Standard>

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関連> <System> <ShellApi> <バグ> <コンポーネント >

0097  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 編集
起動したアプリケーションの終了待ち

WaitForSingleObject という API を使います。
これをキーに過去ログを検索すると、コード例も見つかります。
http://www2.big.or.jp/~osamu/Delphi/search.cgi?key1=WaitForSingleObject
参照:

0103  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 編集
NT のタスクマネージャにアプリケーションのアイコンが表示されない

Delphi で作られるソフトすべてでこの問題が発生します。ちなみに、Delphi 自身も同じ問題を抱えています。
アプリケーションのクラスアイコンをセットしたら表示されるようになると思います。
プロジェクトソースかメインフォームの OnCreate イベントで、

SetClassLong(Application.Handle,
             GCL_HICON,
             Application.Icon.Handle);

を実行して下さい。
参照: [Delphi-ML:21168] <その他Windows関連> <アプリケーション> <バグ> <アイコン>

0105  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 編集
DDeClientConv を使ってスタートメニューにアイコンを登録

3.1 のプログラムマネージャのときと同じですね。
DDEClientConv をフォームに置いて以下のようにします。

var strGroup:String;
    strExeName:String;
    strPrgName:String;
    Temp:String;
begin
    strGroup   := 'グループ名';
    strPrgName := 'ソフト名';
    strExeName := Application.ExeName;

    if not DDEClientConv1.SetLink('PROGMAN','PROGMAN') then begin
        ShowMessage('ショートカットの制作に失敗しました。');
    end else try
        {グループの作成}
        Temp := '[CreateGroup(' + strGroup  + ')]';
        DDEClientConv1.ExecuteMacro(PChar(Temp),False);

        {グループの表示}
        Temp :=  '[ShowGroup(' + strGroup  + ',1)]';
        DDEClientConv1.ExecuteMacro(PChar(Temp),False);

        {アイテムの作成}
        Temp :=  '[AddItem("' + strExeName + '","' + strPrgName + '")]';
        DDEClientConv1.ExecuteMacro(PChar(Temp),False);

        ShowMessage('ショートカットを作成しました。');
    finally
        DDEClientConv1.CloseLink;
    end;
end;
参照: [Delphi-ML:21012] <その他Windows関連> <ShellApi> <スタートメニュー> <配布>

0112  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 編集
スタートメニューを任意の位置にポップアップさせる

スタートメニューのポップアップは、

procedure PopupStartMenu;
var hTaskBar: Integer;
begin
    hTaskBar:= FindWindow(PChar('Shell_TrayWnd'), nil);
    SetForegroundWindow(hTaskBar);
    PostMessage(hTaskBar, WM_USER + $0104, 0, 0);
end;

でOK。
表示されたメニューを MoveWindow で強制的に動かすには、

procedure MoveStartMenu(Point: TPoint);
var hStartMenu: Integer;
    OldRect: TRect;
begin
    hStartMenu:=FindWindow('#32768',nil);
    GetWindowRect(hStartMenu, OldRect);
    MoveWindow(hStartMenu,
        Point.X, Point.Y,
        OldRect.Right-OldRect.Left, OldRect.Bottom-OldRect.Top,
        True);
end;

詳しくはスレッドを追って下さい。
参照: [Delphi-ML:21886] <スタートメニュー>

0028  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 編集
Windowsの「ファイルの検索ダイアログ」を表示させる

ファイルの検索ダイアログを出すには、DDEを使います。

フォームに TDdeClientConv コンポーネント(Systemタブ)を乗っけて、

procedure TForm1.Button1Click(Sender: TObject);
var
  Macro:string;
begin
  DdeClientConv1.SetLink('Folders','AppProperties');
  DdeClientConv1.ServiceApplication:='Explorer';
  DdeClientConv1.OpenLink;
  Macro := Format('[FindFolder("%S")]', ['D:\Delphi 3']);
  DdeClientConv1.ExecuteMacro(PChar(Macro),False);
  DdeClientConv1.CloseLink;
end;

てなふうにします。D:\Delphi 3 フォルダがカレントになります。
ちなみにどこで見つけたかというと、レジストリの

 HKEY_CLASSES_ROOT\Directory\shell\find\ddeexec

です。
参照: [Delphi-ML:20377] <その他Windows関連> <ShellApi> <ダイアログ>

0037  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 編集
自作アプリで作ったオブジェクトを他のアプリに貼り付けたい

自作アプリを OLE サーバにして他のアプリに貼り付けられるデータを作成する方法が Inside Windows の、98年4月号「Delphi の神託」に出ているそうです。
参照: [Delphi-ML:18525] <その他Windows関連> <ShellApi>

0048  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 編集
TrueTypeフォントからベクタ情報を得る

中村@NECさんのサンプルコードが[Delphi-ML:6963]にあります。
参照: [Delphi-ML:06963] <その他コンポーネント関連> <コンポーネント >

0010  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 編集
32bitアプリから16bit DLLを呼び出す

英語ですが、
    http://www.itecuk.com/delmag/thunk95.htm
に詳しく説明があり、サンプルソースも落としてこれます。

ただし、Delphi Magagine で紹介されている方法を解読するには遙かなる時間がかかるでしょう。まあ、これは参考文献にとどめて置いて、やはり実践的なサンプルコードが必要かと思います。

DSP(http://ring.asahi-net.or.jp/archives/pc/delphi/)の、ThunkDownを使ったサンプル「freres.zip」と「zthunk.zip」や、ひきさんの「TExitWinコンポーネント」(http://www.vector.co.jp/authors/VA009712/take/)が参考になると思います。

また、UserリソースやGDIリソースを得るにはGetFreeSystemResourcesを使うのですが、これは16ビットAPIなため、ThunkDownが必要です。
サンプルまでひきさんが書いてくれました。
#でも Web からは添付文書取れないんだよね。。。(^^;;;
参照: [Delphi-ML:18742] <DLL>

0007  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 編集
Delphi3.0でDLLにバージョン情報が入らない

Delphi3.0で、「新規作成」から DLL を作ると、「バージョン情報を含める」のオプションを指定しても、効果が無い。
これは、.dpr ファイルに {$R*.RES} の一文が入らないために、リソースファイルはできるのに、リンクされないためだ。
uses節の後ろに手動で{$R*.RES} を書いてやればよい。
参照: [Delphi-ML:19012] <その他Windows関連> <アプリケーション> <開発環境> <バグ> <DLL>

0000  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 編集
Delphi 1.0 (16bit)で、物理メモリアドレスに直接アクセスする


procedure TForm1.Button1Click(Sender: TObject);
var
  TestSelector:  word;                  {新しいセレクタ}
  P           : ^byte;                  {メモリマップアクセス用ポインタ}
begin
  TestSelector := AllocSelector(DSeg);  {新しいセレクタを作成}
  SetSelectorBase(TestSelector, $C8000);{ベースアドレスを$C8000に設定}
  SetSelectorLimit(TestSelector, $2000);{8KB($2000)確保}
  P  := Ptr(TestSelector, $0100);       {$0100 アドレスにポインタセット}
  P^ := $00;                            {$C8000+$0100=$C8100に$00を書込}
  FreeSelector(TestSelector);           {セレクタの解放}
end;
参照: [Delphi-ML:18551] <メモリ>

0002  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 編集
NTで他のアプリが開いているファイルを知る

WindowsNT上ならば、
   http://www.ntinternals.com/
に NTFilemon があります。
ソースが公開されているので、参考になるかもしれません。
参照: [Delphi-ML:18558] <ファイル>

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

How To
Lounge
KeyWords

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

.