Como posso substituir a mesma parte do console em um aplicativo de console C++ nativo do Windows, sem usar uma biblioteca de terceiros?
Pergunta
Eu tenho um aplicativo de console que precisa exibir o estado dos itens, mas em vez de fazer o texto rolar como um louco, prefiro ver o status atual continuar aparecendo nas mesmas linhas.A título de exemplo:
Running... nn% complete
Buffer size: bbbb bytes
deve ser a saída, onde 'nn' é a porcentagem atual concluída e 'bbbb' é o tamanho do buffer, atualizado periodicamente nas mesmas linhas do console.
A primeira abordagem que tomei simplesmente imprimiu o número correto de retrocessos no console antes de imprimir o novo estado, mas isso tem uma oscilação desagradável da qual quero me livrar.Também quero me ater à biblioteca padrão ou à funcionalidade fornecida pelo MS (VC 8) para não introduzir outra dependência para essa necessidade simples.
Solução
Você pode usar SetConsoleCursorPosition.Você precisará ligar ObterStdHandle para obter um identificador para o buffer de saída.
Outras dicas
Joseph, JP e CodingTheWheel forneceram uma ajuda valiosa.
Para o meu caso simples, a abordagem mais direta parecia basear-se em Resposta do CodingTheWheel:
// before entering update loop
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
GetConsoleScreenBufferInfo(h, &bufferInfo);
// update loop
while (updating)
{
// reset the cursor position to where it was each time
SetConsoleCursorPosition(h, bufferInfo.dwCursorPosition);
//...
// insert combinations of sprintf, printf, etc. here
//...
}
Para problemas mais complicados, o completo API de console conforme fornecido por A resposta do JP, em coordenação com os exemplos fornecidos através do link de A resposta de José pode ser útil, mas achei o trabalho necessário para usar CHAR_INFO
muito tedioso para um aplicativo tão simples.
Se você imprimir usando e não usar uma função que irá gerar uma nova linha ou adicionar ao final, o cursor voltará ao início da linha e apenas imprimirá sobre a próxima coisa que você colocar.Gerar a sequência completa antes da impressão também pode reduzir a cintilação.
ATUALIZAR:A pergunta foi alterada para 2 linhas de saída em vez de 1, o que faz com que minha resposta não esteja mais completa.Provavelmente será necessária uma abordagem mais complicada.JP tem a ideia certa com o API do console.Acredito que o site a seguir detalha muitas das coisas que você precisará para atingir seu objetivo.O site também menciona que a chave para reduzir a cintilação é renderizar tudo fora da tela antes de exibi-lo.Isso é verdade sempre que você exibe algo na tela, seja texto ou gráficos (2D ou 3D).
Caso a sugestão de Joseph não lhe dê flexibilidade suficiente, dê uma olhada na API do Console: http://msdn.microsoft.com/en-us/library/ms682073(VS.85).aspx.
No Linux, você pode fazer isso imprimindo \b e/ou em stderr.Talvez seja necessário experimentar para encontrar a combinação certa de coisas no Windows.