12 years ago

Making a gl window in Windows that is DLL Friendly


Its easier to read if you download this file https://dl.dropboxusercontent.com/u/13278359/Making%20a%20gl%20window%20in%20Windows%20that%20is%20DLL%20Friendly.rtf

This is actually fairly easy and this technique also allows the creation of a window from a dll or just using the standard c++ main() entry functions. (make sure your projects are set to use console)

The main thing WinMain is used for is to get the hInstance, and hPrevInstance, and show Command. So without it hInstance is still very easy to get you simply use HINSTANCE hInstance=getModuleHandle(). hPrevInstance, by microsofts own admission, is always null. I do not at this time know how to get int nCmdShow so I will use SW_SHOWNORMAL

You will need to include <windows.h>, <gl/gl.h> (you may not need this), and <wglext.h>

First we need to create a windows class. Theres cool tricks you can use if you use extended windows classes but we won’t be doing anything fancy here.

<code>

WNDCLASSEX wClass={};//makes sure parameters we don’t use are NULL

wClass.cbSize=sizeof(WNDCLASSEX);//would be different if we used extra info in the extended part

wClass.style=CS_HREDRAW|CS_VREDRAW;//tells windows we want horizantal and vertical redraw

wClass.lpfnWndProc=WindowProc;//the function you want to handle windows messages

wClass.cbClsExtra=0;//forget what this is for

wClass.cbWndExtra=0;//forget what this is for

wClass.hInstance=hInstance;//that instance we just got

wClass.hIcon=LoadIcon(NULL, IDI_APPLICATION);//custom icon

wClass.hCursor=LoadCursor(NULL, IDC_ARROW); //custom cursor

wClass.lpszMenuName=NULL; //we aren’t using a menu

wClass.lpszClassName=”WindowClass1”;//name of the class to use later during window creation, make sure it is unique

wClass.hIconSm=LoadIcon(NULL, IDI_WINLOGO);//you can use a custom icon for your window here

Next we need to register the class

if(!RegisterClassEx(&wClass))

{

//handle the error here if the class was not successfully registered

}

This lets Windows know about our window structure. Now we create the window.

HWNDcwnd=CreateWindowEx(

NULL,//the extended style sometimes if used messes stuff up just be careful

“WindowClass1”, //The name of the registered class

“I’m a window”, //The window name and also what shows up in the title bar first

WS_OVERLAPPEDWINDOW, //The style used for the window there are other settings here for fullscreen

CW_USEDEFAULT, CW_USEDEFAULT, //this is the x,y position of the window. I set it to default

dispParams->sx, dispParams->sy, //the width, height of the window

NULL, //this is the parent window

NULL, //this is the menu

hInstance, //the program instance

NULL//used to pass an lparam on msg WM_CREATE

);

if(cwnd==NULL)

{

//handle the error here if the window was not successfully created

}

ShowWindow(cwnd, SW_SHOWNORMAL);//display the window on the screen

UpdateWindow(cwnd);//force update it to make sure everything is set up

[/code]

Before I go into the creating of the gl Context let me list the setPixelFormat funtion I used.

bool setPixelFormat(HDC hDC, DisplaySettings dispParam)

{

PIXELFORMATDESCRIPTOR pfd = {

sizeof(PIXELFORMATDESCRIPTOR), / size /

1, / version /

PFD_SUPPORT_OPENGL |

PFD_DRAW_TO_WINDOW |

PFD_DOUBLEBUFFER, / support double-buffering /

PFD_TYPE_RGBA, / color type /

32, / prefered color depth /

0, 0, 0, 0, 0, 0, / color bits (ignored) /

0, / no alpha buffer /

0, / alpha bits (ignored) /

0, / no accumulation buffer /

0, 0, 0, 0, / accum bits (ignored) /

32, / depth buffer bits/

0, / stencil buffer bits /

0, / no auxiliary buffers /

PFD_MAIN_PLANE, / main layer /

0, / reserved /

0, 0, 0, / no layer, visible, damage masks/

};

int pixelFormat = ChoosePixelFormat(*hDC, &pfd);

if (pixelFormat==0)

{

returnfalse;

}

if(!SetPixelFormat(*hDC, pixelFormat, &pfd))

{

returnfalse;

}

returntrue;

}

