Discussion:
Creating an opengl viewport in a dialog box
(too old to reply)
Allan Bruce
2003-07-19 16:48:51 UTC
Permalink
Hello,
A few days ago, I was asking how to paint into the dialog box, well I
managed. Thanks to all those who helped.
Now I want to create a small OpenGL viewport in it to display a sphere to
help see what my material properties are like. My current dialog box looks
like
Loading Image...
But when the user changes the specular/diffuse etc. no change is made on a
flat rectangle. Can somebody tell me how to create a small viewport in the
dialog box to render a small sphere?
Thanks
Allan
Shizuka
2003-07-19 18:16:03 UTC
Permalink
Post by Allan Bruce
Hello,
A few days ago, I was asking how to paint into the dialog box, well I
managed. Thanks to all those who helped.
Now I want to create a small OpenGL viewport in it to display a sphere to
help see what my material properties are like. My current dialog box looks
like
http://www.allanmb.f2s.com/images/dialog.GIF
But when the user changes the specular/diffuse etc. no change is made on a
flat rectangle. Can somebody tell me how to create a small viewport in the
dialog box to render a small sphere?
Maybe this will work :

1) In your dialog template, define a "CONTROL" item inside your dialog.
Basically, define your own child window control inside the dialog
box.
This child window will have it's own window procedure and class, etc.

2) Inside the window procedure of this "custom dialog control", you will
need to handle WM_CREATE and WM_PAINT. In WM_CREATE,
you need to setup your device context (DC) and openGl rendering context
(RC).
I'll just assume that you're already familiar with OpenGl type windows,
rendering contexts, drawing etc..

3) When the user operates on the specular/diffuse sliders, you need to
TELL your custom "CONTROL" that the slider properties changed,
and you need to force a WM_PAINT on the window. This can be
done with "InvalidateRect (hOpenGLWnd, NULL, TRUE)".

Hope that helps!

***@goodnet.com
Allan Bruce
2003-07-19 19:39:01 UTC
Permalink
Post by Shizuka
Post by Allan Bruce
Hello,
A few days ago, I was asking how to paint into the dialog box, well I
managed. Thanks to all those who helped.
Now I want to create a small OpenGL viewport in it to display a sphere to
help see what my material properties are like. My current dialog box
looks
Post by Allan Bruce
like
http://www.allanmb.f2s.com/images/dialog.GIF
But when the user changes the specular/diffuse etc. no change is made on a
flat rectangle. Can somebody tell me how to create a small viewport in
the
Post by Allan Bruce
dialog box to render a small sphere?
1) In your dialog template, define a "CONTROL" item inside your dialog.
Basically, define your own child window control inside the dialog
box.
This child window will have it's own window procedure and class, etc.
2) Inside the window procedure of this "custom dialog control", you will
need to handle WM_CREATE and WM_PAINT. In WM_CREATE,
you need to setup your device context (DC) and openGl rendering context
(RC).
I'll just assume that you're already familiar with OpenGl type windows,
rendering contexts, drawing etc..
3) When the user operates on the specular/diffuse sliders, you need to
TELL your custom "CONTROL" that the slider properties changed,
and you need to force a WM_PAINT on the window. This can be
done with "InvalidateRect (hOpenGLWnd, NULL, TRUE)".
Hope that helps!
Ok, i have tried this:

SetWindowText(hDlg, gTextToDisplay);

hwndGL = CreateWindowEx(WS_EX_CLIENTEDGE ,
??, (LPSTR) NULL, WS_VISIBLE | WS_CHILD,
165, 75, 50, 50, hDlg, (HMENU) 0, ghInstance, NULL);
hdcGL = GetDC(hwndGL);

// choose pixel format that best matches that described in PFD
nPixelFormat = ChoosePixelFormat(hdcGL, &pfd);

// set the pixel format for the device context
SetPixelFormat(hdcGL, nPixelFormat, &pfd);

hrcGL=wglCreateContext(hdcGL);
wglMakeCurrent(hdcGL, hrcGL);

core.ChangeViewSize(50, 50);
core.SetupRC();

