main.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /** Example 014 Win32 Window
  2. This example runs only under MS Windows and demonstrates how Irrlicht can
  3. render inside a win32 window. MFC and .NET Windows.Forms windows are possible,
  4. too.*/
  5. #include <irrlicht.h>
  6. #ifndef _IRR_WINDOWS_
  7. #error Windows only example
  8. #else
  9. #include <windows.h> // this example only runs with Windows
  10. #include <iostream>
  11. #include "driverChoice.h"
  12. #include "exampleHelper.h"
  13. using namespace irr;
  14. #ifdef _MSC_VER
  15. #pragma comment(lib, "irrlicht.lib")
  16. #endif
  17. HWND hOKButton = 0;
  18. /*
  19. Windows message handler
  20. */
  21. static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
  22. WPARAM wParam, LPARAM lParam)
  23. {
  24. switch (message)
  25. {
  26. case WM_COMMAND:
  27. {
  28. HWND hwndCtl = (HWND)lParam;
  29. int code = HIWORD(wParam);
  30. if (hwndCtl == hOKButton)
  31. {
  32. DestroyWindow(hWnd);
  33. PostQuitMessage(0);
  34. return 0;
  35. }
  36. }
  37. break;
  38. case WM_DESTROY:
  39. PostQuitMessage(0);
  40. return 0;
  41. }
  42. return DefWindowProc(hWnd, message, wParam, lParam);
  43. }
  44. int main()
  45. {
  46. /*
  47. Ask user for driver
  48. */
  49. video::E_DRIVER_TYPE driverType=driverChoiceConsole();
  50. if (driverType==video::EDT_COUNT)
  51. return 1;
  52. printf("Select the render window (some dead window may exist too):\n"\
  53. " (a) Window with button (via CreationParam)\n"\
  54. " (b) Window with button (via beginScene)\n"\
  55. " (c) Own Irrlicht window (default behavior)\n"\
  56. " (otherKey) exit\n\n");
  57. char key;
  58. std::cin >> key;
  59. if (key != 'a' && key != 'b' && key != 'c')
  60. return 1;
  61. /*
  62. Create the Windows specific window using the Windows API.
  63. Not further explained here, please see the MSDN or a Windows book
  64. for details about doing that.
  65. */
  66. HINSTANCE hInstance = 0;
  67. const fschar_t* Win32ClassName = __TEXT("CIrrlichtWindowsTestDialog");
  68. WNDCLASSEX wcex;
  69. wcex.cbSize = sizeof(WNDCLASSEX);
  70. wcex.style = CS_HREDRAW | CS_VREDRAW;
  71. wcex.lpfnWndProc = (WNDPROC)CustomWndProc;
  72. wcex.cbClsExtra = 0;
  73. wcex.cbWndExtra = DLGWINDOWEXTRA;
  74. wcex.hInstance = hInstance;
  75. wcex.hIcon = NULL;
  76. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  77. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
  78. wcex.lpszMenuName = 0;
  79. wcex.lpszClassName = Win32ClassName;
  80. wcex.hIconSm = 0;
  81. RegisterClassEx(&wcex);
  82. DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
  83. WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;
  84. int windowWidth = 440;
  85. int windowHeight = 380;
  86. HWND hWnd = CreateWindow( Win32ClassName, __TEXT("Irrlicht Win32 window example"),
  87. style, 100, 100, windowWidth, windowHeight,
  88. NULL, NULL, hInstance, NULL);
  89. RECT clientRect;
  90. GetClientRect(hWnd, &clientRect);
  91. windowWidth = clientRect.right;
  92. windowHeight = clientRect.bottom;
  93. // Create OK button
  94. hOKButton = CreateWindow(__TEXT("BUTTON"), __TEXT("OK - Close"), WS_CHILD | WS_VISIBLE | BS_TEXT,
  95. windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);
  96. // Create some text
  97. CreateWindow(__TEXT("STATIC"), __TEXT("This is Irrlicht running inside a standard Win32 window.\n")\
  98. __TEXT("Also mixing with MFC and .NET Windows.Forms is possible."),
  99. WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);
  100. // Create a window to put Irrlicht in
  101. HWND hIrrlichtWindow = CreateWindow(__TEXT("BUTTON"), __TEXT(""),
  102. WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
  103. 50, 80, 320, 220, hWnd, NULL, hInstance, NULL);
  104. /*
  105. So now that we have some Windows window, we can use it with Irrlicht.
  106. There's several options.
  107. */
  108. irr::SIrrlichtCreationParameters param;
  109. param.DriverType = driverType;
  110. /* First option: We create an Irrlicht device inside of the Windows window.
  111. We use Irrlicht createEx() function for this. We do need the
  112. handle (HWND) for that window, set it as windowsID parameter
  113. and start up the engine as usual. That's it.
  114. */
  115. if (key=='a')
  116. param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow);
  117. irr::IrrlichtDevice* device = irr::createDeviceEx(param);
  118. irr::scene::ISceneManager* smgr = device->getSceneManager();
  119. video::IVideoDriver* driver = device->getVideoDriver();
  120. /*
  121. Second option: We create a typical Irrlicht device, but render to the Window window.
  122. For rendering into another Window than the one used for creating the Irrlicht device
  123. we have to pass some changed SExposedVideoData to beginScene which contains the
  124. HWND of the Windows window.
  125. */
  126. video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);
  127. /*
  128. OpenGL needs a bit more setup.
  129. Also not yet working as well (haven't figured out yet how to render into the Irrlicht window as well)
  130. */
  131. if (key == 'b' && driverType==video::EDT_OPENGL)
  132. {
  133. HDC HDc=GetDC(hIrrlichtWindow);
  134. PIXELFORMATDESCRIPTOR pfd={0};
  135. pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
  136. int pf = GetPixelFormat(HDc);
  137. DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  138. pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
  139. pfd.cDepthBits=16;
  140. pf = ChoosePixelFormat(HDc, &pfd);
  141. SetPixelFormat(HDc, pf, &pfd);
  142. videodata.OpenGLWin32.HDc = HDc;
  143. videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
  144. wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
  145. }
  146. /*
  147. Setup a simple 3d scene
  148. */
  149. scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
  150. cam->setTarget(core::vector3df(0,0,0));
  151. scene::ISceneNodeAnimator* anim =
  152. smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
  153. cam->addAnimator(anim);
  154. anim->drop();
  155. scene::ISceneNode* cube = smgr->addCubeSceneNode(20);
  156. const io::path mediaPath = getExampleMediaPath();
  157. cube->setMaterialTexture(0, driver->getTexture(mediaPath + "wall.bmp"));
  158. cube->setMaterialTexture(1, driver->getTexture(mediaPath + "water.jpg"));
  159. cube->setMaterialFlag( video::EMF_LIGHTING, false );
  160. cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );
  161. smgr->addSkyBoxSceneNode(
  162. driver->getTexture(mediaPath + "irrlicht2_up.jpg"),
  163. driver->getTexture(mediaPath + "irrlicht2_dn.jpg"),
  164. driver->getTexture(mediaPath + "irrlicht2_lf.jpg"),
  165. driver->getTexture(mediaPath + "irrlicht2_rt.jpg"),
  166. driver->getTexture(mediaPath + "irrlicht2_ft.jpg"),
  167. driver->getTexture(mediaPath + "irrlicht2_bk.jpg"));
  168. // This shows that we can render to multiple windows within one application
  169. // TODO: Currently not working with OpenGL
  170. device->getGUIEnvironment()->addStaticText(core::stringw("Second screen render").c_str(),core::recti(0,0,200,200));
  171. // show and execute the Windows dialog
  172. ShowWindow(hWnd , SW_SHOW);
  173. UpdateWindow(hWnd);
  174. // do message queue
  175. #if 1 // Irrlicht does the message handling with device->run()
  176. /*
  177. Now the only thing missing is the drawing loop using
  178. IrrlichtDevice::run(). We do this as usual. But instead of this, there
  179. is another possibility: You can also use your own message loop
  180. using GetMessage, DispatchMessage and whatever. Calling
  181. device->run() will cause Irrlicht to dispatch messages internally too.
  182. You need not call device->run() if you want to do your own message
  183. dispatching loop, but Irrlicht will not be able to fetch user input
  184. then and you have to do it on your own using the window messages,
  185. DirectInput, or whatever.
  186. */
  187. while (device->run())
  188. {
  189. // draw 3d scene
  190. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0), 1.f, 0, videodata);
  191. smgr->drawAll();
  192. driver->endScene();
  193. // draw gui into second window
  194. if (key=='b')
  195. {
  196. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb));
  197. device->getGUIEnvironment()->drawAll();
  198. driver->endScene();
  199. }
  200. }
  201. #else // Windows API does the message handling
  202. /*
  203. The alternative, own message dispatching loop without Device->run()
  204. would look like this:
  205. */
  206. MSG msg;
  207. while (true)
  208. {
  209. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  210. {
  211. TranslateMessage(&msg);
  212. DispatchMessage(&msg);
  213. if (msg.message == WM_QUIT)
  214. break;
  215. }
  216. // advance virtual time
  217. device->getTimer()->tick();
  218. // draw 3d scene
  219. driver->beginScene(true, true, 0, videodata);
  220. smgr->drawAll();
  221. driver->endScene();
  222. // draw gui into second window
  223. if (key=='b')
  224. {
  225. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb));
  226. device->getGUIEnvironment()->drawAll();
  227. driver->endScene();
  228. }
  229. }
  230. #endif
  231. device->closeDevice();
  232. device->drop();
  233. return 0;
  234. }
  235. #endif // if windows
  236. /*
  237. That's it, Irrlicht now uses a Windows window.
  238. **/