Pārlūkot izejas kodu

Use new class to show the task bar icon. Try and fix issue with toolbar icon disapearing

ScottBrogden 9 gadi atpakaļ
vecāks
revīzija
ecf608231f
16 mainītis faili ar 2077 papildinājumiem un 256 dzēšanām
  1. 4 1
      AddType.cpp
  2. 49 49
      CP_Main.cpp
  3. 11 1
      CP_Main.rc
  4. 1 0
      CP_Main.rgs
  5. 41 0
      CP_Main.vcxproj
  6. 6 0
      CP_Main.vcxproj.filters
  7. 30 34
      MainFrm.cpp
  8. 5 4
      MainFrm.h
  9. 1 1
      MultiLanguage.cpp
  10. 1453 0
      NTray.cpp
  11. 303 0
      NTray.h
  12. 163 163
      OptionsKeyBoard.cpp
  13. 2 1
      Resource.h
  14. 2 2
      ShowTaskBarIcon.cpp
  15. 5 0
      StdAfx.h
  16. 1 0
      SystemTray.cpp

+ 4 - 1
AddType.cpp

@@ -118,8 +118,11 @@ void CAddType::OnBnClickedRadio1()
 	::ShowWindow(::GetDlgItem(m_hWnd, IDC_LIST1), SW_SHOW);
 	::ShowWindow(::GetDlgItem(m_hWnd, IDC_EDIT1), SW_HIDE);
 	m_lbDefaultTypes.SetFocus();
-	if(m_lbDefaultTypes.GetCount() > 0)
+	if (m_lbDefaultTypes.GetCount() > 0)
+	{
 		m_lbDefaultTypes.SetCurSel(0);
+		m_lbDefaultTypes.SetSel(0);
+	}
 }
 
 void CAddType::OnBnClickedRadio2()

+ 49 - 49
CP_Main.cpp

@@ -107,7 +107,7 @@ CCP_MainApp::CCP_MainApp()
 {
 	theApp.m_activeWnd.TrackActiveWnd(false);
 
-	m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
+	m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
 	m_copyReasonStartTime = 0;
 	m_activeGroupId = -1;
 	m_activeGroupStartTime = 0;
@@ -903,11 +903,11 @@ void CCP_MainApp::SetConnectCV(bool bConnect)
 
 	if(bConnect)
 	{
-		m_pMainFrame->m_TrayIcon.SetIcon(IDR_MAINFRAME);
+		m_pMainFrame->m_trayIcon.SetIcon(IDR_MAINFRAME);
 	}
 	else
 	{
-		m_pMainFrame->m_TrayIcon.SetIcon(IDI_DITTO_NOCOPYCB);
+		m_pMainFrame->m_trayIcon.SetIcon(IDI_DITTO_NOCOPYCB);
 	}
 
 	if(QPasteWnd())
@@ -1134,50 +1134,50 @@ void CCP_MainApp::RefreshShowInTaskBar()
 	}
 }
 
-void CCP_MainApp::SetActiveGroupId(int groupId)
-{
-	m_activeGroupId = groupId;
-	m_activeGroupStartTime = GetTickCount();
-}
-
-int CCP_MainApp::GetActiveGroupId()
-{
-	int ret = -1;
-	DWORD maxDiff = CGetSetOptions::GetSaveToGroupTimeoutMS();
-	DWORD diff = GetTickCount() - m_activeGroupStartTime;
-
-	if(m_activeGroupId > -1 &&
-		diff < maxDiff)
-	{
-		ret = m_activeGroupId;
-	}
-
-	m_activeGroupId = -1;
-	m_activeGroupStartTime = 0;
-
-	return ret;
-}
-
-void CCP_MainApp::SetCopyReason(CopyReasonEnum::CopyReason copyReason)
-{
-	m_copyReason = copyReason;
-	m_copyReasonStartTime = GetTickCount();
-}
-
-CopyReasonEnum::CopyReason CCP_MainApp::GetCopyReason()
-{
-	CopyReasonEnum::CopyReason ret = CopyReasonEnum::COPY_TO_UNKOWN;
-	DWORD maxDiff = CGetSetOptions::GetCopyReasonTimeoutMS();
-	DWORD diff = GetTickCount() - m_copyReasonStartTime;
-
-	if(m_copyReason != CopyReasonEnum::COPY_TO_UNKOWN &&
-		diff < maxDiff)
-	{
-		ret = m_copyReason;
-	}
-
-	m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
-	m_copyReasonStartTime = 0;
-
-	return ret;
+void CCP_MainApp::SetActiveGroupId(int groupId)
+{
+	m_activeGroupId = groupId;
+	m_activeGroupStartTime = GetTickCount();
+}
+
+int CCP_MainApp::GetActiveGroupId()
+{
+	int ret = -1;
+	DWORD maxDiff = CGetSetOptions::GetSaveToGroupTimeoutMS();
+	DWORD diff = GetTickCount() - m_activeGroupStartTime;
+
+	if(m_activeGroupId > -1 &&
+		diff < maxDiff)
+	{
+		ret = m_activeGroupId;
+	}
+
+	m_activeGroupId = -1;
+	m_activeGroupStartTime = 0;
+
+	return ret;
+}
+
+void CCP_MainApp::SetCopyReason(CopyReasonEnum::CopyReason copyReason)
+{
+	m_copyReason = copyReason;
+	m_copyReasonStartTime = GetTickCount();
+}
+
+CopyReasonEnum::CopyReason CCP_MainApp::GetCopyReason()
+{
+	CopyReasonEnum::CopyReason ret = CopyReasonEnum::COPY_TO_UNKOWN;
+	DWORD maxDiff = CGetSetOptions::GetCopyReasonTimeoutMS();
+	DWORD diff = GetTickCount() - m_copyReasonStartTime;
+
+	if(m_copyReason != CopyReasonEnum::COPY_TO_UNKOWN &&
+		diff < maxDiff)
+	{
+		ret = m_copyReason;
+	}
+
+	m_copyReason = CopyReasonEnum::COPY_TO_UNKOWN;
+	m_copyReasonStartTime = 0;
+
+	return ret;
 }

+ 11 - 1
CP_Main.rc

@@ -52,7 +52,8 @@ BEGIN
     "#include ""afxres.rc""         // Standard components\r\n"
     "#include ""afxprint.rc""       // printing/print preview resources\r\n"
     "#endif\r\n"
-    "\0"
+    "\r\n"
+    "1 TYPELIB ""CP_Main.tlb""\0"
 END
 
 #endif    // APSTUDIO_INVOKED
@@ -1283,6 +1284,14 @@ BEGIN
 END
 
 
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_CP_MAIN             REGISTRY                "CP_Main.rgs"
+
+
 /////////////////////////////////////////////////////////////////////////////
 //
 // String Table
@@ -1438,6 +1447,7 @@ LANGUAGE 9, 1
 #include "afxprint.rc"       // printing/print preview resources
 #endif
 
+1 TYPELIB "CP_Main.tlb"
 /////////////////////////////////////////////////////////////////////////////
 #endif    // not APSTUDIO_INVOKED
 

+ 1 - 0
CP_Main.rgs

@@ -0,0 +1 @@
+

+ 41 - 0
CP_Main.vcxproj

@@ -141,6 +141,7 @@
       <EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
       <TargetMachine>MachineX86</TargetMachine>
       <MapExports>true</MapExports>
+      <RegisterOutput>false</RegisterOutput>
     </Link>
     <Midl>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -154,6 +155,7 @@
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <PostBuildEvent>
       <Command>
@@ -195,6 +197,7 @@
       <SubSystem>Windows</SubSystem>
       <EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
       <MapExports>true</MapExports>
+      <RegisterOutput>false</RegisterOutput>
     </Link>
     <Midl>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -207,6 +210,7 @@
     <ResourceCompile>
       <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <PostBuildEvent>
       <Command>
@@ -246,6 +250,7 @@
       <GenerateMapFile>true</GenerateMapFile>
       <MapFileName>.\Debug/Ditto.map</MapFileName>
       <MapExports>true</MapExports>
+      <RegisterOutput>false</RegisterOutput>
     </Link>
     <Midl>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -259,6 +264,7 @@
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <PostBuildEvent>
       <Command>
@@ -300,6 +306,7 @@
       <MapExports>true</MapExports>
       <TargetMachine>MachineX64</TargetMachine>
       <AdditionalLibraryDirectories>C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\x64</AdditionalLibraryDirectories>
+      <RegisterOutput>false</RegisterOutput>
     </Link>
     <Midl>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -312,6 +319,7 @@
     <ResourceCompile>
       <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <Culture>0x0409</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ResourceCompile>
     <PostBuildEvent>
       <Command>
@@ -581,6 +589,7 @@
     <ClCompile Include="MainFrmThread.cpp" />
     <ClCompile Include="MessagePumpThread.cpp" />
     <ClCompile Include="MyDropTarget.cpp" />
+    <ClCompile Include="NTray.cpp" />
     <ClCompile Include="Popup.cpp" />
     <ClCompile Include="PowerManager.cpp" />
     <ClCompile Include="QPasteWndThread.cpp" />
@@ -1852,6 +1861,7 @@
     <ClInclude Include="memdc.h" />
     <ClInclude Include="MessagePumpThread.h" />
     <ClInclude Include="MyDropTarget.h" />
+    <ClInclude Include="NTray.h" />
     <ClInclude Include="NumberEdit.h" />
     <ClInclude Include="Popup.h" />
     <ClInclude Include="PowerManager.h" />
@@ -1980,6 +1990,7 @@
     <ClInclude Include="RulerRichEditCtrl\TextFile\TextFile.h" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="CP_Main.rgs" />
     <None Include="res\back.bmp" />
     <None Include="res\back1.bmp" />
     <None Include="res\back2.bmp" />
@@ -2091,6 +2102,36 @@
   <ItemGroup>
     <Manifest Include="DeclareDPIAware.manifest" />
   </ItemGroup>
+  <ItemGroup>
+    <Midl Include="CP_Main.idl">
+      <MkTypLibCompatible Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</MkTypLibCompatible>
+      <TargetEnvironment Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Win32</TargetEnvironment>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)_i.h</HeaderFileName>
+      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)_i.c</InterfaceIdentifierFileName>
+      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateStublessProxies>
+      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)$(ProjectName).tlb</TypeLibraryName>
+      <MkTypLibCompatible Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</MkTypLibCompatible>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CP_Main_i.h</HeaderFileName>
+      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CP_Main_i.c</InterfaceIdentifierFileName>
+      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</GenerateStublessProxies>
+      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)$(ProjectName).tlb</TypeLibraryName>
+      <MkTypLibCompatible Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</MkTypLibCompatible>
+      <TargetEnvironment Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Win32</TargetEnvironment>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CP_Main_i.h</HeaderFileName>
+      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CP_Main_i.c</InterfaceIdentifierFileName>
+      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateStublessProxies>
+      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)$(ProjectName).tlb</TypeLibraryName>
+      <MkTypLibCompatible Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</MkTypLibCompatible>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CP_Main_i.h</HeaderFileName>
+      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CP_Main_i.c</InterfaceIdentifierFileName>
+      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateStublessProxies>
+      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)$(ProjectName).tlb</TypeLibraryName>
+    </Midl>
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 6 - 0
CP_Main.vcxproj.filters

@@ -399,6 +399,7 @@
     </ClCompile>
     <ClCompile Include="PowerManager.cpp" />
     <ClCompile Include="QuickPasteKeyboard.cpp" />
+    <ClCompile Include="NTray.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="sqlite\CppSQLite3.h">
@@ -850,6 +851,7 @@
     </ClInclude>
     <ClInclude Include="PowerManager.h" />
     <ClInclude Include="QuickPasteKeyboard.h" />
+    <ClInclude Include="NTray.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="CP_Main.rc">
@@ -1128,6 +1130,7 @@
     <None Include="res\system_menu_20_20.png" />
     <None Include="res\system_menu_24_24.png" />
     <None Include="res\system_menu_32_32.png" />
+    <None Include="CP_Main.rgs" />
   </ItemGroup>
   <ItemGroup>
     <Filter Include="sqlite">
@@ -1157,4 +1160,7 @@
       <Filter>header</Filter>
     </Manifest>
   </ItemGroup>
+  <ItemGroup>
+    <Midl Include="CP_Main.idl" />
+  </ItemGroup>
 </Project>

+ 30 - 34
MainFrm.cpp

@@ -27,6 +27,7 @@
 
 #define WM_ICON_NOTIFY			WM_APP+10
 #define MYWM_NOTIFYICON (WM_USER+1)
+#define WM_TRAYNOTIFY WM_USER + 100
 	
 IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
 
@@ -47,7 +48,6 @@ IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
 	ON_WM_CLOSE()
 	ON_MESSAGE(WM_ADD_TO_DATABASE_FROM_SOCKET, OnAddToDatabaseFromSocket)
 	ON_MESSAGE(WM_SEND_RECIEVE_ERROR, OnErrorOnSendRecieve)
-	ON_MESSAGE(WM_CUSTOMIZE_TRAY_MENU, OnCustomizeTrayMenu)
 	ON_COMMAND(ID_FIRST_IMPORT, OnFirstImport)
 	ON_MESSAGE(WM_EDIT_WND_CLOSING, OnEditWndClose)
 	ON_WM_DESTROY()
@@ -55,7 +55,6 @@ IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
 	ON_MESSAGE(WM_SET_CONNECTED, OnSetConnected)
 	ON_MESSAGE(WM_OPEN_CLOSE_WINDWOW, OnOpenCloseWindow)
 	ON_MESSAGE(WM_LOAD_ClIP_ON_CLIPBOARD, OnLoadClipOnClipboard)
-	ON_MESSAGE(WM_TRAY_MENU_MOUSE_MOVE, OnSystemTrayMouseMove)
 	ON_COMMAND(ID_FIRST_GLOBALHOTKEYS, &CMainFrame::OnFirstGlobalhotkeys)
 	ON_MESSAGE(WM_GLOBAL_CLIPS_CLOSED, OnGlobalClipsClosed)
 	ON_MESSAGE(WM_OPTIONS_CLOSED, OnOptionsClosed)
@@ -70,6 +69,7 @@ IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
 	ON_MESSAGE(WM_SHOW_DITTO_GROUP, &CMainFrame::OnShowDittoGroup)
 	ON_COMMAND(ID_FIRST_FIXUPSTICKYCLIPORDER, &CMainFrame::OnFirstFixupstickycliporder)
 	ON_MESSAGE(WM_DISPLAYCHANGE, &CMainFrame::OnResolutionChange)
