Русская справка по Delphi 5
Мастерская Delphi программирования.
Главная Мастерская Архив Ссылки Отдых Для гостей  
Секреты VCL Секреты API            

Манипуляции с системным меню.

пример: sysmenu.zip

Системное меню - это всплывающее меню, назначаемое окну приложения системой. Его можно увидеть, если кликнуть на иконке в заголовке окна. Это меню назначается и управляется исключительно Windows, но Вы можете производить с ним нужные манипуляции.

Рассмотрим пример:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
   SMenu: HMenu;
   AddingItem: Boolean;
   procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
   procedure EnableButton(Enable: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
Id_my = $00a0;

procedure TForm1.FormCreate(Sender: TObject);
begin
 SMenu := GetSystemMenu(HAndle,false);
end;

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = Id_My then
 ShowMessage('Вы выбрали нестандартный пункт системного меню.');
inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var mi: TMenuItemInfo;
begin
 mi.cbSize := 44;
 {Важно! Если присвоить Sizeof(mi) не будет работать}
 mi.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE	or MIIM_TYPE;
 mi.fType := MFT_STRING;
 mi.fState := MFS_ENABLED;
 mi.wID := Id_my;
 mi.hSubMenu := 0;
 mi.hbmpChecked := 0;
 mi.hbmpUnchecked := 0;
 mi.dwTypeData := PChar('Cвой пунк&т');
 AddingItem := InsertMenuItem(SMenu,1,True,Mi);
 EnableButton(AddingItem);
end;

procedure TForm1.EnableButton(Enable: Boolean);
begin
 Button1.Enabled := not Enable;
 Button2.Enabled := Enable;
 Button3.Enabled := Enable;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 EnableMenuItem(SMenu,Id_My,MF_BYCOMMAND or MF_Grayed);
 Button2.Enabled := False;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 DeleteMenu(SMenu,id_My, MF_BYCOMMAND);
 AddingItem := False;
 EnableButton(AddingItem);
end;

end.

Для начала нужно получить идентификатор системного меню назначенного окну. В API есть специальная функция - GetSystemMenu. В обработчике OnCreate формы получаем идентификатор и сохраняем его для последующего использования.

procedure TForm1.FormCreate(Sender: TObject);
begin
 SMenu := GetSystemMenu(Handle,false);
end;

На форме имеется три кнопки позволяющие производить манипуляции с системным меню. Первая кнопка, Button1, позволяет добавить пункт в системное меню, он будет называться "свой пункт".

procedure TForm1.Button1Click(Sender: TObject);
var mi: TMenuItemInfo;
begin
 mi.cbSize := 44;
 {Важно! Если присвоить Sizeof(mi) не будет работать}
 mi.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE	or MIIM_TYPE;
 mi.fType := MFT_STRING;
 mi.fState := MFS_ENABLED;
 mi.wID := Id_my;
 mi.hSubMenu := 0;
 mi.hbmpChecked := 0;
 mi.hbmpUnchecked := 0;
 mi.dwTypeData := PChar('Cвой пунк&т');
 AddingItem := InsertMenuItem(SMenu,1,True,Mi);
 EnableButton(AddingItem);
end;

Для добавления нового пункта используется функция InsertMenuItem. Перед добавлением пункта в меню необходимо заполнить структуру TMenuItemInfo. Эта структура содержит информацию о новом пункте меню. При заполнении структуры есть одна особенность, в поле cbSize, указывающий размер структуры в байтах, необходимо указать число 44. Если указать размер структуры, используя функцию Sizeof(), вызов InsertMenuItem закончится неудачно. Это происходит из-за различия описаний структуры в VCL и С++. Более подробную информацию можно получить в справке по API.

При выборе пункта системного меню, windows посылает приложению сообщение WM_SYSCOMMAND. Чтобы пункт меню реагировал на выбор необходимо обработать это сообщение.

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = Id_My then
 ShowMessage('Вы выбрали нестандартный пункт системного меню.');
inherited;
end;

Здесь проверяется, выбран ли "свой пункт". Если да, Msg.CmdType = Id_My, выводится сообщение. Если нет, вызывается обработчик предка. Константа Id_My однозначно определяющая "свой пункт" должна быть ниже значения $0F000.

Вторая кнопка, Button2, делает "свой пункт" недоступным для использования.

procedure TForm1.Button2Click(Sender: TObject);
begin
 EnableMenuItem(SMenu,Id_My,MF_BYCOMMAND or MF_Grayed);
 Button2.Enabled := False;
end;
Для этого используется функция EnableMenuItem с соответствующими параметрами. Если Вы хотите произвести обратное действие, сделать пункт доступным пункт меню, необходимо вместо параметра MF_Grayed указать MF_ENABLED.

Третья кнопка, Button3, удаляет указанный пункт из меню.

procedure TForm1.Button3Click(Sender: TObject);
begin
 DeleteMenu(SMenu,id_My, MF_BYCOMMAND);
 AddingItem := False;
 EnableButton(AddingItem);
end;
Для этого используется функция DeleteMenu.

Эти же манипуляции можно производить и со стандартными пунктами системного меню. Полный список стандартных команд системного меню можно посмотреть в справке по API, в статье WM_SYSCOMMAND.

Исходный текст примера: sysmenu.zip


Главная Мастерская Архив Ссылки Отдых Для гостей  
Секреты VCL Секреты API            
Дизайн и программирование - Valler© ,2000,2001.
http://www.valler.narod.ru
Используются технологии uCoz