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.

133 lines
4.5KB

  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 GetWindowLongPtr (hwnd, GWLP_USERDATA) == getImprobableWindowNumber();
  59. }
  60. static void setAsJUCEWindow (HWND hwnd, bool isJuceWindow) noexcept
  61. {
  62. SetWindowLongPtr (hwnd, GWLP_USERDATA, isJuceWindow ? getImprobableWindowNumber() : 0);
  63. }
  64. private:
  65. static LONG_PTR getImprobableWindowNumber() noexcept
  66. {
  67. static LONG_PTR number = (LONG_PTR) Random::getSystemRandom().nextInt64();
  68. return number;
  69. }
  70. };
  71. //==============================================================================
  72. class DeviceChangeDetector : private Timer
  73. {
  74. public:
  75. DeviceChangeDetector (const wchar_t* const name)
  76. : messageWindow (name, (WNDPROC) deviceChangeEventCallback)
  77. {
  78. SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
  79. }
  80. virtual ~DeviceChangeDetector() {}
  81. protected:
  82. virtual void systemDeviceChanged() = 0;
  83. private:
  84. HiddenMessageWindow messageWindow;
  85. static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
  86. const WPARAM wParam, const LPARAM lParam)
  87. {
  88. if (message == WM_DEVICECHANGE
  89. && (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
  90. || wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
  91. || wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
  92. {
  93. // We'll pause before sending a message, because on device removal, the OS hasn't always updated
  94. // its device lists correctly at this point. This also helps avoid repeated callbacks.
  95. ((DeviceChangeDetector*) GetWindowLongPtr (h, GWLP_USERDATA))->startTimer (500);
  96. }
  97. return DefWindowProc (h, message, wParam, lParam);
  98. }
  99. void timerCallback()
  100. {
  101. systemDeviceChanged();
  102. }
  103. };
  104. #endif // __JUCE_WIN32_HIDDENMESSAGEWINDOW_JUCEHEADER__