Red de conocimiento informático - Material del sitio web - Cómo escribir software de operación de gráficos en lenguaje C

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 // Archivo de encabezado de Windows

# include //Archivo de encabezado de la biblioteca OpenGL32

#include //Archivo de encabezado de la biblioteca Glu32

#include //Archivo de encabezado de la biblioteca de funciones matemáticas

//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

// 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

{

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

}

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

{

// Ajusta el tamaño de la ventana, incluidos los bordes de la ventana

AjustarWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);

}

// 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

}

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

{

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

{

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

{

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

}

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

{

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

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

}

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 mouse

windowClass.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ó

{

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

}