Classe do dia: HResult
De ccppbrasil.org
É 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
