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

キーワード:その他Windows関連

>> Index

01/22 短いファイル名を長いファイル名に変換したい(COM版)。
07/18 スクリーンセーバーの作り方
06/27 Delphi によるレジストリの操作方法
06/27 コントロールパネルを作る
06/25 自己実行形式の動画
06/25 ActiveX でショートカットキーが使えない
05/17 ActiveX 内部から自身の親ウィンドウのハンドルを得る
12/28 Windows2000の新APIを使った半透明ウィンドウ
11/30 スクリーンセーバーの名前を変更する。
10/07 文字列リソースの編集ツール - 文字列テーブルエディタ
09/27 アップリケーションにサウンドリソースを埋め込んで使いたい。
09/20 エクスプローラのように、アプリケーションにブラウザページをつくりたい。
09/20 MDI等で二重起動を防止して新しいファイルを開く
09/19 二重起動の判定
09/19 インターネット エクスプローラを起動したい/その情報を取得したい
09/17 起動中のブラウザからURLを取得する/ブラウザにURLをセットする方法
09/08 IME に未確定文字列を入力
09/02 Windowsの「ファイルの検索」ダイアログをプログラムから使いたい
08/23 プロセスの実行ファイル名を列挙する
08/21 クリップボードのフォーマットを知る
08/21 クリップボードが更新された時のイベントを取得する
08/19 インターネットエクスプローラのアドレス帳を呼び出す
05/19 独自メッセージとして自由に使える値の範囲
02/11 IME 入力で読み仮名を取得する
02/11 半角カナを確定無しで直接入力させる
02/11 マウスがクリックされた正確な時刻が知りたい
02/11 クリップボードにコピーされたファイル・ディレクトリ
02/11 Bitmap のパレットに使いたい色を追加する
02/08 コントロールパネルのスクリーンセーバの設定画面を表示させる
02/08 メタファイルを wmf 形式でコピーするときの注意
02/08 スクリーンセーバーをプログラムから停止する
02/08 自作コントロールで IME 入力時の変換候補をキャレット位置に表示したい
02/08 TDDEClientConvで最初の行しか実行されない?
02/08 NT のタスクマネージャにアプリケーションのアイコンが表示されない
02/08 DDeClientConv を使ってスタートメニューにアイコンを登録
02/08 Windowsの「ファイルの検索ダイアログ」を表示させる
02/08 自作アプリで作ったオブジェクトを他のアプリに貼り付けたい
02/08 Delphi3.0でDLLにバージョン情報が入らない

最終更新: 6668 日前

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>

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>

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>

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

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> <バグ>

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>

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>

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>

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>

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] <WWW> <ShellApi> <Windows> <通信>

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;


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

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] <WWW> <Windows> <通信>

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>

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] <ShellApi> <Windows> <ダイアログ>

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>

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>

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>

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>

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>

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>

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> <ファイル>

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>

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>

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>

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>

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

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] <ShellApi> <Windows> <スタートメニュー> <配布>

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] <ShellApi> <Windows> <ダイアログ>

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] <ShellApi> <Windows>

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>

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

How To
Lounge
KeyWords

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