The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_WIN32_HIDDENMESSAGEWINDOW_JUCEHEADER__
  19. #define __JUCE_WIN32_HIDDENMESSAGEWINDOW_JUCEHEADER__
  20. //==============================================================================
  21. class HiddenMessageWindow
  22. {
  23. public:
  24. HiddenMessageWindow (const TCHAR* const messageWindowName, WNDPROC wndProc)
  25. {
  26. String className ("JUCE_");
  27. className << String::toHexString (Time::getHighResolutionTicks());
  28. HMODULE moduleHandle = (HMODULE) Process::getCurrentModuleInstanceHandle();
  29. WNDCLASSEX wc = { 0 };
  30. wc.cbSize = sizeof (wc);
  31. wc.lpfnWndProc = wndProc;
  32. wc.cbWndExtra = 4;
  33. wc.hInstance = moduleHandle;
  34. wc.lpszClassName = className.toWideCharPointer();
  35. atom = RegisterClassEx (&wc);
  36. jassert (atom != 0);
  37. hwnd = CreateWindow (getClassNameFromAtom(), messageWindowName,
  38. 0, 0, 0, 0, 0, 0, 0, moduleHandle, 0);
  39. jassert (hwnd != 0);
  40. }
  41. ~HiddenMessageWindow()
  42. {
  43. DestroyWindow (hwnd);
  44. UnregisterClass (getClassNameFromAtom(), 0);
  45. }
  46. inline HWND getHWND() const noexcept { return hwnd; }
  47. private:
  48. ATOM atom;
  49. HWND hwnd;
  50. LPCTSTR getClassNameFromAtom() noexcept { return (LPCTSTR) MAKELONG (atom, 0); }
  51. };
  52. //==============================================================================
  53. class JuceWindowIdentifier
  54. {
  55. public:
  56. static bool isJUCEWindow (HWND hwnd) noexcept
  57. {
  58. return GetWindowLong (hwnd, GWLP_USERDATA) == improbableWindowNumber;
  59. }
  60. static void setAsJUCEWindow (HWND hwnd, bool isJuceWindow) noexcept
  61. {
  62. SetWindowLongPtr (hwnd, GWLP_USERDATA, isJuceWindow ? improbableWindowNumber : 0);
  63. }
  64. private:
  65. enum { improbableWindowNumber = 0xf965aa01 };
  66. };
  67. //==============================================================================
  68. class DeviceChangeDetector : private Timer
  69. {
  70. public:
  71. DeviceChangeDetector (const wchar_t* const name)
  72. : messageWindow (name, (WNDPROC) deviceChangeEventCallback)
  73. {
  74. SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
  75. }
  76. virtual ~DeviceChangeDetector() {}
  77. protected:
  78. virtual void systemDeviceChanged() = 0;
  79. private:
  80. HiddenMessageWindow messageWindow;
  81. static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
  82. const WPARAM wParam, const LPARAM lParam)
  83. {
  84. if (message == WM_DEVICECHANGE
  85. && (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
  86. || wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
  87. || wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
  88. {
  89. // We'll pause before sending a message, because on device removal, the OS hasn't always updated
  90. // its device lists correctly at this point. This also helps avoid repeated callbacks.
  91. ((DeviceChangeDetector*) GetWindowLongPtr (h, GWLP_USERDATA))->startTimer (500);
  92. }
  93. return DefWindowProc (h, message, wParam, lParam);
  94. }
  95. void timerCallback()
  96. {
  97. systemDeviceChanged();
  98. }
  99. };
  100. #endif // __JUCE_WIN32_HIDDENMESSAGEWINDOW_JUCEHEADER__