What Style should I declare for CreateWindowEx()?
am I on the right track?
Thanks
Allan
Lucian Wischik
2003-07-19 22:00:18 UTC
Permalink
Post by Allan Bruce
hwndGL = CreateWindowEx(WS_EX_CLIENTEDGE ,
??, (LPSTR) NULL, WS_VISIBLE | WS_CHILD,
165, 75, 50, 50, hDlg, (HMENU) 0, ghInstance, NULL);
hdcGL = GetDC(hwndGL);
What Style should I declare for CreateWindowEx()?
am I on the right track?
You should read a tutorial on creating custom controls.
Then, use the same classname that you used in your WNDCLASSEX that you
RegisterClass'd.

There's one weird "gotcha". For some drivers, if the opengl window has
moved on the screen, then you have to do the glViewport stuff again.
The problem is that a child window (as you've got here) never gets
notified when it has moved "absolutely" on the screen. I faced the
same problem here:
http://www.codeproject.com/useritems/holsavers.asp#threedee

my solution was to get the screen coordinates of my opengl window
every frame, and see if they had moved since last one, and if so then
I do the glViewport stuff again.

(alternatively, since you're in a dialog, your main DialogProc could
respond to WM_MOVE itself.)

--
Lucian
Shizuka
2003-07-19 22:17:34 UTC
Permalink
Post by Allan Bruce
hwndGL = CreateWindowEx(WS_EX_CLIENTEDGE ,
??, (LPSTR) NULL, WS_VISIBLE | WS_CHILD,
165, 75, 50, 50, hDlg, (HMENU) 0, ghInstance, NULL);
hdcGL = GetDC(hwndGL);
What Style should I declare for CreateWindowEx()?
am I on the right track?
You're a little bit off track here. Are you familiar with custom
"child window" creation?? You first need to register a
new window class, with RegisterClassEx(). For example, you might
name your new class name as "MY_OGL_VIEW". And, when you
register your window class, you must also specify a new window procedure.
For example, you might define a new window procedure that
is named "Gl_ViewProc()".

So, inside "Gl_ViewProc()", you will need to handle any
important messages, like WM_CREATE, WM_PAINT, etc..
During WM_CREATE, you probably want to setup your open-gl
device contexts, rendering contexts, and any application specific data.
It is during WM_PAINT that you will be drawing on your
child window.

Now, after your register the new window class, call CreateWindowEx().
Something like :

hwndGL = CreateWindowEx (WS_EX_CLIENTEDGE ,
"MY_OGL_VIEW", // This is your newly
defined wndclass
"" ,
WS_VISIBLE | WS_CHILD, // These flags are most
important
165, 75, 50, 50, hDlg,
(HMENU) IDC_MYVIEW, // Assign a unique ID to this
window!
ghInstance, NULL);

When the user alters your dialog sliders, you can redraw your OpenGl view
by calling :
InvalidateRect (hwndGl, NULL, TRUE);

See if that works. If not, i can try sending code examples that work.

***@goodnet.com
Lucian Wischik
2003-07-20 08:23:31 UTC
Permalink
wc.style = CS_HREDRAW | CS_VREDRAW;
You need CS_OWNDC for an opengl window.

WM_CREATE is too early to set up the opengl context, for some drivers.
It's better if you create it lazily. (ie. in the WM_PAINT handler,
check to see if the context has been created, and if it hasn't yet
then create it).

--
Lucian
Allan Bruce
2003-07-20 10:36:54 UTC
Permalink
Post by Lucian Wischik
wc.style = CS_HREDRAW | CS_VREDRAW;
You need CS_OWNDC for an opengl window.
WM_CREATE is too early to set up the opengl context, for some drivers.
It's better if you create it lazily. (ie. in the WM_PAINT handler,
check to see if the context has been created, and if it hasn't yet
then create it).
--
Lucian
Still not quite there!
I have never done much extra window creation apart from the main window, so
I think this is where my main problem lies. Anyway, This is what I have.
The LRESULT APIENTRY RenderDialogGL (...) isnt getting called, as I have a
Beep() in the WM_CREATE which isnt playing.
I dont know what you meant by defining a control in my dialog template. I
use VC6 and everything is done graphically.
Can I do this with CreateWindowEx()? If not, could you please tell me how to
edit the dialog template?
Thanks
Allan