All thats left is to create a gl Context. hDC and hRC should be global variables as you need to delete them later.

hDC=GetDC(cwnd);//gets the device context of the window (the draw surface)

if(hDC==NULL)

{

//error did not get a device context

}

if(!setPixelFormat(&hDC, dispParam))

{

//error was not able to set desired pixel format

}

hRC=wglCreateContext(hDC);//create a gl rendering context this is raw gl 1.1

//but we need it to get the context for more advanced gl

if(hRC==NULL)

{

//error did not get a gl rendering context

}

wglMakeCurrent(hDC, hRC);//attatch the rendering surface to the draw surface

PFNWGLCREATECONTEXTATTRIBSARBPROCwglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(“wglCreateContextAttribsARB”);//get the function used to create higher version contexts

if(!wglCreateContextAttribsARB)

{

//error no such function

}

//gl v3.2 major=3 minor=2

int glAttribs[] = {

WGL_CONTEXT_MAJOR_VERSION_ARB, 1,//the major gl version

WGL_CONTEXT_MINOR_VERSION_ARB, 0,//the minor gl version

WGL_CONTEXT_FLAGS_ARB, 0,//this can be used to make a forward compatible context and to set it to debug mode though 0 is normal operation

0};//0 to tell wglCreateContextAttribsARB this is the end

hRC3=NULL;//just make sure its null (may not be needed)

hRC3=wglCreateContextAttribsARB(hDC, 0, glAttribs);//creates the gl rendering context with the attributes we set.

if(hRC3==NULL)

{

//error either version is unsupported or did not get the rendering context

}

wglDeleteContext(hRC);//delete the 1.1 context

wglMakeCurrent(hDC, hRC3);//attatch the new rendering context to the draw context

For continual updating you’ll need a window proc my current bare bones one is listed below

LRESULTCALLBACK WindowProc(HWNDhwnd, UINTmsg, WPARAMwParam, LPARAMlParam)

{

caseWM_KEYDOWN:

if (wParam!=VK_ESCAPE)//allows user to close prgram by pressing esc

{

break;

}

caseWM_DESTROY:

wglMakeCurrent(hDC, NULL);//unlink the contexts

wglDeleteContext(hRC3);//delete the gl Rendering Context

PostQuitMessage(0);//close program

break;

caseWM_SIZE://sets gl up to use the new window size

screenWidth=(int) LOWORD(lParam);

screenHeight=(int) HIWORD(lParam);

glViewport(0, 0, (int) LOWORD(lParam), (int) HIWORD(lParam));

break;

default:

returnDefWindowProc( hwnd, msg, wParam, lParam );

}

return 0;

}

You’ll also need this code called somewhere in your main loop

SwapBuffers(hDC);//switches to the buffer you drew on

MSG cmsg;

while(PeekMessage(&cmsg, 0,NULL,NULL, PM_REMOVE ))

{

TranslateMessage(&cmsg);

DispatchMessage(&cmsg);

}

If you ever want to get rid of the console add this line

#pragmacomment(linker, “/SUBSYSTEM:windows /ENTRY:mainCRTStartup”)

And thats it I did adapt this code somewhat from what I have so if something doesn’t work let me know. Cheers :)



0 comments

Loading...

Next up

What you all think

The whole squad is here!

Interested? Follow me!

One of the most critical update for Sunblaze demo. Now you are able to pet a cat! Finally!

We're glad to announce that Baby Dino Adventures 🦖 is now available in Early Access here on GameJolt! Link: https://gamejolt.com/games/babydinoadventures/508121 Walk, run, and jump as a baby t-rex in this cute platformer Free demo available #IndieGame | #GameDev | #PixelArt

An infected room from the second part of Cybel ! Are you up for some cleansing?

"Day to Day" (also check spud out here he's a great guy and writer: https://soundcloud.com/spudward)

Some Shadow boss fight gameplay 👾

blender animation experimentation, getting the hang of things fast. arms, rig, & gun models by me ofc

I just wanted to introduce you to my latest musical production and hear some opinions about it. Thank you very much.