Delphi Tips
>> Index
● 03/04 フォームの最小化時のアニメーション効果を出す(BCB)
● 05/17 Photoshop のようなツールウィンドウを実現したい
● 05/17 OnShow イベント中で SetFocus すると不具合
● 06/02 フォームの新規作成のデフォルトを変更したい
● 12/22 フォームを1つずつ表示する
● 09/27 アプリケーションを常駐させてタスクトレイに登録したい
● 09/20 フォームのアイコンをアニメーションにしたい
● 09/06 メインフォーム以外のフォームをタスクバーに入れたい。
● 09/06 APPのフォームを最小化して起動したい
● 09/06 カーソルキーでボタン(TButton)のフォーカス移動をやめさせたい
● 09/01 フォームの最小化、最大化をアニメーションでやりたい。(DELPHI)
● 08/30 メインフォーム以外のフォームを最小化した時もAPP全体を最小化したい
● 02/11 フォームの破棄、生成を続けて行うときの注意事項
● 02/11 Delphi2 以上で Form の枠を黒線一本にするには
● 02/11 アプリケーションが最小化されているかどうかを判定する
● 02/11 Form をスクロールして特定のコントロールを表示させる
● 02/08 Scaled/AutoScrollプロパティと実行時のフォームサイズ
● 02/08 起動時にフォームの表示・非表示を決める
● 02/08 サブフォームがアクティブな時はメインフォームのアクセラレータキー・ショートカットキーを無効にしたい
● 02/08 アイコン状態で起動するアプリ
● 02/08 フォームの印刷時にComboBoxの内容が印刷されない
● 02/08 設計時にフォームがエラーで読み込めず変更もできない
最終更新: 7569 日前
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] <Windows>
0327 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 編集
Photoshop のようなツールウィンドウを実現したい
1.細いタイトルバーでクローズボタンのみが付いている
2.アプリケーションがアクティブであればツールウィンドウのタイトルバーもアクティブ色
3.常にアプリケーションのフォームよりも手前にある
というようなツールウィンドウを実現しようと思うと、フォーカス関連のイベントが貧弱な Delphi ではなかなか難しいようです。
[Delphi-ML:66799]、[Delphi-ML:66801] で書かれているように、アプリケーションに飛んでくるすべてのメッセージの中からフォーカスの移動に関係するものをチェックしてやることで実現が可能です。実際のツールウィンドウはコード中の TToolWindow を継承して作成することになります。
参照: [Delphi-ML:66799] <アプリケーション>
0318 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 編集
OnShow イベント中で SetFocus すると不具合
フォームにMemoを貼り付けて実験してみたのですが
procedure TForm1.FormShow(Sender: TObject);
begin
Memo1.SetFocus;
end;
とすると「ソフトを起動したとき、それがアクティブウィンドウになるにもかかわらず、そのソフトを示すタスクバーのボタンが押されない状態で表示される」という症状が出るようです。
Memo1 の TabOrder をゼロにするなど、別の方法でフォーカスをコントロールする必要があるようです。
参照: [Delphi-ML:67321] <アプリケーション>
0310 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 2001/06/02 濱野 rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2001/06/02 濱野 編集
フォームの新規作成のデフォルトを変更したい
例えばはじめからScaled=Falseにしたい、
文字は固定ピッチで大きめのフォントにしたい、
フォームの位置、大きさ、表示状態を最大化で標準化したい、etc....
こういう時、元になるフォームを[プロジェクト]-[リポジトリに追加]
でリポジトリに登録しておき、[ツール]-[リポジトリ]で登録した
フォームを選択して、[フォームの新規作成時に使用]にチェックを入れて
おけばスピードバーや[ファイル]-[フォームの新規作成]を選んだときに
リポジトリに登録したものと同じ内容でフォームを作成することが出来ます。
ただしあくまでもコピーが作成されるだけなので元のフォームを変更しても
その変更は反映されません。そのような変更が予想される場合は[ファイル]
-[新規作成]で[継承]を選んで使用すると後々便利です。
コントロールのデフォルト変更には[コンポーネント]-
[コンポーネントテンプレートの作成]を使用するといいでしょう。
Delphi 5からはさらにフレーム機能という便利な機能もあります。
参照: <開発環境>
0295 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/12/22 濱野 rev 1.1 B1B3B4B5 B6 B7 NT3 NT4 2K XP 更新: 1999/12/22 濱野 編集
フォームを1つずつ表示する
TFormの配列をスタック風に管理し、呼び出し元は
呼び出されたフォームを表示後、非表示にします。
これでフォームが1つずつ表示されるようになります。
前のフォームへの復帰も再表示するだけなので速いです。
この手続きにちょっと手を加える事で位置やサイズを
揃える事も出来ます。
unit FmDsp;
interface
uses
Windows, Messages, SysUtils, Classes, Forms;
procedure SetMainForm(MainForm: TForm);
procedure ShowNextForm(FormClass: TFormClass; Form: TForm);
procedure ShowPrevForm;
implementation
type
TShowType = (stWithCreate, stShowOnly);
TFormRec = record
Form: TForm;
ShowType: TShowType;
end;
var
FormAry: array[0..100] of TFormRec;
FormTop: Integer = 0;
{ 最上階のフォームの登録、プログラムのスタートアップ時
に一回だけ呼び出す。 }
procedure SetMainForm(MainForm: TForm);
begin
FormAry[0].Form := MainForm;
FormAry[0].ShowType := stShowOnly;
FormTop := 0;
end;
{ 次のフォームの表示
FormClass: フォームのクラス名
Form: フォーム変数名、フォームが自動作成でない場合 nilを指定 }
procedure ShowNextForm(FormClass: TFormClass; Form: TForm);
begin
Inc(FormTop);
if Form = nil then
begin
FormAry[FormTop].Form := FormClass.Create(Application);
FormAry[FormTop].ShowType := stWithCreate;
end else
begin
FormAry[FormTop].Form := Form;
FormAry[FormTop].ShowType := stShowOnly;
end;
FormAry[FormTop].Form.Show;
FormAry[FormTop - 1].Form.Hide;
end;
{ 前のフォームの表示、呼び出された側のフォームのCloseイベントで呼び出し }
procedure ShowPrevForm();
begin
FormAry[FormTop - 1].Form.Show;
if FormAry[FormTop].ShowType = stWithCreate then
FormAry[FormTop].Form.Release
else
FormAry[FormTop].Form.Hide;
Dec(FormTop);
end;
end. { unit FmDsp }
参照:
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> <Windows> <コンポーネント >
0265 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 西坂良幸 編集
フォームのアイコンをアニメーションにしたい
タイマーイベントを使って、AppliCationのアイコンをきりかえてやればアニメーションGIFのような効果ができます。
プロジェクトの*.resファイルに、アイコン'ICON1'-'ICON5'をアニメ風に作成して下さい。
フォームにStartBtn、StopBtn の2個のボタンとTTimer(Intervalプロパティを100程度)を貼り付けます。
private 部に
IconStat: integer;
ICon1,ICon2,ICon3,ICon4,ICon5: TIcon;
と書き加えます。
// あらかじめリソースを参照するアイコンを作成
procedure TForm1.FormCreate(Sender: TObject);
begin
ICon1 := TIcon.create;
ICon1.Handle := LoadIcon(HInstance,'ICON1');
ICon2 := TIcon.create;
ICon2.Handle := LoadIcon(HInstance,'ICON2');
ICon3 := TIcon.create;
ICon3.Handle := LoadIcon(HInstance,'ICON3');
ICon4 := TIcon.create;
ICon4.Handle := LoadIcon(HInstance,'ICON4');
ICon5 := TIcon.create;
ICon5.Handle := LoadIcon(HInstance,'ICON5');
Application.Icon.Handle := ICon1.Handle;
IconStat := 1;
end;
// 破棄
procedure TForm1.FormDestroy(Sender: TObject);
begin
ICon1.Free;
ICon2.Free;
ICon3.Free;
ICon4.Free;
ICon5.Free;
end;
// スタート
procedure TForm1.StartBtnClick(Sender: TObject);
begin
Timer1.Enabled := true;
end;
// ストップ
procedure TForm1.StopBtnClick(Sender: TObject);
begin
Timer1.Enabled := false;
IconStat := 1;
Application.Icon.Handle := ICon1.Handle;
end;
// タイマーイベントでアイコンの切り替え
procedure TForm1.Timer1Timer(Sender: TObject);
begin
If IconStat = 5 then IconStat :=1
else IconStat := IconStat + 1;
Case IconStat of
1: Application.Icon.Handle := ICon1.Handle;
2: Application.Icon.Handle := ICon2.Handle;
3: Application.Icon.Handle := ICon3.Handle;
4: Application.Icon.Handle := ICon4.Handle;
else Application.Icon.Handle := ICon5.Handle;
end;
end;
4−5個アイコンを作るとスムースです。
注意事項として。resファイルを書き直した時は、[プロジェクトの再構築]を行ってから実行して下さい。resの変更が反映されません。また、アイコンの名称はイメージエディタでは、デフォルトでIcon?となりますので、オリジナルな名称に変えて下さい。
また、イメージリストを使えば、以下のようにすれば、ほぼ同じ結果が得られます。
var
IconCount : integer;
procedure TForm1.Button1Click(Sender: TObject); // start
begin
Timer1.Interval := 100;
Timer1.Enabled := True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if IconCount >=ImageList1.Count then IconCount := 0;
ImageList1.GetIcon(IconCount, Application.Icon);
inc(IconCount);
end;
この場合は、使用するアイコンイメージは、リソースに入りませんので、プログラムアイコンとして使用出来ません。必要ならば、リソースからイメージリストへロードする処理を加えて下さい。
参照: [Delphi-ML:42725] [Delphi-ML:42748] <アイコン>
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] <タスクバー> <Windows>
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] <タスクバー> <Windows>
0237 D1 D2 D3 D4 D5 D6 D7 3.1 95 98 作成: 1999/09/06 西坂良幸 rev 1.1 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 1999/09/06 西坂良幸 編集
カーソルキーでボタン(TButton)のフォーカス移動をやめさせたい
TButtonのOnKeyPress、OnKeyDownなどでやってみてもダメですね。これは、Windowsのボタンの仕様です。
フォームへのCM_DialogKeyメッセージをとらえて処理すると可能です。
procedure TForm1.CMDialogKey(var Msg:TCMDialogKey);
begin
case Msg.CharCode of
VK_UP,VK_DOWN,VK_LEFT,VK_RIGHT : Msg.CharCode:=0;
end;
inherited;
end;
このメッセ−ジはタブキー(VK_TAB)もとらえることが出来ます。
参照: [Delphi-ML:3691] [Delphi-ML:33541] <コンポーネント > <Standard>
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] <Windows>
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] <Windows>
0166 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 編集
フォームの破棄、生成を続けて行うときの注意事項
> プログラム中でフォームを破棄し、直後に生成するとイベントが妙な順で
> 発生してしまい困っています。
>
> Form1.Release;
> :
> Form1 := TForm1.Create( Application );
> :
> Form1.Show;
> 処理A
>
> と、こんな感じで記述すると、Form1 の Create イベントや処理 A の後に、
> Form1のDestroy イベントが走っているようなのです。
Release の後で Application.ProcessMessages してみるとどうですか。Release のヘルプを見てみてください。
Form1 がアクセスされていないことが分かっているのなら、Free でも良いです(場合によって推奨されない方法です)。
参照: [Delphi-ML:31893]
0154 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 編集
Delphi2 以上で Form の枠を黒線一本にするには
Form の枠を一本線にするために Ctrl3D = True, BorderStyle = bsSingle としても、望みの結果が得られません。問題は、ControlStyle に csFrame が無いとき CTRL3D := False は無視されてしまうということです。
constructor を再定義して
# constructor TForm1.Create(AOwner: TComponent);
# begin
# inhelited;
# ControlStyle := ControlStyle + [csFramed] ;
# end;
を加えれば望みの結果が得られます。
参照: [Delphi-ML:30137] <バグ>
0148 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 編集
アプリケーションが最小化されているかどうかを判定する
最小化された状態の判定:
IsIconic(Application.Handle)
「元のサイズに戻す」
Application.Restore;
で良いと思います。
参照: [Delphi-ML:25293] <アプリケーション>
0145 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 編集
Form をスクロールして特定のコントロールを表示させる
TForm には ScrollInView / AutoScrollInView などという便利なメソッドがあります。
参照: [Delphi-ML:25041]
0054 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 編集
Scaled/AutoScrollプロパティと実行時のフォームサイズ
中村@NECさんの、[builder-ML:4674] からの引用です。
(1) Scaled = False, AutoScroll = False
フォームのフォントの大きさ、フォームのクライアント領域、
コントロールの大きさは設計時のピクセル単位のサイズが
そのまま使われる。
(2) Scaled = False, AutoScroll = True
(1) とほとんど同じだが、フォームは Width と Height で大きさが
設定されるので、タイトルバーの高さ、枠の幅、メニューの高さ
によりクライアント領域の大きさが若干かわるので、場合によっては
コントロールがはみ出したりする。
(3) Scaled = True, AutoScroll = False
フォームのフォントの大きさ、フォームのクライアント領域、
コントロールの大きさは設計時のピクセル単位のサイズに
フォントの大きさの変化に応じたスケール比を掛けたものが
使われる。
(4) Scaled = True, AutoScroll = True
フォームのフォントの大きさ、コントロールの大きさは設計時の
ピクセル単位のサイズにフォントの大きさの変化に応じた
スケール比を掛けたものが使われる。しかし、フォームの
大きさは設計時のピクセル単位の大きさがそのまま使われるので
コントロールがはみ出したりする。使わない方がよいでしょう(^^
Delphi-MLで詳しく解説してくださったのが [Delphi-ML:19661]。
参照: [Delphi-ML:19661]
0056 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 編集
起動時にフォームの表示・非表示を決める
Main Form の表示は Application の ShowMainForm と Main Form の Visible Property で決まります。
Application.Run が呼ばれる前に ShowMainForm を適切に設定して下さい。
参照: [Delphi-ML:19468]
0109 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 編集
サブフォームがアクティブな時はメインフォームのアクセラレータキー・ショートカットキーを無効にしたい
メインフォームのメニューに指定されたアクセラレータキー([File(&F)]とした時の 'F')は、サブフォームがアクティブであっても、そのサブフォームがメインメニューを持たない場合には、メインフォームのメニューを起動してしまいます。
また、メインフォームのメニューに指定されたショートカットキー([Open(&O)... Ctrl+O] とした時の 'Ctrl+O')は、サブフォームがアクティブである場合にも有効です。
これらを回避するには以下のようにします。
function TForm1.Hook(var Message: TMessage): Boolean;
begin
case Message.Msg of
CM_APPKEYDOWN:
Result := True; // ショートカットを無効にする
CM_APPSYSCOMMAND:
Result := True; // アクセラレータを無効にする
else
Result := False;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.HookMainWindow(Hook);
end;
参照: [Delphi-ML:21685] <メニュー>
0027 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-ML:13173] [Delphi-ML:13185] <バグ>
0040 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 編集
フォームの印刷時にComboBoxの内容が印刷されない
Delphi3 になって、フォームの印刷時に TComboBox の内容(テキスト)が印刷表示されなくなりました。
Delphi2 ではちゃんと印刷されます。
kohiroさんが[Delphi-ML:19070]で解法を示してくださっています。
参照: [Delphi-ML:19070] <印刷> <バグ> <Standard> <コンポーネント >
0020 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 編集
設計時にフォームがエラーで読み込めず変更もできない
> フォームのActiveControlプロパティにタブシードで
> 隠れている(つまりアクティブシートでない)コントロール
> にのせてあるものをせっていしてしまい、その後セーブ
> はできたのですが、プロジェクトをロードすると以下のような
> エラーがでて、フォームが二度と表示されなくなってしまいました。
.dfmファイルをDelphiのエディタに放り込んでみましょう。
もしくは[ファイルを開く]で.dfmファイルを読み込みます。
すると、.dfmファイルがテキストとして編集できますので、ActiveControlプロパティの設定部分を書き換えられます。
参照: [Delphi-ML:5705] <開発環境>
[新規作成] [最新の情報に更新]
How To
Lounge
KeyWords
Osamu Takeuchi osamu@big.or.jp
Tips
Delphi
Home