BOOL CALLBACK ChooseColour (HWND hDlg, UINT message, WPARAM wParam, LPARAM
lParam)
{
static HDC hdc, hdcGL;
static PAINTSTRUCT ps;
static HWND hwndGL;
static HGLRC hrcGL;
unsigned SelectedColour;
HBRUSH CurrentBrush, OldBrush;
unsigned Red, Green, Blue;
RECT rect;
static done = false;
WNDCLASSEX wc;

switch (message)
{
case WM_INITDIALOG :
if (done) // move the dialog to the last position the user specified
MoveWindow(hDlg,
gDialogPosition.left,
gDialogPosition.top,
gDialogPosition.right - gDialogPosition.left,
gDialogPosition.bottom - gDialogPosition.top,
TRUE);
else
done = true;

ghDlg = hDlg;

SetDlgItemText(hDlg, IDC_TEXT, gTextToDisplay);

// set ranges
SendMessage(GetDlgItem(hDlg, IDC_RED), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 255));
SendMessage(GetDlgItem(hDlg, IDC_GREEN), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 255));
SendMessage(GetDlgItem(hDlg, IDC_BLUE), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 255));
SendMessage(GetDlgItem(hDlg, IDC_RED), TBM_SETPOS, (WPARAM)TRUE,
(LPARAM)127);
SendMessage(GetDlgItem(hDlg, IDC_GREEN), TBM_SETPOS, (WPARAM)TRUE,
(LPARAM)127);
SendMessage(GetDlgItem(hDlg, IDC_BLUE), TBM_SETPOS, (WPARAM)TRUE,
(LPARAM)127);

SendMessage(GetDlgItem(hDlg, IDC_DIFFUSE), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 100));
SendMessage(GetDlgItem(hDlg, IDC_SPECULAR), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 100));
SendMessage(GetDlgItem(hDlg, IDC_TRANSPARENCY), TBM_SETRANGE,
(WPARAM)TRUE, MAKELONG(0, 100));
SendMessage(GetDlgItem(hDlg, IDC_SHININESS), TBM_SETRANGE, (WPARAM)TRUE,
MAKELONG(0, 100));

// set ticks
SendMessage(GetDlgItem(hDlg, IDC_RED), TBM_SETTICFREQ , (WPARAM)32, 0);
SendMessage(GetDlgItem(hDlg, IDC_GREEN), TBM_SETTICFREQ , (WPARAM)32, 0);
SendMessage(GetDlgItem(hDlg, IDC_BLUE), TBM_SETTICFREQ , (WPARAM)32, 0);

SendMessage(GetDlgItem(hDlg, IDC_DIFFUSE), TBM_SETTICFREQ , (WPARAM)10,
0);
SendMessage(GetDlgItem(hDlg, IDC_SPECULAR), TBM_SETTICFREQ , (WPARAM)10,
0);
SendMessage(GetDlgItem(hDlg, IDC_TRANSPARENCY), TBM_SETTICFREQ ,
(WPARAM)10, 0);
SendMessage(GetDlgItem(hDlg, IDC_SHININESS), TBM_SETTICFREQ , (WPARAM)10,
0);

SetWindowText(hDlg, gTextToDisplay);

wc.cbSize = sizeof (wc);
wc.lpszClassName = "WndClass_OglView";
wc.lpfnWndProc = RenderDialogGL;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.lpszMenuName = NULL;
wc.hInstance = ghInstance;

if (!RegisterClassEx(&wc)) // Register class named "WndClass_OglView"
Beep(1000, 100);

return TRUE;

case WM_PAINT:
return TRUE;

case WM_VSCROLL :
GetClientRect(hDlg, &rect);
InvalidateRect(hDlg, &rect, FALSE);
return TRUE;

