In my current project I create a few menus on the fly and have a LOT of "if" statements to handle the API functions failing. Is it possible to group these into a big "try" block?
[code]
try
{
AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, 1001, L"&Import");
AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, 1002, L"&Export");
AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, 1003, L"&Backup");
AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, 1004, L"E&xit");
}
catch
{
while(GetMenuItemCount(this->hFileMenu) > 0)
DeleteMenu(this->hFileMenu, 0, MF_BYPOSITION);
return false;
}
[/code]
This will save a TON of checking if it works. Note that "AppendMenu()" is of type "BOOL", not "bool". That means that it is an integer return value, not a single bit.
-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
Comments
to create the items, sort of like this:
[code]
int i, ret;
UINT ids[]={1001,1002,1003,1004,0};
TCHAR* names[]={L"&Import", L"&Export", L"&Backup", L"E&xit"};
i=0;
while(ids[i])
{
ret = AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, ids[i], names[i]);
if (ret == 0)
{
while(GetMenuItemCount(this->hFileMenu) > 0)
DeleteMenu(this->hFileMenu, 0, MF_BYPOSITION);
break;
}
i++;
}[/code]
Afaik Winapi functions don't throw C++ exceptions, except when you
crash the function by passing it an invalid pointer or something like that,
but I'm not entirely sure of this.
[code]
try
{
}
catch (...)
{
}
[/code]
[color=Blue]On the other hand - no need really to delete menu items if anything fails - just delete the whole menu with DestroyMenu().[/color]
[code]
//Attempt to add the import option
if(!AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, IDM_IMPORT, L"&Import"))
{
DestroyMenu(this->hFileMenu);
DestroyMenu(this->hMainMenu);
return false;
}
//Attempt to add the export option
if(!AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, IDM_EXPORT, L"&Export"))
{
DestroyMenu(this->hFileMenu);
DestroyMenu(this->hMainMenu);
return false;
}
//Attempt to add a separator
if(!AppendMenu(this->hFileMenu, MF_SEPARATOR, 0, 0))
{
DestroyMenu(this->hFileMenu);
DestroyMenu(this->hMainMenu);
return false;
}
//Attempt to add the backup now option
if(!AppendMenu(this->hFileMenu, MF_ENABLED | MF_STRING, IDM_BACKUP, L"&Backup"))
{
DestroyMenu(this->hFileMenu);
DestroyMenu(this->hMainMenu);
return false;
}
[/code]
This is a waste of space and there has GOT to be a better way to check for a single menu failing without a thousand "if" checks. This is actually only part of the code, and it's about double that for everything.
-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
You need to use the error checking wisely. For example, if you logically think - you will see that AppendMenu() call will not involve any hardware interaction - it can fail only for TWO reasons: no memory and wrong HMENU passed to it.
I never seen a program fail due to memory limits (not recently, anyhow). Also, if you check the HMENU you passing once for all calls, then you are SURE - it will not fail.
If you still have a need to check each of these calls - there is a trick. The failing value for this function is FALSE. Which is ZERO! That means if you create a string of return values - its length (string length) will be EXACTLY equal to the number of times you call AppendMenu():
[/color]
[code]
char strCheck [32];
strCheck [0] = (char) AppendMenu (...);
strCheck [1] = (char) AppendMenu (...);
strCheck [2] = (char) AppendMenu (...);
strCheck [3] = (char) AppendMenu (...);
strCheck [4] = (char) AppendMenu (...);
strCheck [5] = (char) AppendMenu (...);
strCheck [6] = (char) AppendMenu (...);
strCheck [7] = (char) AppendMenu (...);
strCheck [8] = 0;
if (lstrlen (strCheck) != 8)
{
// Something failed in that "string" :-) of calls!
}
[/code]
[color=Blue]
That works nicely for BOOL return values. Beware of handles. If returned handle is, say: 0x0FD7A300 - this will turn to zero once turned into char type, so the trick will fail miserably.
[/color]
[code]
int i = 0;
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
i += AppendMenu (...);
// boolean TRUE == 1, so i should equal 8
if (i != 8)
{
// Something failed and returned 0!
}
[/code]
Though I still can't figure out why my [link=http://www.programmersheaven.com/mb/CandCPP/384469/384481/re-will-trycatch-work-with-api-functions/#384481]original suggestion[/link] of looping
through an array of menu items and checking for failure once per
iteration is any worse than these tricks :-)
-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]