PDA

View Full Version : OpenGL with MDI without MFC



KurtCob
08-05-2000, 02:52 PM
Hello people http://www.opengl.org/discussion_boards/ubb/smile.gif,

I,m trying to use MDI without using MFC, does anyone know a way to do this ?

It is taking me alot of time, so, if some one, can help me, I would be Really happy.

Thanks for any suggestions/solutions

Best regards

Kurt

NewROmancer
08-06-2000, 08:30 PM
What do you understand with without MFC? You want to say that you wanna program without CWnd aso? It's hard as hell.
Be more specific: you want some code or you want some general advices about what you have to do?
I have somewhere some code about how to register a window only with SDK but I have to search for it.

NewROmancer

Relic
08-06-2000, 10:43 PM
Hi,

sorry, for the long post, but I don't have a web page. http://www.opengl.org/discussion_boards/ubb/frown.gif

This is a code snippet from a generic MDI application I wrote as a starting point for MDI applications. No MFC at all!
It shows the basic steps to register the two new window classes and opens the three window types (frame, client, child) necessary for MDI applications.
The main trick is that the MDICLIENT is a system wide window class which is already present.
You'll have to add some resources to the project.

This code is free.
Have fun.




// MDIMain.c
// MDI Main Frame Implementation

// ##### INCLUDES
#include <windows.h>
#include <commctrl.h>
// with OpenGL in mind http://www.opengl.org/discussion_boards/ubb/smile.gif
// #include <gl\gl.h>
// #include <gl\glu.h>
// Standard resource defines like ID_FILE_NEW
#include <afxres.h>
#include "MDIChild.h"
// Own resource defines
#include "resource.h"

// ##### DEFINES

// ##### TYPEDEFS

// ##### VARIABLES

// Windows
HINSTANCE hInstanceMain;
HACCEL hAccel;
HWND hwndMDIMainFrame = NULL;
HWND hwndMDIClient = NULL;
// MDI main frame window class
char szMDIMainFrameWindowClassName[] = "MDIMainFrameWindowClass";
char szMDIMainFrameWindowName[] = "MDI MainFrame";

// The client window class is defined system wide.
// Don't implement client behaviour here!

// MDI child window class
char szMDIChildWindowClassName[] = "MDIChildWindowClass";
char szMDIChildWindowName[] = "MDI Child";

// ##### PROTOTYPES
BOOL InitApplication(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK MDIMainFrameWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

// ##### FUNCTIONS
int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!hPrevInstance)
{
// Other instances of app running?
if (!InitApplication(hInstance))
{
// Initialize shared things
return FALSE; // Exits if unable to initialize
}
}
// Perform initializations that apply to a specific instance.
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
// Acquire and dispatch messages until a WM_QUIT message is received.
while (GetMessage(&amp;msg, // message structure
NULL, // handle of window receiving the message
0, // lowest message to examine
0)) // highest message to examine
{
if (!TranslateAccelerator(msg.hwnd, hAccel, &amp;msg))
{
TranslateMessage(&amp;msg); // Translates virtual key codes
DispatchMessage(&amp;msg); // Dispatches message to window
}
}
return (msg.wParam); // Returns the value from PostQuitMessage
}


BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
// MDI main frame window class (one per application)
wc.style = 0; // not needed for frame: CS_HREDRAW | CS_VREDRAW; // Class style(s).
wc.lpfnWndProc = (WNDPROC) MDIMainFrameWndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); // Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Cursor
wc.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1); // Default color
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); // Menu name
wc.lpszClassName = szMDIMainFrameWindowClassName; // Name to register as
// Register the window class
if (RegisterClass(&amp;wc) == 0)
{
// failure to register the MDIMainFrameWindowClass
return FALSE;
}
// Don't declare the MDIClient window class as it is already defined in the system!
// MDI child window class (multiple per MDI client frame window)
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // Class style(s).
wc.lpfnWndProc = (WNDPROC) MDIChildWndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)); // Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Cursor
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Default color
wc.lpszMenuName = NULL; // Menu name
wc.lpszClassName = szMDIChildWindowClassName; // Name to register as
// Register the window class
if (RegisterClass(&amp;wc) == 0)
{
// failure to register the MDIChild
return FALSE;
}
return TRUE;
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
CLIENTCREATESTRUCT ccs;
RECT rect;
int nWidth;
int nHeight;

// Save the instance handle in static variable, which will be used in
// many subsequence calls from this application to Windows.
hInstanceMain = hInstance; // Store instance handle in our global variable

// Ensure that the common control dynamic-link library (DLL) is loaded
// if special crontrol resources are used.
// InitCommonControls();