case WM_COMMAND :
switch (LOWORD (wParam))
{
case ID_CCOK:
GetWindowRect(hDlg, &gDialogPosition);

gMaterial.colour[0] = (float)(255 - SendMessage(GetDlgItem(hDlg,
IDC_RED), TBM_GETPOS, 0, 0))/255;
gMaterial.colour[1] = (float)(255 - SendMessage(GetDlgItem(hDlg,
IDC_GREEN),TBM_GETPOS, 0, 0))/255;
gMaterial.colour[2] = (float)(255 - SendMessage(GetDlgItem(hDlg,
IDC_BLUE), TBM_GETPOS, 0, 0))/255;
gMaterial.colour[3] = 1.0f;

gMaterial.diffuse[0] = (float)(SendMessage(GetDlgItem(hDlg, IDC_DIFFUSE),
TBM_GETPOS, 0, 0))/100;
gMaterial.diffuse[1] = (float)(SendMessage(GetDlgItem(hDlg, IDC_DIFFUSE),
TBM_GETPOS, 0, 0))/100;
gMaterial.diffuse[2] = (float)(SendMessage(GetDlgItem(hDlg, IDC_DIFFUSE),
TBM_GETPOS, 0, 0))/100;
gMaterial.diffuse[3] = 1.0f;

gMaterial.specularity[0] = (float)(SendMessage(GetDlgItem(hDlg,
IDC_SPECULAR), TBM_GETPOS, 0, 0))/100;
gMaterial.specularity[1] = (float)(SendMessage(GetDlgItem(hDlg,
IDC_SPECULAR), TBM_GETPOS, 0, 0))/100;
gMaterial.specularity[2] = (float)(SendMessage(GetDlgItem(hDlg,
IDC_SPECULAR), TBM_GETPOS, 0, 0))/100;
gMaterial.specularity[3] = 1.0f;

gMaterial.shininess = (float)(SendMessage(GetDlgItem(hDlg,
IDC_SHININESS), TBM_GETPOS, 0, 0))/100;

gMaterial.transparency = (float)(SendMessage(GetDlgItem(hDlg,
IDC_TRANSPARENCY), TBM_GETPOS, 0, 0))/100;

GetDlgItemText(hDlg, IDC_TEXNAME, gMaterial.texture, 64);
if (gMaterial.texture[0] == '\0')
strcpy(gMaterial.texture, "NULL");

else if ((toupper(gMaterial.texture[strlen(gMaterial.texture-1)]) != 'P')
||
(toupper(gMaterial.texture[strlen(gMaterial.texture-2)]) != 'M') ||
(toupper(gMaterial.texture[strlen(gMaterial.texture-3)]) != 'B') ||
(gMaterial.texture[strlen(gMaterial.texture-1)] != '.'))
strcat(gMaterial.texture, ".bmp"); // if user didnt specify .bmp then
add it

EndDialog(hDlg, 0);
break;

case ID_EXIT:
gUserQuits = true;
EndDialog(hDlg, 0);
wglMakeCurrent(hDC, hRC); // select main window for rendering
wglDeleteContext(hrcGL); // delete dialog GL window
return FALSE;
}
return TRUE;
}

return FALSE ;
}

LRESULT APIENTRY RenderDialogGL (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HWND hwndGL;
HDC hdcGL;
HGLRC hrcGL;

int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this structure
1, // Version of this structure
PFD_DRAW_TO_WINDOW | // draw to window (not bitmap)
PFD_SUPPORT_OPENGL | // support OpenGL calls
PFD_DOUBLEBUFFER, // Double-buffered mode
PFD_TYPE_RGBA, // RGBA colour mode
24, // Use 24-bit colour
0,0,0,0,0,0, // not used to select mode
0,0, // not used to select mode
0,0,0,0,0, // not used to select mode
32, // size of depth buffer
0, // not used to select mode
0, // not used to select mode
PFD_MAIN_PLANE, // draw in main plane
0, // not used to select mode
0,0,0 }; // not used to select mode

switch (message)
{
case WM_CREATE:
Beep(1000, 1000);
hwndGL = CreateWindowEx(WS_EX_CLIENTEDGE ,
"WndClass_OglView" , (LPSTR) NULL, WS_VISIBLE | WS_CHILD,
165, 75, 50, 50, ghDlg, (HMENU) 0, ghInstance, NULL);
hdcGL = GetDC(hwndGL);

// choose pixel format that best matches that described in PFD
nPixelFormat = ChoosePixelFormat(hdcGL, &pfd);

// set the pixel format for the device context
SetPixelFormat(hdcGL, nPixelFormat, &pfd);

hrcGL=wglCreateContext(hdcGL);
wglMakeCurrent(hdcGL, hrcGL);

core.ChangeViewSize(50, 50);
core.SetupRC();
break;

case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
auxSolidSphere(2.0f);
EndPaint(hwnd, &ps);
break;

default :
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}
Jakob Bieling
2003-07-20 12:16:12 UTC
Permalink
My current dialog box looks like
http://www.allanmb.f2s.com/images/dialog.GIF
But when the user changes the specular/diffuse etc. no change is made on a
flat rectangle.
Are invalidating the rectangle (with InvalidateRect) when the user
changes the slider positions? You need to tell Windows to redraw your
rectangle, otherwise the color of the rectangle will not change.

