CIrrDeviceWin32.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #ifndef __C_IRR_DEVICE_WIN32_H_INCLUDED__
  5. #define __C_IRR_DEVICE_WIN32_H_INCLUDED__
  6. #include "IrrCompileConfig.h"
  7. #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
  8. #include "CIrrDeviceStub.h"
  9. #include "IrrlichtDevice.h"
  10. #include "IImagePresenter.h"
  11. #define WIN32_LEAN_AND_MEAN
  12. #if !defined(_IRR_XBOX_PLATFORM_)
  13. #include <windows.h>
  14. #include <mmsystem.h> // For JOYCAPS
  15. #include <windowsx.h>
  16. #endif
  17. #if !defined(GET_X_LPARAM)
  18. #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
  19. #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
  20. #endif
  21. namespace irr
  22. {
  23. struct SJoystickWin32Control;
  24. class CIrrDeviceWin32 : public CIrrDeviceStub, video::IImagePresenter
  25. {
  26. friend struct SJoystickWin32Control;
  27. public:
  28. //! constructor
  29. CIrrDeviceWin32(const SIrrlichtCreationParameters& params);
  30. //! destructor
  31. virtual ~CIrrDeviceWin32();
  32. //! runs the device. Returns false if device wants to be deleted
  33. virtual bool run();
  34. //! Cause the device to temporarily pause execution and let other processes to run
  35. // This should bring down processor usage without major performance loss for Irrlicht
  36. virtual void yield();
  37. //! Pause execution and let other processes to run for a specified amount of time.
  38. virtual void sleep(u32 timeMs, bool pauseTimer);
  39. //! sets the caption of the window
  40. virtual void setWindowCaption(const wchar_t* text);
  41. //! returns if window is active. if not, nothing need to be drawn
  42. virtual bool isWindowActive() const;
  43. //! returns if window has focus
  44. virtual bool isWindowFocused() const;
  45. //! returns if window is minimized
  46. virtual bool isWindowMinimized() const;
  47. //! presents a surface in the client area
  48. virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0);
  49. //! notifies the device that it should close itself
  50. virtual void closeDevice();
  51. //! \return Returns a pointer to a list with all video modes
  52. //! supported by the gfx adapter.
  53. video::IVideoModeList* getVideoModeList();
  54. //! Notifies the device, that it has been resized
  55. void OnResized();
  56. //! Sets if the window should be resizable in windowed mode.
  57. virtual void setResizable(bool resize=false);
  58. //! Minimizes the window.
  59. virtual void minimizeWindow();
  60. //! Maximizes the window.
  61. virtual void maximizeWindow();
  62. //! Restores the window size.
  63. virtual void restoreWindow();
  64. //! Activate any joysticks, and generate events for them.
  65. virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo);
  66. //! Set the current Gamma Value for the Display
  67. virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast );
  68. //! Get the current Gamma Value for the Display
  69. virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast );
  70. //! Remove all messages pending in the system message loop
  71. virtual void clearSystemMessages();
  72. //! Get the device type
  73. virtual E_DEVICE_TYPE getType() const
  74. {
  75. return EIDT_WIN32;
  76. }
  77. //! Compares to the last call of this function to return double and triple clicks.
  78. //! \return Returns only 1,2 or 3. A 4th click will start with 1 again.
  79. virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent )
  80. {
  81. // we just have to make it public
  82. return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent );
  83. }
  84. //! switchs to fullscreen
  85. bool switchToFullScreen(bool reset=false);
  86. //! Check for and show last Windows API error to help internal debugging.
  87. //! Does call GetLastError and on errors formats the errortext and displays it in a messagebox.
  88. static void ReportLastWinApiError();
  89. // convert an Irrlicht texture to a windows cursor
  90. HCURSOR TextureToCursor(HWND hwnd, irr::video::ITexture * tex, const core::rect<s32>& sourceRect, const core::position2d<s32> &hotspot);
  91. //! Implementation of the win32 cursor control
  92. class CCursorControl : public gui::ICursorControl
  93. {
  94. public:
  95. CCursorControl(CIrrDeviceWin32* device, const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen);
  96. ~CCursorControl();
  97. //! Changes the visible state of the mouse cursor.
  98. virtual void setVisible(bool visible)
  99. {
  100. CURSORINFO info;
  101. info.cbSize = sizeof(CURSORINFO);
  102. BOOL gotCursorInfo = GetCursorInfo(&info);
  103. while ( gotCursorInfo )
  104. {
  105. if ( (visible && info.flags == CURSOR_SHOWING) // visible
  106. || (!visible && info.flags == 0 ) ) // hidden
  107. {
  108. break;
  109. }
  110. int showResult = ShowCursor(visible); // this only increases an internal display counter in windows, so it might have to be called some more
  111. if ( showResult < 0 )
  112. {
  113. break;
  114. }
  115. info.cbSize = sizeof(CURSORINFO); // yes, it really must be set each time
  116. gotCursorInfo = GetCursorInfo(&info);
  117. }
  118. IsVisible = visible;
  119. }
  120. //! Returns if the cursor is currently visible.
  121. virtual bool isVisible() const
  122. {
  123. _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
  124. return IsVisible;
  125. }
  126. //! Sets the new position of the cursor.
  127. virtual void setPosition(const core::position2d<f32> &pos)
  128. {
  129. setPosition(pos.X, pos.Y);
  130. }
  131. //! Sets the new position of the cursor.
  132. virtual void setPosition(f32 x, f32 y)
  133. {
  134. if (!UseReferenceRect)
  135. setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height));
  136. else
  137. setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight()));
  138. }
  139. //! Sets the new position of the cursor.
  140. virtual void setPosition(const core::position2d<s32> &pos)
  141. {
  142. setPosition(pos.X, pos.Y);
  143. }
  144. //! Sets the new position of the cursor.
  145. virtual void setPosition(s32 x, s32 y)
  146. {
  147. if (UseReferenceRect)
  148. {
  149. SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,
  150. ReferenceRect.UpperLeftCorner.Y + y);
  151. }
  152. else
  153. {
  154. RECT rect;
  155. if (GetWindowRect(HWnd, &rect))
  156. SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);
  157. }
  158. CursorPos.X = x;
  159. CursorPos.Y = y;
  160. }
  161. //! Returns the current position of the mouse cursor.
  162. virtual const core::position2d<s32>& getPosition()
  163. {
  164. updateInternalCursorPosition();
  165. return CursorPos;
  166. }
  167. //! Returns the current position of the mouse cursor.
  168. virtual core::position2d<f32> getRelativePosition()
  169. {
  170. updateInternalCursorPosition();
  171. if (!UseReferenceRect)
  172. {
  173. return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
  174. CursorPos.Y * InvWindowSize.Height);
  175. }
  176. return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
  177. CursorPos.Y / (f32)ReferenceRect.getHeight());
  178. }
  179. //! Sets an absolute reference rect for calculating the cursor position.
  180. virtual void setReferenceRect(core::rect<s32>* rect=0)
  181. {
  182. if (rect)
  183. {
  184. ReferenceRect = *rect;
  185. UseReferenceRect = true;
  186. // prevent division through zero and uneven sizes
  187. if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
  188. ReferenceRect.LowerRightCorner.Y += 1;
  189. if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
  190. ReferenceRect.LowerRightCorner.X += 1;
  191. }
  192. else
  193. UseReferenceRect = false;
  194. }
  195. /** Used to notify the cursor that the window was resized. */
  196. virtual void OnResize(const core::dimension2d<u32>& size)
  197. {
  198. WindowSize = size;
  199. if (size.Width!=0)
  200. InvWindowSize.Width = 1.0f / size.Width;
  201. else
  202. InvWindowSize.Width = 0.f;
  203. if (size.Height!=0)
  204. InvWindowSize.Height = 1.0f / size.Height;
  205. else
  206. InvWindowSize.Height = 0.f;
  207. }
  208. /** Used to notify the cursor that the window resizable settings changed. */
  209. void updateBorderSize(bool fullscreen, bool resizable)
  210. {
  211. if (!fullscreen)
  212. {
  213. if (resizable)
  214. {
  215. BorderX = GetSystemMetrics(SM_CXSIZEFRAME);
  216. BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME);
  217. }
  218. else
  219. {
  220. BorderX = GetSystemMetrics(SM_CXDLGFRAME);
  221. BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
  222. }
  223. }
  224. else
  225. {
  226. BorderX = BorderY = 0;
  227. }
  228. }
  229. //! Sets the active cursor icon
  230. virtual void setActiveIcon(gui::ECURSOR_ICON iconId);
  231. //! Gets the currently active icon
  232. virtual gui::ECURSOR_ICON getActiveIcon() const
  233. {
  234. return ActiveIcon;
  235. }
  236. //! Add a custom sprite as cursor icon.
  237. virtual gui::ECURSOR_ICON addIcon(const gui::SCursorSprite& icon);
  238. //! replace the given cursor icon.
  239. virtual void changeIcon(gui::ECURSOR_ICON iconId, const gui::SCursorSprite& icon);
  240. //! Return a system-specific size which is supported for cursors. Larger icons will fail, smaller icons might work.
  241. virtual core::dimension2di getSupportedIconSize() const;
  242. void update();
  243. private:
  244. //! Updates the internal cursor position
  245. void updateInternalCursorPosition()
  246. {
  247. POINT p;
  248. if (!GetCursorPos(&p))
  249. {
  250. DWORD xy = GetMessagePos();
  251. p.x = GET_X_LPARAM(xy);
  252. p.y = GET_Y_LPARAM(xy);
  253. }
  254. if (UseReferenceRect)
  255. {
  256. CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;
  257. CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;
  258. }
  259. else
  260. {
  261. RECT rect;
  262. if (GetWindowRect(HWnd, &rect))
  263. {
  264. CursorPos.X = p.x-rect.left-BorderX;
  265. CursorPos.Y = p.y-rect.top-BorderY;
  266. }
  267. else
  268. {
  269. // window seems not to be existent, so set cursor to
  270. // a negative value
  271. CursorPos.X = -1;
  272. CursorPos.Y = -1;
  273. }
  274. }
  275. }
  276. CIrrDeviceWin32* Device;
  277. core::position2d<s32> CursorPos;
  278. core::dimension2d<u32> WindowSize;
  279. core::dimension2d<f32> InvWindowSize;
  280. HWND HWnd;
  281. s32 BorderX, BorderY;
  282. core::rect<s32> ReferenceRect;
  283. bool UseReferenceRect;
  284. bool IsVisible;
  285. struct CursorFrameW32
  286. {
  287. CursorFrameW32() : IconHW(0) {}
  288. CursorFrameW32(HCURSOR icon) : IconHW(icon) {}
  289. HCURSOR IconHW; // hardware cursor
  290. };
  291. struct CursorW32
  292. {
  293. CursorW32() {}
  294. explicit CursorW32(HCURSOR iconHw, u32 frameTime=0) : FrameTime(frameTime)
  295. {
  296. Frames.push_back( CursorFrameW32(iconHw) );
  297. }
  298. core::array<CursorFrameW32> Frames;
  299. u32 FrameTime;
  300. };
  301. core::array<CursorW32> Cursors;
  302. gui::ECURSOR_ICON ActiveIcon;
  303. u32 ActiveIconStartTime;
  304. void initCursors();
  305. };
  306. //! returns the win32 cursor control
  307. CCursorControl* getWin32CursorControl();
  308. private:
  309. //! create the driver
  310. void createDriver();
  311. //! Process system events
  312. void handleSystemMessages();
  313. void getWindowsVersion(core::stringc& version);
  314. void resizeIfNecessary();
  315. HWND HWnd;
  316. bool ChangedToFullScreen;
  317. bool Resized;
  318. bool ExternalWindow;
  319. CCursorControl* Win32CursorControl;
  320. DEVMODE DesktopMode;
  321. SJoystickWin32Control* JoyControl;
  322. };
  323. } // end namespace irr
  324. #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_
  325. #endif // __C_IRR_DEVICE_WIN32_H_INCLUDED__