German
German

Reputation: 345

Child window with OpenGL not responding to gluOrtho2D()

I created a child window using WinAPI, now I'm trying to draw a triangle there.
It is drawn, but its scale is not correct.
I think this is due to the fact that I have not properly installed orthogonal system. It is set in the init() function, I call it when the child window is created in the WM_CREATE message, it is triggered, but the orthographic projection is still not set to the desired size. So I only see the bottom of the triangle.

#include <Windows.h>
#include <GL/GL.h>
#include <GL/GLU.h>

#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "glu32.lib")

//opengl values
int windowWidth = 600, windowHeight = 800, windowDepth = 600;
void init();

HWND childOpenGLWindowHWND = NULL;

HWND CreateOpenGLChildWindow(wchar_t* title, int x, int y, int width, int height,
  BYTE type, DWORD flags, HWND hWndParent, HINSTANCE hInstance, WNDPROC wndProc)
{
  int         pf;
  HDC         hDC;
  HWND        hWnd;
  PIXELFORMATDESCRIPTOR pfd;

  WNDCLASS wc;
  wc.style = CS_OWNDC;
  wc.lpfnWndProc = wndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = NULL;
  wc.lpszMenuName = NULL;
  wc.lpszClassName = L"OpenGL";

  if (!RegisterClass(&wc)) {
    MessageBox(NULL, L"RegisterClass() failed:  "
      L"Cannot register window class.", L"Error", MB_OK);
    return NULL;
  }

  hWnd = CreateWindow(
    L"OpenGL",
    title,
    WS_CHILD,
    x,
    y,
    width,
    height,
    hWndParent,
    NULL,
    NULL,
    NULL
  );

  if (!hWnd) {
    MessageBox(NULL, L"CreateWindow() failed:  Cannot create a window.",
      L"Error", MB_OK);
    return NULL;
  }

  hDC = GetDC(hWnd);

  /* there is no guarantee that the contents of the stack that become
      the pfd are zeroed, therefore _make sure_ to clear these bits. */
  memset(&pfd, 0, sizeof(pfd));
  pfd.nSize = sizeof(pfd);
  pfd.nVersion = 1;
  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | flags;
  pfd.iPixelType = type;
  pfd.cColorBits = 32;

  pf = ChoosePixelFormat(hDC, &pfd);
  if (pf == 0) {
    MessageBox(NULL, L"ChoosePixelFormat() failed:  "
      "Cannot find a suitable pixel format.", L"Error", MB_OK);
    return 0;
  }

  if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
    MessageBox(NULL, L"SetPixelFormat() failed:  "
      "Cannot set format specified.", L"Error", MB_OK);
    return 0;
  }

  DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

  ReleaseDC(hWnd, hDC);

  return hWnd;

}

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
wchar_t WinName[] = L"MainFrame";

int WINAPI WinMain(
  HINSTANCE This,
  HINSTANCE Prev,
  LPSTR cmd,
  int mode
)
{
  HDC hDC;              /* device context */
  HGLRC hRC;                /* opengl context */

  HWND hWnd;
  MSG msg;
  WNDCLASS wc;
  wc.hInstance = This;
  wc.lpszClassName = WinName;
  wc.lpfnWndProc = WndProc;
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.lpszMenuName = NULL;
  wc.cbClsExtra = NULL;
  wc.cbWndExtra = NULL;
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  if (!RegisterClass(&wc)) return NULL;
  int windowWidth = 800;
  int windowHeight = 800;
  int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  hWnd = CreateWindow(
    WinName,
    L"Title",
    WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX,
    (screenWidth - windowWidth) / 2,
    (screenHeight - windowHeight) / 2,
    windowWidth,
    windowHeight,
    HWND_DESKTOP,
    NULL,
    This,
    NULL
  );

  if (!hWnd)
  {
    MessageBox(NULL, L"MAIN HWND ERROR!!!",
      L"Error", MB_OK);
    exit(1);
  }

  childOpenGLWindowHWND = CreateOpenGLChildWindow(
    WinName,
    0,
    0,
    600,
    800,
    NULL,
    NULL,
    hWnd,
    This,
    WndProc
  );

  if (!childOpenGLWindowHWND)
  {
    MessageBox(NULL, L"Child window init error", L"Error", MB_OK);
    return 0;
  }



  hDC = GetDC(childOpenGLWindowHWND);
  hRC = wglCreateContext(hDC);
  wglMakeCurrent(hDC, hRC);

  SendMessage(hWnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS), NULL);
  ShowWindow(hWnd, mode);
  ShowWindow(childOpenGLWindowHWND, mode);
  while (GetMessage(&msg, NULL, NULL, NULL))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  wglMakeCurrent(NULL, NULL);
  ReleaseDC(childOpenGLWindowHWND, hDC);
  wglDeleteContext(hRC);
  DestroyWindow(childOpenGLWindowHWND);

  return msg.wParam;

  //return NULL;
}

void init()
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2);
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
  glColor3f(0, 1, 0);
  glVertex3f(-50, 0, 0);
  glVertex3f(50, 0, 0);
  glVertex3f(0, 50, 0);
  glEnd();
  glFlush();
}

LRESULT CALLBACK WndProc(
  HWND hWnd,
  UINT message,
  WPARAM wParam,
  LPARAM lParam
)
{

  PAINTSTRUCT ps;

  switch (message)
  {
  case WM_CREATE:
    init();
  case WM_PAINT:
    display();
    BeginPaint(hWnd, &ps);
    EndPaint(hWnd, &ps);
    return NULL;
  case WM_SIZE:
    glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
    PostMessage(hWnd, WM_PAINT, 0, 0);
    return NULL;
  case WM_CHAR:
    switch (wParam) {
    case 27:
      PostQuitMessage(0);
      break;
    }
    return 0;
  case WM_DESTROY:
    PostQuitMessage(NULL);
    break;
  default: return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return NULL;
}

Upvotes: 4

Views: 147

Answers (1)

Rabbid76
Rabbid76

Reputation: 210968

The WM_CREATE message is triggered by CreateWindow. This is before the OpenGL Context is created by wglCreateContext and made current by wglMakeCurrent.
Thus not any OpenGL instruction takes effect at this point.

I recommend to implement the WM_SHOWWINDOW message instead:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;

    HDC hDC;
    switch (message)
    {
    // [...]

    case WM_SHOWWINDOW:
        BeginPaint(hWnd, &ps);
        init();
        EndPaint(hWnd, &ps);
        return NULL;

    case WM_PAINT:
        BeginPaint(hWnd, &ps);
        display();
        EndPaint(hWnd, &ps);
        return NULL;

    // [...]
    }
    return NULL;
}

Upvotes: 4

Related Questions