Btw, I think using OpenGL for that purpose is overkill. If you want to
show a sphere that changes color you simply create a gray-scale picture of a
sphere in your favorite graphics program and then use BitBlt with MERGECOPY
(and a brush with the wanted color) to draw the colored sphere. See the MSDN
for details. Also, I am not 100% sure if MERGECOPY is the right method, but
given the description ("Merges the colors of the source rectangle with the
brush currently selected in hdcDest, by using the Boolean AND operator.") it
seems to be correct.

hth
--
jb

(replace y with x if you want to reply by e-mail)
Allan Bruce
2003-07-20 14:46:49 UTC
Permalink
Post by Jakob Bieling
My current dialog box looks like
http://www.allanmb.f2s.com/images/dialog.GIF
But when the user changes the specular/diffuse etc. no change is made on a
flat rectangle.
Are invalidating the rectangle (with InvalidateRect) when the user
changes the slider positions? You need to tell Windows to redraw your
rectangle, otherwise the color of the rectangle will not change.
Btw, I think using OpenGL for that purpose is overkill. If you want to
show a sphere that changes color you simply create a gray-scale picture of a
sphere in your favorite graphics program and then use BitBlt with MERGECOPY
(and a brush with the wanted color) to draw the colored sphere. See the MSDN
for details. Also, I am not 100% sure if MERGECOPY is the right method, but
given the description ("Merges the colors of the source rectangle with the
brush currently selected in hdcDest, by using the Boolean AND operator.") it
seems to be correct.
hth
--
jb
(replace y with x if you want to reply by e-mail)
The REctangle is changing fine. The reason I want to use OpenGL is to see
the difference the lights make. It is quite easy to think of common
materials diffuse/specular properties, but it's nice to see them rendered
just to make sure - especially if the material is not a common one.
Allan
Jakob Bieling
2003-07-20 14:57:23 UTC
Permalink
Post by Jakob Bieling
Post by Jakob Bieling
My current dialog box looks like
http://www.allanmb.f2s.com/images/dialog.GIF
But when the user changes the specular/diffuse etc. no change is made
on
Post by Jakob Bieling
a
Post by Jakob Bieling
flat rectangle.
Are invalidating the rectangle (with InvalidateRect) when the user
changes the slider positions? You need to tell Windows to redraw your
rectangle, otherwise the color of the rectangle will not change.
Btw, I think using OpenGL for that purpose is overkill. If you want to
show a sphere that changes color you simply create a gray-scale picture
of
Post by Jakob Bieling
a
Post by Jakob Bieling
sphere in your favorite graphics program and then use BitBlt with
MERGECOPY
Post by Jakob Bieling
(and a brush with the wanted color) to draw the colored sphere. See the
MSDN
Post by Jakob Bieling
for details. Also, I am not 100% sure if MERGECOPY is the right method,
but
Post by Jakob Bieling
given the description ("Merges the colors of the source rectangle with the
brush currently selected in hdcDest, by using the Boolean AND
operator.")
Post by Jakob Bieling
it
Post by Jakob Bieling
seems to be correct.
hth
--
jb
(replace y with x if you want to reply by e-mail)
The REctangle is changing fine. The reason I want to use OpenGL is to see
the difference the lights make. It is quite easy to think of common
materials diffuse/specular properties, but it's nice to see them rendered
just to make sure - especially if the material is not a common one.
Oh ok, then I have misunderstood your statement. In that case you cannot
use BitBlt, of course.

regards
--
jb

(replace y with x if you want to reply by e-mail)

Loading...