// Create a main window for this application instance.
hwndMDIMainFrame = CreateWindow(szMDIMainFrameWindowClassName, // pointer to registered class name
szMDIMainFrameWindowName, // pointer to window name
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // window style
0, // horizontal position of window
0, // vertical position of window
640, // window width
480, // window height
NULL, // handle to parent or owner window
// overlapped windows have no parent
NULL, // handle to menu or child-window identifier
// use the window class menu
hInstanceMain, // handle to application instance
NULL); // pointer to window-creation data
// If window could not be created, return "failure"
if (!hwndMDIMainFrame)
{
return (FALSE);
}
// Make the window visible
ShowWindow(hwndMDIMainFrame, nCmdShow); // Show the window
UpdateWindow(hwndMDIMainFrame); // Sends WM_PAINT message

GetClientRect(hwndMDIMainFrame, &amp;rect);
nWidth = rect.right - rect.left;
nHeight = rect.bottom - rect.top;

ccs.hWindowMenu = GetSubMenu(GetMenu(hwndMDIMainFrame), 1); // TODO: change the ID of the "Window" menu
ccs.idFirstChild = ID_WINDOW_CLIENT;
// Create the MDIClient window. This name is defined system wide!
hwndMDIClient = CreateWindow("MDICLIENT", // pointer to registered class name
NULL, // pointer to window name
WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, // window style
0, // horizontal position of window
0, // vertical position of window
nWidth, // window width
nHeight, // window height
hwndMDIMainFrame, // handle to parent or owner window
NULL, // handle to menu or child-window identifier
// use the window class menu
hInstanceMain, // handle to application instance
&amp;ccs); // pointer to window-creation data

// If window could not be created, return "failure"
if (!hwndMDIClient)
{
return (FALSE);
}
ShowWindow(hwndMDIClient, SW_SHOW); // Show the window
// UpdateWindow(hwndMDIClient); // Sends WM_PAINT message
return (TRUE);
}


LRESULT CALLBACK MDIMainFrameWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
MDICREATESTRUCT mdic;

switch (uMessage)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_FILE_NEW:
mdic.szClass = szMDIChildWindowClassName;
mdic.szTitle = szMDIChildWindowName;
mdic.hOwner = hInstanceMain;
mdic.x = CW_USEDEFAULT;
mdic.y = CW_USEDEFAULT;
mdic.cx = CW_USEDEFAULT;
mdic.cy = CW_USEDEFAULT;
mdic.style = 0;
mdic.lParam = 0L;
SendMessage(hwndMDIClient, WM_MDICREATE, 0, (LONG) &amp;mdic);
return 0;

case IDCANCEL: // Quick exit for faster turnaround while implementing.
case ID_FILE_EXIT:
SendMessage(hwnd, WM_DESTROY, 0, 0L);
return 0;

case ID_WINDOW_CASCADE:
SendMessage(hwndMDIClient, WM_MDICASCADE, 0, 0L);
return 0;

case ID_WINDOW_TILE_VERT:
SendMessage(hwndMDIClient, WM_MDITILE, 0, 0L);
return 0;

case ID_WINDOW_ARRANGE:
SendMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
return 0;
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
}
return (DefFrameProc(hwnd, hwndMDIClient, uMessage, wParam, lParam));
}


// MDIChild.h
// MDI Child Implementation Header File
#ifndef _MDICHILD_H
#define _MDICHILD_H
LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
#endif


// MDICild.c
// MDI Child Window Procedure
#include <windows.h>
#include "MDIChild.h"
LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
return (DefMDIChildProc(hwnd, uMessage, wParam, lParam));
}



[This message has been edited by Relic (edited 08-07-2000).]

KurtCob
08-08-2000, 12:19 PM
Its not exactly what I want.

The dificult that Im finding is to know a way to have a device context for each MDI child, exactly the same as a MDI Aplicattion using MFC, but I want to use Windows SDK.

Can someone give me some help ?

Thanks

Kurt

Relic
08-08-2000, 10:37 PM
The hints are all in the code and comments.

Look at the WNDCLASS fields for the MDIChild above.
There is a member called cbWndExtra which is currently set to zero, and the comment tells you "no per window data".
This can be used to link any data to each of the child windows.

From the MS Help:
"cbWndExtra
Specifies the number of extra bytes to allocate following the window instance."

Normally I define a struct which contains all stuff I need per child window, allocate it at WM_CREATE of the child and plug the pointer to that structure with SetWindowLong (or SetWindowsLongPtr now) into the cbWndExtra bytes I reserved to contain one pointer.
The data can be read from extra space with the GetWindowLong (or GetWindowLongPtr.)

You could also use the Set/GetWindowLong with GWL_USERDATA to store a 32 bit value.

Each window message you handle in the MDIChildWndProc which needs data from the struct (OpenGL render contexts, anyone?) calls a GetWindowLong and has the pointer to the window's structure available.

Don't forget the free the struct at WM_DESTROY.

This is the function which has to be filled with per-child message handling. Put all the stuff from you SDI WndProc in here and you're almost done.



LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam){ return (DefMDIChildProc(hwnd, uMessage, wParam, lParam));}



I feel it is essential to know what MS Windows programming really means. MFC has a very steep leaning curve without that knowledge.

[This message has been edited by Relic (edited 08-09-2000).]