我在此代码中禁用并启用了表单的关闭按钮:
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;
答案 0 :(得分:9)
你正在犯Win32编程的经典错误。您正在调用Win32 API函数并且无法检查错误。你怎么知道他们是否成功了?答案是你没有。因为你不检查。您必须切换思维模式,以便在调用Win32 API函数时检查错误是第二天性。这些函数不会引发异常。它们通过其他方式发出故障信号,通常是通过返回值。了解如何阅读您呼叫的每个功能的文档。
对GetMenuItemInfo
的调用失败,因为您没有按照文档中的说明操作。具体来说,这部分涵盖了项目信息参数:
请注意,在调用此函数之前,必须将cbSize成员设置为sizeof(MENUITEMINFO)。
遵循该指示可以解决您的问题。
如果您检查过错误,则会看到GetMenuItemInfo
返回False
,GetLastError
返回ERROR_INVALID_PARAMETER
。
您的代码会调用以下API函数:GetSystemMenu
,EnableMenuItem
和GetMenuItemInfo
。您无法检查每个呼叫中的错误。
你应该使用bitwise并检查状态中的标志,而不是相等。尽管您的测试在我的系统上运行,但它在语义上是错误的。例如,如果该项是默认项,则它将失败。
坦率地说,与检查错误的重要性相比,手头的问题是微不足道的。我希望你拿走这一课。所以,请不要只设置cbSize
并继续,请同时添加错误检查。