diff --git a/OBS.rc b/OBS.rc index 9a2659a7..1fb237ee 100644 --- a/OBS.rc +++ b/OBS.rc @@ -162,6 +162,10 @@ BEGIN PUSHBUTTON "Rename",IDC_RENAME,224,58,76,14 PUSHBUTTON "Remove",IDC_REMOVE,301,58,75,14 LTEXT "Settings.General.Restart",IDC_INFO,7,145,409,48,NOT WS_VISIBLE + CONTROL "Settings.General.Notification",IDC_NOTIFICATIONICON, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,94,108,10,WS_EX_RIGHT + CONTROL "Settings.General.NotificationMinimize",IDC_MINIZENOTIFICATION, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,146,110,134,10,WS_EX_RIGHT END IDD_SETTINGS_AUDIO DIALOGEX 0, 0, 427, 336 @@ -648,6 +652,7 @@ IDI_SOUND_MIC ICON "ui\\mic2.ico" IDI_SOUND_MIC_MUTED ICON "ui\\mic2-muted.ico" IDI_SOUND_DESKTOP ICON "ui\\speaker.ico" IDI_SOUND_DESKTOP_MUTED ICON "ui\\speaker-muted.ico" +IDI_ICON2 ICON "ui\\test2\\recording.ico" ///////////////////////////////////////////////////////////////////////////// // diff --git a/OBS.vcxproj b/OBS.vcxproj index c5a4748f..046fc8dd 100644 --- a/OBS.vcxproj +++ b/OBS.vcxproj @@ -299,6 +299,7 @@ + diff --git a/OBS.vcxproj.filters b/OBS.vcxproj.filters index 72150123..cc4d04a9 100644 --- a/OBS.vcxproj.filters +++ b/OBS.vcxproj.filters @@ -230,6 +230,9 @@ Shaders + + Resources + diff --git a/Source/Main.h b/Source/Main.h index 1fe725f6..56d929f3 100644 --- a/Source/Main.h +++ b/Source/Main.h @@ -27,6 +27,7 @@ #define ISOLATION_AWARE_ENABLED 1 #include #include +#include #include #include diff --git a/Source/OBS.cpp b/Source/OBS.cpp index c00cc85d..a4e29a6b 100644 --- a/Source/OBS.cpp +++ b/Source/OBS.cpp @@ -446,6 +446,16 @@ OBS::OBS() 0, 0, 0, 0, hwndMain, (HMENU)ID_SOURCES_TEXT, 0, 0); SendMessage(hwndTemp, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE); + //----------------------------------------------------- + // notification area + + bNotificationAreaIcon = false; + wmExplorerRestarted = RegisterWindowMessage(TEXT("TaskbarCreated")); + if (AppConfig->GetInt(TEXT("General"), TEXT("ShowNotificationAreaIcon"), 0) != 0) + { + ShowNotificationAreaIcon(); + } + //----------------------------------------------------- // populate scenes @@ -661,6 +671,11 @@ OBS::~OBS() pluginInfo.strFile.Clear(); } + if (AppConfig->GetInt(TEXT("General"), TEXT("ShowNotificationAreaIcon"), 0) != 0) + { + App->HideNotificationAreaIcon(); + } + //DestroyWindow(hwndMain); // Remember window state for next launch @@ -1541,3 +1556,51 @@ void OBS::SetSourceRender(CTSTR sourceName, bool render) } } } + +BOOL OBS::SetNotificationAreaIcon(DWORD dwMessage, int idIcon, const String &tooltip) +{ + NOTIFYICONDATA niData; + ZeroMemory(&niData, sizeof(NOTIFYICONDATA)); + niData.cbSize = sizeof(niData); + niData.hWnd = hwndMain; + niData.uID = 0; + if (NIM_DELETE != dwMessage) + { + niData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + niData.uCallbackMessage = OBS_NOTIFICATIONAREA; + niData.hIcon = LoadIcon(hinstMain, MAKEINTRESOURCE(idIcon)); + lstrcpy(niData.szTip, tooltip); + } + return Shell_NotifyIcon(dwMessage, &niData); +} + +BOOL OBS::ShowNotificationAreaIcon() +{ + BOOL result = FALSE; + int idIcon = bRunning ? IDI_ICON2 : IDI_ICON1; + String tooltip(TEXT("OBS")); + + if (!bNotificationAreaIcon) + { + bNotificationAreaIcon = true; + result = SetNotificationAreaIcon(NIM_ADD, idIcon, tooltip); + } + else + { + result = SetNotificationAreaIcon(NIM_MODIFY, idIcon, tooltip); + } + return result; +} + +BOOL OBS::UpdateNotificationAreaIcon() +{ + if (bNotificationAreaIcon) + return ShowNotificationAreaIcon(); + return TRUE; +} + +BOOL OBS::HideNotificationAreaIcon() +{ + bNotificationAreaIcon = false; + return SetNotificationAreaIcon(NIM_DELETE, 0, TEXT("")); +} diff --git a/Source/OBS.h b/Source/OBS.h index 5dec19cc..4f6deaa3 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -341,6 +341,7 @@ enum OBS_SETSOURCEORDER, OBS_SETSOURCERENDER, OBS_UPDATESTATUSBAR, + OBS_NOTIFICATIONAREA, }; //---------------------------- @@ -656,6 +657,12 @@ private: bool QueryNewAudio(QWORD ×tamp); void MainAudioLoop(); + //--------------------------------------------------- + // notification area icon + UINT wmExplorerRestarted; + bool bNotificationAreaIcon; + BOOL SetNotificationAreaIcon(DWORD dwMessage, int idIcon, const String &tooltip); + //--------------------------------------------------- // random bla-haa @@ -930,6 +937,10 @@ public: virtual void ReportMicVolumeChange(float level, bool muted, bool finalValue); virtual void ReportDesktopVolumeChange(float level, bool muted, bool finalValue); + // notification area icon functions + BOOL ShowNotificationAreaIcon(); + BOOL UpdateNotificationAreaIcon(); + BOOL HideNotificationAreaIcon(); }; LONG CALLBACK OBSExceptionHandler (PEXCEPTION_POINTERS exceptionInfo); diff --git a/Source/OBSCapture.cpp b/Source/OBSCapture.cpp index f2ef27f5..a70dddbe 100644 --- a/Source/OBSCapture.cpp +++ b/Source/OBSCapture.cpp @@ -312,6 +312,7 @@ void OBS::Start() //------------------------------------------------------------- bRunning = true; + UpdateNotificationAreaIcon(); if(sceneElement) { @@ -484,6 +485,7 @@ void OBS::Stop() ReportStopStreamTrigger(); bRunning = false; + UpdateNotificationAreaIcon(); if(hMainThread) { OSTerminateThread(hMainThread, 20000); diff --git a/Source/SettingsGeneral.cpp b/Source/SettingsGeneral.cpp index 76b0d4fe..96af9dd9 100644 --- a/Source/SettingsGeneral.cpp +++ b/Source/SettingsGeneral.cpp @@ -79,6 +79,17 @@ void SettingsGeneral::DestroyPane() void SettingsGeneral::ApplySettings() { + //-------------------------------------------------- + + bool bShowNotificationAreaIcon = SendMessage(GetDlgItem(hwnd, IDC_NOTIFICATIONICON), BM_GETCHECK, 0, 0) == BST_CHECKED; + AppConfig->SetInt(TEXT("General"), TEXT("ShowNotificationAreaIcon"), bShowNotificationAreaIcon); + if (bShowNotificationAreaIcon) + App->ShowNotificationAreaIcon(); + else + App->HideNotificationAreaIcon(); + + bool bMinimizeToNotificationArea = SendMessage(GetDlgItem(hwnd, IDC_MINIZENOTIFICATION), BM_GETCHECK, 0, 0) == BST_CHECKED; + AppConfig->SetInt(TEXT("General"), TEXT("MinimizeToNotificationArea"), bMinimizeToNotificationArea); } void SettingsGeneral::CancelSettings() @@ -145,6 +156,14 @@ INT_PTR SettingsGeneral::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) //---------------------------------------------- + bool bShowNotificationAreaIcon = AppConfig->GetInt(TEXT("General"), TEXT("ShowNotificationAreaIcon"), 0) != 0; + SendMessage(GetDlgItem(hwnd, IDC_NOTIFICATIONICON), BM_SETCHECK, bShowNotificationAreaIcon ? BST_CHECKED : BST_UNCHECKED, 0); + + bool bMinimizeToNotificationArea = AppConfig->GetInt(TEXT("General"), TEXT("MinimizeToNotificationArea"), 0) != 0; + SendMessage(GetDlgItem(hwnd, IDC_MINIZENOTIFICATION), BM_SETCHECK, bMinimizeToNotificationArea ? BST_CHECKED : BST_UNCHECKED, 0); + + //---------------------------------------------- + SetChangedSettings(false); return TRUE; } @@ -322,6 +341,22 @@ INT_PTR SettingsGeneral::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) break; } + + case IDC_NOTIFICATIONICON: + if (SendMessage(GetDlgItem(hwnd, IDC_NOTIFICATIONICON), BM_GETCHECK, 0, 0) == BST_UNCHECKED) + { + SendMessage(GetDlgItem(hwnd, IDC_MINIZENOTIFICATION), BM_SETCHECK, BST_UNCHECKED, 0); + } + SetChangedSettings(true); + break; + + case IDC_MINIZENOTIFICATION: + if (SendMessage(GetDlgItem(hwnd, IDC_MINIZENOTIFICATION), BM_GETCHECK, 0, 0) == BST_CHECKED) + { + SendMessage(GetDlgItem(hwnd, IDC_NOTIFICATIONICON), BM_SETCHECK, BST_CHECKED, 0); + } + SetChangedSettings(true); + break; } } diff --git a/Source/WindowStuff.cpp b/Source/WindowStuff.cpp index 604891c4..45b1dd8c 100644 --- a/Source/WindowStuff.cpp +++ b/Source/WindowStuff.cpp @@ -2484,6 +2484,10 @@ LRESULT CALLBACK OBS::OBSProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if(!App->bDragResize) App->bSizeChanging = false; } + else if (wParam == SIZE_MINIMIZED && AppConfig->GetInt(TEXT("General"), TEXT("MinimizeToNotificationArea"), 0) != 0) + { + ShowWindow(hwnd, SW_HIDE); + } break; } @@ -2537,11 +2541,44 @@ LRESULT CALLBACK OBS::OBSProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa App->SetStatusBarData(); break; + case OBS_NOTIFICATIONAREA: + switch (lParam) { + case WM_LBUTTONUP: + { + bool bMinimizeToNotificationArea = AppConfig->GetInt(TEXT("General"), TEXT("MinimizeToNotificationArea"), 0) != 0; + if (bMinimizeToNotificationArea) + { + if (IsWindowVisible(hwnd)) + { + ShowWindow(hwnd, SW_MINIMIZE); + ShowWindow(hwnd, SW_HIDE); + } + else + { + ShowWindow(hwnd, SW_SHOW); + ShowWindow(hwnd, SW_RESTORE); + } + } + else + { + if (IsIconic(hwnd)) + ShowWindow(hwnd, SW_RESTORE); + else + ShowWindow(hwnd, SW_MINIMIZE); + } + } + } + break; + case WM_CLOSE: PostQuitMessage(0); break; default: + if (message == App->wmExplorerRestarted) + { + App->UpdateNotificationAreaIcon(); + } return DefWindowProc(hwnd, message, wParam, lParam); } diff --git a/resource.h b/resource.h index df71bacb..2bfdb1b9 100644 --- a/resource.h +++ b/resource.h @@ -31,6 +31,7 @@ #define IDD_BUILDINGMP4 137 #define IDD_CONFIGURETEXTSOURCE 139 #define IDD_ENDINGDELAY 140 +#define IDI_ICON2 142 #define IDC_SETTINGSLIST 1006 #define IDC_SUBDIALOG 1007 #define IDC_MODE 1008 @@ -84,6 +85,7 @@ #define IDC_OPACITY 1041 #define IDC_USETEXTEXTENTS 1041 #define IDC_CUSTOMBUFFER 1041 +#define IDC_NOTIFICATIONICON 1041 #define IDC_SERVEREDIT 1042 #define IDC_USESENDBUFFER 1042 #define IDC_FORCEMONO 1042 @@ -194,6 +196,7 @@ #define IDC_CAPTURELAYERED 1099 #define IDC_USEOUTLINE 1099 #define IDC_LOWLATENCYMODE 1099 +#define IDC_MINIZENOTIFICATION 1099 #define IDC_TIMER1 1100 #define IDC_CAPTURERAM 1100 #define IDC_COMPATIBILITYMODE 1100 @@ -283,7 +286,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 141 +#define _APS_NEXT_RESOURCE_VALUE 143 #define _APS_NEXT_COMMAND_VALUE 40051 #define _APS_NEXT_CONTROL_VALUE 1157 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/rundir/locale/en.txt b/rundir/locale/en.txt index 4ab698f2..e8f19bdd 100644 --- a/rundir/locale/en.txt +++ b/rundir/locale/en.txt @@ -169,6 +169,8 @@ Settings.General.ConfirmDelete "Are you sure you wish to remove the profile '$1 Settings.General.InvalidName "Profile names cannot use the following characters:\r\n\\ / : * ? \" < > |" Settings.General.Language "Language:" Settings.General.Profile "Setting Profile:" +Settings.General.Notification "Notification Area Icon" +Settings.General.NotificationMinimize "Minimize to Notification Area" Settings.General.Restart "Changing the language will require restarting OBS.\r\n\r\n..Though I suppose if you're changing the language you can't understand this" Settings.Publish.AutoReconnect "Auto-Reconnect:" diff --git a/ui/test2/recording.ico b/ui/test2/recording.ico new file mode 100644 index 00000000..a498debb Binary files /dev/null and b/ui/test2/recording.ico differ