| @@ -30,15 +30,15 @@ CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr; | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace WindowsMessageHelpers | namespace WindowsMessageHelpers | ||||
| { | { | ||||
| const unsigned int specialId = WM_APP + 0x4400; | |||||
| const unsigned int broadcastId = WM_APP + 0x4403; | |||||
| const unsigned int customMessageID = WM_USER + 123; | |||||
| const unsigned int broadcastMessageMagicNumber = 0xc403; | |||||
| const TCHAR messageWindowName[] = _T("JUCEWindow"); | const TCHAR messageWindowName[] = _T("JUCEWindow"); | ||||
| ScopedPointer<HiddenMessageWindow> messageWindow; | ScopedPointer<HiddenMessageWindow> messageWindow; | ||||
| void dispatchMessageFromLParam (LPARAM lParam) | void dispatchMessageFromLParam (LPARAM lParam) | ||||
| { | { | ||||
| if (MessageManager::MessageBase* const message = reinterpret_cast<MessageManager::MessageBase*> (lParam)) | |||||
| if (MessageManager::MessageBase* message = reinterpret_cast<MessageManager::MessageBase*> (lParam)) | |||||
| { | { | ||||
| JUCE_TRY | JUCE_TRY | ||||
| { | { | ||||
| @@ -50,12 +50,44 @@ namespace WindowsMessageHelpers | |||||
| } | } | ||||
| } | } | ||||
| BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam) | |||||
| { | |||||
| if (hwnd != juce_messageWindowHandle) | |||||
| { | |||||
| TCHAR windowName[64] = { 0 }; // no need to read longer strings than this | |||||
| GetWindowText (hwnd, windowName, 63); | |||||
| if (String (windowName) == messageWindowName) | |||||
| reinterpret_cast<Array<HWND>*> (lParam)->add (hwnd); | |||||
| } | |||||
| return TRUE; | |||||
| } | |||||
| void handleBroadcastMessage (const COPYDATASTRUCT* const data) | |||||
| { | |||||
| if (data != nullptr && data->dwData == broadcastMessageMagicNumber) | |||||
| { | |||||
| struct BroadcastMessage : public CallbackMessage | |||||
| { | |||||
| BroadcastMessage (CharPointer_UTF32 text, size_t length) : message (text, length) {} | |||||
| void messageCallback() override { MessageManager::getInstance()->deliverBroadcastMessage (message); } | |||||
| String message; | |||||
| }; | |||||
| (new BroadcastMessage (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData), | |||||
| data->cbData / sizeof (CharPointer_UTF32::CharType))) | |||||
| ->post(); | |||||
| } | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept | LRESULT CALLBACK messageWndProc (HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam) noexcept | ||||
| { | { | ||||
| if (h == juce_messageWindowHandle) | if (h == juce_messageWindowHandle) | ||||
| { | { | ||||
| if (message == specialId) | |||||
| if (message == customMessageID) | |||||
| { | { | ||||
| // (These are trapped early in our dispatch loop, but must also be checked | // (These are trapped early in our dispatch loop, but must also be checked | ||||
| // here in case some 3rd-party code is running the dispatch loop). | // here in case some 3rd-party code is running the dispatch loop). | ||||
| @@ -63,43 +95,15 @@ namespace WindowsMessageHelpers | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (message == broadcastId) | |||||
| { | |||||
| if (String* const m = reinterpret_cast<String*> (lParam)) | |||||
| { | |||||
| const ScopedPointer<String> messageString (m); | |||||
| MessageManager::getInstance()->deliverBroadcastMessage (*m); | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| if (message == WM_COPYDATA) | if (message == WM_COPYDATA) | ||||
| { | { | ||||
| if (const COPYDATASTRUCT* const data = reinterpret_cast<const COPYDATASTRUCT*> (lParam)) | |||||
| { | |||||
| if (data->dwData == broadcastId) | |||||
| { | |||||
| const String messageString (CharPointer_UTF32 ((const CharPointer_UTF32::CharType*) data->lpData), | |||||
| data->cbData / sizeof (CharPointer_UTF32::CharType)); | |||||
| PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString)); | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| handleBroadcastMessage (reinterpret_cast<const COPYDATASTRUCT*> (lParam)); | |||||
| return 0; | |||||
| } | } | ||||
| } | } | ||||
| return DefWindowProc (h, message, wParam, lParam); | return DefWindowProc (h, message, wParam, lParam); | ||||
| } | } | ||||
| BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam) | |||||
| { | |||||
| if (hwnd != juce_messageWindowHandle) | |||||
| reinterpret_cast<Array<HWND>*> (lParam)->add (hwnd); | |||||
| return TRUE; | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -113,7 +117,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||||
| if (GetMessage (&m, (HWND) 0, 0, 0) >= 0) | if (GetMessage (&m, (HWND) 0, 0, 0) >= 0) | ||||
| { | { | ||||
| if (m.message == specialId && m.hwnd == juce_messageWindowHandle) | |||||
| if (m.message == customMessageID && m.hwnd == juce_messageWindowHandle) | |||||
| { | { | ||||
| dispatchMessageFromLParam (m.lParam); | dispatchMessageFromLParam (m.lParam); | ||||
| } | } | ||||
| @@ -146,36 +150,28 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||||
| bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message) | ||||
| { | { | ||||
| message->incReferenceCount(); | message->incReferenceCount(); | ||||
| return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::specialId, 0, (LPARAM) message) != 0; | |||||
| return PostMessage (juce_messageWindowHandle, WindowsMessageHelpers::customMessageID, 0, (LPARAM) message) != 0; | |||||
| } | } | ||||
| void MessageManager::broadcastMessage (const String& value) | void MessageManager::broadcastMessage (const String& value) | ||||
| { | { | ||||
| Array<HWND> windows; | |||||
| EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows); | |||||
| const String localCopy (value); | const String localCopy (value); | ||||
| COPYDATASTRUCT data; | |||||
| data.dwData = WindowsMessageHelpers::broadcastId; | |||||
| data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType); | |||||
| data.lpData = (void*) localCopy.toUTF32().getAddress(); | |||||
| Array<HWND> windows; | |||||
| EnumWindows (&WindowsMessageHelpers::broadcastEnumWindowProc, (LPARAM) &windows); | |||||
| for (int i = windows.size(); --i >= 0;) | for (int i = windows.size(); --i >= 0;) | ||||
| { | { | ||||
| HWND hwnd = windows.getUnchecked(i); | |||||
| TCHAR windowName[64] = { 0 }; // no need to read longer strings than this | |||||
| GetWindowText (hwnd, windowName, 63); | |||||
| if (String (windowName) == WindowsMessageHelpers::messageWindowName) | |||||
| { | |||||
| DWORD_PTR result; | |||||
| SendMessageTimeout (hwnd, WM_COPYDATA, | |||||
| (WPARAM) juce_messageWindowHandle, | |||||
| (LPARAM) &data, | |||||
| SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result); | |||||
| } | |||||
| COPYDATASTRUCT data; | |||||
| data.dwData = WindowsMessageHelpers::broadcastMessageMagicNumber; | |||||
| data.cbData = (localCopy.length() + 1) * sizeof (CharPointer_UTF32::CharType); | |||||
| data.lpData = (void*) localCopy.toUTF32().getAddress(); | |||||
| DWORD_PTR result; | |||||
| SendMessageTimeout (windows.getUnchecked(i), WM_COPYDATA, | |||||
| (WPARAM) juce_messageWindowHandle, | |||||
| (LPARAM) &data, | |||||
| SMTO_BLOCK | SMTO_ABORTIFHUNG, 8000, &result); | |||||
| } | } | ||||
| } | } | ||||