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

Hwa*_*wau 1 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);
Run Code Online (Sandbox Code Playgroud)

我正在尝试检查关闭按钮当前是启用还是禁用.检查这个MSDN页面后,我写了这段代码:

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');
Run Code Online (Sandbox Code Playgroud)

它始终显示"已禁用"(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;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 9

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

GetMenuItemInfo由于您未遵循文档中的说明,因此调用失败.具体来说,这部分涵盖了项目信息参数:

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

遵循该指令可以解决您的问题.

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

您的代码调用以下API函数:GetSystemMenu,EnableMenuItemGetMenuItemInfo.您无法检查每个呼叫中​​的错误.

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

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