irrlicht/examples/14.Win32Window/tutorial.html

211 lines
20 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Tutorial 14: Win32 Window</title>
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit.
Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
Feel free to improve :)
-->
<style>
body, table, div, p, dl {
font: 400 14px/22px;
}
body {
background-color: #F0F0F0;
color: black;
margin-left: 5%;
margin-right: 5%;
}
p.reference, p.definition {
font: 400 14px/22px;
}
.title {
font: 400 14px/28px;
font-size: 150%;
font-weight: bold;
margin: 10px 2px;
}
h1, h2, h3, h4, h5, h6 {
-webkit-transition: text-shadow 0.5s linear;
-moz-transition: text-shadow 0.5s linear;
-ms-transition: text-shadow 0.5s linear;
-o-transition: text-shadow 0.5s linear;
transition: text-shadow 0.5s linear;
margin-right: 15px;
}
caption {
font-weight: bold;
}
h3.version {
font-size: 90%;
text-align: center;
}
a {
color: #3D578C;
font-weight: normal;
text-decoration: none;
}
.contents a:visited {
color: #4665A2;
}
a:hover {
text-decoration: underline;
}
a.el {
font-weight: bold;
}
a.code, a.code:visited, a.line, a.line:visited {
color: #4665A2;
}
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
color: #4665A2;
}
pre.fragment {
border: 1px solid #C4CFE5;
background-color: #FBFCFD;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
overflow: auto;
word-wrap: break-word;
font-size: 9pt;
line-height: 125%;
font-family: monospace, fixed;
font-size: 105%;
}
div.fragment {
padding: 0px;
margin: 4px 8px 4px 2px;
background-color: #FBFCFD;
border: 1px solid #C4CFE5;
}
div.line {
font-family: monospace, fixed;
font-size: 13px;
min-height: 13px;
line-height: 1.0;
text-wrap: unrestricted;
white-space: -moz-pre-wrap; /* Moz */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS3 */
word-wrap: break-word; /* IE 5.5+ */
text-indent: -53px;
padding-left: 53px;
padding-bottom: 0px;
margin: 0px;
-webkit-transition-property: background-color, box-shadow;
-webkit-transition-duration: 0.5s;
-moz-transition-property: background-color, box-shadow;
-moz-transition-duration: 0.5s;
-ms-transition-property: background-color, box-shadow;
-ms-transition-duration: 0.5s;
-o-transition-property: background-color, box-shadow;
-o-transition-duration: 0.5s;
transition-property: background-color, box-shadow;
transition-duration: 0.5s;
}
div.contents {
margin-top: 10px;
margin-left: 12px;
margin-right: 8px;
}
div.center {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
padding: 0px;
}
div.center img {
border: 0px;
}
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
blockquote {
background-color: #F7F8FB;
border-left: 2px solid #9CAFD4;
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}
hr {
height: 0px;
border: none;
border-top: 1px solid #4A6AAA;
}
address {
font-style: normal;
color: #2A3D61;
}
div.header {
background-image:url('nav_h.png');
background-repeat:repeat-x;
background-color: #F9FAFC;
margin: 0px;
border-bottom: 1px solid #C4CFE5;
}
div.headertitle {
padding: 5px 5px 5px 10px;
}
.image {
text-align: center;
}
.caption {
font-weight: bold;
}
div.zoom {
border: 1px solid #90A5CE;
}
tr.heading h2 {
margin-top: 12px;
margin-bottom: 4px;
}
</style>
</head>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--END TITLEAREA-->
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">Tutorial 14: Win32 Window </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><div class="image">
<img src="../../media/example_screenshots/014shot.jpg" alt="014shot.jpg"/>
</div>
<p>This example only runs under MS Windows and demonstrates that Irrlicht can render inside a win32 window. MFC and .NET Windows.Forms windows are possible, too.</p>
<p>In the beginning, we create a windows window using the windows API. I'm not going to explain this code, because it is windows specific. See the MSDN or a windows book for details. </p><div class="fragment"><div class="line"><span class="preprocessor">#include &lt;irrlicht.h&gt;</span></div><div class="line"><span class="preprocessor">#ifndef _IRR_WINDOWS_</span></div><div class="line"><span class="preprocessor">#error Windows only example</span></div><div class="line"><span class="preprocessor">#else</span></div><div class="line"><span class="preprocessor">#include &lt;windows.h&gt;</span> <span class="comment">// this example only runs with windows</span></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &quot;driverChoice.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;exampleHelper.h&quot;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><span class="preprocessor">#pragma comment(lib, &quot;irrlicht.lib&quot;)</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line">HWND hOKButton;</div><div class="line">HWND hWnd;</div><div class="line"></div><div class="line"><span class="keyword">static</span> LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,</div><div class="line"> WPARAM wParam, LPARAM lParam)</div><div class="line">{</div><div class="line"> <span class="keywordflow">switch</span> (message)</div><div class="line"> {</div><div class="line"> <span class="keywordflow">case</span> WM_COMMAND:</div><div class="line"> {</div><div class="line"> HWND hwndCtl = (HWND)lParam;</div><div class="line"> <span class="keywordtype">int</span> code = HIWORD(wParam);</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (hwndCtl == hOKButton)</div><div class="line"> {</div><div class="line"> DestroyWindow(hWnd);</div><div class="line"> PostQuitMessage(0);</div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keywordflow">break</span>;</div><div class="line"> <span class="keywordflow">case</span> WM_DESTROY:</div><div class="line"> PostQuitMessage(0);</div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> DefWindowProc(hWnd, message, wParam, lParam);</div><div class="line">}</div></div><!-- fragment --><p> Now ask for the driver and create the Windows specific window. </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main()</div><div class="line">{</div><div class="line"> <span class="comment">// ask user for driver</span></div><div class="line"> video::E_DRIVER_TYPE driverType=driverChoiceConsole();</div><div class="line"> <span class="keywordflow">if</span> (driverType==video::EDT_COUNT)</div><div class="line"> <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line"> printf(<span class="stringliteral">&quot;Select the render window (some dead window may exist too):\n&quot;</span>\</div><div class="line"> <span class="stringliteral">&quot; (a) Window with button (via CreationParam)\n&quot;</span>\</div><div class="line"> <span class="stringliteral">&quot; (b) Window with button (via beginScene)\n&quot;</span>\</div><div class="line"> <span class="stringliteral">&quot; (c) Own Irrlicht window (default behavior)\n&quot;</span>\</div><div class="line"> <span class="stringliteral">&quot; (otherKey) exit\n\n&quot;</span>);</div><div class="line"></div><div class="line"> <span class="keywordtype">char</span> key;</div><div class="line"> std::cin &gt;&gt; key;</div><div class="line"> <span class="keywordflow">if</span> (key != <span class="charliteral">&#39;a&#39;</span> &amp;&amp; key != <span class="charliteral">&#39;b&#39;</span> &amp;&amp; key != <span class="charliteral">&#39;c&#39;</span>)</div><div class="line"> <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line"> HINSTANCE hInstance = 0;</div><div class="line"> <span class="comment">// create dialog</span></div><div class="line"></div><div class="line"> <span class="keyword">const</span> fschar_t* Win32ClassName = __TEXT(<span class="stringliteral">&quot;CIrrlichtWindowsTestDialog&quot;</span>);</div><div class="line"></div><div class="line"> WNDCLASSEX wcex;</div><div class="line"> wcex.cbSize = <span class="keyword">sizeof</span>(WNDCLASSEX);</div><div class="line"> wcex.style = CS_HREDRAW | CS_VREDRAW;</div><div class="line"> wcex.lpfnWndProc = (WNDPROC)CustomWndProc;</div><div class="line"> wcex.cbClsExtra = 0;</div><div class="line"> wcex.cbWndExtra = DLGWINDOWEXTRA;</div><div class="line"> wcex.hInstance = hInstance;</div><div class="line"> wcex.hIcon = NULL;</div><div class="line"> wcex.hCursor = LoadCursor(NULL, IDC_ARROW);</div><div class="line"> wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);</div><div class="line"> wcex.lpszMenuName = 0;</div><div class="line"> wcex.lpszClassName = Win32ClassName;</div><div class="line"> wcex.hIconSm = 0;</div><div class="line"></div><div class="line"> RegisterClassEx(&amp;wcex);</div><div class="line"></div><div class="line"> DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |</div><div class="line"> WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;</div><div class="line"></div><div class="line"> <span class="keywordtype">int</span> windowWidth = 440;</div><div class="line"> <span class="keywordtype">int</span> windowHeight = 380;</div><div class="line"></div><div class="line"> hWnd = CreateWindow( Win32ClassName, __TEXT(<span class="stringliteral">&quot;Irrlicht Win32 window example&quot;</span>),</div><div class="line"> style, 100, 100, windowWidth, windowHeight,</div><div class="line"> NULL, NULL, hInstance, NULL);</div><div class="line"></div><div class="line"> RECT clientRect;</div><div class="line"> GetClientRect(hWnd, &amp;clientRect);</div><div class="line"> windowWidth = clientRect.right;</div><div class="line"> windowHeight = clientRect.bottom;</div><div class="line"></div><div class="line"> <span class="comment">// create ok button</span></div><div class="line"></div><div class="line"> hOKButton = CreateWindow(__TEXT(<span class="stringliteral">&quot;BUTTON&quot;</span>), __TEXT(<span class="stringliteral">&quot;OK - Close&quot;</span>), WS_CHILD | WS_VISIBLE | BS_TEXT,</div><div class="line"> windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);</div><div class="line"></div><div class="line"> <span class="comment">// create some text</span></div><div class="line"></div><div class="line"> CreateWindow(__TEXT(<span class="stringliteral">&quot;STATIC&quot;</span>), __TEXT(<span class="stringliteral">&quot;This is Irrlicht running inside a standard Win32 window.\n&quot;</span>)\</div><div class="line"> __TEXT(<span class="stringliteral">&quot;Also mixing with MFC and .NET Windows.Forms is possible.&quot;</span>),</div><div class="line"> WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);</div><div class="line"></div><div class="line"> <span class="comment">// create window to put irrlicht in</span></div><div class="line"></div><div class="line"> HWND hIrrlichtWindow = CreateWindow(__TEXT(<span class="stringliteral">&quot;BUTTON&quot;</span>), __TEXT(<span class="stringliteral">&quot;&quot;</span>),</div><div class="line"> WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,</div><div class="line"> 50, 80, 320, 220, hWnd, NULL, hInstance, NULL);</div><div class="line"> video::SExposedVideoData videodata((key==<span class="charliteral">&#39;b&#39;</span>)?hIrrlichtWindow:0);</div></div><!-- fragment --><p> So now that we have some window, we can create an Irrlicht device inside of it. We use Irrlicht createEx() function for this. We only need the handle (HWND) to that window, set it as windowsID parameter and start up the engine as usual. That's it. </p><div class="fragment"><div class="line"><span class="comment">// create irrlicht device in the button window</span></div><div class="line"></div><div class="line">irr::SIrrlichtCreationParameters param;</div><div class="line">param.DriverType = driverType;</div><div class="line"><span class="keywordflow">if</span> (key==<span class="charliteral">&#39;a&#39;</span>)</div><div class="line"> param.WindowId = <span class="keyword">reinterpret_cast&lt;</span><span class="keywordtype">void</span>*<span class="keyword">&gt;</span>(hIrrlichtWindow);</div><div class="line"></div><div class="line">irr::IrrlichtDevice* device = irr::createDeviceEx(param);</div><div class="line"></div><div class="line"><span class="comment">// setup a simple 3d scene</span></div><div class="line"></div><div class="line">irr::scene::ISceneManager* smgr = device-&gt;getSceneManager();</div><div class="line">video::IVideoDriver* driver = device-&gt;getVideoDriver();</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (driverType==video::EDT_OPENGL)</div><div class="line">{</div><div class="line"> HDC HDc=GetDC(hIrrlichtWindow);</div><div class="line"> PIXELFORMATDESCRIPTOR pfd={0};</div><div class="line"> pfd.nSize=<span class="keyword">sizeof</span>(PIXELFORMATDESCRIPTOR);</div><div class="line"> <span class="keywordtype">int</span> pf = GetPixelFormat(HDc);</div><div class="line"> DescribePixelFormat(HDc, pf, <span class="keyword">sizeof</span>(PIXELFORMATDESCRIPTOR), &amp;pfd);</div><div class="line"> pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;</div><div class="line"> pfd.cDepthBits=16;</div><div class="line"> pf = ChoosePixelFormat(HDc, &amp;pfd);</div><div class="line"> SetPixelFormat(HDc, pf, &amp;pfd);</div><div class="line"> videodata.OpenGLWin32.HDc = HDc;</div><div class="line"> videodata.OpenGLWin32.HRc=wglCreateContext(HDc);</div><div class="line"> wglShareLists((HGLRC)driver-&gt;getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);</div><div class="line">}</div><div class="line">scene::ICameraSceneNode* cam = smgr-&gt;addCameraSceneNode();</div><div class="line">cam-&gt;setTarget(core::vector3df(0,0,0));</div><div class="line"></div><div class="line">scene::ISceneNodeAnimator* anim =</div><div class="line"> smgr-&gt;createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);</div><div class="line">cam-&gt;addAnimator(anim);</div><div class="line">anim-&gt;drop();</div><div class="line"></div><div class="line">scene::ISceneNode* cube = smgr-&gt;addCubeSceneNode(20);</div><div class="line"></div><div class="line"><span class="keyword">const</span> io::path mediaPath = getExampleMediaPath();</div><div class="line"></div><div class="line">cube-&gt;setMaterialTexture(0, driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;wall.bmp&quot;</span>));</div><div class="line">cube-&gt;setMaterialTexture(1, driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;water.jpg&quot;</span>));</div><div class="line">cube-&gt;setMaterialFlag( video::EMF_LIGHTING, <span class="keyword">false</span> );</div><div class="line">cube-&gt;setMaterialType( video::EMT_REFLECTION_2_LAYER );</div><div class="line"></div><div class="line">smgr-&gt;addSkyBoxSceneNode(</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_up.jpg&quot;</span>),</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_dn.jpg&quot;</span>),</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_lf.jpg&quot;</span>),</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_rt.jpg&quot;</span>),</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_ft.jpg&quot;</span>),</div><div class="line">driver-&gt;getTexture(mediaPath + <span class="stringliteral">&quot;irrlicht2_bk.jpg&quot;</span>));</div><div class="line"></div><div class="line"><span class="comment">// This shows that we can render to multiple windows within one application</span></div><div class="line">device-&gt;getGUIEnvironment()-&gt;addStaticText(core::stringw(<span class="stringliteral">&quot;Second screen render&quot;</span>).c_str(),core::recti(0,0,200,200));</div><div class="line"></div><div class="line"><span class="comment">// show and execute dialog</span></div><div class="line"></div><div class="line">ShowWindow(hWnd , SW_SHOW);</div><div class="line">UpdateWindow(hWnd);</div><div class="line"></div><div class="line"><span class="comment">// do message queue</span></div></div><!-- fragment --><p> Now the only thing missing is the drawing loop using IrrlichtDevice::run(). We do this as usual. But instead of this, there is another possibility: You can also simply use your own message loop using GetMessage, DispatchMessage and whatever. Calling Device-&gt;run() will cause Irrlicht to dispatch messages internally too. You need not call Device-&gt;run() if you want to do your own message dispatching loop, but Irrlicht will not be able to fetch user input then and you have to do it on your own using the window messages, DirectInput, or whatever. </p><div class="fragment"><div class="line"><span class="keywordflow">while</span> (device-&gt;run())</div><div class="line">{</div><div class="line"> driver-&gt;beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0), 1.f, 0, videodata);</div><div class="line"> smgr-&gt;drawAll();</div><div class="line"> driver-&gt;endScene();</div><div class="line"> <span class="keywordflow">if</span> (key==<span class="charliteral">&#39;b&#39;</span>)</div><div class="line"> {</div><div class="line"> driver-&gt;beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb));</div><div class="line"> device-&gt;getGUIEnvironment()-&gt;drawAll();</div><div class="line"> driver-&gt;endScene();</div><div class="line"> }</div><div class="line">}</div></div><!-- fragment --><p> The alternative, own message dispatching loop without Device-&gt;run() would look like this: </p><div class="fragment"></div><!-- fragment --><p> MSG msg; while (true) { if (PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&amp;msg); DispatchMessage(&amp;msg);</p>
<p>if (msg.message == WM_QUIT) break; }</p>
<p>advance virtual time device-&gt;getTimer()-&gt;tick();</p>
<p>draw engine picture driver-&gt;beginScene(true, true, 0, (key=='c')?hIrrlichtWindow:0); smgr-&gt;drawAll(); driver-&gt;endScene(); }</p><div class="fragment"><div class="line"> device-&gt;closeDevice();</div><div class="line"> device-&gt;drop();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"><span class="preprocessor">#endif // if windows</span></div></div><!-- fragment --><p> That's it, Irrlicht now runs in your own windows window. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.13-->
<!-- start footer part -->
<p>&nbsp;</p>
</body>
</html>