From 841768ed03d645b26ecb3d484c045b6cfd306f1e Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 14:07:54 -0500 Subject: [PATCH 1/8] add Windows installer and shell changes needed to add Brackets to the Windows Explorer 'Open With...' menu and dialog for supported file types --- appshell/cefclient_win.cpp | 84 +++++++++++++++++++- installer/win/Brackets.wxs | 25 ++++++ installer/win/brackets-win-install-build.xml | 2 +- 3 files changed, 107 insertions(+), 4 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 07f2e014f..73d33f3a2 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -35,6 +35,9 @@ #define CLOSING_PROP L"CLOSING" +#define FIRST_INSTANCE_MUTEX_NAME L"FIRST_INSTANCE_MUTEX" +#define ID_WM_COPYDATA_SENDOPENFILECOMMAND 1001 + // Global Variables: DWORD g_appStartupTime; HINSTANCE hInst; // current instance @@ -44,6 +47,7 @@ std::wstring gFilesToOpen; // Filenames passed as arguments to app TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name char szWorkingDir[MAX_PATH]; // The current working directory +static const TCHAR szMutexName[] = APP_NAME FIRST_INSTANCE_MUTEX_NAME; // proper name of first instance mutex TCHAR szInitialUrl[MAX_PATH] = {0}; @@ -142,6 +146,28 @@ std::wstring GetFilenamesFromCommandLine() { return result; } +// EnumWindowsProc callback function +// - searches for an already running Brackets application window +BOOL CALLBACK FindFirstBracketsInstance(HWND hwnd, LPARAM lParam) +{ + ASSERT(lParam != NULL); // must be passed an HWND pointer to return, if found + + // check for the Brackets application window by class name and title + WCHAR cName[MAX_PATH+1] = {0}, cTitle[MAX_PATH+1] = {0}; + ::GetClassName(hwnd, cName, MAX_PATH); + ::GetWindowText(hwnd, cTitle, MAX_PATH); + if ((wcscmp(cName, szWindowClass) == 0) && (wcsstr(cTitle, APP_NAME) != 0)) { + // found it! return the window handle and stop searching + *(HWND*)lParam = hwnd; + return FALSE; + } + + return TRUE; // otherwise, continue searching +} + +// forward declaration; implemented in appshell_extensions_win.cpp +void ConvertToUnixPath(ExtensionString& filename); + // Program entry point function. int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, @@ -167,6 +193,37 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // Parse command line arguments. The passed in values are ignored on Windows. AppInitCommandLine(0, NULL); + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_CEFCLIENT, szWindowClass, MAX_LOADSTRING); + + // Determine if we should use an already running instance of Brackets. + HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, szMutexName); + if (hMutex == NULL) { + // first instance of this app, so create the mutex and continue execution of this instance. + hMutex = ::CreateMutex(NULL, FALSE, szMutexName); + } else if (AppGetCommandLine()->HasArguments() && (lpCmdLine != NULL)) { + // for subsequent instances, re-use an already running instance if we're being called to + // open an existing file on the command-line (eg. Open With.. from Windows Explorer) + HWND hFirstInstanceWnd = NULL; + ::EnumWindows(FindFirstBracketsInstance, (LPARAM)&hFirstInstanceWnd); + ASSERT(hFirstInstanceWnd != NULL); + ::SetForegroundWindow(hFirstInstanceWnd); + + // message the other Brackets instance to actually open the given filename + std::wstring wstrFilename = lpCmdLine; + ConvertToUnixPath(wstrFilename); + // note: WM_COPYDATA will manage passing the string across process space + COPYDATASTRUCT data; + data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; + data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); + data.lpData = (LPVOID)wstrFilename.c_str(); + ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); + + // exit this instance + return 0; + } + CefSettings settings; // Populate the settings based on command line arguments. @@ -180,9 +237,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // Initialize CEF. CefInitialize(main_args, settings, app.get()); - // Initialize global strings - LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); - LoadString(hInstance, IDC_CEFCLIENT, szWindowClass, MAX_LOADSTRING); + // Register window class MyRegisterClass(hInstance, *(app->GetCurrentLanguage().GetStruct())); CefRefPtr cmdLine = AppGetCommandLine(); @@ -272,6 +327,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // Shut down CEF. CefShutdown(); + // release the first instance mutex + if (hMutex != NULL) + ReleaseMutex(hMutex); + return result; } @@ -867,6 +926,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, PostQuitMessage(0); return 0; + case WM_COPYDATA: + // handle the interprocess communication request from another Brackets running instance + if (lParam != NULL) { + PCOPYDATASTRUCT data = (PCOPYDATASTRUCT)lParam; + if ((data->dwData == ID_WM_COPYDATA_SENDOPENFILECOMMAND) && (data->cbData > 0)) { + // another Brackets instance requests that we open the given filename + std::wstring wstrFilename = (LPCWSTR)data->lpData; + // Windows Explorer might enclose the filename in double-quotes. We need to strip these off. + if ((wstrFilename.front() == '\"') && wstrFilename.back() == '\"') + wstrFilename = wstrFilename.substr(1, wstrFilename.length() - 2); + ASSERT(g_handler != NULL); + CefRefPtr browser = g_handler->GetBrowser(); + // call into Javascript code to handle the open file command + ASSERT(browser != NULL); + g_handler->SendOpenFileCommand(browser, CefString(wstrFilename.c_str())); + } + } + break; + case WM_INITMENUPOPUP: // Notify before popping up g_handler->SendJSCommand(g_handler->GetBrowser(), APP_BEFORE_MENUPOPUP); diff --git a/installer/win/Brackets.wxs b/installer/win/Brackets.wxs index 73fff5a19..cc1de185f 100644 --- a/installer/win/Brackets.wxs +++ b/installer/win/Brackets.wxs @@ -42,6 +42,29 @@ xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension"> + + + + + + + + + + + + + + + + + + + + + + + @@ -78,6 +101,8 @@ xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension"> + + diff --git a/installer/win/brackets-win-install-build.xml b/installer/win/brackets-win-install-build.xml index 66a9f3346..23accaf58 100644 --- a/installer/win/brackets-win-install-build.xml +++ b/installer/win/brackets-win-install-build.xml @@ -16,7 +16,7 @@ default="build.mul"> - + From 578e7ba670d5ab5e7bb1a41573e7c3533c1c40d4 Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 14:52:37 -0500 Subject: [PATCH 2/8] added missing .txt extension from installer script --- installer/win/Brackets.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/win/Brackets.wxs b/installer/win/Brackets.wxs index 76b32b103..a8dee7a57 100644 --- a/installer/win/Brackets.wxs +++ b/installer/win/Brackets.wxs @@ -49,7 +49,7 @@ xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension"> - + From e0432ca9069513f40cee50b4f9706984b3dd902b Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 15:13:32 -0500 Subject: [PATCH 3/8] when opening a file in an already running instance of Brackets, restore the application window if Brackets is minimized --- appshell/cefclient_win.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 73d33f3a2..b03c6a0ea 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -209,6 +209,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance, ::EnumWindows(FindFirstBracketsInstance, (LPARAM)&hFirstInstanceWnd); ASSERT(hFirstInstanceWnd != NULL); ::SetForegroundWindow(hFirstInstanceWnd); + if (::IsIconic(hFirstInstanceWnd)) + ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); // message the other Brackets instance to actually open the given filename std::wstring wstrFilename = lpCmdLine; From 6986083a57799adfeb534d09a22fb881862bc547 Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 17:32:47 -0500 Subject: [PATCH 4/8] launch new instance of Brackets if the current one is disabled (eg. modal dialog) or if we can't find the Brackets window --- appshell/cefclient_win.cpp | 54 ++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index b03c6a0ea..84a3b0e43 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -157,9 +157,13 @@ BOOL CALLBACK FindFirstBracketsInstance(HWND hwnd, LPARAM lParam) ::GetClassName(hwnd, cName, MAX_PATH); ::GetWindowText(hwnd, cTitle, MAX_PATH); if ((wcscmp(cName, szWindowClass) == 0) && (wcsstr(cTitle, APP_NAME) != 0)) { - // found it! return the window handle and stop searching - *(HWND*)lParam = hwnd; - return FALSE; + // found an already running instance of Brackets. Now, check that that window + // isn't currently disabled (eg. modal dialog). If it is keep searching. + if ((::GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED) == 0) { + //return the window handle and stop searching + *(HWND*)lParam = hwnd; + return FALSE; + } } return TRUE; // otherwise, continue searching @@ -199,31 +203,35 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // Determine if we should use an already running instance of Brackets. HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, szMutexName); - if (hMutex == NULL) { - // first instance of this app, so create the mutex and continue execution of this instance. - hMutex = ::CreateMutex(NULL, FALSE, szMutexName); - } else if (AppGetCommandLine()->HasArguments() && (lpCmdLine != NULL)) { + if ((hMutex != NULL) && AppGetCommandLine()->HasArguments() && (lpCmdLine != NULL)) { // for subsequent instances, re-use an already running instance if we're being called to // open an existing file on the command-line (eg. Open With.. from Windows Explorer) HWND hFirstInstanceWnd = NULL; ::EnumWindows(FindFirstBracketsInstance, (LPARAM)&hFirstInstanceWnd); - ASSERT(hFirstInstanceWnd != NULL); - ::SetForegroundWindow(hFirstInstanceWnd); - if (::IsIconic(hFirstInstanceWnd)) - ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); - - // message the other Brackets instance to actually open the given filename - std::wstring wstrFilename = lpCmdLine; - ConvertToUnixPath(wstrFilename); - // note: WM_COPYDATA will manage passing the string across process space - COPYDATASTRUCT data; - data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; - data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); - data.lpData = (LPVOID)wstrFilename.c_str(); - ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); + if (hFirstInstanceWnd != NULL) { + ::SetForegroundWindow(hFirstInstanceWnd); + if (::IsIconic(hFirstInstanceWnd)) + ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); + + // message the other Brackets instance to actually open the given filename + std::wstring wstrFilename = lpCmdLine; + ConvertToUnixPath(wstrFilename); + // note: WM_COPYDATA will manage passing the string across process space + COPYDATASTRUCT data; + data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; + data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); + data.lpData = (LPVOID)wstrFilename.c_str(); + ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); - // exit this instance - return 0; + // exit this instance + return 0; + } + // otherwise, fall thru and launch a new instance + } + + if (hMutex == NULL) { + // first instance of this app, so create the mutex and continue execution of this instance. + hMutex = ::CreateMutex(NULL, FALSE, szMutexName); } CefSettings settings; From 203b3f30984ef5b5221d70edef5c2e99cbf060ba Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 17:39:33 -0500 Subject: [PATCH 5/8] code cleanup per code review requests --- appshell/cefclient_win.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 84a3b0e43..35317989e 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -35,8 +35,8 @@ #define CLOSING_PROP L"CLOSING" -#define FIRST_INSTANCE_MUTEX_NAME L"FIRST_INSTANCE_MUTEX" -#define ID_WM_COPYDATA_SENDOPENFILECOMMAND 1001 +#define FIRST_INSTANCE_MUTEX_NAME L".Shell.Instance" +#define ID_WM_COPYDATA_SENDOPENFILECOMMAND (WM_USER+1001) // Global Variables: DWORD g_appStartupTime; @@ -47,7 +47,6 @@ std::wstring gFilesToOpen; // Filenames passed as arguments to app TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name char szWorkingDir[MAX_PATH]; // The current working directory -static const TCHAR szMutexName[] = APP_NAME FIRST_INSTANCE_MUTEX_NAME; // proper name of first instance mutex TCHAR szInitialUrl[MAX_PATH] = {0}; @@ -202,7 +201,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, LoadString(hInstance, IDC_CEFCLIENT, szWindowClass, MAX_LOADSTRING); // Determine if we should use an already running instance of Brackets. - HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, szMutexName); + HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, APP_NAME FIRST_INSTANCE_MUTEX_NAME); if ((hMutex != NULL) && AppGetCommandLine()->HasArguments() && (lpCmdLine != NULL)) { // for subsequent instances, re-use an already running instance if we're being called to // open an existing file on the command-line (eg. Open With.. from Windows Explorer) @@ -231,7 +230,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, if (hMutex == NULL) { // first instance of this app, so create the mutex and continue execution of this instance. - hMutex = ::CreateMutex(NULL, FALSE, szMutexName); + hMutex = ::CreateMutex(NULL, FALSE, APP_NAME FIRST_INSTANCE_MUTEX_NAME); } CefSettings settings; From 21dadf66ea3701234fabbdb18bbc9cf6cf184063 Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 17:43:54 -0500 Subject: [PATCH 6/8] refactoring function name to better describe the refactored behavior --- appshell/cefclient_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 35317989e..53d566d8d 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -147,7 +147,7 @@ std::wstring GetFilenamesFromCommandLine() { // EnumWindowsProc callback function // - searches for an already running Brackets application window -BOOL CALLBACK FindFirstBracketsInstance(HWND hwnd, LPARAM lParam) +BOOL CALLBACK FindSuitableBracketsInstance(HWND hwnd, LPARAM lParam) { ASSERT(lParam != NULL); // must be passed an HWND pointer to return, if found @@ -206,7 +206,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // for subsequent instances, re-use an already running instance if we're being called to // open an existing file on the command-line (eg. Open With.. from Windows Explorer) HWND hFirstInstanceWnd = NULL; - ::EnumWindows(FindFirstBracketsInstance, (LPARAM)&hFirstInstanceWnd); + ::EnumWindows(FindSuitableBracketsInstance, (LPARAM)&hFirstInstanceWnd); if (hFirstInstanceWnd != NULL) { ::SetForegroundWindow(hFirstInstanceWnd); if (::IsIconic(hFirstInstanceWnd)) From 45ec711b7e5edf1b7fc25ecaa9c6e922a075de84 Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Wed, 14 Aug 2013 17:58:36 -0500 Subject: [PATCH 7/8] re-indenting to fix VS2010 tabs --- appshell/cefclient_win.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 53d566d8d..8b35dbbb6 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -207,24 +207,24 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // open an existing file on the command-line (eg. Open With.. from Windows Explorer) HWND hFirstInstanceWnd = NULL; ::EnumWindows(FindSuitableBracketsInstance, (LPARAM)&hFirstInstanceWnd); - if (hFirstInstanceWnd != NULL) { - ::SetForegroundWindow(hFirstInstanceWnd); - if (::IsIconic(hFirstInstanceWnd)) - ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); - - // message the other Brackets instance to actually open the given filename - std::wstring wstrFilename = lpCmdLine; - ConvertToUnixPath(wstrFilename); - // note: WM_COPYDATA will manage passing the string across process space - COPYDATASTRUCT data; - data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; - data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); - data.lpData = (LPVOID)wstrFilename.c_str(); - ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); - - // exit this instance - return 0; - } + if (hFirstInstanceWnd != NULL) { + ::SetForegroundWindow(hFirstInstanceWnd); + if (::IsIconic(hFirstInstanceWnd)) + ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); + + // message the other Brackets instance to actually open the given filename + std::wstring wstrFilename = lpCmdLine; + ConvertToUnixPath(wstrFilename); + // note: WM_COPYDATA will manage passing the string across process space + COPYDATASTRUCT data; + data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; + data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); + data.lpData = (LPVOID)wstrFilename.c_str(); + ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); + + // exit this instance + return 0; + } // otherwise, fall thru and launch a new instance } From 3dc1a0f5a3ee80adfe86e040b28c49a4fddf6fb1 Mon Sep 17 00:00:00 2001 From: Bryan Chin Date: Thu, 15 Aug 2013 14:09:17 -0500 Subject: [PATCH 8/8] refactoring per code review --- appshell/cefclient_win.cpp | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/appshell/cefclient_win.cpp b/appshell/cefclient_win.cpp index 8b35dbbb6..97441e5ba 100644 --- a/appshell/cefclient_win.cpp +++ b/appshell/cefclient_win.cpp @@ -35,7 +35,7 @@ #define CLOSING_PROP L"CLOSING" -#define FIRST_INSTANCE_MUTEX_NAME L".Shell.Instance" +#define FIRST_INSTANCE_MUTEX_NAME (APP_NAME L".Shell.Instance") #define ID_WM_COPYDATA_SENDOPENFILECOMMAND (WM_USER+1001) // Global Variables: @@ -201,36 +201,36 @@ int APIENTRY wWinMain(HINSTANCE hInstance, LoadString(hInstance, IDC_CEFCLIENT, szWindowClass, MAX_LOADSTRING); // Determine if we should use an already running instance of Brackets. - HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, APP_NAME FIRST_INSTANCE_MUTEX_NAME); + HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, FIRST_INSTANCE_MUTEX_NAME); if ((hMutex != NULL) && AppGetCommandLine()->HasArguments() && (lpCmdLine != NULL)) { // for subsequent instances, re-use an already running instance if we're being called to // open an existing file on the command-line (eg. Open With.. from Windows Explorer) HWND hFirstInstanceWnd = NULL; ::EnumWindows(FindSuitableBracketsInstance, (LPARAM)&hFirstInstanceWnd); - if (hFirstInstanceWnd != NULL) { - ::SetForegroundWindow(hFirstInstanceWnd); - if (::IsIconic(hFirstInstanceWnd)) - ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); - - // message the other Brackets instance to actually open the given filename - std::wstring wstrFilename = lpCmdLine; - ConvertToUnixPath(wstrFilename); - // note: WM_COPYDATA will manage passing the string across process space - COPYDATASTRUCT data; - data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; - data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); - data.lpData = (LPVOID)wstrFilename.c_str(); - ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); - - // exit this instance - return 0; - } + if (hFirstInstanceWnd != NULL) { + ::SetForegroundWindow(hFirstInstanceWnd); + if (::IsIconic(hFirstInstanceWnd)) + ::ShowWindow(hFirstInstanceWnd, SW_RESTORE); + + // message the other Brackets instance to actually open the given filename + std::wstring wstrFilename = lpCmdLine; + ConvertToUnixPath(wstrFilename); + // note: WM_COPYDATA will manage passing the string across process space + COPYDATASTRUCT data; + data.dwData = ID_WM_COPYDATA_SENDOPENFILECOMMAND; + data.cbData = (wstrFilename.length() + 1) * sizeof(WCHAR); + data.lpData = (LPVOID)wstrFilename.c_str(); + ::SendMessage(hFirstInstanceWnd, WM_COPYDATA, (WPARAM)(HWND)hFirstInstanceWnd, (LPARAM)(LPVOID)&data); + + // exit this instance + return 0; + } // otherwise, fall thru and launch a new instance } if (hMutex == NULL) { // first instance of this app, so create the mutex and continue execution of this instance. - hMutex = ::CreateMutex(NULL, FALSE, APP_NAME FIRST_INSTANCE_MUTEX_NAME); + hMutex = ::CreateMutex(NULL, FALSE, FIRST_INSTANCE_MUTEX_NAME); } CefSettings settings;