+	ON_MESSAGE(WM_TRAYNOTIFY, &CMainFrame::OnTrayNotification)
 	END_MESSAGE_MAP()
 
 	static UINT indicators[] = 
@@ -128,14 +128,13 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	SetTimer(READ_RANDOM_DB_FILE, g_Opt.ReadRandomFileInterval() * 1000, 0);
 
     SetWindowText(_T("Ditto"));
+	
+	m_trayIcon.Create(this, IDR_MENU, _T("Ditto"), CTrayNotifyIcon::LoadIcon(IDR_MAINFRAME), WM_TRAYNOTIFY, 0, 1);
+	m_trayIcon.SetDefaultMenuItem(ID_FIRST_SHOWQUICKPASTE, FALSE);	    
+    m_trayIcon.MinimiseToTray(this);
 
-    HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
-
-    m_TrayIcon.Create(NULL, WM_ICON_NOTIFY, _T("Ditto"), hIcon, IDR_MENU, FALSE, _T(""), _T(""), NULL, 20);
-    m_TrayIcon.SetSingleClickSelect(TRUE);
-    m_TrayIcon.MinimiseToTray(this);
-    m_TrayIcon.SetMenuDefaultItem(ID_FIRST_SHOWQUICKPASTE, FALSE);
-
+	theApp.m_Language.UpdateTrayIconRightClickMenu(&m_trayIcon.GetMenu());
+	
     //Only if in release
     #ifndef _DEBUG
         {
@@ -165,6 +164,17 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
     return 0;
 }
 
