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

Shadow The Hedgehog X pixel art

I was bored, so... ManutKat.

Werehog transformation process. #sonicunleashed

The whole squad is here!

Interested? Follow me!

Back in my art school days I used to ride the 710 COPSA line from Parque Del Plata to Montevideo almost everyday. This is the Marcopolo Viaggio G4 Mercedes Benz model from the late 80s, one of the older bus models that was running on the line.

Strange Umbrella

The Darkside Detective: A Fumble in the Dark is out TODAY! 🖱️Advanced pointing, clicking action 🖨️Very funny words! Loads of them! 👻6 sarcastic, spectral cases to solve

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

Spaaaace~

These are background sprites I've created for a game I'm working on at school ^w^ Click on the post to see how the sprites connect. You won't regret it! (personally, I think it's pretty heheh)

Drawn in Piskel using my mouse. Whaddya think?

Path of Kami, running around the shrine area