Mejorar el código en C++ nativo

Iniciado por Meta, 7 Julio 2020, 15:05 PM

0 Miembros y 1 Visitante están viendo este tema.

Meta

Buenas:

Tengo este código en C++ nativo, en el cual aún no logro que funcione tal como lo quiero. Lo que hace este código es, que si pulsas la letra A o a, se abre la bandeja del lector del disco, si pulsas C o c se cierra.

Código C++ nativo:
Código (cpp) [Seleccionar]
#include <iostream>
#include <windows.h> // Para mostrar texto en el título de la ventana.

using namespace std;
//using std::cout;
//using std::cin;

// Función posición del cursor.
void gotoxy(int x, int y)
{
HANDLE hcon;
hcon = GetStdHandle(STD_OUTPUT_HANDLE);
COORD dwPos;
dwPos.X = x;
dwPos.Y = y;
SetConsoleCursorPosition(hcon, dwPos);
}

int main(void)
{
// Mostrar caracteres correctamente en pantalla y título de la ventana.
SetConsoleOutputCP(65001);
wchar_t titulo[128];
MultiByteToWideChar(CP_UTF8, 0, "Consola C++ nativo 2019.", -1, titulo, 128);
SetConsoleTitle(titulo);

// Variable.
char entrada[] = "\0"; // Guarda A, a, C, y c tipo string que introduces desde la consola.

// Tamaño de la pantalla. Se cambia en los dos últimos dígitos.
SMALL_RECT r = { 0, 0, 29, 8 }; // X = 29, Y = 8.
SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &r);

// Ocultar cursor.
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
cci.bVisible = 0; // 0 oculta. 1 muestra cursor.
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);

// Muestra textos en pantalla.
cout << "Control bandeja del lector: " << endl << endl;
cout << "A - Abrir bandeja." << endl;
cout << "C - Cerrar bandeja." << endl;
cout << "===========================" << endl;

while (true)
{


// Aquí introduces letras A, a, C y c.
cin >> entrada;
cout << "\n" << endl;

// Abrir bandeja.
if ((entrada[0] == 'a') || (entrada[0] == 'A'))
{
// Posición del cursor.
gotoxy(0, 6);
cout << "Abriendo..." << endl << endl; // Muestra texto en pantalla.
mciSendString(L"set cdaudio door open", nullptr, 0, nullptr);
gotoxy(0, 6);
cout << "Abierto.   " << endl << endl; // Muestra texto en pantalla.
}

// Cerrar bandeja.
else if ((entrada[0] == 'c') || (entrada[0] == 'C'))
{
gotoxy(0, 6);
cout << "Cerrando..." << endl << endl; // Muestra texto en pantalla.
mciSendString(L"set cdaudio door closed", nullptr, 0, nullptr);
gotoxy(0, 6);
cout << "Cerrado.   " << endl << endl; // Muestra texto en pantalla.
}

// Si haz pulsado otro caracter distinto de A, C, a y c aparece
else
{
gotoxy(0, 6);
// este mensaje.
cout << "Solo pulsa A o C." << endl << endl;
}

}
return EXIT_SUCCESS;
}


En el código de C# si funciona tal como lo quiero, pongo un ejemplo abajo.

