You need to set the window pixel format and then create an OpenGL context.
You should be able to pick out the parts required to get it running in your window from this example:
#include <windows.h>
#include <gl/gl.h>
#pragma comment (lib, "opengl32.lib")
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Main
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// Window class
WNDCLASSEX wc = {};
wc.cbSize = sizeof(wc);
wc.lpszClassName = TEXT("MyClass");
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.style = CS_OWNDC;
RegisterClassEx(&wc);
// Window
HWND hWnd = CreateWindowEx(
0,
wc.lpszClassName,
TEXT("OpenGL Window"),
WS_OVERLAPPEDWINDOW |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
// Get DC
HDC hDC = GetDC(hWnd);
// Pixel format
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags =
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_SUPPORT_COMPOSITION;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
int pf = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pf, &pfd);
// OpenGL context
HGLRC hGLRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hGLRC);
// Get OpenGL version and set it as window title
SetWindowTextA(hWnd, (char*)glGetString(GL_VERSION));
// Main loop
ShowWindow(hWnd, nCmdShow);
while(true) {
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
if(msg.message == WM_QUIT)
break;
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else {
// Draw
glClearColor(1.0f, 0.7f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(hDC);
}
}
// Clean up
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hGLRC);
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
// Window proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
// Resize GL rendering area to match window size
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
However, that will only really allow you to use quite old OpenGL functionality without some extra work, as the newer version functions aren't readily available in opengl32.lib. The default library only provides version 1.1 or something like that (even when the context version is 4.5).
To load more functions you need to request their function pointers from WGL while your GL context is current, for example to use the glCompileShader function:
PFNGLCOMPILESHADERPROC glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
The function pointer will match a function in the NVidia or AMD driver for example, not in the system OpenGL DLL.
This is a bit tedious, and if you want to do it manually the best way is probably to download glcorearb.h from opengl.org and write a script that goes through it and loads all the functions into some appropriate wrapper or global pointers or something.
There are libraries written specifically to take care of all this, such as GLEW for example: http://glew.sourceforge.net/
It can take care of checking all extensions etc. for you and help make sure everything is loaded properly and detect when it isn't. This is especially useful when loading extensions that may be available only on some drivers. If you make sure the context version is 4.x and you load only core functionality matching that version it's just about loading all the function pointers.