如何检查表单的关闭按钮的状态(启用/禁用)

时间:2016-05-07 16:19:42

标签: delphi winapi

我在此代码中禁用并启用了表单的关闭按钮:

uses WinApi.Windows;
...
//disabling
EnableMenuItem(GetSystemMenu(MyForm.Handle, False), SC_CLOSE, MF_BYCOMMAND OR MF_DISABLED);
//enabling
EnableMenuItem(GetSystemMenu(MyForm.Handle, False), SC_CLOSE, MF_BYCOMMAND OR MF_ENABLED);

我试图检查关闭按钮当前是启用还是禁用。检查this MSDN page后,我写了这段代码:

var
  ItemInfo : TMenuItemInfo;
  MyForm : TForm;
begin
  MyForm := GetAFormInSomeWay();
  ItemInfo.fMask := MIIM_STATE;
  GetMenuItemInfo(GetSystemMenu(MyForm.Handle, False), SC_CLOSE, False, ItemInfo);
  if(ItemInfo.fState = MFS_ENABLED)
  then ShowMessage('Enabled')
  else ShowMessage('Disabled');

它始终显示'已禁用' (ItemInfo.fState始终为5395358)。 我做错了什么?

更新

现在它可以了,感谢你的建议。

uses
  WinApi.Windows, Vcl.Forms, System, System.SysUtils;

...

var
  ItemInfo : TMenuItemInfo;
  MyForm : TForm;
  SystemMenu : HMENU;
begin
  MyForm := GetAFormInSomeWay();
  ItemInfo.fMask := MIIM_STATE;
  ItemInfo.cbSize := SizeOf(MENUITEMINFO);

  SystemMenu := GetSystemMenu(MyForm.Handle, False);
  if((SystemMenu = 0) OR (GetMenuItemInfo(SystemMenu, SC_CLOSE, False, ItemInfo) = False))
  then raise Exception.Create(SysErrorMessage(GetLastError()));

  if((ItemInfo.fState AND MFS_DISABLED) = 0)
  then ShowMessage('Enabled')
  else ShowMessage('Disabled');
end;

1 个答案:

答案 0 :(得分:9)

你正在犯Win32编程的经典错误。您正在调用Win32 API函数并且无法检查错误。你怎么知道他们是否成功了?答案是你没有。因为你不检查。您必须切换思维模式,以便在调用Win32 API函数时检查错误是第二天性。这些函数不会引发异常。它们通过其他方式发出故障信号,通常是通过返回值。了解如何阅读您呼叫的每个功能的文档。

GetMenuItemInfo的调用失败,因为您没有按照文档中的说明操作。具体来说,这部分涵盖了项目信息参数:

  

请注意,在调用此函数之前,必须将cbSize成员设置为sizeof(MENUITEMINFO)。

遵循该指示可以解决您的问题。

如果您检查过错误,则会看到GetMenuItemInfo返回FalseGetLastError返回ERROR_INVALID_PARAMETER

您的代码会调用以下API函数:GetSystemMenuEnableMenuItemGetMenuItemInfo。您无法检查每个呼叫中​​的错误。

你应该使用bitwise并检查状态中的标志,而不是相等。尽管您的测试在我的系统上运行,但它在语义上是错误的。例如,如果该项是默认项,则它将失败。

坦率地说,与检查错误的重要性相比,手头的问题是微不足道的。我希望你拿走这一课。所以,请不要只设置cbSize并继续,请同时添加错误检查。