Delphi Tips
>> Index
● 06/20 システムメニューに項目を追加/削除したい
● 09/08 ショートカットキーに'+'を使う。
● 08/14 ショートカットキーのキー名を独自に設定する
● 02/11 表示中のポップアップメニューを消す
● 02/08 プログラムからWindowsのスタートメニューを表示する
● 02/08 PopupMenu に MainMenu のサブ項目をそのまま表示する
● 02/08 サブフォームがアクティブな時はメインフォームのアクセラレータキー・ショートカットキーを無効にしたい
最終更新: 7411 日前
0065 D1D2 D3 D4 D5 D6 D7 3.195 98 作成: 1999/02/08 osamu rev 1.4 B1 B3 B4 B5 B6 B7 NT3 NT4 2K XP 更新: 2004/06/20 kakken 編集
システムメニューに項目を追加/削除したい
海外製のコンポーネントですがこういうのがあるそうです(ソース付だそうだ)
http://www.torry.ru/vcl/menus/ksysmenu.zip
実際にやってみましょう。まず削除です。
デファウルトでシステムメニューはこのようになっています
+−−−−−−−−−+
|元のサイズに戻す |
|移動 |
|サイズ変更 |
|最小化 |
|最大化 |
|−−−−−−−−−|
|終了 |
+−−−−−−−−−+
// 上の例から移動と、終了だけ残します。
procedure TForm1.Button1Click(Sender: TObject);
var
hSysMenu:integer;
begin
hSysMenu := GetSystemMenu(Handle,False);
DeleteMenu(hSysMenu, 0, MF_BYPOSITION);
DeleteMenu(hSysMenu, 1, MF_BYPOSITION);
DeleteMenu(hSysMenu, 1, MF_BYPOSITION);
DeleteMenu(hSysMenu, 1, MF_BYPOSITION);
end;
MF_BYPOSITION を指定した時は、第二パラメータで位置を0..で指定します。
削除ごとに位置が変わることに注意して下さい。
MF_BYCOMMAND を指定した時は SC_SIZE、SC_MOVE、SC_MINIMIZE、SC_MAXIMIZE、SC_CLOSE などでメニューを特定します。
次に追加です。
const
NewMenu1_Command = 10; // この値は重複しないように任意
NewMenu2_Command = 11;
procedure TForm2.Button1Click(Sender: TObject);
var
hSysMenu:integer;
begin
hSysMenu := GetSystemMenu(Handle,False);
// 底に(最後に)追加する
// セパレータを追加
AppendMenu(hSysMenu, MF_SEPARATOR,0,nil);
// 'NewMenu_1'を追加
AppendMenu(hSysMenu, MF_STRING, NewMenu1_Command, 'NewMenu_1');
// セパレータ(位置=1)の上の挿入
InsertMenu(hSysMenu, 1, MF_BYPOSITION or MF_STRING, NewMenu2_Command, 'NewMenu_2');
end;
Const で定義した値が、TMenuItemで、Commandプロパティにあたるものです。
でも、これだけでは、表示されるだけです。追加した項目をクリックしたらイベントハンドラを呼び出さねばなりません。
(ここでは、イベントハンドラではなく、メッセージボックスで代用)それには、WM_COMMANDメッセージを捕まえます。
procedure WMCOMMAND(var msg: TWMSysCommand);message WM_COMMAND;
を、フォームのPrivateに定義して、
procedure TForm1.WMCOMMAND(var msg: TWMSysCommand);
begin
case Msg.CmdType of
NewMenu1_Command: ShowMessage('NewMenu_1が押されました');
NewMenu2_Command: ShowMessage('NewMenu_2が押されました');
end;
inherited;
end;
ですね。
たくさん作るときは、TPopupMenuを貼り付け、TMenuItemを作成してこのCaption、Command、OnClickなどのプロパティを利用した方が簡単です。
参照: [Delphi-ML:19712] [Delphi-ML:42000]
0003 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 更新: 1999/09/08 osamu 編集
ショートカットキーに'+'を使う。
Delphi2.0 以上では、『!"#$%&'()=~|^{}`*+_?><』など、101のフルキー側(テンキーを除いた部分)で、Shiftと同時にキーを押さなければ入力できない文字はショートカットに使えない。
テンキーがついてたり、JISキーボードならばワンキーで押せるものもあるのに。
こういったキーを使うには、ShortCut プロパティにキーコードを直接セットすればいい。
たとえば、
Test2.ShortCut:=$6B; // <- + キーのキーコード
でも、これだとメニューの右端にキー名が表示されない。 (;_;)
対処方法は [Tips:4]。
参照: [Delphi-ML:17954] [Tips:4] <コンポーネント > <Standard>
0004 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/08/14 osamu 編集
ショートカットキーのキー名を独自に設定する
例えば、テンキーの + キーをショートカットにした場合に、'Num +'とか表示させたい。
TMenuItem.AppendTo()を参照すると、
TestMenu1.Caption:=TestMenu1.Caption+#9+'Num +'+#0;
とすればよいことが分かる。
キャプションとショートカット名との間にはさんだタブ文字と、自動で追加されるショートカットを隠すために最後にくっつけられた #0 とが味噌。
参照: [Delphi-ML:17989] <コンポーネント > <Standard>
0135 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 編集
表示中のポップアップメニューを消す
>プログラム上でポップアップメニューを表示するにはPopup メソッドを
>使えば出来るのですが、逆に非表示させるにはどうしたらよいのでしょう。
>よろしくお願いします。
キーボードイベントを送って非表示にする、というのはどうでしょう。
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Interval := 1000;
Timer1.Enabled := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled := True;
PopupMenu1.Popup(Button1.ClientOrigin.x,
Button1.ClientOrigin.y + Button1.Height);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
keybd_event(VK_ESCAPE, 0, 0, 0);
keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0);
Timer1.Enabled := False;
end;
以上のコードで実行すると、ボタンを押すとポップアップしますが、約1秒後にポップアップが非表示になります。
参照: [Delphi-ML:24269] <Standard> <コンポーネント >
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] <Windows>
0066 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 編集
PopupMenu に MainMenu のサブ項目をそのまま表示する
一つのメニューアイテムを、同時に二つのメニューに結び付ける事は出来ないようなので、実行時に、MainMenu と PopupMenu 、それぞれが開く時点で、共有するアイテムをそのメニューに結びつけ直す、という方法をとりました。ある位置から下を全部共有アイテムとする仕様です。
結び付け直すタイミングですが、PopupMenu の方は、OnPopup イベントで良いのですが、MainMenu の方は、(エディットメニュー以下をすべて使う場合に) Edit1 のOnClick だと、位置がずれたりしてうまくないので、WndProc をオーバーライドして、WM_INITMENU メッセージに応答させました。
以下は PASCAL 翻訳版
const COMMON_ITEM_START = 3; // 共有アイテムの始まる位置
procedure TForm1.PopupMenu1Popup(Sender: TObject);
var Item: TMenuItem;
begin
while Edit1.Count > COMMON_ITEM_START do begin
Item:= Edit1.Items[COMMON_ITEM_START];
Edit1.Remove(Item);
PopupMenu1.Items.Add(Item);
end;
end;
procedure TForm1.WndProc(var Msg: TMessage);
var Item: TMenuItem;
begin
if (Msg.Msg=WM_INITMENU) and (Msg.WParam=Menu.Handle) then begin
while PopupMenu1.Items.Count > COMMON_ITEM_START do begin
Item:= PopupMenu1.Items[COMMON_ITEM_START];
PopupMenu1.Items.Remove(Item);
Edit1.Add(Item);
end;
end;
inherited WndProc(Msg);
end;
参照: [builder:5012] <コンポーネント > <Standard>
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] <フォーム>
[新規作成] [最新の情報に更新]
How To
Lounge
KeyWords
Osamu Takeuchi osamu@big.or.jp
Tips
Delphi
Home