Desenvolvimento - C/C++
Classe do dia: HResult
A classe do artigo apenas facilita o lançamento de exceções exatamente para que um bloco de código fique entre uma cláusula try-catch (o que documenta a falta de if's) e você tenha que se preocupar com tratamento em um ponto apenas da função.
por Wanderley Caloni JrÉ chato ter que escrever tantos if"s só para verificar falhas. Ao mesmo tempo é importante saber tratar todos os erros que podem ocorrer em programação. A classe abaixo apenas facilita o lançamento de exceções exatamente para que um bloco de código fique entre uma cláusula try-catch (o que documenta a falta de if"s) e você tenha que se preocupar com tratamento em um ponto apenas da função. De certa forma, essa é a idéia geral por trás do conceito de exceções: não deixar o tratamento ofuscar a clareza do algoritmo. Eis o código:
/** @file hresult.h * * Use esta classe no lugar de HRESULT para que na atribuição de valor este * seja testado. Caso determine falha, a função AtlThrow() será chamada. * * @sa AtlThrow(), CAtlException. */ #include <atlbase.h> #include <atlexcept.h> class HResult { public: /// No começo, o HRESULT é igual a S_OK. HResult(): m_hr(S_OK) { } /// Testa falha do hr recebido. Caso FAILED(hr) retorne true, será /// chamada a função AtlThrow(). HResult &operator = (HRESULT hr) { if( FAILED(m_hr = hr) ) AtlThrow(hr); return *this; } /// Conversão para o HRESULT armazenado. operator HRESULT () { return m_hr; } HRESULT m_hr; };
O exemplo de uso é um programa que exibe o endereço de todas as janelas por onde o usuário está navegando no momento (isso inclui as janelas do Windows Explorer e exclui navegadores que não utilizem o componente do IE):
/** @file hresult.cpp */ #include "hresult.h" #include <exdisp.h> // IShellWindows, IWebBrowser #include <windows.h> #include <tchar.h> #include <atlcomcli.h> #include <algorithm> #include <iostream> #include <vector> #define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) // ks.h using namespace std; /// @remark Não podemos usar diretamente CComBSTR por esta sobrecarregar o operador &. /// Agradecimentos a Rodrigo Strauss pela correção. typedef vector<CAdapt<CComBSTR> > URLList; HRESULT WhereIsUserNavigating(URLList &lst) { HResult hr; CComPtr<IShellWindows> shell; try { hr = shell.CoCreateInstance(CLSID_ShellWindows); // quantas janelas navegáveis? CComVariant count(0L); hr = shell->get_Count(&count.lVal); while( count.lVal-- ) { // obtemos a página que corresponde ao índice atual CComPtr<IDispatch> disp; if( (hr = shell->Item(count, &disp)) == S_FALSE ) continue; // obtemos a interface obter o endereço da página CComPtr<IWebBrowser> webb; hr = disp.QueryInterface(&webb); // obtemos o endereço e colocamos na lista CComBSTR url; hr = webb->get_LocationURL(&url); lst.push_back(url); } } catch(CAtlException &e) { cout << "Error 0x" << hex << e.m_hr << "\n"; } return hr; } void printBSTR(CComBSTR& bs) { wcout << BSTR(bs) << endl; } int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr; URLList lst; CoInitialize(NULL); // iniciando COM hr = WhereIsUserNavigating(lst); // obtendo lista de páginas navegáveis if( SUCCEEDED(hr) ) // imprimindo a lista for_each(lst.begin(), lst.end(), printBSTR); CoUninitialize(); // finalizando COM return (int) hr; }
PS: Uma outra idéia interessante derivada da minha foi apresentada em outro artigo do Code Project. Ele também pega o nome do fonte e o número da linha onde ocorreu a exceção. Vale a pena dar uma olhada e conhecer a macro _E().
Artigo original: Caloni.com.br