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

Wanderley Caloni Jr

Wanderley Caloni Jr