Código C#:
Código (c#) [Seleccionar]
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Bandeja_consola_cs
{
    class Program
    {
        [DllImport("winmm.dll")]
        public static extern Int32 mciSendString(string lpstrCommand, StringBuilder lpstrReturnString,
        int uReturnLength, IntPtr hwndCallback);
        public static StringBuilder rt = new StringBuilder(127);
        public static void DoEventsAbriendo()
        {
            Console.SetCursorPosition(0, 6);
            Console.Write("Abriendo...");
        }
        public static void DoEventsCerrando()
        {
            Console.SetCursorPosition(0, 6);
            Console.Write("Cerrando...");
        }
        static void Main(string[] args)
        {
            // Título de la ventana.
            Console.Title = "Consola C# 2017";
            // Tamaño ventana consola.
            Console.WindowWidth = 29; // X. Ancho.
            Console.WindowHeight = 8; // Y. Alto.
            // Cursor invisible.
            Console.CursorVisible = false;
            // Posición del mansaje en la ventana.
            Console.SetCursorPosition(0, 0);
            Console.Write(@"Control bandeja del lector:
A - Abrir bandeja.
C - Cerrar bandeja.
===========================");
            ConsoleKey key;
            //Console.CursorVisible = false;
            do
            {
                key = Console.ReadKey(true).Key;
                string mensaje = string.Empty;
                //Asignamos la tecla presionada por el usuario
                switch (key)
                {
                    case ConsoleKey.A:
                        // mensaje = "Abriendo...";
                        Console.SetCursorPosition(0, 6);
                        DoEventsAbriendo();
                        mciSendString("set CDAudio door open", rt, 127, IntPtr.Zero);
                        mensaje = "Abierto.   ";
                        break;
                    case ConsoleKey.C:
                        // mensaje = "Cerrando...";
                        Console.SetCursorPosition(0, 6);
                        DoEventsCerrando();
                        mciSendString("set CDAudio door closed", rt, 127, IntPtr.Zero);
                        mensaje = "Cerrado.   ";
                        break;
                }
                Console.SetCursorPosition(0, 6);
                Console.Write(" ");
                Console.SetCursorPosition(0, 6);
                Console.Write(mensaje);
            }
            while (key != ConsoleKey.Escape);
        }
    }
}


Lo que hace el código C# exactamente todos estos comportamientos.

1. Te pregunta si pulsas teclas, por ejemplo la A para abrir la bandeja y C para cerrar, independientemente si es mayúscula o no. Funciona todo.

2. Desde que pulse cualquier letra del teclado que non corresponda la A, a, C y la c, el programa no hace nada, como debe ser.

3. Si quiero abrir la bandeja del lector y pulso la tecla A, desde que pulse la tecla, se abre la bandeja.

4. Desde que pulse la tecla A, dice el mensaje "Abriendo...", cuando esté abierto la bandeja del todo, dice "Abierto.".

Lo que hace el código C++ nativo y no quiero.


1. Pulso la tecla A o la a, y aparece escrito en la consola.

2. Luego tengo que pulsar la tecla Enter para que la letra A o la a, funcione el comando. Entonces ya puede abrir la bandeja y mostrar los mensajes Abriendo... y Aabierto.

La pregunta es. ¿Se puede corregir este comportamiento de C++ nativo que sea igual al ejemplo de C#?

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

ThunderCls

#1
No creo que exista una manera estandar en C++ para lograr lo que deseas, sin embargo puedes usar un par de opciones:

1- Usando la funcion "getch()" de la libreria NO estandar "conio.h" (getch() espera una entrada del teclado pero no la muestra en la consola)

2- Usando la API de Windows para modificar el comportamiento de la consola:
Código (cpp) [Seleccionar]
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE) & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
   
   Para leer y escribir:
       
Código (cpp) [Seleccionar]
ReadConsole(...)/WriteConsole(...)

3- Usando GetAsyncKeyState(...) en un loop

4- Usando un hook de teclado con GetConsoleWindow(...)/SetWindowsHookEx(...)

Saludos
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

Meta

Buenas:

Por lo que entiendo. cambiar esto:
Código (cpp) [Seleccionar]
cin >> entrada;
Por esto otro:
Código (cpp) [Seleccionar]
entrada = getch();

En la línea 58 aparecen estos dos errores.

Gravedad   Código   Descripción   Proyecto   Archivo   Línea   Origen   Estado suprimido
Error (activo)   E0137   la expresión debe ser un valor L modificable   Bandeja_consola_nativo_cpp   C:\Users\Meta\Documents\Visual Studio 2019\Projects\Bandeja_consola_nativo_cpp\Bandeja_consola_nativo_cpp\Bandeja_consola_nativo_cpp.cpp   58   IntelliSense   


Gravedad   Código   Descripción   Proyecto   Archivo   Línea   Origen   Estado suprimido
Error   C3863   el tipo de matriz 'char [2]' no es asignable   Bandeja_consola_nativo_cpp   C:\Users\Meta\Documents\Visual Studio 2019\Projects\Bandeja_consola_nativo_cpp\Bandeja_consola_nativo_cpp\Bandeja_consola_nativo_cpp.cpp   58   Compilación   
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

ThunderCls

No lo tomes a mal, pero en mi opinion creo que necesitas esforzarte un poco mas en buscar respuestas por ti mismo a problemas sencillos con los que te encuentras, intentar entenderlos te ayudara a avanzar y obtener experiencia, no puedes pretender que todo te lo den hecho o que cada vez que tengas un minimo error recurrir al foro. En fin, como dije al principio, no lo tomes a mal, pero necesitas aprender a usar Google e intentar entender por ti mismo lo que te sucede.

Habiendo dicho lo anterior, si buscas el prototipo de la funcion getch() te daras cuenta de como usarla correctamente:

Código (cpp) [Seleccionar]

// por cierto getch esta obsoleto, debes usar _getch en su lugar
int _getch(void);


La funcion no toma parametros y devuelve un int que equivale al valor de la tecla presionada. En tu codigo intentas usar la variable "entrada" que esta definida como un arreglo de chars, por lo que evidentemente tendras ese error. Visual Studio te advierte de esta operacion "el tipo de matriz 'char [2]' no es asignable". El modo correcto de uso seria:

Código (cpp) [Seleccionar]
int key = _getch();
// o usando la conversion implicita a char
char key = _getch();


Saludos

-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/