Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Facebook Sign In with Google Sign In with OpenID

Categories

We have migrated to a new platform! Please note that you will need to reset your password to log in (your credentials are still in-tact though). Please contact lee@programmersheaven.com if you have questions.
Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Will try/catch work with API functions?

SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
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

  • anthrax11anthrax11 Posts: 511Member
    You could make arrays with the ID numbers and names and then run a loop
    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.
  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [color=Blue]Catching depends on compiler options. As an example - there are few "exceptional" options in VS 2005 (I am not sure if your compiler has it). One of the options is to use SEH and one of the others is to use C++ exceptions. The SEH option will usually catch exceptions with the following code:[/color]
    [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]
  • SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
    I know, I use DestroyMenu() now. The thing is, my current code looks like this:
    [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]
  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [color=Blue]
    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]
  • anthrax11anthrax11 Posts: 511Member
    This is also possible:
    [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 :-)
  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [color=Blue]Your idea was great! Even less code![/color]
  • SephirothSephiroth Fayetteville, NC, USAPosts: 1,035Member
    I like that idea. I'll implement it the next time I work on the backup utility. I am working on my windowing library right now, and enjoying some VERY nice new wallpapers I just grabbed in KDE. Yeah, I'm a Linux-lover, but I have to stay in Windows to play my games! >.<

    -[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]
Sign In or Register to comment.