//========= Copyright Valve Corporation, All rights reserved. ============// // // VPROJECT.CPP // //=====================================================================================// #include "vproject.h" #define MAX_PROJECTS 50 #define ID_PROJECTS_LISTVIEW 100 // column id #define ID_PROJECT_NAME 0 #define ID_PROJECT_DIRECTORY 1 #define WM_TRAY (WM_APP + 1) #define ID_TRAY 5000 #define ID_TRAY_ADDVPROJECT 6000 #define ID_TRAY_MODIFYVPROJECT 6001 #define ID_TRAY_MOVEUP 6002 #define ID_TRAY_MOVEDOWN 6003 #define ID_TRAY_EXIT 6004 typedef struct { char *pName; char *pGamedir; } project_t; HWND g_hWnd; char g_project_name[256]; char g_project_gamedir[256]; HINSTANCE g_hInstance; project_t g_projects[MAX_PROJECTS]; int g_numProjects; NOTIFYICONDATA g_iconData; HMENU g_hMenu; int g_nActiveVProject; POINT g_cursorPoint; void TrayMessageHandler( HWND hWnd, UINT uMessageID ); //----------------------------------------------------------------------------- // SetVProject // //----------------------------------------------------------------------------- void SetVProject( const char *pProjectName ) { char *pGamedir; char project[256]; int i; if ( pProjectName ) { strcpy( project, pProjectName ); Sys_StripQuotesFromToken( project ); for ( i=0; i= g_numProjects ) { // not found return; } pGamedir = g_projects[i].pGamedir; } else { pGamedir = ""; } // Changed to CURRENT_USER to solve security issues in vista! Sys_SetRegistryString( //"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment\\VProject", "HKEY_CURRENT_USER\\Environment\\VProject" pGamedir ); DWORD result; SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 0, &result ); } //----------------------------------------------------------------------------- // ModifyVProject // //----------------------------------------------------------------------------- void ModifyVProject( int index, const char *pName, const char *pGamedir ) { free( g_projects[index].pName ); free( g_projects[index].pGamedir ); if ( !pName || !pName[0] ) { // delete if ( g_numProjects-index-1 > 0 ) { // shift remaining elements memcpy( &g_projects[index], &g_projects[index+1], (g_numProjects-index-1)*sizeof( project_t ) ); } g_projects[g_numProjects-1].pName = NULL; g_projects[g_numProjects-1].pGamedir = NULL; g_numProjects--; if ( g_nActiveVProject == index+1 ) { // deleted current vproject if ( !g_numProjects ) { // no more projects g_nActiveVProject = 0; SetVProject( NULL ); } else { // set to top g_nActiveVProject = 1; SetVProject( g_projects[0].pName ); } } } else { g_projects[index].pName = strdup( pName ); g_projects[index].pGamedir = strdup( pGamedir ); } } //----------------------------------------------------------------------------- // AddVProject // //----------------------------------------------------------------------------- void AddVProject( const char *pName, const char *pGamedir ) { if ( !pName || !pName[0] ) { // do not add empty projects return; } ModifyVProject( g_numProjects, pName, pGamedir ); g_numProjects++; } //----------------------------------------------------------------------------- // LoadRegistryValues // //----------------------------------------------------------------------------- void LoadRegistryValues() { char keyBuff[32]; char valueBuff[256]; char projectName[256]; char gamedirString[256]; char *ptr; char *token; int i; for ( i=0; i 2 && g_project_gamedir[len-1] == '\\' ) { g_project_gamedir[len-1] = '\0'; } // fall through case IDCANCEL: case IDC_CANCEL: EndDialog( hWnd, wParam ); return ( TRUE ); } break; } return ( FALSE ); } //----------------------------------------------------------------------------- // ModifyDlg_Open // //----------------------------------------------------------------------------- BOOL ModifyDlg_Open() { int result; result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_VPROJECT ), g_hWnd, ( DLGPROC )ModifyDlg_Proc ); if ( LOWORD( result ) != IDC_OK ) { return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // ShowPopupMenu // //----------------------------------------------------------------------------- void ShowPopupMenu( HWND hWnd, bool bUseCachedMenuPos ) { BOOL bDelete = true; // delete existing entries for ( int nIndex = 1; nIndex < ID_TRAY_ADDVPROJECT && bDelete; nIndex++ ) { bDelete = DeleteMenu( g_hMenu, nIndex, MF_BYCOMMAND ); } // Insert projects char szMenuItem[MAX_PATH]; for ( int nIndex = 0; nIndex < g_numProjects; nIndex++ ) { strcpy( szMenuItem, g_projects[nIndex].pName ); strcat( szMenuItem, "\t" ); strcat( szMenuItem, g_projects[nIndex].pGamedir ); strcat( szMenuItem, " " ); InsertMenu( g_hMenu, nIndex, MF_BYPOSITION | MF_STRING, nIndex + 1, szMenuItem ); } if ( g_nActiveVProject ) { CheckMenuItem( g_hMenu, g_nActiveVProject, MF_BYCOMMAND|MF_CHECKED ); SetMenuDefaultItem( g_hMenu, g_nActiveVProject, FALSE ); } // Display the popup menu at the current cursor location // Use the cached cursor position if set if ( !bUseCachedMenuPos || ( !g_cursorPoint.x && !g_cursorPoint.y ) ) { GetCursorPos( &g_cursorPoint ); } SetForegroundWindow( hWnd ); TrackPopupMenu( g_hMenu, 0, g_cursorPoint.x, g_cursorPoint.y, 0, hWnd, 0 ); PostMessage( hWnd, WM_NULL, 0, 0 ); } //----------------------------------------------------------------------------- // TrayMessageHandler // //----------------------------------------------------------------------------- void TrayMessageHandler( HWND hWnd, UINT uMessageID ) { switch ( uMessageID ) { case 0: break; case ID_TRAY_EXIT: DestroyWindow( hWnd ); break; case ID_TRAY_ADDVPROJECT: SetForegroundWindow( hWnd ); g_project_name[0] = '\0'; g_project_gamedir[0] = '\0'; if ( ModifyDlg_Open() ) { AddVProject( g_project_name, g_project_gamedir ); SaveRegistryValues(); } ShowPopupMenu( hWnd, true ); break; case ID_TRAY_MODIFYVPROJECT: SetForegroundWindow( hWnd ); if ( g_nActiveVProject ) { strcpy( g_project_name, g_projects[g_nActiveVProject-1].pName ); strcpy( g_project_gamedir, g_projects[g_nActiveVProject-1].pGamedir ); if ( ModifyDlg_Open() ) { ModifyVProject( g_nActiveVProject-1, g_project_name, g_project_gamedir ); SaveRegistryValues(); } ShowPopupMenu( hWnd, true ); } break; case ID_TRAY_MOVEUP: SetForegroundWindow( hWnd ); if ( g_nActiveVProject ) { ShiftActiveProjectUp(); SaveRegistryValues(); ShowPopupMenu( hWnd, true ); } break; case ID_TRAY_MOVEDOWN: SetForegroundWindow( hWnd ); if ( g_nActiveVProject ) { ShiftActiveProjectDown(); SaveRegistryValues(); ShowPopupMenu( hWnd, true ); } break; default: if ( uMessageID >= 1 && uMessageID <= MAX_PROJECTS ) { // set current vproject g_nActiveVProject = uMessageID; SetVProject( g_projects[uMessageID-1].pName ); } break; } } //----------------------------------------------------------------------------- // Main_WndProc // //----------------------------------------------------------------------------- LRESULT CALLBACK Main_WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_DESTROY: PostQuitMessage( 0 ); return 0L; case WM_TRAY: if ( lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN ) { ShowPopupMenu( hWnd, false ); return 0L; } break; case WM_COMMAND: TrayMessageHandler( hWnd, LOWORD( wParam ) ); break; } return ( DefWindowProc( hWnd, message, wParam, lParam ) ); } //----------------------------------------------------------------------------- // Startup // //----------------------------------------------------------------------------- bool Startup() { int i; // set up our window class WNDCLASS wndclass; memset( &wndclass, 0, sizeof( wndclass ) ); wndclass.style = 0; wndclass.lpfnWndProc = Main_WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = g_hInstance; wndclass.hIcon = LoadIcon( g_hInstance, (LPCTSTR)IDI_VPROJECT ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = VPROJECT_CLASSNAME; if ( !RegisterClass( &wndclass ) ) { return false; } // create the hidden window g_hWnd = CreateWindow( VPROJECT_CLASSNAME, 0, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_hInstance, NULL ); // Create tray icon g_iconData.cbSize = sizeof( NOTIFYICONDATA ); g_iconData.hIcon = LoadIcon( g_hInstance, (LPCTSTR)IDI_VPROJECT ); g_iconData.hWnd = g_hWnd; g_iconData.uCallbackMessage = WM_TRAY; g_iconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; g_iconData.uID = ID_TRAY; strcpy(g_iconData.szTip, "VPROJECT"); Shell_NotifyIcon( NIM_ADD, &g_iconData ); // Create popup menu and add initial items g_hMenu = CreatePopupMenu(); AppendMenu( g_hMenu, MF_SEPARATOR, 0, 0); AppendMenu( g_hMenu, MF_STRING, ID_TRAY_ADDVPROJECT, "Add VProject" ); AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MODIFYVPROJECT, "Modify VProject" ); AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MOVEUP, "Move Up" ); AppendMenu( g_hMenu, MF_STRING, ID_TRAY_MOVEDOWN, "Move Down" ); AppendMenu( g_hMenu, MF_SEPARATOR, 0, 0); AppendMenu( g_hMenu, MF_STRING, ID_TRAY_EXIT, "Remove From Tray" ); // find the current vproject char* vproject = getenv( "vproject" ); if ( vproject && vproject[0] ) { char temp[MAX_PATH]; strcpy( temp, vproject ); Sys_NormalizePath( temp, false ); for ( i=0; i