+LRESULT CMainFrame::OnTrayNotification(WPARAM wParam, LPARAM lParam)
+{
+	if (WM_MOUSEFIRST <= LOWORD(lParam) && LOWORD(lParam) <= WM_MOUSELAST)
+	{
+		theApp.m_activeWnd.TrackActiveWnd(true);
+	}
+	
+	m_trayIcon.OnTrayNotification(wParam, lParam);
+	return 0L;
+}
+
 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs)
 {
     if(cs.hMenu != NULL)
@@ -580,7 +590,7 @@ void CMainFrame::OnTimer(UINT_PTR nIDEvent)
     {
         case HIDE_ICON_TIMER:
             {
-                m_TrayIcon.HideIcon();
+				m_trayIcon.Hide();
                 KillTimer(nIDEvent);
             }
 			break;
@@ -711,7 +721,7 @@ LRESULT CMainFrame::OnShowTrayIcon(WPARAM wParam, LPARAM lParam)
 {
     if(lParam)
     {
-        if(!m_TrayIcon.Visible())
+        if(!m_trayIcon.IsHidden())
         {
             KillTimer(HIDE_ICON_TIMER);
             SetTimer(HIDE_ICON_TIMER, 40000, 0);
@@ -720,11 +730,11 @@ LRESULT CMainFrame::OnShowTrayIcon(WPARAM wParam, LPARAM lParam)
 
     if(wParam)
     {
-        m_TrayIcon.ShowIcon();
+		m_trayIcon.Show();
     }
     else
     {
-        m_TrayIcon.HideIcon();
+        m_trayIcon.Hide();
     }
 
     return TRUE;
@@ -835,12 +845,6 @@ bool CMainFrame::CloseAllOpenDialogs()
     return bRet;
 }
 
-LRESULT CMainFrame::OnSystemTrayMouseMove(WPARAM wParam, LPARAM lParam)
-{
-	theApp.m_activeWnd.TrackActiveWnd(true);
-	return 0;
-}
-
 LRESULT CMainFrame::OnLoadClipOnClipboard(WPARAM wParam, LPARAM lParam)
 {
 	CClip *pClip = (CClip*)wParam;
@@ -947,17 +951,6 @@ void CMainFrame::OnFirstHelp()
     CHyperLink::GotoURL(csFile, SW_SHOW);
 }
 
-LRESULT CMainFrame::OnCustomizeTrayMenu(WPARAM wParam, LPARAM lParam)
-{
-    CMenu *pMenu = (CMenu*)wParam;
-    if(pMenu)
-    {
-        theApp.m_Language.UpdateTrayIconRightClickMenu(pMenu);
-    }
-
-    return true;
-}
-
 void CMainFrame::ShowErrorMessage(CString csTitle, CString csMessage)
 {
     Log(StrF(_T("ShowErrorMessage %s - %s"), csTitle, csMessage));
@@ -1118,7 +1111,7 @@ LRESULT CMainFrame::OnShowOptions(WPARAM wParam, LPARAM lParam)
 
 LRESULT CMainFrame::OnOptionsClosed(WPARAM wParam, LPARAM lParam)
 {
-	m_TrayIcon.MinimiseToTray(this);
+	m_trayIcon.MinimiseToTray(this);
 	CAlphaBlend tran;
 	tran.SetTransparent(m_hWnd, 255, 0);
 
@@ -1130,12 +1123,15 @@ LRESULT CMainFrame::OnOptionsClosed(WPARAM wParam, LPARAM lParam)
 		m_quickPaste.m_pwndPaste->PostMessage(NM_POST_OPTIONS_WINDOW);
 	}
 
+	m_trayIcon.SetMenu(NULL, IDR_MENU);
+	theApp.m_Language.UpdateTrayIconRightClickMenu(&m_trayIcon.GetMenu());
+
 	return 0;
 }
 
 LRESULT CMainFrame::OnGlobalClipsClosed(WPARAM wParam, LPARAM lParam)
 {
-	m_TrayIcon.MinimiseToTray(this);
+	m_trayIcon.MinimiseToTray(this);
 	CAlphaBlend tran;
 	tran.SetTransparent(m_hWnd, 255, 0);
 
@@ -1159,7 +1155,7 @@ void CMainFrame::RefreshShowInTaskBar()
 
 LRESULT CMainFrame::OnDeleteClipDataClosed(WPARAM wParam, LPARAM lParam)
 {
-	m_TrayIcon.MinimiseToTray(this);
+	m_trayIcon.MinimiseToTray(this);
 	CAlphaBlend tran;
 	tran.SetTransparent(m_hWnd, 255, 0);
 
@@ -1231,7 +1227,7 @@ LRESULT CMainFrame::OnReAddTaskBarIcon(WPARAM wParam, LPARAM lParam)
 {
 	if(CGetSetOptions::GetShowIconInSysTray())
 	{
-		m_TrayIcon.AddIcon();
+		m_trayIcon.SetIcon(CTrayNotifyIcon::LoadIcon(IDR_MAINFRAME));
 	}
 	return TRUE;
 }

+ 5 - 4
MainFrm.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "SystemTray.h"
+//#include "SystemTray.h"
 #include "QuickPaste.h"
 #include "ToolTipEx.h"
 #include "EditFrameWnd.h"
@@ -8,6 +8,7 @@
 #include "ClipboardSaveRestore.h"
 #include "PowerManager.h"
 #include "DittoPopupWindow.h"
+#include "NTray.h"
 
 #define CLOSE_WINDOW_TIMER				1	
 #define HIDE_ICON_TIMER					2
@@ -54,7 +55,8 @@ public:
     #endif 
 
     CQuickPaste m_quickPaste;
-    CSystemTray m_TrayIcon;
+    //CSystemTray m_TrayIcon;
+	CTrayNotifyIcon m_trayIcon;
     ULONG m_ulCopyGap;
     CString m_csKeyboardPaste;
     CAlphaBlend m_Transparency;
@@ -108,12 +110,10 @@ protected:
     afx_msg LRESULT OnClipboardCopied(WPARAM wParam, LPARAM lParam);
     afx_msg LRESULT OnAddToDatabaseFromSocket(WPARAM wParam, LPARAM lParam);
     afx_msg LRESULT OnErrorOnSendRecieve(WPARAM wParam, LPARAM lParam);
-    afx_msg LRESULT OnCustomizeTrayMenu(WPARAM wParam, LPARAM lParam);
     afx_msg LRESULT OnEditWndClose(WPARAM wParam, LPARAM lParam);
     afx_msg LRESULT OnSetConnected(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnOpenCloseWindow(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnLoadClipOnClipboard(WPARAM wParam, LPARAM lParam);
-	afx_msg LRESULT OnSystemTrayMouseMove(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnGlobalClipsClosed(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnDeleteClipDataClosed(WPARAM wParam, LPARAM lParam);
 	afx_msg LRESULT OnOptionsClosed(WPARAM wParam, LPARAM lParam);
@@ -134,4 +134,5 @@ DECLARE_MESSAGE_MAP()public:
 	afx_msg LRESULT OnShowDittoGroup(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnFirstFixupstickycliporder();
 	afx_msg LRESULT OnResolutionChange(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnTrayNotification(WPARAM wParam, LPARAM lParam);
 };

+ 1 - 1
MultiLanguage.cpp

@@ -383,7 +383,7 @@ bool CMultiLanguage::LoadSection(TiXmlNode &doc, LANGUAGE_ARRAY &Array, CString
 	if(!node)
 	{
 		m_csLastError.Format(_T("Error finding the section %s"), csSection);
-		ASSERT(!m_csLastError);
+		//ASSERT(!m_csLastError);
 		Log(m_csLastError);
 		return false;
 	}

+ 1453 - 0
NTray.cpp

@@ -0,0 +1,1453 @@
+/*
+Module : NTray.cpp
+Purpose: implementation for a MFC class to encapsulate Shell_NotifyIcon
+Created: PJN / 14-05-1997
+History: PJN / 25-11-1997 Addition of the following
+                          1. HideIcon(), ShowIcon() & MoveToExtremeRight() 
+                          2. Support for animated tray icons
+         PJN / 23-06-1998 Class now supports the new Taskbar Creation Notification 
+                          message which comes with IE 4. This allows the tray icon
+                          to be recreated whenever the explorer restarts (Crashes!!)
+         PJN / 22-07-1998 1. Code now compiles cleanly at warning level 4
+                          2. Code is now UNICODE enabled + build configurations are provided
+                          3. The documentation for the class has been updated
+         PJN / 27-01-1999 1. Code first tries to load a 16*16 icon before loading the 32*32
+                          version. This removes the blurryness which was previously occuring
+         PJN / 28-01-1999 1. Fixed a number of level 4 warnings which were occurring.
+         PJN / 09-05-1999 1. Fixed a problem as documented in KB article "PRB: Menus for 
+                          Notification Icons Do Not Work Correctly", Article ID: Q135788 
+         PJN / 15-05-1999 1. Now uses the author's hookwnd class. This prevents the need to 
+                          create the two hidden windows namely CTrayRessurectionWnd and
+                          CTrayTimerWnd
+                          2. Code now compiles cleanly at warning level 4
+                          3. General code tidy up and rearrangement
+                          4. Added numerous ASSERT's to improve the code's robustness
+                          5. Added functions to allow context menu to be customized
+         PJN / 01-01-2001 1. Now includes copyright message in the source code and documentation. 
+                          2. Fixed problem where the window does not get focus after double clicking 
+                          on the tray icon
+                          3. Now fully supports the Windows 2000 balloon style tooltips
+                          4. Fixed a off by one problem in some of the ASSERT's
+                          5. Fixed problems with Unicode build configurations
+                          6. Provided Win2k specific build configurations
+         PJN / 10-02-2001 1. Now fully supports creation of 2 tray icons at the same time
+         PJN / 13-06-2001 1. Now removes windows hook upon call to RemoveIcon
+         PJN / 26-08-2001 1. Fixed memory leak in RemoveIcon.
+                          2. Fixed GPF in RemoveIcon by removing call to Unhook
+         PJN / 28-08-2001 1. Added support for direct access to the System Tray's HDC. This allows
+                          you to generate an icon for the tray on the fly using GDI calls. The idea
+                          came from the article by Jeff Heaton in the April issue of WDJ. Also added
+                          are overriden Create methods to allow you to easily costruct a dynamic
+                          tray icon given a BITMAP instead of an ICON.
+         PJN / 21-03-2003 1. Fixed icon resource leaks in SetIcon(LPCTSTR lpIconName) and 
+                          SetIcon(UINT nIDResource). Thanks to Egor Pervouninski for reporting this.
+                          2. Fixed unhooking of the tray icon when the notification window is being
+                          closed.
+         PJN / 31-03-2003 1. Now uses V1.05 of my Hookwnd class
+         PJN / 02-04-2003 1. Now uses v1.06 of my Hookwnd class
+                          2. Fixed a bug in the sample app for this class where the hooks should
+                          have been created as global instances rather than as member variables of
+                          the mainframe window. This ensures that the hooks remain valid even after
+                          calling DefWindowProc on the mainframe.
+         PJN / 23-07-2004 1. Minor update to remove unnecessary include of "resource.h"
+         PJN / 03-03-2006 1. Updated copyright details.
+                          2. Updated the documentation to use the same style as the web site.
+                          3. Did a spell check of the documentation.        
+                          4. Fixed some issues when the code is compiled using /Wp64. Please note that
+                          to support this the code now requires a recentish Platform SDK to be installed
+                          if the code is compiled with Visual C++ 6.
+                          5. Replaced all calls to ZeroMemory with memset.
+                          6. Fixed an issue where SetBalloonDetails was not setting the cbSize parameter.
+                          Thanks to Enrique Granda for reporting this issue.
+                          7. Added support for NIIF_USER and NIIF_NONE flags.
+                          8. Now includes support for NIM_NIMSETVERSION via SetVersion. In addition this
+                          is now automatically set in the Create() calls if the Win2k boolean parameter
+                          is set.
+                          9. Removed derivation from CObject as it was not really needed.
+                          10. Now includes support for NIM_SETFOCUS
+                          11. Added support for NIS_HIDDEN via the ShowIcon and HideIcon methods.
+                          12. Added support for NIIF_NOSOUND
+         PJN / 27-06-2006 1. Code now uses new C++ style casts rather than old style C casts where necessary.
+                          2. The class framework now requires the Platform SDK if compiled using VC 6.  
+                          3. Updated the logic of the ASSERTs which validate the various string lengths.
+                          4. Fixed a bug in CTrayNotifyIcon::SetFocus() where the cbSize value was not being
+                          set correctly.
+                          5. CTrayIconHooker class now uses ATL's CWindowImpl class in preference to the author's
+                          CHookWnd class. This does mean that for MFC only client projects, you will need to add
+                          ATL support to your project.
+                          6. Optimized CTrayIconHooker constructor code
+                          7. Updated code to compile cleanly using VC 2005. Thanks to "Itamar" for prompting this
+                          update.
+                          8. Addition of a CTRAYNOTIFYICON_EXT_CLASS and CTRAYNOTIFYICON_EXT_API macros which makes 
+                          the class easier to use in an extension dll.
+                          9. Made CTrayNotifyIcon destructor virtual
+         PJN / 03-07-2005 1. Fixed a bug where the HideIcon functionality did not work on Windows 2000. This was 
+                          related to how the cbSize member of the NOTIFYICONDATA structure was initialized. The code
+                          now dynamically determines the correct size to set at runtime according to the instructions
+                          provided by the MSDN documentation for this structure. As a result of this, all "bWin2k" 
+                          parameters which were previously exposed via CTrayNotifyIcon have now been removed as there
+                          is no need for them. Thanks to Edwin Geng for reporting this important bug. Client code will
+                          still need to intelligently make decisions on what is supported by the OS. For example balloon
+                          tray icons are only supported on Shell v5 (nominally Windows 2000 or later). CTrayNotifyIcon
+                          will ASSERT if for example calls are made to it to create a balloon tray icon on operating 
+                          systems < Windows 2000.
+         PJN / 04-07-2006 1. Fixed a bug where the menu may pop up a second time after a menu item is chosen on 
+                          Windows 2000. The problem was tracked down to the code in CTrayNotifyIcon::OnTrayNotification. 
+                          During testing of this bug, I was unable to get a workable solution using the new shell 
+                          messages of WM_CONTEXTMENU, NIN_KEYSELECT & NIN_SELECT on Windows 2000 and Windows XP. 
+                          This means that the code in CTrayNotifyIcon::OnTrayNotification uses the old way of handling 
+                          notifications (WM_RBUTTDOWN*). This does mean that by default, client apps which use the 
+                          CTrayNotifyIcon class will not support the new keyboard and mouse semantics for tray icons
+                          (IMHO this is no big loss!). Client code is of course free to handle their own notifications. 
+                          If you go down this route then I would advise you to thoroughly test your application on 
+                          Windows 2000 and Windows XP as my testing has shown that there is significant differences in 
+                          how tray icons handle their messaging on these 2 operating systems. Thanks to Edwin Geng for 
+                          reporting this issue.
+                          2. Class now displays the menu based on the current message's screen coordinates, rather than
+                          the current cursor screen coordinates.
+                          3. Fixed bug in sample app where if the about dialog is already up and it is reactivated 
+                          from the tray menu, it did not bring itself into the foreground
+         PJN / 06-07-2006 1. Reverted the change made for v1.53 where the screen coordinates used to show the context 
+                          menu use the current message's screen coordinates. Instead the pre v1.53 mechanism which 
+                          uses the current cursor's screen coordinates is now used. Thanks to Itamar Syn-Hershko for 
+                          reporting this issue.
+         PJN / 19-07-2006 1. The default menu item can now be customized via SetDefaultMenuItem and 
+                          GetDefaultMenuItem. Thanks to Mikhail Bykanov for suggesting this nice update.
+                          2. Optimized CTrayNotifyIcon constructor code
+         PJN / 19-08-2005 1. Updated the code to operate independent of MFC if so desired. This requires WTL which is an
+                          open source library extension for ATL to provide UI support along the lines of MFC. Thanks to 
+                          zhiguo zhao for providing this very nice addition.
+         PJN / 15-09-2006 1. Fixed a bug where WM_DESTROY messages were not been handled correctly for the top level window
+                          which the CTrayIconHooker class subclasses in order to handle the tray resurrection message,
+                          the animation timers and auto destroying of the icons when the top level window is destroyed. 
+                          Thanks to Edward Livingston for reporting this bug.
+                          2. Fixed a bug where the tray icons were not being recreated correctly when we receive the 
+                          "TaskbarCreated" when Explorer is restarted. Thanks to Nuno Esculcas for reporting this bug.
+                          3. Split the functionality of hiding versus deleting and showing versus creating of the tray
+                          icon into 4 separate functions, namely Delete(), Create(), Hide() and Show(). Note that Hide 
+                          and Show functionality is only available on Shell v5 or later.
+                          4. Fixed an issue with recreation of tray icons which use a dynamic icon created from a bitmap
+                          (through the use of BitmapToIcon).
+                          5. CTrayNotifyIcon::LoadIconResource now loads up an icon as a shared icon resource using 
+                          LoadImage. This should avoid resource leaks using this function.
+         PJN / 15-06-2007 1. Updated copyright messages.
+                          2. If the code detects that MFC is not included in the project, the code uses the standard
+                          preprocessor define "_CSTRING_NS" to declare the string class to use rather than explicitly 
+                          using WTL::CString. Thanks to Krzysztof Suszka for reporting this issue.
+                          3. Updated sample app to compile cleanly on VC 2005.
+                          4. Addition of a "BOOL bShow" to all the Create methods. This allows you to create an icon 
+                          without actually showing it. This avoids the flicker which previously occurred if you created 
+                          the icon and then immediately hid the icon. Thanks to Krzysztof Suszka for providing this 
+                          suggestion.
+                          5. Demo app now initially creates the first icon as hidden for demonstration purposes.
+                          6. Added support for NIIF_LARGE_ICON. This Vista only feature allows you to create a large 
+                          balloon icon.
+                          7. Added support for NIF_REALTIME. This Vista only flag allows you to specify not to bother 
+                          showing the balloon if it is delayed due to the presence of an existing balloon.
+                          8. Added support for NOTIFYICONDATA::hBalloonIcon. This Vista only feature allows you to 
+                          create a user specified balloon icon which is different to the actual tray icon.
+                          9. LoadIconResource method now includes support for loading large icons and has been renamed
+                          to simply LoadIcon. Also two overridden versions of this method have been provided which allow
+                          the hInstance resource ID to be specified to load the icon from.
+                          10. Reworked the internal code to CTrayNotifyIcon which detects the shell version.
+                          11. Updated the tray icon text in the demo app to better demonstrate the features of the class.
+                          12. Updated the WTL sample to be consistent with the MFC sample code
+                          13. Updated comments in documentation about usage of the Platform SDK.
+         PJN / 13-10-2007 1. Subclassing of the top level window is now not down internally by the CTrayNotifyIcon class
+                          using the CTrayIconHooker class. Instead now a hidden top level window is created for each tray 
+                          icon you create and these look after handling the tray resurrection and animated icon timer
+                          messages. This refactoring of the internals of the class now also fixes a bug where an application
+                          which creates multiples tray icons would only get one icon recreated when the tray resurrection
+                          message was received. Thanks to Steven Dwyer for prompting this update. 
+                          2. Updated the MFC sample app to correctly initialize ATL for VC 6
+         PJN / 12-03-2008 1. Updated copyright details
+                          2. Fixed a bug in SetBalloonDetails where the code did not set the flag NIF_ICON if a user defined
+                          icon was being set. Thanks to "arni" for reporting this bug. 
+                          3. Updated the sample app to clean compile on VC 2008
+         PJN / 22-06-2008 1. Code now compiles cleanly using Code Analysis (/analyze)
+                          2. Updated code to compile correctly using _ATL_CSTRING_EXPLICIT_CONSTRUCTORS define
+                          3. Removed VC 6 style AppWizard comments from the code.
+                          4. The code now only supports VC 2005 or later. 
+         PJN / 10-04-2010 1. Updated copyright details.
+                          2. Updated the project settings to more modern default values.
+                          3. Updated the WTL version of LoadIcon to use the more modern ModuleHelper class from WTL to get 
+                          the resource instance. Thanks to "Yarp" for reporting this issue.
+                          4. The class now has support for the Windows 7 "NIIF_RESPECT_QUIET_TIME" flag. This value can be
+                          set via the new "bQuietTime" parameter to the Create method.
+                          5. Updated the code which does version detection of the Shell version
+         PJN / 10-07-2010 1. Updated the sample app to compile cleanly on VS 2010.
+                          2. Fixed a bug in CTrayNotifyIcon::Delete where the code would ASSERT if the tray notify icon was
+                          never actually created. Thanks to "trophim" for reporting this bug.
+         PJN / 06-11-2010 1. Minor update to code in SetTooltipText to code which handles unreferenced variable compiler 
+                          warning
+                          2. Implemented a GetTooltipMaxSize method which reports the maximum size which the tooltip can be
+                          for a tray icon. Thanks to Geert van Horrik for this nice addition
+                          3. All places which copy text to the underlying NOTIFYICONDATA now use the _TRUNCATE parameter in 
+                          their call to the Safe CRT runtime. This change in behaviour means that client apps will no longer
+                          crash if they supply data larger than this Windows structure can accommadate. Thanks to Geert van 
+                          Horrik for prompting this update.
+                          4. All calls to sizeof(struct)/sizeof(first element) have been replaced with _countof
+                          5. Fixed a linker error when compiling the WTL sample app in release mode.
+         PJN / 26-11-2010 1. Minor update to use DBG_UNREFERENCED_LOCAL_VARIABLE macro. Thanks to Jukka Ojanen for prompting this 
+                          update.
+         PJN / 27-04-2016 1. Updated copyright details.
+                          2. Updated the code to clean compile on VC 2012 - VC 2015.
+                          3. Removed support for CTRAYNOTIFYICON_NOWIN2K preprocessor macro
+                          4. Removed various redefines of ShellApi.h constants from the code
+                          5. Added SAL annotations to all the code.
+                          6. Reworked the definition of the string class to now use a typedef internal to the CTrayNotifyIcon 
+                          class.
+                          7. Updated CTrayNotifyIcon::OnTrayNotification to handle NOTIFYICON_VERSION_4 style notifications.
+                          8. Reworked the internal storage of the animation icons to use ATL::CHeapPtr
+
+Copyright (c) 1997 - 2016 by PJ Naughter (Web: www.naughter.com, Email: [email protected])
+
+All rights reserved.
+
+Copyright / Usage Details:
+
+You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
+when your product is released in binary form. You are allowed to modify the source code in any way you want 
+except you cannot modify the copyright details at the top of each module. If you want to distribute source 
+code with your application, then you are only allowed to distribute versions released by the author. This is 
+to maintain a single distribution point for the source code. 
+
+*/
+
+
+/////////////////////////////////  Includes  //////////////////////////////////
+
+#include "stdafx.h"
+#include "NTray.h"
+#ifndef _INC_SHELLAPI
+#pragma message("To avoid this message, please put ShellApi.h in your pre compiled header (normally stdafx.h)")
+#include <ShellApi.h>
+#endif //#ifndef _INC_SHELLAPI
+
+
+/////////////////////////////////  Macros /////////////////////////////////////
+
+#ifdef _AFX
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif //#ifdef _DEBUG
+#endif //#ifdef _AFX
+
+#ifndef NIF_REALTIME
+#define NIF_REALTIME 0x00000040
+#endif //#ifndef NIF_REALTIME
+
+#ifndef NIIF_LARGE_ICON
+#define NIIF_LARGE_ICON 0x00000020
+#endif //#ifndef NIIF_LARGE_ICON
+
+#ifndef NIIF_RESPECT_QUIET_TIME
+#define NIIF_RESPECT_QUIET_TIME 0x00000080
+#endif //#ifndef NIIF_RESPECT_QUIET_TIME
+
+
+///////////////////////////////// Implementation //////////////////////////////
+
+const UINT wm_TaskbarCreated = RegisterWindowMessage(_T("TaskbarCreated"));
+
+CTrayNotifyIcon::CTrayNotifyIcon() : m_bCreated(FALSE),
+                                     m_bHidden(FALSE),
+                                     m_pNotificationWnd(NULL),
+                                     m_bDefaultMenuItemByPos(TRUE),
+                                     m_nDefaultMenuItem(0),
+                                     m_hDynamicIcon(NULL),
+                                     m_ShellVersion(Version4), //Assume version 4 of the shell
+                                     m_nNumIcons(0),
+                                     m_nTimerID(0),
+                                     m_nCurrentIconIndex(0),
+                                     m_nTooltipMaxSize(-1)
+{
+  typedef HRESULT (CALLBACK DLLGETVERSION)(DLLVERSIONINFO*);
+  typedef DLLGETVERSION* LPDLLGETVERSION;
+
+  //Try to get the details with DllGetVersion
+  HMODULE hShell32 = GetModuleHandle(_T("SHELL32.DLL"));
+  if (hShell32 != NULL)
+  {
+    LPDLLGETVERSION lpfnDllGetVersion = reinterpret_cast<LPDLLGETVERSION>(GetProcAddress(hShell32, "DllGetVersion"));
+    if (lpfnDllGetVersion != NULL)
+    {
+      DLLVERSIONINFO vinfo;
+      vinfo.cbSize = sizeof(DLLVERSIONINFO);
+      if (SUCCEEDED(lpfnDllGetVersion(&vinfo)))
+      {
+        if ((vinfo.dwMajorVersion > 6) || (vinfo.dwMajorVersion == 6 && vinfo.dwMinorVersion > 0))
+          m_ShellVersion = Version7;
+        else if (vinfo.dwMajorVersion == 6)
+        {
+          if (vinfo.dwBuildNumber >= 6000)
+            m_ShellVersion = VersionVista;
+          else
+            m_ShellVersion = Version6;
+        }
+        else if (vinfo.dwMajorVersion >= 5)
+          m_ShellVersion = Version5;
+      }
+    }
+  }
+
+  memset(&m_NotifyIconData, 0, sizeof(m_NotifyIconData));
+  m_NotifyIconData.cbSize = GetNOTIFYICONDATASizeForOS();
+}
+
+CTrayNotifyIcon::~CTrayNotifyIcon()
+{
+  //Delete the tray icon
+  Delete(TRUE);
+  
+  //Free up any dynamic icon we may have
+  if (m_hDynamicIcon != NULL)
+  {
+    DestroyIcon(m_hDynamicIcon);
+    m_hDynamicIcon = NULL;
+  }
+}
+
+BOOL CTrayNotifyIcon::Delete(_In_ BOOL bCloseHelperWindow)
+{
+  //What will be the return value from this function (assume the best)
+  BOOL bSuccess = TRUE;
+
+  if (m_bCreated)
+  {
+    m_NotifyIconData.uFlags = 0;
+    bSuccess = Shell_NotifyIcon(NIM_DELETE, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+    m_bCreated = FALSE;
+  }
+  
+  //Close the helper window if requested to do so
+  if (bCloseHelperWindow && IsWindow())
+    SendMessage(WM_CLOSE);
+  
+  return bSuccess;
+}
+
+BOOL CTrayNotifyIcon::Create(_In_ BOOL bShow)
+{
+  m_NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+  
+  if (!bShow)
+  {
+    ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+    m_NotifyIconData.uFlags |= NIF_STATE;
+    m_NotifyIconData.dwState = NIS_HIDDEN;
+    m_NotifyIconData.dwStateMask = NIS_HIDDEN;
+  }
+  
+  BOOL bSuccess = Shell_NotifyIcon(NIM_ADD, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+  if (bSuccess)
+  {
+    m_bCreated = TRUE;
+    
+    if (!bShow)
+      m_bHidden = TRUE;
+  }
+  return bSuccess;
+}
+
+BOOL CTrayNotifyIcon::Hide()
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+//  ATLASSERT(!m_bHidden); //Only makes sense to hide the icon if it is not already hidden
+
+  m_NotifyIconData.uFlags = NIF_STATE;
+  m_NotifyIconData.dwState = NIS_HIDDEN;
+  m_NotifyIconData.dwStateMask = NIS_HIDDEN; 
+  BOOL bSuccess = Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+  if (bSuccess)
+    m_bHidden = TRUE;
+  return bSuccess;
+}
+
+BOOL CTrayNotifyIcon::Show()
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+//  ATLASSERT(m_bHidden); //Only makes sense to show the icon if it has been previously hidden
+  ATLASSERT(m_bCreated);
+
+  m_NotifyIconData.uFlags = NIF_STATE;
+  m_NotifyIconData.dwState = 0;
+  m_NotifyIconData.dwStateMask = NIS_HIDDEN;
+  BOOL bSuccess = Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+  if (bSuccess)
+    m_bHidden = FALSE;
+  return bSuccess;
+}
+
+void CTrayNotifyIcon::SetMenu(_In_ HMENU hMenu, UINT menuId)
+{
+  m_Menu.DestroyMenu();
+
+  if (menuId != 0)
+  {
+	  if (!m_Menu.LoadMenu(menuId))
+	  {
+		  ATLASSERT(FALSE);
+		  return;
+	  }
+  }
+  else
+  {
+	  m_Menu.Attach(hMenu);
+  }
+
+#ifdef _AFX
+  CMenu* pSubMenu = m_Menu.GetSubMenu(0);
+  ATLASSUME(pSubMenu != NULL); //Your menu resource has been designed incorrectly
+    
+  //Make the specified menu item the default (bold font)
+  pSubMenu->SetDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#else
+  CMenuHandle subMenu = m_Menu.GetSubMenu(0);
+  ATLASSERT(subMenu.IsMenu()); //Your menu resource has been designed incorrectly
+
+  //Make the specified menu item the default (bold font)
+  subMenu.SetMenuDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#endif //#ifdef _AFX
+}
+
+CMenu& CTrayNotifyIcon::GetMenu()
+{
+  return m_Menu;
+}
+
+void CTrayNotifyIcon::SetDefaultMenuItem(_In_ UINT uItem, _In_ BOOL fByPos)
+{ 
+  m_nDefaultMenuItem = uItem; 
+  m_bDefaultMenuItemByPos = fByPos; 
+
+  //Also update in the live menu if it is present
+  if (m_Menu.operator HMENU())
+  {
+  #ifdef _AFX
+    CMenu* pSubMenu = m_Menu.GetSubMenu(0);
+    ATLASSUME(pSubMenu != NULL); //Your menu resource has been designed incorrectly
+
+    pSubMenu->SetDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+  #else
+    CMenuHandle subMenu = m_Menu.GetSubMenu(0);
+    ATLASSERT(subMenu.IsMenu()); //Your menu resource has been designed incorrectly
+    
+    subMenu.SetMenuDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+  #endif //#ifdef _AFX
+  }
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Validate our parameters
+  ATLASSUME((pNotifyWnd != NULL) && ::IsWindow(pNotifyWnd->operator HWND()));
+#ifdef _DEBUG
+  if (m_ShellVersion >= Version5) //If on Shell v5 or higher, then use the larger size tooltip
+  {
+    NOTIFYICONDATA_2 dummy;
+    ATLASSERT(_tcslen(pszTooltipText) < _countof(dummy.szTip));
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  }
+  else
+  {
+    NOTIFYICONDATA_1 dummy;
+    ATLASSERT(_tcslen(pszTooltipText) < _countof(dummy.szTip));
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  }
+#endif //#ifdef _DEBUG
+  ATLASSERT(hIcon != NULL); 
+  ATLASSERT(nNotifyMessage >= WM_USER); //Make sure we avoid conflict with other messages
+
+  //Load up the menu resource which is to be used as the context menu
+  if (!m_Menu.LoadMenu(uMenuID == 0 ? uID : uMenuID))
+  {
+    ATLASSERT(FALSE);
+    return FALSE;
+  }
+#ifdef _AFX
+  CMenu* pSubMenu = m_Menu.GetSubMenu(0);
+  if (pSubMenu == NULL) 
+  {
+    ATLASSERT(FALSE); //Your menu resource has been designed incorrectly
+    return FALSE;
+  }
+  //Make the specified menu item the default (bold font)
+  pSubMenu->SetDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#else
+  CMenuHandle subMenu = m_Menu.GetSubMenu(0);
+  if (!subMenu.IsMenu())
+  {
+    ATLASSERT(FALSE); //Your menu resource has been designed incorrectly
+    return FALSE;
+  }
+  subMenu.SetMenuDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#endif //#ifdef _AFX
+
+  //Create the helper window
+  if (!CreateHelperWindow())
+    return FALSE;
+
+  //Call the Shell_NotifyIcon function
+  m_pNotificationWnd = pNotifyWnd;
+  m_NotifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+  m_NotifyIconData.hWnd = pNotifyWnd->operator HWND();
+  m_NotifyIconData.uID = uID;
+  m_NotifyIconData.uCallbackMessage = nNotifyMessage;
+  m_NotifyIconData.hIcon = hIcon;
+  _tcsncpy_s(m_NotifyIconData.szTip, _countof(m_NotifyIconData.szTip), pszTooltipText, _TRUNCATE);
+
+  if (!bShow)
+  {
+    ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+    m_NotifyIconData.uFlags |= NIF_STATE;
+    m_NotifyIconData.dwState = NIS_HIDDEN;
+    m_NotifyIconData.dwStateMask = NIS_HIDDEN;
+  }
+  m_bCreated = Shell_NotifyIcon(NIM_ADD, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+  if (m_bCreated)
+  {
+    if (!bShow)
+      m_bHidden = TRUE;
+    
+    //Turn on Shell v5 style behaviour if supported
+    if (m_ShellVersion >= Version5)
+      SetVersion(NOTIFYICON_VERSION);
+  }
+  
+  return m_bCreated;
+}
+
+BOOL CTrayNotifyIcon::SetVersion(_In_ UINT uVersion)
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+
+  //Call the Shell_NotifyIcon function
+  m_NotifyIconData.uVersion = uVersion;
+  return Shell_NotifyIcon(NIM_SETVERSION, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+HICON CTrayNotifyIcon::BitmapToIcon(_In_ CBitmap* pBitmap)
+{
+  //Validate our parameters
+  ATLASSUME(pBitmap != NULL);
+
+  //Get the width and height of a small icon
+  int w = GetSystemMetrics(SM_CXSMICON);
+  int h = GetSystemMetrics(SM_CYSMICON);
+
+  //Create a 0 mask
+  int nMaskSize = h*(w/8);
+  ATL::CHeapPtr<BYTE> pMask;
+  if (!pMask.Allocate(nMaskSize))
+    return NULL;
+  memset(pMask.m_pData, 0, nMaskSize);
+
+  //Create a mask bitmap
+  CBitmap maskBitmap;
+#ifdef _AFX
+  BOOL bSuccess = maskBitmap.CreateBitmap(w, h, 1, 1, pMask.m_pData);
+#else
+  maskBitmap.CreateBitmap(w, h, 1, 1, pMask.m_pData);
+  BOOL bSuccess = !maskBitmap.IsNull();
+#endif //#ifdef _AFX
+
+  //Handle the error
+  if (!bSuccess)
+    return NULL;
+
+  //Create an ICON base on the bitmap just created
+  ICONINFO iconInfo;
+  iconInfo.fIcon = TRUE;
+  iconInfo.xHotspot = 0;
+  iconInfo.yHotspot = 0;
+  iconInfo.hbmMask = maskBitmap;
+  iconInfo.hbmColor = *pBitmap; 
+  return CreateIconIndirect(&iconInfo); 
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Convert the bitmap to an Icon
+  if (m_hDynamicIcon != NULL)
+    DestroyIcon(m_hDynamicIcon);
+  m_hDynamicIcon = BitmapToIcon(pBitmap);
+
+  //Pass the buck to the other function to do the work
+  return Create(pNotifyWnd, uID, pszTooltipText, m_hDynamicIcon, nNotifyMessage, uMenuID, bShow);
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Validate our parameters
+  ATLASSUME(phIcons != NULL);
+  ATLASSERT(nNumIcons >= 2); //must be using at least 2 icons if you are using animation
+  ATLASSERT(dwDelay);
+
+  //let the normal Create function do its stuff
+  BOOL bSuccess = Create(pNotifyWnd, uID, pszTooltipText, phIcons[0], nNotifyMessage, uMenuID, bShow);
+  if (bSuccess)
+  {
+    //Start the animation
+    bSuccess = StartAnimation(phIcons, nNumIcons, dwDelay);
+  }
+
+  return bSuccess;
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Validate our parameters
+  ATLASSUME((pNotifyWnd != NULL) && ::IsWindow(pNotifyWnd->operator HWND()));
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+#ifdef _DEBUG
+  NOTIFYICONDATA_2 dummy;
+  ATLASSERT(_tcslen(pszTooltipText) < _countof(dummy.szTip));
+  ATLASSERT(_tcslen(pszBalloonText) < _countof(dummy.szInfo));
+  ATLASSERT(_tcslen(pszBalloonCaption) < _countof(dummy.szInfoTitle));
+  ATLASSERT(hIcon); 
+  ATLASSERT(nNotifyMessage >= WM_USER); //Make sure we avoid conflict with other messages
+  DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+#endif //#ifdef _DEBUG
+
+  //Load up the menu resource which is to be used as the context menu
+  if (!m_Menu.LoadMenu(uMenuID == 0 ? uID : uMenuID))
+  {
+    ATLASSERT(FALSE);
+    return FALSE;
+  }
+#ifdef _AFX
+  CMenu* pSubMenu = m_Menu.GetSubMenu(0);
+  if (pSubMenu == NULL) 
+  {
+    ATLASSERT(FALSE); //Your menu resource has been designed incorrectly
+    return FALSE;
+  }
+  //Make the specified menu item the default (bold font)
+  pSubMenu->SetDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#else
+  CMenuHandle subMenu = m_Menu.GetSubMenu(0);
+  if (!subMenu.IsMenu()) 
+  {
+    ATLASSERT(FALSE); //Your menu resource has been designed incorrectly
+    return FALSE;
+  }
+  //Make the specified menu item the default (bold font)
+  subMenu.SetMenuDefaultItem(m_nDefaultMenuItem, m_bDefaultMenuItemByPos);
+#endif //#ifdef _AFX
+
+  //Create the helper window
+  if (!CreateHelperWindow())
+    return FALSE;
+
+  //Call the Shell_NotifyIcon function
+  m_pNotificationWnd = pNotifyWnd;
+  m_NotifyIconData.hWnd = pNotifyWnd->operator HWND();
+  m_NotifyIconData.uID = uID;
+  m_NotifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
+  m_NotifyIconData.uCallbackMessage = nNotifyMessage;
+  m_NotifyIconData.hIcon = hIcon;
+  _tcsncpy_s(m_NotifyIconData.szTip, _countof(m_NotifyIconData.szTip), pszTooltipText, _TRUNCATE);
+  _tcsncpy_s(m_NotifyIconData.szInfo, _countof(m_NotifyIconData.szInfo), pszBalloonText, _TRUNCATE);
+  _tcsncpy_s(m_NotifyIconData.szInfoTitle, _countof(m_NotifyIconData.szInfoTitle), pszBalloonCaption, _TRUNCATE);
+  m_NotifyIconData.uTimeout = nTimeout;
+  switch (style)
+  {
+    case Warning:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_WARNING;
+      break;
+    }
+    case Error:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_ERROR;
+      break;
+    }
+    case Info:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_INFO;
+      break;
+    }
+    case None:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_NONE;
+      break;
+    }
+    case User:
+    {
+      if (hBalloonIcon != NULL)
+      {
+        ATLASSERT(m_ShellVersion >= VersionVista);
+        m_NotifyIconData.hBalloonIcon = hBalloonIcon;
+      }
+      else
+      {
+        ATLASSERT(hIcon != NULL); //You forget to provide a user icon
+      }
+      m_NotifyIconData.dwInfoFlags = NIIF_USER;
+      break;
+    }
+    default:
+    {
+      ATLASSERT(FALSE);
+      break;
+    }
+  }
+  if (bNoSound)
+    m_NotifyIconData.dwInfoFlags |= NIIF_NOSOUND;
+  if (bLargeIcon)
+  {
+    ATLASSERT(m_ShellVersion >= VersionVista); //Only supported on Vista Shell
+    m_NotifyIconData.dwInfoFlags |= NIIF_LARGE_ICON;
+  }
+  if (bRealtime)
+  {
+    ATLASSERT(m_ShellVersion >= VersionVista); //Only supported on Vista Shell
+    m_NotifyIconData.uFlags |= NIF_REALTIME;
+  }
+  if (!bShow)
+  {
+    ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+    m_NotifyIconData.uFlags |= NIF_STATE;
+    m_NotifyIconData.dwState = NIS_HIDDEN;
+    m_NotifyIconData.dwStateMask = NIS_HIDDEN;
+  }
+  if (bQuietTime)
+  {
+    ATLASSERT(m_ShellVersion >= Version7); //Only supported on Windows 7 Shell
+    m_NotifyIconData.dwInfoFlags |= NIIF_RESPECT_QUIET_TIME;
+  }
+  
+  m_bCreated = Shell_NotifyIcon(NIM_ADD, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+  if (m_bCreated)
+  {
+    if (!bShow)
+      m_bHidden = TRUE;
+  
+    //Turn on Shell v5 tray icon behaviour
+    SetVersion(NOTIFYICON_VERSION);
+  }
+
+  return m_bCreated;
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Convert the bitmap to an ICON
+  if (m_hDynamicIcon != NULL)
+    DestroyIcon(m_hDynamicIcon);
+  m_hDynamicIcon = BitmapToIcon(pBitmap);
+
+  //Pass the buck to the other function to do the work
+  return Create(pNotifyWnd, uID, pszTooltipText, pszBalloonText, pszBalloonCaption, nTimeout, style, m_hDynamicIcon, nNotifyMessage, uMenuID, bNoSound, bLargeIcon, bRealtime, hBalloonIcon, bQuietTime, bShow);
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#else
+BOOL CTrayNotifyIcon::Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_opt_ HICON hBalloonIcon, _In_ BOOL bQuietTime, _In_ BOOL bShow)
+#endif //#ifdef _AFX
+{
+  //Validate our parameters
+  ATLASSUME(phIcons != NULL);
+  ATLASSERT(nNumIcons >= 2); //must be using at least 2 icons if you are using animation
+  ATLASSERT(dwDelay);
+
+  //let the normal Create function do its stuff
+  BOOL bSuccess = Create(pNotifyWnd, uID, pszTooltipText, pszBalloonText, pszBalloonCaption, nTimeout, style, phIcons[0], nNotifyMessage, uMenuID, bNoSound, bLargeIcon, bRealtime, hBalloonIcon, bQuietTime, bShow);
+  if (bSuccess)
+  {
+    //Start the animation
+    bSuccess = StartAnimation(phIcons, nNumIcons, dwDelay);
+  }
+
+  return bSuccess;
+}
+
+BOOL CTrayNotifyIcon::SetBalloonDetails(_In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ BalloonStyle style, _In_ UINT nTimeout, _In_ HICON hUserIcon, _In_ BOOL bNoSound, _In_ BOOL bLargeIcon, _In_ BOOL bRealtime, _In_ HICON hBalloonIcon)
+{
+  if (!m_bCreated)
+    return FALSE;
+
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+#ifdef _DEBUG
+  NOTIFYICONDATA_2 dummy;
+  ATLASSERT(_tcslen(pszBalloonText) < _countof(dummy.szInfo));
+  ATLASSERT(_tcslen(pszBalloonCaption) < _countof(dummy.szInfoTitle));
+  DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+#endif //#ifdef _DEBUG
+
+  //Call the Shell_NotifyIcon function
+  m_NotifyIconData.uFlags = NIF_INFO;
+  _tcsncpy_s(m_NotifyIconData.szInfo, _countof(m_NotifyIconData.szInfo), pszBalloonText, _TRUNCATE);
+  _tcsncpy_s(m_NotifyIconData.szInfoTitle, _countof(m_NotifyIconData.szInfoTitle), pszBalloonCaption, _TRUNCATE);
+  m_NotifyIconData.uTimeout = nTimeout;
+  switch (style)
+  {
+    case Warning:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_WARNING;
+      break;
+    }
+    case Error:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_ERROR;
+      break;
+    }
+    case Info:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_INFO;
+      break;
+    }
+    case None:
+    {
+      m_NotifyIconData.dwInfoFlags = NIIF_NONE;
+      break;
+    }
+    case User:
+    {
+      if (hBalloonIcon != NULL)
+      {
+        ATLASSERT(m_ShellVersion >= VersionVista);
+        m_NotifyIconData.hBalloonIcon = hBalloonIcon;
+      }
+      else
+      {
+        ATLASSERT(hUserIcon != NULL); //You forget to provide a user icon
+        m_NotifyIconData.uFlags |= NIF_ICON;
+        m_NotifyIconData.hIcon = hUserIcon;
+      }
+        
+      m_NotifyIconData.dwInfoFlags = NIIF_USER;
+      break;
+    }
+    default:
+    {
+      ATLASSERT(FALSE);
+      break;
+    }
+  }
+  if (bNoSound)
+    m_NotifyIconData.dwInfoFlags |= NIIF_NOSOUND;
+  if (bLargeIcon)
+    m_NotifyIconData.dwInfoFlags |= NIIF_LARGE_ICON;
+  if (bRealtime)
+    m_NotifyIconData.uFlags |= NIF_REALTIME;
+
+  return Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+CTrayNotifyIcon::String CTrayNotifyIcon::GetBalloonText() const
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+
+  String sText;
+  if (m_bCreated)
+    sText = m_NotifyIconData.szInfo;
+
+  return sText;
+}
+
+CTrayNotifyIcon::String CTrayNotifyIcon::GetBalloonCaption() const
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+
+  String sText;
+  if (m_bCreated)
+    sText = m_NotifyIconData.szInfoTitle;
+
+  return sText;
+}
+
+UINT CTrayNotifyIcon::GetBalloonTimeout() const
+{
+  //Validate our parameters
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or later
+
+  UINT nTimeout = 0;
+  if (m_bCreated)
+    nTimeout = m_NotifyIconData.uTimeout;
+
+  return nTimeout;
+}
+
+BOOL CTrayNotifyIcon::SetTooltipText(_In_ LPCTSTR pszTooltipText)
+{
+  if (!m_bCreated)
+    return FALSE;
+
+  if (m_ShellVersion >= Version5) //Allow the larger size tooltip text if on Shell v5 or later
+  {
+  #ifdef _DEBUG
+    NOTIFYICONDATA_2 dummy;
+    ATLASSERT(_tcslen(pszTooltipText) < _countof(dummy.szTip));
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  #endif //#ifdef _DEBUG
+  }
+  else 
+  {
+  #ifdef _DEBUG
+    NOTIFYICONDATA_1 dummy;
+    ATLASSERT(_tcslen(pszTooltipText) < _countof(dummy.szTip));
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  #endif //#ifdef _DEBUG
+  }
+
+  //Call the Shell_NotifyIcon function
+  m_NotifyIconData.uFlags = NIF_TIP;
+  _tcsncpy_s(m_NotifyIconData.szTip, _countof(m_NotifyIconData.szTip), pszTooltipText, _TRUNCATE);
+  return Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+BOOL CTrayNotifyIcon::SetTooltipText(_In_ UINT nID)
+{
+  String sToolTipText;
+  if (!sToolTipText.LoadString(nID))
+    return FALSE;
+
+  //Let the other version of the function handle the rest
+  return SetTooltipText(sToolTipText);
+}
+
+int	CTrayNotifyIcon::GetTooltipMaxSize()
+{
+  //Return the cached value if we have one
+  if (m_nTooltipMaxSize != -1) 
+    return m_nTooltipMaxSize;
+
+  //Otherwise calculate the maximum based on the shell version
+  if (m_ShellVersion >= Version5)
+  {
+    NOTIFYICONDATA_2 dummy;
+    m_nTooltipMaxSize = _countof(dummy.szTip) - 1; //The -1 is to allow size for the NULL terminator
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  }
+  else
+  {
+    NOTIFYICONDATA_1 dummy;
+    m_nTooltipMaxSize = _countof(dummy.szTip) - 1; //The -1 is to allow size for the NULL terminator
+    DBG_UNREFERENCED_LOCAL_VARIABLE(dummy);
+  }
+
+  return m_nTooltipMaxSize;
+}
+
+BOOL CTrayNotifyIcon::SetIcon(_In_ CBitmap* pBitmap)
+{
+  //Convert the bitmap to an ICON
+  if (m_hDynamicIcon != NULL)
+    DestroyIcon(m_hDynamicIcon);
+  m_hDynamicIcon = BitmapToIcon(pBitmap);
+
+  //Pass the buck to the other function to do the work
+  return SetIcon(m_hDynamicIcon);
+}
+
+BOOL CTrayNotifyIcon::SetIcon(_In_ HICON hIcon)
+{
+  //Validate our parameters
+  ATLASSERT(hIcon != NULL);
+
+  if (!m_bCreated)
+    return FALSE;
+
+  //Since we are going to use one icon, stop any animation
+  StopAnimation();
+
+  //Call the Shell_NotifyIcon function
+  m_NotifyIconData.uFlags = NIF_ICON;
+  m_NotifyIconData.hIcon = hIcon;
+  return Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+BOOL CTrayNotifyIcon::SetIcon(_In_ LPCTSTR lpIconName)
+{
+  return SetIcon(LoadIcon(lpIconName));
+}
+
+BOOL CTrayNotifyIcon::SetIcon(_In_ UINT nIDResource)
+{
+  return SetIcon(LoadIcon(nIDResource));
+}
+
+BOOL CTrayNotifyIcon::SetStandardIcon(_In_ LPCTSTR lpIconName)
+{
+  return SetIcon(::LoadIcon(NULL, lpIconName));
+}
+
+BOOL CTrayNotifyIcon::SetStandardIcon(_In_ UINT nIDResource)
+{
+  return SetIcon(::LoadIcon(NULL, MAKEINTRESOURCE(nIDResource)));
+}
+
+BOOL CTrayNotifyIcon::SetIcon(_In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay)
+{
+  //Validate our parameters
+  ATLASSERT(nNumIcons >= 2); //must be using at least 2 icons if you are using animation
+  ATLASSUME(phIcons != NULL);
+  ATLASSERT(dwDelay);
+
+  if (!SetIcon(phIcons[0]))
+    return FALSE;
+
+  //Start the animation
+  return StartAnimation(phIcons, nNumIcons, dwDelay);
+}
+
+HICON CTrayNotifyIcon::LoadIcon(_In_ HINSTANCE hInstance, _In_ LPCTSTR lpIconName, _In_ BOOL bLargeIcon)
+{
+  return static_cast<HICON>(::LoadImage(hInstance, lpIconName, IMAGE_ICON, bLargeIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXSMICON), bLargeIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYSMICON), LR_SHARED));
+}
+
+HICON CTrayNotifyIcon::LoadIcon(_In_ HINSTANCE hInstance, _In_ UINT nIDResource, _In_ BOOL bLargeIcon)
+{
+  return LoadIcon(hInstance, MAKEINTRESOURCE(nIDResource), bLargeIcon);
+}
+
+HICON CTrayNotifyIcon::LoadIcon(_In_ LPCTSTR lpIconName, _In_ BOOL bLargeIcon)
+{
+#ifdef _AFX
+  return LoadIcon(AfxGetResourceHandle(), lpIconName, bLargeIcon);
+#else
+  return LoadIcon(ModuleHelper::GetResourceInstance(), lpIconName, bLargeIcon);
+#endif //#ifdef _AFX
+}
+
+HICON CTrayNotifyIcon::LoadIcon(_In_ UINT nIDResource, _In_ BOOL bLargeIcon)
+{
+  return LoadIcon(MAKEINTRESOURCE(nIDResource), bLargeIcon);
+}
+
+#ifdef _AFX
+BOOL CTrayNotifyIcon::SetNotificationWnd(_In_ CWnd* pNotifyWnd)
+#else
+BOOL CTrayNotifyIcon::SetNotificationWnd(_In_ CWindow* pNotifyWnd)
+#endif //#ifdef _AFX
+{
+  //Validate our parameters
+  ATLASSUME((pNotifyWnd != NULL) && ::IsWindow(pNotifyWnd->operator HWND()));
+
+  if (!m_bCreated)
+    return FALSE;
+
+  //Call the Shell_NotifyIcon function
+  m_pNotificationWnd = pNotifyWnd;
+  m_NotifyIconData.hWnd = pNotifyWnd->operator HWND();
+  m_NotifyIconData.uFlags = 0;
+  return Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+CTrayNotifyIcon::String CTrayNotifyIcon::GetTooltipText() const
+{
+  String sText;
+  if (m_bCreated)
+    sText = m_NotifyIconData.szTip;
+
+  return sText;
+}
+
+HICON CTrayNotifyIcon::GetIcon() const
+{
+  HICON hIcon = NULL;
+  if (m_bCreated)
+  {
+    if (UsingAnimatedIcon())
+      hIcon = GetCurrentAnimationIcon();
+    else
+      hIcon = m_NotifyIconData.hIcon;
+  }
+
+  return hIcon;
+}
+
+#ifdef _AFX
+CWnd* CTrayNotifyIcon::GetNotificationWnd() const
+#else
+CWindow* CTrayNotifyIcon::GetNotificationWnd() const
+#endif //#ifdef _AFX
+{
+  return m_pNotificationWnd;
+}
+
+BOOL CTrayNotifyIcon::SetFocus()
+{
+  ATLASSERT(m_ShellVersion >= Version5); //Only supported on Shell v5 or greater
+
+  //Call the Shell_NotifyIcon function
+  return Shell_NotifyIcon(NIM_SETFOCUS, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+LRESULT CTrayNotifyIcon::OnTrayNotification(WPARAM wParam, LPARAM lParam)
+{
+  BOOL bShowMenu = FALSE;
+  BOOL bDoubleClick = FALSE;
+  BOOL bSingleClick = FALSE;
+  UINT nIconID = 0;
+  if ((m_NotifyIconData.uVersion == 0) || (m_NotifyIconData.uVersion == NOTIFYICON_VERSION))
+  {
+    nIconID = static_cast<UINT>(wParam);
+    bShowMenu = (lParam == WM_RBUTTONUP);
+    bDoubleClick = (lParam == WM_LBUTTONDBLCLK);
+	bSingleClick = (lParam == WM_LBUTTONUP);
+  }
+  else
+  {
+    nIconID = HIWORD(lParam);
+    bShowMenu = (LOWORD(lParam) == WM_CONTEXTMENU);
+    bDoubleClick = (LOWORD(lParam) == WM_LBUTTONDBLCLK);
+	bSingleClick = (LOWORD(lParam) == WM_LBUTTONUP);
+  }
+
+  //Return quickly if its not for this tray icon
+  if (nIconID != m_NotifyIconData.uID)
+    return 0L;
+
+  //Show the context menu or handle the double click
+  if (bShowMenu || bDoubleClick || bSingleClick)
+  {
+  #ifdef _AFX
+    CMenu* pSubMenu = m_Menu.GetSubMenu(0);
+    ATLASSUME(pSubMenu != NULL); //Your menu resource has been designed incorrectly
+  #else
+    CMenuHandle subMenu = m_Menu.GetSubMenu(0);
+    ATLASSERT(subMenu.IsMenu());
+  #endif //#ifdef _AFX
+  
+    if (bShowMenu)
+    {
+      CPoint ptCursor;
+      GetCursorPos(&ptCursor);
+      ::SetForegroundWindow(m_NotifyIconData.hWnd);  
+    #ifdef _AFX
+      ::TrackPopupMenu(pSubMenu->m_hMenu, TPM_LEFTBUTTON, ptCursor.x, ptCursor.y, 0, m_NotifyIconData.hWnd, NULL);
+    #else
+      ::TrackPopupMenu(subMenu, TPM_LEFTBUTTON, ptCursor.x, ptCursor.y, 0, m_NotifyIconData.hWnd, NULL);
+    #endif //#ifdef _AFX
+      ::PostMessage(m_NotifyIconData.hWnd, WM_NULL, 0, 0);
+    }
+    else if (bDoubleClick || bSingleClick) //double click received, the default action is to execute first menu item 
+    {
+      ::SetForegroundWindow(m_NotifyIconData.hWnd);
+    #ifdef _AFX
+      UINT nDefaultItem = pSubMenu->GetDefaultItem(GMDI_GOINTOPOPUPS, FALSE);
+    #else
+      UINT nDefaultItem = subMenu.GetMenuDefaultItem(FALSE, GMDI_GOINTOPOPUPS);
+    #endif //#ifdef _AFX
+      if (nDefaultItem != -1)
+        ::SendMessage(m_NotifyIconData.hWnd, WM_COMMAND, nDefaultItem, 0);
+    }
+  }
+
+  return 1; // handled
+}
+
+BOOL CTrayNotifyIcon::GetDynamicDCAndBitmap(_In_ CDC* pDC, _In_ CBitmap* pBitmap)
+{
+  //Validate our parameters
+  ATLASSUME(pDC != NULL);
+  ATLASSUME(pBitmap != NULL);
+
+  //Get the HWND for the desktop
+#ifdef _AFX
+  CWnd* pWndScreen = CWnd::GetDesktopWindow();
+  if (pWndScreen == NULL)
+    return FALSE;
+#else
+  CWindow WndScreen(::GetDesktopWindow());
+  if (!WndScreen.IsWindow())
+    return FALSE;
+#endif //#ifdef _AFX
+
+  //Get the desktop HDC to create a compatible bitmap from
+#ifdef _AFX
+  CDC* pDCScreen = pWndScreen->GetDC();
+  if (pDCScreen == NULL)
+    return FALSE;
+#else
+  CDC DCScreen(WndScreen.GetDC());
+  if (DCScreen.IsNull())
+    return FALSE;
+#endif //#ifdef _AFX
+
+  //Get the width and height of a small icon
+  int w = GetSystemMetrics(SM_CXSMICON);
+  int h = GetSystemMetrics(SM_CYSMICON);
+
+  //Create an off-screen bitmap that the dynamic tray icon 
+  //can be drawn into (Compatible with the desktop DC)
+#ifdef _AFX
+  BOOL bSuccess = pBitmap->CreateCompatibleBitmap(pDCScreen, w, h);
+#else
+  BOOL bSuccess = (pBitmap->CreateCompatibleBitmap(DCScreen.operator HDC(), w, h) != NULL);
+#endif //#ifdef _AFX
+  if (!bSuccess)
+  {
+  #ifdef _AFX
+    pWndScreen->ReleaseDC(pDCScreen);
+  #else
+    WndScreen.ReleaseDC(DCScreen);
+  #endif //#ifdef _AFX
+    return FALSE;
+  }
+
+  //Get a HDC to the newly created off-screen bitmap
+#ifdef _AFX
+  bSuccess = pDC->CreateCompatibleDC(pDCScreen);
+#else
+  bSuccess = (pDC->CreateCompatibleDC(DCScreen.operator HDC()) != NULL);
+#endif //#ifdef _AFX
+  if (!bSuccess)
+  {
+  //Release the Screen DC now that we are finished with it
+  #ifdef _AFX
+    pWndScreen->ReleaseDC(pDCScreen);
+  #else
+    WndScreen.ReleaseDC(DCScreen);
+  #endif //#ifdef _AFX
+
+    //Free up the bitmap now that we are finished with it
+    pBitmap->DeleteObject();
+
+    return FALSE;
+  }
+
+  //Select the bitmap into the offscreen DC
+#ifdef _AFX
+  pDC->SelectObject(pBitmap);
+#else
+  pDC->SelectBitmap(pBitmap->operator HBITMAP());
+#endif //#ifdef _AFX
+
+  //Release the Screen DC now that we are finished with it
+#ifdef _AFX
+  pWndScreen->ReleaseDC(pDCScreen);
+#else
+  WndScreen.ReleaseDC(DCScreen);
+#endif //#ifdef _AFX
+
+  return TRUE;
+}
+
+DWORD CTrayNotifyIcon::GetNOTIFYICONDATASizeForOS()
+{
+  //What will be the return value from this function
+  DWORD dwSize = sizeof(NOTIFYICONDATA_1);
+
+  switch (m_ShellVersion)
+  {
+    case Version7: //Deliberate fallthrough
+    case VersionVista:
+    {
+      dwSize = sizeof(NOTIFYICONDATA_4);
+      break;
+    }
+    case Version6:
+    {
+      dwSize = sizeof(NOTIFYICONDATA_3);
+      break;
+    }
+    case Version5:
+    {
+      dwSize = sizeof(NOTIFYICONDATA_2);
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+  
+  return dwSize;
+}
+
+BOOL CTrayNotifyIcon::StartAnimation(_In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay)
+{
+  //Validate our parameters
+  ATLASSERT(nNumIcons >= 2);  //must be using at least 2 icons if you are using animation
+  ATLASSUME(phIcons != NULL); //array of icon handles must be valid
+  ATLASSERT(dwDelay);         //must be non zero timer interval
+
+  //Stop the animation if already started  
+  StopAnimation();
+
+  //Hive away all the values locally
+  ATLASSERT(m_Icons.m_pData == NULL);
+  if (!m_Icons.Allocate(nNumIcons))
+    return FALSE;
+  ATLASSUME(m_Icons.m_pData != NULL);
+  for (int i=0; i<nNumIcons; i++)
+    m_Icons.m_pData[i] = phIcons[i];
+  m_nNumIcons = nNumIcons;
+
+  //Start up the timer 
+  m_nTimerID = SetTimer(m_NotifyIconData.uID, dwDelay);
+
+  return TRUE;
+}
+
+void CTrayNotifyIcon::StopAnimation()
+{
+  //Kill the timer
+  if (m_nTimerID)
+  {
+    if (::IsWindow(m_hWnd))
+      KillTimer(m_nTimerID);
+    m_nTimerID = 0;
+  }
+ 
+  //Free up the memory
+  if (m_Icons.m_pData != NULL)
+    m_Icons.Free();
+
+  //Reset the other animation related variables
+  m_nCurrentIconIndex = 0;
+  m_nNumIcons = 0;
+}
+
+BOOL CTrayNotifyIcon::UsingAnimatedIcon() const
+{
+  return (m_nNumIcons != 0);
+}
+
+HICON CTrayNotifyIcon::GetCurrentAnimationIcon() const 
+{ 
+  //Valiate our parameters
+  ATLASSERT(UsingAnimatedIcon());
+  ATLASSUME(m_Icons.m_pData != NULL);
+  
+  return m_Icons.m_pData[m_nCurrentIconIndex];
+}
+
+BOOL CTrayNotifyIcon::ProcessWindowMessage(_In_ HWND /*hWnd*/, _In_ UINT nMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD /*dwMsgMapID*/)
+{
+  lResult = 0;
+  BOOL bHandled = FALSE;
+
+  if (nMsg == wm_TaskbarCreated)
+  {
+    lResult = OnTaskbarCreated(wParam, lParam);
+    bHandled = TRUE;
+  }
+  else if ((nMsg == WM_TIMER) && (wParam == m_NotifyIconData.uID))
+  {
+    OnTimer(m_NotifyIconData.uID); 
+    bHandled = TRUE;
+  }
+  else if (nMsg == WM_DESTROY)
+  {
+    OnDestroy();
+    bHandled = TRUE;
+  }
+
+  return bHandled;
+}
+
+void CTrayNotifyIcon::OnDestroy()
+{
+  StopAnimation();
+}
+
+LRESULT CTrayNotifyIcon::OnTaskbarCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
+{
+  //Refresh the tray icon if necessary
+  BOOL bShowing = IsShowing();
+  Delete(FALSE);
+  Create(bShowing);
+  
+  return 0;
+}
+
+#ifdef _DEBUG
+void CTrayNotifyIcon::OnTimer(UINT_PTR nIDEvent)
+#else
+void CTrayNotifyIcon::OnTimer(UINT_PTR /*nIDEvent*/)
+#endif //#ifdef _DEBUG
+{
+  //Validate our parameters
+  ATLASSERT(nIDEvent == m_nTimerID);
+  ATLASSUME(m_Icons.m_pData != NULL);
+
+  //increment the icon index
+  ++m_nCurrentIconIndex;
+  m_nCurrentIconIndex = m_nCurrentIconIndex % m_nNumIcons;
+
+  //update the tray icon
+  m_NotifyIconData.uFlags = NIF_ICON;
+  m_NotifyIconData.hIcon = m_Icons.m_pData[m_nCurrentIconIndex];
+  Shell_NotifyIcon(NIM_MODIFY, reinterpret_cast<PNOTIFYICONDATA>(&m_NotifyIconData));
+}
+
+BOOL CTrayNotifyIcon::CreateHelperWindow()
+{
+  //Let the base class do its thing
+  return (CWindowImpl<CTrayNotifyIcon>::Create(NULL, CWindow::rcDefault, _T("CTrayNotifyIcon Helper Window"), WS_OVERLAPPEDWINDOW) != NULL);
+}
+
+CTrayWnd  CTrayNotifyIcon::m_wndInvisible;
+
+BOOL CTrayNotifyIcon::RemoveTaskbarIcon(CWnd* pWnd)
+{
+	LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
+
+	// Create static invisible window
+	if (!::IsWindow(m_wndInvisible.m_hWnd))
+	{
+		if (!m_wndInvisible.CreateEx(0, pstrOwnerClass, _T(""), WS_POPUP,
+			CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+			NULL, 0))
+		{
+			return FALSE;
+		}
+	}
+
+	pWnd->SetParent(&m_wndInvisible);
+
+	return TRUE;
+}
+
+void CTrayNotifyIcon::MinimiseToTray(CWnd* pWnd)
+{
+	RemoveTaskbarIcon(pWnd);
+	pWnd->ModifyStyle(WS_VISIBLE, 0);
+}
+
+void CTrayNotifyIcon::MaximiseFromTray(CWnd* pWnd)
+{
+	pWnd->SetParent(NULL);
+
+	pWnd->ModifyStyle(0, WS_VISIBLE);
+	pWnd->RedrawWindow(NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME |
+		RDW_INVALIDATE | RDW_ERASE);
+
+	// Move focus away and back again to ensure taskbar icon is recreated
+	if (::IsWindow(m_wndInvisible.m_hWnd))
+		m_wndInvisible.SetActiveWindow();
+	pWnd->SetActiveWindow();
+	pWnd->SetForegroundWindow();
+}

+ 303 - 0
NTray.h

@@ -0,0 +1,303 @@
+/*
+Module : NTray.h
+Purpose: Interface for a MFC class to encapsulate Shell_NotifyIcon
+Created: PJN / 14-05-1997
+
+Copyright (c) 1997 - 2016 by PJ Naughter (Web: www.naughter.com, Email: [email protected])
+
+All rights reserved.
+
+Copyright / Usage Details:
+
+You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
+when your product is released in binary form. You are allowed to modify the source code in any way you want 
+except you cannot modify the copyright details at the top of each module. If you want to distribute source 
+code with your application, then you are only allowed to distribute versions released by the author. This is 
+to maintain a single distribution point for the source code. 
+
+*/
+
+
+/////////////////////////// Macros / Defines ///////////////////////////
+
+#pragma once
+
+#ifndef _NTRAY_H__
+#define _NTRAY_H__
+
+#ifndef CTRAYNOTIFYICON_EXT_CLASS
+#define CTRAYNOTIFYICON_EXT_CLASS
+#endif //#ifndef CTRAYNOTIFYICON_EXT_CLASS
+
+#ifndef _In_
+#define _In_
+#endif //#ifndef _In_
+
+#ifndef _In_opt_
+#define _In_opt_
+#endif //#ifndef _In_opt_
+
+#ifndef _Out_
+#define _Out_
+#endif //#ifndef _Out_
+
+#ifndef _Inout_
+#define _Inout_
+#endif //#ifndef _Inout_
+
+#ifndef __ATLWIN_H__
+#pragma message("CTrayNotifyIcon as of v1.51 requires ATL support to implement its functionality. If your project is MFC only, then you need to update it to include ATL support")
+#endif //#ifndef __ATLWIN_H__
+
+#ifndef _AFX
+#ifndef __ATLMISC_H__
+#pragma message("To avoid this message, please put atlmisc.h (part of WTL) in your pre compiled header (normally stdafx.h)")
+#include <atlmisc.h> //If you do want to use CTrayNotifyIcon independent of MFC, then you need to download and install WTL from http://sourceforge.net/projects/wtl
+#endif //#ifndef __ATLMISC_H__
+#endif //#ifndef _AFX
+
+#include "TrayWnd.h"
+
+
+/////////////////////////// Classes ///////////////////////////////////////////
+
+//the actual tray notification class wrapper
+class CTRAYNOTIFYICON_EXT_CLASS CTrayNotifyIcon : public CWindowImpl<CTrayNotifyIcon>
+{
+public:
+//Enums / Typedefs
+ #ifndef _AFX
+  typedef _CSTRING_NS::CString String;
+#else
+  typedef CString String;
+#endif //#ifndef _AFX
+
+  enum BalloonStyle
+  {
+    Warning,
+    Error,
+    Info,
+    None,
+    User
+  };
+
+  //We use our own definitions of the NOTIFYICONDATA structs so that
+  //we can use all the functionality without requiring client code to 
+  //define _WIN32_IE >= 0x500
+  typedef struct _NOTIFYICONDATA_1 //The version of the structure supported by Shell v4
+  {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    TCHAR szTip[64];
+  } NOTIFYICONDATA_1;
+
+  typedef struct _NOTIFYICONDATA_2 //The version of the structure supported by Shell v5
+  {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    TCHAR szTip[128];
+    DWORD dwState;
+    DWORD dwStateMask;
+    TCHAR szInfo[256];
+    union 
+    {
+      UINT uTimeout;
+      UINT uVersion;
+    } DUMMYUNIONNAME;
+    TCHAR szInfoTitle[64];
+    DWORD dwInfoFlags;
+  } NOTIFYICONDATA_2;
+
+  typedef struct _NOTIFYICONDATA_3 //The version of the structure supported by Shell v6
+  {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    TCHAR szTip[128];
+    DWORD dwState;
+    DWORD dwStateMask;
+    TCHAR szInfo[256];
+    union 
+    {
+      UINT uTimeout;
+      UINT uVersion;
+    } DUMMYUNIONNAME;
+    TCHAR szInfoTitle[64];
+    DWORD dwInfoFlags;
+    GUID guidItem;
+  } NOTIFYICONDATA_3;
+
+  typedef struct _NOTIFYICONDATA_4 //The version of the structure supported by Shell v7
+  {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    TCHAR szTip[128];
+    DWORD dwState;
+    DWORD dwStateMask;
+    TCHAR szInfo[256];
+    union 
+    {
+      UINT uTimeout;
+      UINT uVersion;
+    } DUMMYUNIONNAME;
+    TCHAR szInfoTitle[64];
+    DWORD dwInfoFlags;
+    GUID guidItem;
+    HICON hBalloonIcon;
+  } NOTIFYICONDATA_4;
+
+  DECLARE_WND_CLASS(_T("TrayNotifyIconClass"))
+
+
+//Constructors / Destructors
+  CTrayNotifyIcon();
+  virtual ~CTrayNotifyIcon();
+
+//Create the tray icon
+#ifdef _AFX
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWnd* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+#else
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON hIcon, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ CBitmap* pBitmap, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+  BOOL Create(_In_ CWindow* pNotifyWnd, _In_ UINT uID, _In_ LPCTSTR pszTooltipText, _In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ UINT nTimeout, _In_ BalloonStyle style, _In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay, _In_ UINT nNotifyMessage, _In_ UINT uMenuID = 0, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_opt_ HICON hBalloonIcon = NULL, _In_ BOOL bQuietTime = FALSE, _In_ BOOL bShow = TRUE);
+#endif //#ifdef _AFX
+
+  BOOL RemoveTaskbarIcon(CWnd* pWnd);
+  void MinimiseToTray(CWnd* pWnd);
+  void MaximiseFromTray(CWnd* pWnd);
+
+//Sets or gets the Tooltip text
+  BOOL   SetTooltipText(_In_ LPCTSTR pszTooltipText);
+  BOOL   SetTooltipText(_In_ UINT nID);
+  String GetTooltipText() const;
+  int	   GetTooltipMaxSize();
+
+//Sets or gets the icon displayed
+  BOOL SetIcon(_In_ HICON hIcon);
+  BOOL SetIcon(_In_ CBitmap* pBitmap);
+  BOOL SetIcon(_In_ LPCTSTR lpIconName);
+  BOOL SetIcon(_In_ UINT nIDResource);
+  BOOL SetIcon(_In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay);
+  BOOL SetStandardIcon(_In_ LPCTSTR lpIconName);
+  BOOL SetStandardIcon(_In_ UINT nIDResource);
+  HICON GetIcon() const;
+  BOOL UsingAnimatedIcon() const;
+
+//Sets or gets the window to send notification messages to
+#ifdef _AFX
+  BOOL SetNotificationWnd(_In_ CWnd* pNotifyWnd);
+  CWnd* GetNotificationWnd() const;
+#else
+  BOOL SetNotificationWnd(_In_ CWindow* pNotifyWnd);
+  CWindow* GetNotificationWnd() const;
+#endif //#ifdef _AFX
+
+//Modification of the tray icons
+  BOOL Delete(_In_ BOOL bCloseHelperWindow = TRUE);
+  BOOL Create(_In_ BOOL bShow = TRUE);
+  BOOL Hide();
+  BOOL Show();
+
+//Dynamic tray icon support
+  HICON BitmapToIcon(_In_ CBitmap* pBitmap);
+  static BOOL GetDynamicDCAndBitmap(_In_ CDC* pDC, _In_ CBitmap* pBitmap);
+
+//Modification of the menu to use as the context menu
+  void SetMenu(_In_ HMENU hMenu, UINT menuId);
+  CMenu& GetMenu();
+  void SetDefaultMenuItem(_In_ UINT uItem, _In_ BOOL fByPos);
+  void GetDefaultMenuItem(_Out_ UINT& uItem, _Out_ BOOL& fByPos) { uItem = m_nDefaultMenuItem; fByPos = m_bDefaultMenuItemByPos; };
+
+//Default handler for tray notification message
+  virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
+
+//Status information
+  BOOL IsShowing() const { return !IsHidden(); };
+  BOOL IsHidden() const { return m_bHidden; };
+
+//Sets or gets the Balloon style tooltip settings
+  BOOL         SetBalloonDetails(_In_ LPCTSTR pszBalloonText, _In_ LPCTSTR pszBalloonCaption, _In_ BalloonStyle style, _In_ UINT nTimeout, _In_ HICON hUserIcon = NULL, _In_ BOOL bNoSound = FALSE, _In_ BOOL bLargeIcon = FALSE, _In_ BOOL bRealtime = FALSE, _In_ HICON hBalloonIcon = NULL);
+  String       GetBalloonText() const;
+  String       GetBalloonCaption() const;
+  BalloonStyle GetBalloonStyle() const;
+  UINT         GetBalloonTimeout() const;
+
+//Other functionality
+  BOOL SetVersion(_In_ UINT uVersion);
+  BOOL SetFocus();
+
+//Helper functions to load tray icon from resources
+  static HICON LoadIcon(_In_ LPCTSTR lpIconName, _In_ BOOL bLargeIcon = FALSE);
+  static HICON LoadIcon(_In_ UINT nIDResource, _In_ BOOL bLargeIcon = FALSE);
+  static HICON LoadIcon(_In_ HINSTANCE hInstance, _In_ LPCTSTR lpIconName, _In_ BOOL bLargeIcon = FALSE);
+  static HICON LoadIcon(_In_ HINSTANCE hInstance, _In_ UINT nIDResource, _In_ BOOL bLargeIcon = FALSE);
+
+protected:
+//Methods
+  BOOL         CreateHelperWindow();
+  BOOL         StartAnimation(_In_ HICON* phIcons, _In_ int nNumIcons, _In_ DWORD dwDelay);
+  void         StopAnimation();
+  HICON        GetCurrentAnimationIcon() const;
+  virtual BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT nMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID);
+  LRESULT      OnTaskbarCreated(WPARAM wParam, LPARAM lParam);
+  void         OnTimer(UINT_PTR nIDEvent);
+  void         OnDestroy();
+  DWORD        GetNOTIFYICONDATASizeForOS();
+
+  static CTrayWnd  m_wndInvisible;
+
+//Enums
+  enum ShellVersion
+  {
+    Version4     = 0, //PreWin2k
+    Version5     = 1, //Win2k
+    Version6     = 2, //XP
+    VersionVista = 3, //Vista
+    Version7     = 4, //Windows7
+  };
+
+//Member variables
+  NOTIFYICONDATA_4     m_NotifyIconData;
+  BOOL                 m_bCreated;
+  BOOL                 m_bHidden;
+#ifdef _AFX
+  CWnd*                m_pNotificationWnd;
+#else
+  CWindow*             m_pNotificationWnd;
+#endif //#ifdef _AFX
+  CMenu                m_Menu;
+  UINT                 m_nDefaultMenuItem;
+  BOOL                 m_bDefaultMenuItemByPos;
+  ShellVersion         m_ShellVersion;
+  HICON                m_hDynamicIcon; //Our cached copy of the last icon created with BitmapToIcon
+  ATL::CHeapPtr<HICON> m_Icons;
+  int                  m_nNumIcons;
+  UINT_PTR             m_nTimerID;
+  int                  m_nCurrentIconIndex;
+  int                  m_nTooltipMaxSize;
+};
+
+#endif //#ifndef _NTRAY_H__

+ 163 - 163
OptionsKeyBoard.cpp

@@ -1,164 +1,164 @@
-// OptionsKeyBoard.cpp : implementation file
-//
-
-#include "stdafx.h"
-#include "CP_Main.h"
-#include "OptionsKeyBoard.h"
-
-#ifdef _DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// COptionsKeyBoard property page
-
-IMPLEMENT_DYNCREATE(COptionsKeyBoard, CPropertyPage)
-
-COptionsKeyBoard::COptionsKeyBoard() : CPropertyPage(COptionsKeyBoard::IDD)
-{
-	m_csTitle = theApp.m_Language.GetString("KeyboardShortcutsTitle", "Keyboard Shortcuts");
-	m_psp.pszTitle = m_csTitle;
-	m_psp.dwFlags |= PSP_USETITLE;
-	
-	//{{AFX_DATA_INIT(COptionsKeyBoard)
-	//}}AFX_DATA_INIT
-}
-
-COptionsKeyBoard::~COptionsKeyBoard()
-{
-}
-
-void COptionsKeyBoard::DoDataExchange(CDataExchange* pDX)
-{
-	CPropertyPage::DoDataExchange(pDX);
-	//{{AFX_DATA_MAP(COptionsKeyBoard)
-	DDX_Control(pDX, IDC_CHECK_SEND_PASTE, m_btSendPaste);
-	DDX_Control(pDX, IDC_HOTKEY9, m_Nine);
-	DDX_Control(pDX, IDC_HOTKEY8, m_Eight);
-	DDX_Control(pDX, IDC_HOTKEY7, m_Seven);
-	DDX_Control(pDX, IDC_HOTKEY6, m_Six);
-	DDX_Control(pDX, IDC_HOTKEY5, m_Five);
-	DDX_Control(pDX, IDC_HOTKEY4, m_Four);
-	DDX_Control(pDX, IDC_HOTKEY3, m_Three);
-	DDX_Control(pDX, IDC_HOTKEY2, m_Two);
-	DDX_Control(pDX, IDC_HOTKEY10, m_Ten);
-	DDX_Control(pDX, IDC_HOTKEY1, m_One);
-	DDX_Control(pDX, IDC_HOTKEY, m_HotKey);
-	DDX_Control(pDX, IDC_HOTKEY_TEXT_ONLY, m_TextOnlyKey);
-	//}}AFX_DATA_MAP
-	DDX_Control(pDX, IDC_STATIC_CUSTOM_KEYS, m_CustomeKeysHelp);
-	DDX_Control(pDX, IDC_CHECK_MOVE_CLIPS_ON_PASTE, m_btMoveClipOnGlobal10);
+// OptionsKeyBoard.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "OptionsKeyBoard.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsKeyBoard property page
+
+IMPLEMENT_DYNCREATE(COptionsKeyBoard, CPropertyPage)
+
+COptionsKeyBoard::COptionsKeyBoard() : CPropertyPage(COptionsKeyBoard::IDD)
+{
+	m_csTitle = theApp.m_Language.GetString("KeyboardShortcutsTitle", "Keyboard Shortcuts");
+	m_psp.pszTitle = m_csTitle;
+	m_psp.dwFlags |= PSP_USETITLE;
+	
+	//{{AFX_DATA_INIT(COptionsKeyBoard)
+	//}}AFX_DATA_INIT
+}
+
+COptionsKeyBoard::~COptionsKeyBoard()
+{
+}
+
+void COptionsKeyBoard::DoDataExchange(CDataExchange* pDX)
+{
+	CPropertyPage::DoDataExchange(pDX);
+	//{{AFX_DATA_MAP(COptionsKeyBoard)
+	DDX_Control(pDX, IDC_CHECK_SEND_PASTE, m_btSendPaste);
+	DDX_Control(pDX, IDC_HOTKEY9, m_Nine);
+	DDX_Control(pDX, IDC_HOTKEY8, m_Eight);
+	DDX_Control(pDX, IDC_HOTKEY7, m_Seven);
+	DDX_Control(pDX, IDC_HOTKEY6, m_Six);
+	DDX_Control(pDX, IDC_HOTKEY5, m_Five);
+	DDX_Control(pDX, IDC_HOTKEY4, m_Four);
+	DDX_Control(pDX, IDC_HOTKEY3, m_Three);
+	DDX_Control(pDX, IDC_HOTKEY2, m_Two);
+	DDX_Control(pDX, IDC_HOTKEY10, m_Ten);
+	DDX_Control(pDX, IDC_HOTKEY1, m_One);
+	DDX_Control(pDX, IDC_HOTKEY, m_HotKey);
+	DDX_Control(pDX, IDC_HOTKEY_TEXT_ONLY, m_TextOnlyKey);
+	//}}AFX_DATA_MAP
+	DDX_Control(pDX, IDC_STATIC_CUSTOM_KEYS, m_CustomeKeysHelp);
+	DDX_Control(pDX, IDC_CHECK_MOVE_CLIPS_ON_PASTE, m_btMoveClipOnGlobal10);
 	DDX_Control(pDX, IDC_HOTKEY_SAVE_CLIPBOARD, m_saveClipboardHotKey);
-}
-
-BEGIN_MESSAGE_MAP(COptionsKeyBoard, CPropertyPage)
-	//{{AFX_MSG_MAP(COptionsKeyBoard)
-	//}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// COptionsKeyBoard message handlers
-
-BOOL COptionsKeyBoard::OnInitDialog() 
-{
-	CPropertyPage::OnInitDialog();
-
-	CString csHelpPath = CGetSetOptions::GetPath(PATH_HELP);
-	csHelpPath += "DittoCustomKeys.htm";
-	m_CustomeKeysHelp.SetURL(csHelpPath);
-
-	m_pParent = (COptionsSheet *)GetParent();
-
-	theApp.m_pDittoHotKey->CopyToCtrl(m_HotKey, m_hWnd, IDC_CHECK_WIN_DITTO);
-
-	theApp.m_pPosOne->CopyToCtrl(m_One, m_hWnd, IDC_CHECK_WIN1);
-	theApp.m_pPosTwo->CopyToCtrl(m_Two, m_hWnd, IDC_CHECK_WIN2);
-	theApp.m_pPosThree->CopyToCtrl(m_Three, m_hWnd, IDC_CHECK_WIN3);
-	theApp.m_pPosFour->CopyToCtrl(m_Four, m_hWnd, IDC_CHECK_WIN4);
-	theApp.m_pPosFive->CopyToCtrl(m_Five, m_hWnd, IDC_CHECK_WIN5);
-	theApp.m_pPosSix->CopyToCtrl(m_Six, m_hWnd, IDC_CHECK_WIN6);
-	theApp.m_pPosSeven->CopyToCtrl(m_Seven, m_hWnd, IDC_CHECK_WIN7);
-	theApp.m_pPosEight->CopyToCtrl(m_Eight, m_hWnd, IDC_CHECK_WIN8);
-	theApp.m_pPosNine->CopyToCtrl(m_Nine, m_hWnd, IDC_CHECK_WIN9);
-	theApp.m_pPosTen->CopyToCtrl(m_Ten, m_hWnd, IDC_CHECK_WIN10);
-	theApp.m_pTextOnlyPaste->CopyToCtrl(m_TextOnlyKey, m_hWnd, IDC_CHECK_WIN_TEXT_ONLY);
-	theApp.m_pSaveClipboard->CopyToCtrl(m_saveClipboardHotKey, m_hWnd, IDC_CHECK_WIN_SAVE_CLIPBOARD);
-
-
-	//Unregister hotkeys and Reregister them on cancel or ok
-	g_HotKeys.UnregisterAll();
-
-	m_btSendPaste.SetCheck(g_Opt.m_bSendPasteOnFirstTenHotKeys);
-
-	m_btMoveClipOnGlobal10.SetCheck(g_Opt.GetMoveClipsOnGlobal10());
-
-	m_HotKey.SetFocus();
-
-	theApp.m_Language.UpdateOptionShortcuts(this);	
-		
-	return FALSE;
-}
-
-LRESULT COptionsKeyBoard::OnWizardNext() 
-{
-	return CPropertyPage::OnWizardNext();
-}
-
-BOOL COptionsKeyBoard::OnWizardFinish() 
-{
-	return CPropertyPage::OnWizardFinish();
-}
-
-BOOL COptionsKeyBoard::OnApply()
-{
-	CGetSetOptions::SetSendPasteOnFirstTenHotKeys(m_btSendPaste.GetCheck());
-	CGetSetOptions::SetMoveClipsOnGlobal10(m_btMoveClipOnGlobal10.GetCheck());
-					
-	INT_PTR x,y;
-	CString str;
-	ARRAY keys;
-	
-	g_HotKeys.GetKeys( keys ); // save old keys just in case new ones are invalid
-	
-	theApp.m_pDittoHotKey->CopyFromCtrl(m_HotKey, m_hWnd, IDC_CHECK_WIN_DITTO);
-	
-	theApp.m_pPosOne->CopyFromCtrl(m_One, m_hWnd, IDC_CHECK_WIN1);
-	theApp.m_pPosTwo->CopyFromCtrl(m_Two, m_hWnd, IDC_CHECK_WIN2);
-	theApp.m_pPosThree->CopyFromCtrl(m_Three, m_hWnd, IDC_CHECK_WIN3);
-	theApp.m_pPosFour->CopyFromCtrl(m_Four, m_hWnd, IDC_CHECK_WIN4);
-	theApp.m_pPosFive->CopyFromCtrl(m_Five, m_hWnd, IDC_CHECK_WIN5);
-	theApp.m_pPosSix->CopyFromCtrl(m_Six, m_hWnd, IDC_CHECK_WIN6);
-	theApp.m_pPosSeven->CopyFromCtrl(m_Seven, m_hWnd, IDC_CHECK_WIN7);
-	theApp.m_pPosEight->CopyFromCtrl(m_Eight, m_hWnd, IDC_CHECK_WIN8);
-	theApp.m_pPosNine->CopyFromCtrl(m_Nine, m_hWnd, IDC_CHECK_WIN9);
-	theApp.m_pPosTen->CopyFromCtrl(m_Ten, m_hWnd, IDC_CHECK_WIN10);
-	theApp.m_pTextOnlyPaste->CopyFromCtrl(m_TextOnlyKey, m_hWnd, IDC_CHECK_WIN_TEXT_ONLY);
-	theApp.m_pSaveClipboard->CopyFromCtrl(m_saveClipboardHotKey, m_hWnd, IDC_CHECK_WIN_SAVE_CLIPBOARD);
-
-	ARRAY NewKeys;
-	g_HotKeys.GetKeys(NewKeys);
-	
-	if(g_HotKeys.FindFirstConflict(NewKeys, &x, &y))
-	{
-		str =  g_HotKeys.ElementAt(x)->GetName();
-		str += " and ";
-		str += g_HotKeys.ElementAt(y)->GetName();
-		str += " cannot be the same.";
-		MessageBox(str);
-		g_HotKeys.SetKeys(keys); // restore the original values
-		return FALSE;
-	}
-	
-	g_HotKeys.SaveAllKeys();
-	g_HotKeys.RegisterAll(true);
-	
-	return CPropertyPage::OnApply();
-}
-
-void COptionsKeyBoard::OnCancel() 
-{
-	g_HotKeys.RegisterAll( true );
-	CPropertyPage::OnCancel();
-}
+}
+
+BEGIN_MESSAGE_MAP(COptionsKeyBoard, CPropertyPage)
+	//{{AFX_MSG_MAP(COptionsKeyBoard)
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COptionsKeyBoard message handlers
+
+BOOL COptionsKeyBoard::OnInitDialog() 
+{
+	CPropertyPage::OnInitDialog();
+
+	CString csHelpPath = CGetSetOptions::GetPath(PATH_HELP);
+	csHelpPath += "DittoCustomKeys.htm";
+	m_CustomeKeysHelp.SetURL(csHelpPath);
+
+	m_pParent = (COptionsSheet *)GetParent();
+
+	theApp.m_pDittoHotKey->CopyToCtrl(m_HotKey, m_hWnd, IDC_CHECK_WIN_DITTO);
+
+	theApp.m_pPosOne->CopyToCtrl(m_One, m_hWnd, IDC_CHECK_WIN1);
+	theApp.m_pPosTwo->CopyToCtrl(m_Two, m_hWnd, IDC_CHECK_WIN2);
+	theApp.m_pPosThree->CopyToCtrl(m_Three, m_hWnd, IDC_CHECK_WIN3);
+	theApp.m_pPosFour->CopyToCtrl(m_Four, m_hWnd, IDC_CHECK_WIN4);
+	theApp.m_pPosFive->CopyToCtrl(m_Five, m_hWnd, IDC_CHECK_WIN5);
+	theApp.m_pPosSix->CopyToCtrl(m_Six, m_hWnd, IDC_CHECK_WIN6);
+	theApp.m_pPosSeven->CopyToCtrl(m_Seven, m_hWnd, IDC_CHECK_WIN7);
+	theApp.m_pPosEight->CopyToCtrl(m_Eight, m_hWnd, IDC_CHECK_WIN8);
+	theApp.m_pPosNine->CopyToCtrl(m_Nine, m_hWnd, IDC_CHECK_WIN9);
+	theApp.m_pPosTen->CopyToCtrl(m_Ten, m_hWnd, IDC_CHECK_WIN10);
+	theApp.m_pTextOnlyPaste->CopyToCtrl(m_TextOnlyKey, m_hWnd, IDC_CHECK_WIN_TEXT_ONLY);
+	theApp.m_pSaveClipboard->CopyToCtrl(m_saveClipboardHotKey, m_hWnd, IDC_CHECK_WIN_SAVE_CLIPBOARD);
+
+
+	//Unregister hotkeys and Reregister them on cancel or ok
+	g_HotKeys.UnregisterAll();
+
+	m_btSendPaste.SetCheck(g_Opt.m_bSendPasteOnFirstTenHotKeys);
+
+	m_btMoveClipOnGlobal10.SetCheck(g_Opt.GetMoveClipsOnGlobal10());
+
+	m_HotKey.SetFocus();
+
+	theApp.m_Language.UpdateOptionShortcuts(this);	
+		
+	return FALSE;
+}
+
+LRESULT COptionsKeyBoard::OnWizardNext() 
+{
+	return CPropertyPage::OnWizardNext();
+}
+
+BOOL COptionsKeyBoard::OnWizardFinish() 
+{
+	return CPropertyPage::OnWizardFinish();
+}
+
+BOOL COptionsKeyBoard::OnApply()
+{
+	CGetSetOptions::SetSendPasteOnFirstTenHotKeys(m_btSendPaste.GetCheck());
+	CGetSetOptions::SetMoveClipsOnGlobal10(m_btMoveClipOnGlobal10.GetCheck());
+					
+	INT_PTR x,y;
+	CString str;
+	ARRAY keys;
+	
+	g_HotKeys.GetKeys( keys ); // save old keys just in case new ones are invalid
+	
+	theApp.m_pDittoHotKey->CopyFromCtrl(m_HotKey, m_hWnd, IDC_CHECK_WIN_DITTO);
+	
+	theApp.m_pPosOne->CopyFromCtrl(m_One, m_hWnd, IDC_CHECK_WIN1);
+	theApp.m_pPosTwo->CopyFromCtrl(m_Two, m_hWnd, IDC_CHECK_WIN2);
+	theApp.m_pPosThree->CopyFromCtrl(m_Three, m_hWnd, IDC_CHECK_WIN3);
+	theApp.m_pPosFour->CopyFromCtrl(m_Four, m_hWnd, IDC_CHECK_WIN4);
+	theApp.m_pPosFive->CopyFromCtrl(m_Five, m_hWnd, IDC_CHECK_WIN5);
+	theApp.m_pPosSix->CopyFromCtrl(m_Six, m_hWnd, IDC_CHECK_WIN6);
+	theApp.m_pPosSeven->CopyFromCtrl(m_Seven, m_hWnd, IDC_CHECK_WIN7);
+	theApp.m_pPosEight->CopyFromCtrl(m_Eight, m_hWnd, IDC_CHECK_WIN8);
+	theApp.m_pPosNine->CopyFromCtrl(m_Nine, m_hWnd, IDC_CHECK_WIN9);
+	theApp.m_pPosTen->CopyFromCtrl(m_Ten, m_hWnd, IDC_CHECK_WIN10);
+	theApp.m_pTextOnlyPaste->CopyFromCtrl(m_TextOnlyKey, m_hWnd, IDC_CHECK_WIN_TEXT_ONLY);
+	theApp.m_pSaveClipboard->CopyFromCtrl(m_saveClipboardHotKey, m_hWnd, IDC_CHECK_WIN_SAVE_CLIPBOARD);
+
+	ARRAY NewKeys;
+	g_HotKeys.GetKeys(NewKeys);
+	
+	if(g_HotKeys.FindFirstConflict(NewKeys, &x, &y))
+	{
+		str =  g_HotKeys.ElementAt(x)->GetName();
+		str += " and ";
+		str += g_HotKeys.ElementAt(y)->GetName();
+		str += " cannot be the same.";
+		MessageBox(str);
+		g_HotKeys.SetKeys(keys); // restore the original values
+		return FALSE;
+	}
+	
+	g_HotKeys.SaveAllKeys();
+	g_HotKeys.RegisterAll(true);
+	
+	return CPropertyPage::OnApply();
+}
+
+void COptionsKeyBoard::OnCancel() 
+{
+	g_HotKeys.RegisterAll( true );
+	CPropertyPage::OnCancel();
+}

+ 2 - 1
Resource.h

@@ -3,6 +3,7 @@
 // Used by CP_Main.rc
 //
 #define IDD_ABOUTBOX                    100
+#define IDR_CP_MAIN                     103
 #define IDR_MAINFRAME                   128
 #define IDR_CP_MAITYPE                  129
 #define IDR_EDIT_WND                    129
@@ -580,6 +581,6 @@
 #define _APS_NEXT_RESOURCE_VALUE        258
 #define _APS_NEXT_COMMAND_VALUE         32925
 #define _APS_NEXT_CONTROL_VALUE         2146
-#define _APS_NEXT_SYMED_VALUE           101
+#define _APS_NEXT_SYMED_VALUE           104
 #endif
 #endif

+ 2 - 2
ShowTaskBarIcon.cpp

@@ -6,7 +6,7 @@ volatile long CShowTaskBarIcon::m_refCount = 0;
 
 CShowTaskBarIcon::CShowTaskBarIcon(void)
 {
-	theApp.m_pMainFrame->m_TrayIcon.MaximiseFromTray(theApp.m_pMainFrame);
+	theApp.m_pMainFrame->m_trayIcon.MaximiseFromTray(theApp.m_pMainFrame);
 	m_hWnd = theApp.m_pMainFrame->GetSafeHwnd();
 	::InterlockedIncrement(&m_refCount);
 }
@@ -18,6 +18,6 @@ CShowTaskBarIcon::~CShowTaskBarIcon(void)
 
 	if(m_hWnd && ::IsWindow(m_hWnd) && m_refCount == 0)
 	{
-		theApp.m_pMainFrame->m_TrayIcon.MinimiseToTray(theApp.m_pMainFrame);
+		theApp.m_pMainFrame->m_trayIcon.MinimiseToTray(theApp.m_pMainFrame);
 	}	
 }

+ 5 - 0
StdAfx.h

@@ -4,6 +4,7 @@
 //
 
 #if !defined(AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_)
+//#define _ATL_APARTMENT_THREADED 
 #define AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_
 
 #if _MSC_VER > 1000
@@ -47,4 +48,8 @@ using namespace Gdiplus;
 //{{AFX_INSERT_LOCATION}}
 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
 #endif // !defined(AFX_STDAFX_H__56F3D184_7208_47FE_AFE2_E270325F356A__INCLUDED_)

+ 1 - 0
SystemTray.cpp

@@ -124,6 +124,7 @@ CSystemTray::CSystemTray(CWnd* pParent,             // The window that will reci
            szBalloonTip, szBalloonTitle, dwBalloonIcon, uBalloonTimeout);
 }
 
+
 void CSystemTray::Initialise()
 {
     memset(&m_tnd, 0, sizeof(m_tnd));