19-08-2015, 08:33 PM
Tutorial 14: Win32 Window
Questo esempio gira solo su MS Windiws e dimostra come Irrlicht può produrre rendering dentro una finestra win32 originale. E' possibile anche farlo su finestre create con le librerie MFC e con le finestre Windows.Forms della libreria .NET.
All'inizio creiamo una finestra di Windows usando le API. Non spiegherò in dettaglio come funziona questo codice. Per maggiori approfondimenti si rimanda al sito MSDN o a testi specifici sulla programmazione di Windows.
Ora chiediamo quale driver usare e creiamo una istanza della finestra Windows definita prima.
Adesso che abbiamo la finestra aperta possiamo crearci dentro il nostro device Irrlicht. Per farlo usiamo la funzione di Irrlicht createEx(). Ci servono l'handle (HWND) a quella finestra, impostarla come parametro di windowsID e poi lanciare l'engine come al solito. Questo è tutto.
L'ultima cosa che manca è il loop del disegno tramite IrrlichtDevice::run(). Lo facciamo come di solito abbiamo fatto. Ma potremmo anche fare in un altro modo: semplicemente utilizzare un nostro loop di messaggi windows tramite GetMessage, DispatchMessage. Poiché richiamare Device->run() causa l'invio dei messaggi internamente a Irrlicht, non vi serve più richiamarlo. Considerate però che se vorrete farvi da soli il vostro loop per la messaggistica Windows, Irrlicht non potrà più gestire nemmeno gli input utente che dovrete quindi gestire da soli usando la messaggistica di Window, oppure con le DirectInput, o una qualsiasi altra soluzione alternativa.
In alternativa un proprio sistema di messaggistica interno senza l'uso della Device->run() potrebbe assomigliare a qualcosa del genere:
Ed è tutto, ora Irrlicht gira dentro la vostra finestra Windows.
Versione pdf scaricabile da QUI
Questo esempio gira solo su MS Windiws e dimostra come Irrlicht può produrre rendering dentro una finestra win32 originale. E' possibile anche farlo su finestre create con le librerie MFC e con le finestre Windows.Forms della libreria .NET.
All'inizio creiamo una finestra di Windows usando le API. Non spiegherò in dettaglio come funziona questo codice. Per maggiori approfondimenti si rimanda al sito MSDN o a testi specifici sulla programmazione di Windows.
Codice PHP:
#include <irrlicht.h>
#ifndef _IRR_WINDOWS_
#error Windows only example
#else
#include <windows.h> // this example only runs with windows
#include <iostream>
#include "driverChoice.h"
using namespace irr;
#pragma comment(lib, "irrlicht.lib")
HWND hOKButton;
HWND hWnd;
static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
HWND hwndCtl = (HWND)lParam;
int code = HIWORD(wParam);
if (hwndCtl == hOKButton)
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Codice PHP:
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
printf("Select the render window (some dead window may exist too):\n"\
" (a) Window with button (via CreationParam)\n"\
" (b) Window with button (via beginScene)\n"\
" (c) Own Irrlicht window (default behavior)\n"\
" (otherKey) exit\n\n");
char key;
std::cin >> key;
if (key != 'a' && key != 'b' && key != 'c')
return 1;
HINSTANCE hInstance = 0;
// create dialog
const char* Win32ClassName = "CIrrlichtWindowsTestDialog";
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)CustomWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = DLGWINDOWEXTRA;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = Win32ClassName;
wcex.hIconSm = 0;
RegisterClassEx(&wcex);
DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;
int windowWidth = 440;
int windowHeight = 380;
hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example",
style, 100, 100, windowWidth, windowHeight,
NULL, NULL, hInstance, NULL);
RECT clientRect;
GetClientRect(hWnd, &clientRect);
windowWidth = clientRect.right;
windowHeight = clientRect.bottom;
// create ok button
hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT,
windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);
// create some text
CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\
"Also mixing with MFC and .NET Windows.Forms is possible.",
WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);
// create window to put irrlicht in
HWND hIrrlichtWindow = CreateWindow("BUTTON", "",
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
50, 80, 320, 220, hWnd, NULL, hInstance, NULL);
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);
Codice PHP:
// create irrlicht device in the button window
irr::SIrrlichtCreationParameters param;
param.DriverType = driverType;
if (key=='a')
param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow);
irr::IrrlichtDevice* device = irr::createDeviceEx(param);
if (!device)
return 1;
// setup a simple 3d scene
irr::scene::ISceneManager* smgr = device->getSceneManager();
video::IVideoDriver* driver = device->getVideoDriver();
if (driverType==video::EDT_OPENGL)
{
HDC HDc=GetDC(hIrrlichtWindow);
PIXELFORMATDESCRIPTOR pfd={0};
pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
int pf = GetPixelFormat(HDc);
DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.cDepthBits=16;
pf = ChoosePixelFormat(HDc, &pfd);
SetPixelFormat(HDc, pf, &pfd);
videodata.OpenGLWin32.HDc = HDc;
videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
}
scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0));
scene::ISceneNodeAnimator* anim =
smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam->addAnimator(anim);
anim->drop();
scene::ISceneNode* cube = smgr->addCubeSceneNode(20);
cube->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
cube->setMaterialTexture(1, driver->getTexture("../../media/water.jpg"));
cube->setMaterialFlag( video::EMF_LIGHTING, false );
cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );
smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));
// show and execute dialog
ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd);
// do message queue
Codice PHP:
while (device->run())
{
driver->beginScene(true, true, 0, videodata);
smgr->drawAll();
driver->endScene();
}
Codice PHP:
MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT) break;
}
advance virtual time device->getTimer()->tick();
draw engine picture driver->beginScene(true, true, 0, (key=='c')? hIrrlichtWindow:0);
smgr->drawAll();
driver->endScene(); }
device->closeDevice();
device->drop();
return 0;
}
#endif // if windows
Versione pdf scaricabile da QUI