Изменение системного меню
Для того, чтобы получить доступ к системному меню, нужно использовать функцию GetSystemMenu API Windows. Также далее мы будем использовать AppendMenu, SetMenuItemInfo, а также структуру TMenuItemInfo. После добавления своего пункта меню, нужно добавить ловушку на сообщение WM_SYSCOMMAND, чтобы узнать, когда будет выбран наш пункт меню.
Добавление пункта меню
Следующий код демонстрирует исользование функции AppendMenu для добавления нового пункта в системное меню формы. Для начала, нам нужно определить новую константу SC_MyMenuItem, которая будет идентифицировать наш новый пункт меню.
const SC_MyMenuItem = WM_USER + 1; { ... } procedure TForm1.btnAddItemClick(Sender: TObject); const sItemCaption = 'Новый пункт меню'; var sysMenu: HMenu; begin { Получаем идентификатор системного меню } sysMenu:= GetSystemMenu(Handle, false); { Добавляем разделитель меню } AppendMenu(sysMenu, MF_SEPARATOR, 0, ''); { Добавляем наше меню } AppendMenu(sysMenu, MF_STRING, SC_MyMenuItem, sItemCaption); end;
После добавления пункта меню, мы должны отловить сообщение WM_SYSCOMMAND для обработки щелчка.
private { Private declarations } procedure WMSysCommand( var Msg: TWMSysCommand); message WM_SYSCOMMAND; { ... } procedure TForm1.WMSysCommand(var Msg: TWMSysCommand); begin if Msg.CmdType = SC_MyMenuItem then { Здесь идет код для пункта меню } ShowMessage('Щелкнули по новому пункту меню!') else inherited; end;
Примечание: при сворачивании приложения, значок представляет собой приложение, а не форму. Поэтому, чтобы измененное меню работало и в свернутом виде, нужно использовать Application.Handle, а не просто Handle, когда будете добавлять свой пункт меню.
Удаление системного пункта меню
При удалении пункта системного меню, мы также удаляем возможность выполнения его из системного меню формы. При помощи DeleteMenu давайте удалим пункт Переместить.
Обратите внимание: после удаления этого пункта меню, мы не сможем больше перемещать форму. Это не самый лучший способ удаления меню.
procedure TForm1.btnDeleteItemClick(Sender: TObject); const mnuCommand = SC_MOVE; var sysMenu: HMenu; begin sysMenu:= GetSystemMenu(Handle, false); DeleteMenu(sysMenu, mnuCommand, MF_BYCOMMAND); end;
Изменение заголовка пункта меню
Чтобы изменить заголовок пункта системного меню, мы должны вызвать функцию SetMenuItemInfo и отправить ей структуру TMenuItemInfo, которая содержит информацию о пункте меню.
Давайте изменим заголовок пункта меню Закрыть.
procedure TForm1.btnChangeItemCaptionClick(Sender: TObject); const sCaption = 'Закрыть наше окно'; var sysMenu: HMenu; menuItemInfo: TMenuItemInfo; begin sysMenu:= GetSystemMenu(Handle, false); FillChar(MenuItemInfo, SizeOf(TMenuItemInfo), #0); with MenuItemInfo do begin cbSize:= SizeOf(TMenuItemInfo); fMask:= MIIM_TYPE or MIIM_ID or MIIM_STATE; fType:= MFT_STRING; wID:= SC_CLOSE; dwTypeData:= sCaption; cch:= Length(sCaption); end; SetMenuItemInfo(sysMenu, SC_CLOSE, false, MenuItemInfo); end;
Добавление изображения в пункт меню
Для этого выберите изображение в формате bmp и поместите его в папку с проектом. Я взял изображение, которое идет вместе с Delphi и находится в папке Program Files\Common Files\Borland Shared\Images\Icons
и называется CHEM16.BMP
.
Запишите следующий код:
private { Private declarations } myBmp: TBitmap; { ... } procedure TForm1.FormCreate(Sender: TObject); begin myBmp:= TBitmap.Create; myBmp.LoadFromFile('CHEM16.BMP'); end; procedure TForm1.FormDestroy(Sender: TObject); begin myBmp.Free; end; procedure TForm1.btnChangeItemCaptionClick(Sender: TObject); const sCaption = 'Закрыть наше окно'; var sysMenu: HMenu; menuItemInfo: TMenuItemInfo; begin sysMenu:= GetSystemMenu(Handle, false); FillChar(menuItemInfo, SizeOf(TMenuItemInfo), #0); with menuItemInfo do begin cbSize:= SizeOf(TMenuItemInfo); fMask:= MIIM_TYPE or MIIM_ID or MIIM_STATE; fType:= MFT_STRING; wID:= SC_CLOSE; dwTypeData:= sCaption; cch:= Length(sCaption); end; SetMenuItemInfo(sysMenu, SC_CLOSE, false, menuItemInfo); end;
Вот и все по работе с системным меню формы нашего приложения.
Комментарии