Cómo escribir software de operación de gráficos en lenguaje C
Aprende MFC~~Tu confusión se aliviará en poco tiempo~~~
No es imposible usar lenguaje C puro para crear una interfaz~~Solo necesitas usar WINDOWS API~~Déjame darte un fragmento de código para que lo pruebes~~Es un programa OPENGL que hice~~~Fue compilado y aprobado bajo VISUAL STUDIO.NET 2003~~El código es el siguiente~~
#define WM_TOGGLEFULLSCREEN (WM_USER +1) // Definir mensaje de cambio de ventana/pantalla completa
#define TIMER1 101 // Definir código de reloj, establecido en el No. 101
#define TITLE "5DG'S Color Shading" // Definición del título de la ventana
#define CLASSNAME "5DG_OPENGL" // Definir el nombre de la clase de la ventana
#define WIDTH 640 // Definir el ancho de la ventana
#define HEIGHT 480 // Definir la altura de la ventana
#define BPP 16 // Definir el número de bits por píxel
#define NUM 200 // Definir el número de vértices utilizado para dibujar un círculo (segmentos de línea compuestos por vértices que se aproximan a un círculo)
//Cite aquí el archivo de encabezado requerido por el programa:
#include
# include
#include
#include
//Agregue las bibliotecas requeridas por el programa al vinculador aquí:
# pragma comment(lib, "opengl32.lib" ) // Buscar OpenGL32.lib al vincular
#pragma comment(lib, "glu32.lib") // Buscar glu32.lib al vincular p>
// Defina aquí lo mismo que las estructuras relacionadas con Windows:
typedef struct { // Defina la estructura para el procesamiento del teclado
BOOL keyDown [256] // Matriz para almacenar el estado de las teclas del teclado
} Keys;
typedef struct { // Definir la estructura que almacena las instancias de la aplicación
HINSTANCE hInstance; // Instancias de la aplicación
const char* className; // Nombre de clase de aplicación
} Aplicación;
typedef struct { // Definir la información requerida para la ventana de inicialización
Aplicación* aplicación; // Pertenece a la aplicación
char* título; // título de la ventana
int width; // Ancho de la ventana
int height; // Alto de la ventana
int bitsPerPixel; // Bits por píxel
BOOL isFullScreen; pantalla completa
} GL_WindowInit;
typedef struct { // Definir la estructura de la ventana
Teclas* teclas // Teclado
HWND hWnd; // Identificador de ventana
HDC hDC; // Tabla de contexto del dispositivo
HGLRC hRC; // Tabla de contexto de dibujo
GL_WindowInit init; Estructura de la información de inicialización
} GL_Window;
// Declaración directa de funciones contenidas en este módulo de código:
BOOL Inicializar(GL_Window* ventana, Keys* teclas ); //Establece tus valores de inicialización antes de dibujar
void DrawSceneGL(void); // Completa el dibujo de la escena aquí
void Update(void); la acción en el mensaje aquí
void Deinitialize(void); // Realiza el trabajo final antes de salir aquí
// Define las variables globales aquí:
GL_Window * OGL_window; // Almacena información de la ventana
Claves* OGL_keys; // Almacena información de la clave
// Define las variables de usuario aquí:
void ResizeWindowGL(int width) , int height) // Cambiar el tamaño de la ventana
{
glViewport(0, 0, (GLsizei)(width), (GLsizei)(height )); tamaño de la ventana gráfica
glMatrixMode(GL_PROJECTION); // Cambiar al modo de matriz de proyección
glLoadIdentity(); // Restablecer la matriz de proyección
gluPerspective(45, ( float)width/(float)height, 0.1, 100); // Establecer proyección de perspectiva
glMatrixMode(GL_MODELVIEW); // Cambiar a la matriz de vista del modelo
glLoadIdentity(); / Restablecer la matriz de vista del modelo
}
BOOL ChangeScreenResolution(int width, int height, int bitsPerPixel) // Modificar la resolución de la pantalla p>
{
DEVMODE dmScreenSettings; // Modo de configuración del dispositivo
ZeroMemory(&dmSc
reenSettings, sizeof(DEVMODE)); // Borrar
dmScreenSettings.dmSize = sizeof(DEVMODE); // Tamaño de la estructura de Devmode
dmScreenSettings.dmPelsWidth = ancho; Ancho de pantalla
dmScreenSettings.dmPelsHeight = height; // Establecer la altura de la pantalla
dmScreenSettings.dmBitsPerPel = bitsPerPixel; // Establecer la longitud de bits especificada;
dmScreenSettings .dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Intenta configurar el modo de visualización y devolver el resultado.
Nota: CDS_FULLSCREEN elimina la barra de estado
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
return FALSE // Fallo de modificación de resolución, return False
}
return TRUE; // Resolución modificada correctamente, devuelve True;
}
BOOL CreateWindowGL( GL_Window* ventana ) // Crear una ventana OpenGL
{
DWORD windowStyle = WS_OVERLAPPEDWINDOW; // Establecer el estilo de la ventana
DWORD windowExtendedStyle = WS_EX_APPWINDOW; Estilo extendido
PIXELFORMATDESCRIPTOR pfd = // Configuración del descriptor de formato de píxel (pfd)
{
sizeof(PIXELFORMATDESCRIPTOR), // Tamaño de píxel
p >1, // Número de versión
PFD_DRAW_TO_WINDOW | // pfd debe admitir el dibujo de ventanas
PFD_SUPPORT_OPENGL | // pfd debe admitir OpenGL
PFD_DOUBLEBUFFER , // pfd debe admitir doble almacenamiento en búfer
PFD_TYPE_RGBA, // El formato de píxeles es RGBA
ventana->init.bitsPerPixel, // Establece la profundidad del color
0, 0, 0, 0, 0, 0, // Ignorar bits de color
0, // Sin caché alfa
0, // Ignorar bits de desplazamiento
0, // Sin caché de acumulación
0, 0, 0, 0, // Ignora los bits de caché de acumulación
16, // El caché de profundidad es de 16 bits
0, // Sin caché de plantilla
0, // Sin caché auxiliar
PFD_MAIN_PLANE, // Capa de dibujo principal
0, // Reservado bits
0, 0, 0 // Ignorar máscara de capa
};
RECT ventanaRect = {0, 0, ventana->init.width, ventana ->init.height}; // Definir el tamaño de la ventana
GLuint PixelFormat; // Guardar formato de píxeles
if (window->init.isFu
llScreen == TRUE) // Cambiar a pantalla completa
{
if (ChangeScreenResolution(window->init.width, window->init.height, window->init.bitsPerPixel ) = = FALSE)
{
// Error al cambiar de pantalla completa
MessageBox(HWND_DESKTOP, "No se puede cambiar al modo de pantalla completa, ejecutándose en modo de ventana .\nError en el cambio de modo, ejecutándose en modo ventana.", "Error", MB_OK | MB_ICONEXCLAMATION);
ventana->init.isFullScreen = FALSE; // Establecer isFullscreen en False
} p>
else // Cambio de pantalla completa exitoso
{
ShowCursor (FALSE); // Ocultar mouse
windowStyle = WS_POPUP ; // Establecer estilo de ventana
windowExtendedStyle |= WS_EX_TOPMOST; // Establecer estilo de ventana extendido
}
}
else p>
{
// Ajusta el tamaño de la ventana, incluidos los bordes de la ventana
AjustarWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
} p>
// Comience a crear una ventana OpenGL
ventana->hWnd = CreateWindowEx(windowExtendedStyle, // Estilo extendido de ventana
ventana->init.application->className, //Nombre de clase de aplicación
ventana->init.title, // Título de la ventana
windowStyle, // Estilo de ventana
0, 0, // X , Coordenadas Y de la ventana Posición
windowRect.right - windowRect.left, // ancho de la ventana
windowRect.bottom - windowRect.top, // alto de la ventana
HWND_DESKTOP, // La ventana principal es el escritorio
0, // Sin menú
ventana->init.application->hInstance, // Pasar la instancia de la aplicación
ventana) ;
if (ventana->hWnd == 0) // Si la ventana se creó correctamente
{
return FALSO; // Si falló
, luego devuelve FALSE
}
window->hDC = GetDC(window->hWnd); // Obtiene la tabla de descripción del dispositivo de la ventana actual
if ( window->hDC == 0) // Si no se obtiene el contexto del dispositivo
{
DestroyWindow(window->hWnd); // Destruye la ventana
ventana->hWnd = 0; // Borrar identificador de ventana
return FALSE; // Devolver FALSE
}
PixelFormat = ChoosePixelFormat(ventana) -> hDC, &pfd); // Selecciona un formato de píxel compatible
if (PixelFormat == 0) // Si la selección falla
{
ReleaseDC (window- >hWnd, window->hDC); // Liberar el contexto del dispositivo
window->hDC = 0; // Borrar el contexto del dispositivo
DestroyWindow(window-> hWnd ); // Destruye la ventana
ventana->hWnd = 0; // Borra el identificador de la ventana
return FALSE; // Devuelve FALSE
} p>
if (SetPixelFormat(window->hDC, PixelFormat, &pfd) == FALSE) // Establece el formato de píxel y determina si falló
{
ReleaseDC( window- >hWnd, window->hDC); // Liberar la tabla de contexto del dispositivo
window->hDC = 0; // Borrar la tabla de contexto del dispositivo
DestroyWindow(window- >hWnd ); // Destruir ventana
ventana->hWnd = 0; // Borrar identificador de ventana
return FALSE // Devolver FALSE
}< / p>
window->hRC = wglCreateContext(window->hDC); // Obtener la tabla de contexto del dibujo
if (window->hRC == 0) // Si la tabla de contexto del dibujo no se obtiene
{
ReleaseDC(window->hWnd, window->hDC // Libera el contexto del dispositivo
window->hDC = 0); ; // Borrará la tabla de descripción del dispositivo
DestroyWindow(window->hWnd); // Destruirá la ventana
window->hWnd = 0; // Borrará el identificador de la ventana
regresar
FALSE; // Devuelve FALSE
}
if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) // Establece la tabla de descripción del dibujo y determina si fallido
{
wglDeleteContext(window->hRC); // Eliminar la tabla de contexto del dibujo
window->hRC = 0; tabla de contexto a cero
ReleaseDC(window->hWnd, window->hDC); // Libera la tabla de contexto del dispositivo
window->hDC = 0; tabla de contexto
p>DestroyWindow(window->hWnd); // Destruye la ventana
window->hWnd = 0 // Borra el identificador de la ventana
> return FALSE; // Devuelve FALSE
}
ShowWindow(ventana->hWnd, SW_NORMAL); // Mostrar ventana
ResizeWindowGL(ventana->init); .width, window->init .height); // Restablecer ventana
ZeroMemory(window->keys, sizeof (Keys)); // Borrar el búfer del teclado
return TRUE; // Ventana creada exitosamente
}
BOOL DestroyWindowGL(GL_Window* window) // Destruye la ventana y libera los recursos utilizados por el programa
{ p>
if (window ->hWnd != 0) // ¿La ventana tiene un identificador?
{
if (window->hDC != 0) / / ¿La ventana obtiene un contexto de dibujo?
{
wglMakeCurrent(window->hDC, 0 // Establece el puntero de contexto actual en 0
); if (window->hRC != 0 ) // ¿Esta ventana tiene un contexto de dibujo?
{
wglDeleteContext(window->hRC); // Liberar el contexto de dibujo
window->hRC = 0; // Borrar la tabla de contexto de dibujo
}
ReleaseDC(window->hWnd, window->hDC); Liberar la tabla de contexto del dispositivo
window->hDC = 0; // Borrar la tabla de contexto del dispositivo
}
DestroyWindow(window->hWnd); / Destruye la ventana
window->hWnd = 0; // Borra el identificador de la ventana
Cero
}
if (window->init.isFullScreen) // Si la ventana está en modo de pantalla completa
{
ChangeDisplaySettings( NULL ,0); // Cambiar a la resolución del escritorio
ShowCursor(TRUE); // Mostrar el mouse
}
return TRUE; VERDADERO
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)//Procesamiento de mensajes de ventana
{
GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA));//Obtener información de la ventana
switch (uMsg) //Obtener información de la ventana
{ p>
case WM_SYSCOMMAND: // Interceptar comandos del sistema
{
switch (wParam) // Monitorear llamadas del sistema
{
case SC_SCREENSAVE: // ¿Quieres ejecutar un protector de pantalla?
case SC_MONITORPOWER: // ¿El monitor ingresa al modo de ahorro de energía?
return 0 // Devuelve 0 por adelantado a evitar que se ejecuten llamadas al sistema
}
break; // Salir
}
case WM_CREATE: // Crear ventana p>
{
CREATESTRUCT* creación = (CREATESTRUCT*)(lParam); // Guardar puntero de estructura de ventana
ventana = (GL_Window*)(creación->lpCreateParams) ;
SetWindowLong(hWnd, GWL_USERDATA, (LONG)(ventana)); // Cambiar propiedades de la ventana
return 0; // Regresar
} p>
case WM_TIMER : // evento TIMER
{
InvalidateRect(window->hWnd, NULL, FALSE // Invalidar la ventana
break;
}
case WM_PAINT: //PAINT procesamiento de mensajes, dibuja aquí
{
DrawSceneGL(); Dibujar aquí
SwapBuffers(window->hDC); // Intercambiar caché
ValidateRect(window->hWnd, NULL);
break;
}
case WM_CLOSE: // Cerrar la ventana
{
PostMessage(ventana - >hWnd, WM_QUIT, 0, 0); // Finalizar programa
return 0;
}
case WM_SIZE: // Cambios de tamaño de ventana p >
{
ResizeWindowGL(LOWORD(lParam), HIWORD(lParam)); // Modifica el tamaño de la ventana a Ancho = LoWord, Alto = HiWord
return 0; // Retorno
}
case WM_KEYDOWN: //Actualiza el buffer del teclado cuando se presiona la tecla
if ((wParam >= 0) && (wParam <= 255) ) // ¿Es legal la clave?
{
window->keys->keyDown[wParam] = TRUE // Establece la clave correspondiente en True p>
return 0; // Regresar
}
break; // Salir
case WM_KEYUP: // Actualiza el búfer del teclado cuando se presiona la tecla. se libera
if ((wParam >= 0) && (wParam <= 255)) // ¿Las claves son legales?
{
ventana-> llaves->keyDown[wParam] = FALSE ; // Establece la clave correspondiente en FALSE
return 0; // Retorno
}
break; Salir
case WM_TOGGLEFULLSCREEN: // Cambiar el modo de pantalla completa
{
Deinitialize(); // Hacer el trabajo final
DestroyWindowGL(window); // Destruye la ventana
window->init.isFullScreen = !window->init.isFullScreen; // Cambia el modo de ventana
CreateWindowGL(window); / Volver a crear ventana
Inicializar( ventana, ventana->teclas); // Inicializar programa de dibujo OpenGL
break; // Salir
} p>
predeterminado:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pasa mensajes no procesados por); este programa a DefWindowPr
oc
}
BOOL RegisterWindowClass(Aplicación* aplicación) //Registrar una clase para esta aplicación
{
WNDCLASSEX windowClass; / Clase de ventana
ZeroMemory (&windowClass, sizeof(WNDCLASSEX)); // Borrar memoria
windowClass.cbSize = sizeof(WNDCLASSEX) // El tamaño de la clase de ventana
p >windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redibujar cuando la ventana se mueve y cambia de tamaño
windowClass.lpfnWndProc = (WNDPROC)(WindowProc);
windowClass.hInstance = application->hInstance; // Establecer instancia
windowClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE) // Color del pincel del fondo de la clase
<); p> windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Carga el puntero del mousewindowClass.lpszClassName = application->className // Establece el nombre de la clase de la aplicación
if (RegisterClassEx(&windowClass) == 0) // ¿Error en el registro de la clase?
{
MessageBox(HWND_DESKTOP, "¡Error en el registro de la clase de aplicación!\n¡RegisterClassEx falló!", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Devuelve Falso (registro fallido)
}
return TRUE; // Devuelve Verdadero (registro exitoso)
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Aplicación de aplicación //; Aplicación
GL_Window ventana; // Ventana
Teclas teclas; // Teclas del teclado
MSG msg // Mensaje de ventana
BOOL bRet; // Si el mensaje se guardó correctamente
// Asigna un valor a la aplicación
application.className = CLASSNAME // Nombre de la clase del programa
aplicación.hInstancia = hInstancia;
// Entrada del programa
// Configuración de información relacionada con la ventana
ZeroMemory(&window, sizeof(GL_Window) // Borrar el espacio de memoria de las variables de la ventana
window.keys = &keys; // Establecer claves
window.init.application = &application; // Establecer programa de ventana
window.init.title = TITLE; /p>
window.init.width = WIDTH; // Establece el ancho de la ventana
window.init.height = HEIGHT; // Establece el alto de la ventana
window. init. bitsPerPixel = BPP; // Establece el número de bits por píxel
window.init.isFullScreen = FALSE // Establece si la ventana inicial es de pantalla completa (FALSE)
ZeroMemory(&keys, sizeof (Keys)); // Borrar el búfer del teclado
if (RegisterWindowClass(&application) == FALSE) // Si la clase de registro falló
{ p>
MessageBox (HWND_DESKTOP, "¡Error en el registro de la clase de ventana!\n¡Error al registrar la clase de ventana!", "Error", MB_OK | MB_ICONEXCLAMATION);
return -1; p>
}
if (CreateWindowGL(&window) == TRUE) // Si la ventana se creó correctamente
{
if (Initialize( &window, &keys) == FALSE) // Inicializa el programa de dibujo OpenGL
{
PostMessage(window.hWnd, WM_QUIT, 0, 0); // Lanzar mensaje WM_QUIT
}
}
else
{
return 0; // Salir del programa
}
while ((bRet = GetMessage(&msg, NULL, 0, 0) != 0)) // Bucle hasta que el mensaje sea WM_QUIT
{
if (bRet != - 1)
{
Update(); // Actualiza el evento del mensaje
TranslateMessage(&msg); el mensaje
DispatchMessage(&msg); // Mensaje de envío
}
else
{
break ;
//Salir del bucle
}
}
//Salir del bucle de mensajes y prepararse para salir del programa
Deinitialize() ; // Hacer el trabajo de limpieza antes de salir
DestroyWindowGL(&window); // Destruir la ventana
UnregisterClass(application.className, application.hInstance);
return 0; // Salir del programa
}
BOOL Inicializar(GL_Window* ventana, Keys* teclas) // Las funciones relacionadas con las escenas de dibujo del usuario son definido aquí
{
// Establecer variables globales
OGL_window = ventana;
OGL_keys = claves;
// Establece el reloj
SetTimer(window->hWnd, TIMER1, 33, NULL);
// Inicializa la escena de dibujo aquí
glClearColor(0.0 f, 0.0f, 0.0f, 0.5f); // Borrar la pantalla a negro
glClearDepth(1.0f); // Establecer el búfer de profundidad
glDepthFunc(GL_LEQUAL); // Seleccione el método de prueba de profundidad
glEnable(GL_DEPTH_TEST); // Habilite la prueba de profundidad
glShadeModel(GL_SMOOTH); // Utilice el método de suavizado para el procesamiento de sombras
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // El cálculo de perspectiva más preciso
return TRUE; // Devuelve TRUE si la inicialización es exitosa
}
void DrawSceneGL (void) // Dibujar la escena
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Borrar el caché de color y profundidad
glLoadIdentity(); / Restablecer la matriz actual
//Agregar código aquí para dibujar:
glShadeModel(GL_SMOOTH); // Smooth Shading se utiliza para el procesamiento de sombras
glTranslatef( -1.5f, 1.0f, -6.0 f); // Mueve el origen de las coordenadas 1.5f hacia la izquierda, 1.0f hacia arriba y 6.0f hacia adentro
glBegin(GL_TRIANGLES);
glColor3ub (255, 0, 0); // Definir el vértice superior como rojo
glVertex3f(0.0f, 1.0f, 0.0f); // Dibujar el vértice superior
glColor3ub(0, 255, 0); // Definir la parte superior inferior izquierda
El punto es verde
glVertex3f( -1.0f, -1.0f, 0.0f); // Dibuja el vértice inferior izquierdo
glColor3ub(255, 255, 0); Definir el vértice inferior derecho es amarillo
glVertex3f(1.0f, -1.0f, 0.0f); // Dibuja el vértice inferior derecho
glEnd();
glTranslatef(3.0 f, 0.0f, 0.0f); // Traducir 3.0f a la derecha
glColor3ub(0, 255, 255); // Definir el color del cuadrado
glBegin(GL_QUADS); // Comienza a dibujar un cuadrado
glVertex3f(-1.0f, 1.0f, 0.0f); // Dibuja el vértice superior izquierdo
glVertex3f); (-1.0f,-1.0f, 0.0 f); // Dibuja el vértice inferior izquierdo
glVertex3f( 1.0f,-1.0f, 0.0f); // Dibuja el vértice inferior derecho
glVertex3f( 1.0f, 1.0f, 0.0f); // Dibuja el vértice superior derecho
glEnd();
glTranslatef(-1.5f, -2.0f , 0.0f); // Mueve 1.5f hacia la izquierda, Baja 2.0f
glColor3f(0.0f, 0.8f, 0.2f); // Verde
glBegin(GL_LINE_LOOP); ); // Dibujar círculo
for (int i=0; i { glVertex3f(1.5f*(float)sin (2.0f*3.14f*i/NUM), 0.0 f, 1.5f*(flotante)cos(2.0f*3.14f*i/NUM)); } glEnd(); glFlush( ); // Actualiza la cola de comandos GL } void Update(void) // Actualiza la acción en el mensaje aquí { if (OGL_keys->keyDown[VK_ESCAPE] == TRUE) // Determina si se presiona la tecla ESC { PostMessage(OGL_window->hWnd, WM_QUIT, 0, 0); // Finalizar programa } if (OGL_keys->keyDown[VK_F1] == TRUE) / / Determinar si se presiona F1 { PostMessage(OGL_window->hWnd, WM_TOGGLEFULLSCREEN, 0, 0 // Cambiar entre modo de pantalla completa/ventana } } void Deinitialize(void) // Haz el trabajo final antes de salir aquí { KillTimer(OGL_window- > hWnd, TIM ER1); // Liberar reloj }