Tech Support > Microsoft Windows > Development Resources > Creating an opengl viewport in a dialog box
Creating an opengl viewport in a dialog box
Posted by Allan Bruce on July 19th, 2003


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?
Thanks
Allan


Posted by Shizuka on July 19th, 2003



"Allan Bruce" <allanmb@TAKEAWAYf2s.com> wrote in message
news:bfbsmm$b69$1@news.freedom2surf.net...

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!

rman@goodnet.com




Posted by Allan Bruce on July 19th, 2003



"Shizuka" <rman@goodnet.com> wrote in message
news:3f198aa6_2@news.binaries.net...
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



Posted by Lucian Wischik on July 19th, 2003


"Allan Bruce" <allanmb@TAKEAWAYf2s.com> wrote:
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...s.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

Posted by Shizuka on July 19th, 2003



"Allan Bruce" <allanmb@TAKEAWAYf2s.com> wrote in message
news:bfc6lo$fjf$1@news.freedom2surf.net...
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.

rman@goodnet.com





Posted by Lucian Wischik on July 20th, 2003


"Shizuka" <rman@goodnet.com> wrote:
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

Posted by Allan Bruce on July 20th, 2003



"Lucian Wischik" <lu.nn@wischik.com> wrote in message
news:s8kkhvc70ha984pk0cem47jln7v9elhem8@4ax.com...

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;
}



Posted by Jakob Bieling on July 20th, 2003


"Allan Bruce" <allanmb@TAKEAWAYf2s.com> wrote in message
news:bfbsmm$b69$1@news.freedom2surf.net...

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)



Posted by Allan Bruce on July 20th, 2003



"Jakob Bieling" <netsurf@gmy.net> wrote in message
news:bfe14m$rea$06$1@news.t-online.com...
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



Posted by Jakob Bieling on July 20th, 2003


"Allan Bruce" <allanmb@TAKEAWAYf2s.com> wrote in message
news:bfe9tr$c7e$1@news.freedom2surf.net...

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)




Similar Posts