logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

Atendendo a pedidos: Controle de Contrações para PC, baixável e feito em WTL

Atendendo aos pedidos do meu amigo Wanderley e da minha querida doula Ana Cris, resolvi fazer uma versão do meu Programa Para Controle de Contrações Para Parturientes e Similares que roda em PC e feito em WTL. O layout do programa não é lá essas coisas, mas eu tentei manter o design e o funcionamento parecidos com a versão para PocketPC. E apesar do pedido da Ana Cris para que o programa fosse "instalável", eu resolvi teimar e fazer um que não precisa instalar, é só baixar e rodar. :-)

Chega de ladainha, eu só quero fazer o download...

O programa foi desenvolvido usando o Visual C++ 7.1 e o WTL 7.5. Como eu não usei nada esotérico, acredito que ele deve ser compilável usando versões mais antigas do WTL. Mesmo assim, não sei se isso vai compilar no Visual C++ 6.0.

Como em Win32 não existe DataGrid, eu usei um ListView, que serve muito bem para esse propósito. Ao invés de usar um DataSet para gravar os dados, eu usei um std::list e populei o ListView "na mão".

Foi difícil resistir a tentação de usar o ATL::CAtlList no lugar do std::list, mas eu estou querendo me livrar do vício do ATL e ser um pouquinho mais multiplataforma. Acho que eu nunca escrevi sobre isso ainda, mas eu me recuso a usar a lib do C. Eu gosto mesmo é de CreateFile, ATL::CAtlFile, CreateFileMapping, CoCreateInstance e CoMarshalInterThreadInterfaceInStream :-)

Olhem os trechos principais do código:


typedef struct _CONTRA_INFO
{
   __time64_t StartTime;
   __time64_t EndTime;
} CONTRA_INFO;

typedef std::list CContraList;

...

void CMainDlg::ChangeButtonText()
{
   m_Button.SetWindowText(m_bContraInProgress ?
                          _T("Ufa, acabou...") : 
                          _T("Está doendo, socorro!!"));
}

void CMainDlg::UpdateList()
{
   CContraList::iterator CurrentIterator, PreviousIterator;
   int iItem;
   
   ATL::CTime CurrentTime, PreviousTime;
   ATL::CTimeSpan Duration, Interval;
 
   CurrentIterator = m_ContraList.end();
   CurrentIterator--;
   
   if(m_bContraInProgress)
   {
      //
      // contração acabou de iniciar. Calcular o intervalo entre 
      // a última e colocar o horário inicial no ListView
      //

      //
      // Colocar no ListView
      //
      CurrentTime = CurrentIterator->StartTime;
      iItem = m_lstContra.InsertItem(100000, CurrentTime.Format(_T("%x %X")));

      //
      // se for a primeira contração, não tem intervalo para calcular
      //
      if(CurrentIterator != m_ContraList.begin())
      {
         PreviousIterator = CurrentIterator;
         PreviousIterator--;
         

         ATLASSERT(PreviousIterator->EndTime != 0);
         Interval = CurrentIterator->StartTime - PreviousIterator->EndTime;

         m_TotalInterval += Interval.GetTimeSpan();

         m_lstContra.SetItemText(iItem,2,Interval.Format(_T("%M:%S")));
      }
   }
   else
   {
      //
      // a contração acabou. É só calcular a duração e colocar no último item
      //
      iItem = m_lstContra.GetItemCount() - 1;
      
      ATLASSERT(CurrentIterator->StartTime & CurrentIterator->EndTime);
      Duration = CurrentIterator->EndTime - CurrentIterator->StartTime;

      m_TotalDuration += Duration.GetTimeSpan();

      m_lstContra.SetItemText(iItem,1,Duration.Format(_T("%M:%S")));
   }
}

void CMainDlg::DoStatistics()
{
   ATL::CTimeSpan t;
   int iItemCount = m_ContraList.size();
   
   if(iItemCount < 2)
      return;

   t = m_TotalDuration / (iItemCount - (m_bContraInProgress ? 1 : 0));
   m_stcDuration.SetWindowText(t.Format(_T("%H:%M:%S")));


   //
   // como o primeiro item não tem intervalo, é -1
   //
   t = m_TotalInterval / (iItemCount - 1);
   m_stcInterval.SetWindowText(t.Format(_T("%H:%M:%S")));
}

LRESULT CMainDlg::OnContraClick(WORD,WORD,HWND,BOOL&)
{
   CONTRA_INFO ContraInfo;
   CContraList::iterator i;
   
   if(!m_bContraInProgress)
   {
      //
      // início da contração
      //
      ContraInfo.StartTime = _time64(NULL);
      ContraInfo.EndTime = 0;

      m_bContraInProgress = TRUE;
      m_ContraList.push_back(ContraInfo);
   }
   else
   {
      ATLASSERT(!m_ContraList.empty());
      i = m_ContraList.end();
      i--;
      
      i->EndTime = _time64(NULL);
      m_bContraInProgress = FALSE;
   }

   UpdateList();
   ChangeButtonText();
   DoStatistics();
         
   return TRUE;
}

Algumas coisas podem ser notadas nesse trecho de código:

  • Não acho que esse código seja muito mais complicado do que um código em .NET. Complicado e difícil de compreender é a lib do C, que tem mais de 3 décadas. ATL/WTL facilitam muito as coisas, e o código fica MUITO pequeno e MUITO rápido.
  • Eu não me preocupei com otimizações. O máximo que eu fiz é usar __time64_t ao invés de ATL::CTime na hora de gravar os horários, para reduzir a atividade desenfreada de copy constructors. Até porque, hoje em dia todo mundo usa .NET, que é muuuuuuuuito lento (não me venham com esse papo de "depende"). Então não me venham falar que meu código em C++ poderia ser mais rápido... :-)
  • Programar drivers faz bem! Quem já programou KernelMode vê a clara influência do estilo WinDDK no meu código. Uso de ASSERTS, código claro, comentários claros e destacados, variáveis com nomes claros. Olhe algum sample do DDK e veja o que é programar bonito!
  • Eu usei TCHAR (veja as macros _T()) para que eu pudesse compilar em UNICODE (Windows NT/2000/XP/2003) e em ANSI (Windows 9x/Me). No projeto existem 3 configurações: Debug, Release e Release ANSI. Eu costumo compilar somente UNICODE, mas resolvi de última hora ser solidário com os usuários de Win9x, afinal, eles já têm problemas suficientes.
  • Eu coloquei o ATL:: antes de CTime e CTimeSpan para deixar bem claro que o código não tem nada a ver com MFC.

Como o programa é feito em WTL (a melhor lib do planeta para desenvolver código Win32), nós temos um executável de 84kb sem dependência de nenhuma runtime ou DLL. É só baixar o executável e rodar.

Downloads
Executável UNICODE (Windows NT/2000/XP/2003/Longhorn)
Executável ANSI (Windows 9x/Me). Eu não tenho uma máquina Windows 9x para testar, me avisem caso não funcione.
Fontes do programa. Você vai precisar do WTL para compilar.

Em 07/11/2004 23:41, por Rodrigo Strauss


  
 
 
Comentários
null | em 16/09/2012 | #
quero só baixar
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::