Click here to Skip to main content
15,885,720 members
Articles / Programming Languages / C++

Sourcecode Control Switcher

Rate me:
Please Sign up or sign in to vote.
4.90/5 (15 votes)
8 Dec 2004CPOL2 min read 153.2K   2.7K   37  
A tool to switch the Sourcecode Control Provider which is used in a development environment.
// SCCSwitcher.cpp : 
// Created by S�nke Schau, Germany sccswitcher@schau.org
#include "stdafx.h"
#include "resource.h"

#include "pubscc.h"

#define MAX_LOADSTRING          100

#define LEFTBUTTONMENU_ID_BASE  2000
#define MAX_SCCENTRIES          100

#define LEFTBUTTONMENU_ID_BASE_MAX      (LEFTBUTTONMENU_ID_BASE+MAX_SCCENTRIES)
#define RIGHTBUTTONMENU_ID_BASE         (LEFTBUTTONMENU_ID_BASE_MAX)
#define RIGHTBUTTONMENU_ID_BASE_MAX     (RIGHTBUTTONMENU_ID_BASE+MAX_SCCENTRIES)

// Global Variables:
HINSTANCE   hInst;                                  // current instance

TCHAR       aTitle[ MAX_LOADSTRING ];               // The title bar text
TCHAR       aStartSCCPrefix[ MAX_LOADSTRING ];      // Prefix for Text in "Start ..."
TCHAR       aDisableSCCMenutext[ MAX_LOADSTRING ];  // Menuentry "Disable SCC"
TCHAR       aPathToExecutable[ MAX_PATH ];          // The path to this executable

// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
BOOL				ExitInstance(HINSTANCE);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

// Get an Errormessage from the resource, optional add system errorcode to message
void ErrorMessageFromResource( UINT Resource, bool AddError=false )
{
    TCHAR aCaption[ 1000 ];
    TCHAR aMessage[ 4000 ];

    // Get the strings
	LoadString( hInst, IDS_ERROR_CAPTION,   aCaption, sizeof aCaption / sizeof TCHAR );
	LoadString( hInst, Resource,            aMessage, ( sizeof aMessage / sizeof TCHAR ) / 2 );

    if ( AddError )
    {
        TCHAR    *pBuffer;

        // Get an appropriate message from sysstem
        FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
            NULL,
            GetLastError(),
            MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
            (TCHAR*)&pBuffer,
            sizeof( FORMAT_MESSAGE_MAX_WIDTH_MASK ),
            NULL );

        // Add to retrieved messages
        if ( pBuffer )
        {
            _tcscat( aMessage, _T("\r\n") );
            _tcscat( aMessage, pBuffer );
            LocalFree( pBuffer );
        }
    }

    // Display Box
    MessageBox( NULL, aMessage, aCaption, MB_OK|MB_ICONERROR|MB_SETFOREGROUND );
}

// Internal message used when something happens for us in the taskbar
const UINT  wm_iconmessage    = RegisterWindowMessage( _T("VCSwitcher_Iconmessage") );
// Message send when explorer restarts
const UINT  wm_TaskbarRestart = RegisterWindowMessage( _T("TaskbarCreated") );

HWND        hTrayWnd;
HICON       MyIcon;
HMENU       MainMenu;
HMENU       LeftButtonSubMenu;
HMENU       RightButtonSubMenu;
HKEY        ProviderKey;
UINT        CurrentChecked;
HKEY        WindowsRunKey = 0;
BOOL        Autostart = FALSE;

// Datastructure to store information about scc providers
struct ProviderDefinition
{
    TCHAR   aProviderName[ 1000 ];
    TCHAR   aProviderRegistryPath[ 1000 ];
    TCHAR   aProviderDll[ 1000 ];
    HICON   ProviderIcon;
    HBITMAP ProviderBitmap;
};
// a max of 20 should be enough
ProviderDefinition *ProviderDefinitions;

// Adds an icon to the taskbar
void addTaskbarIcon()
{
    // Add Icon to tray
    NOTIFYICONDATA NIData;
    NIData.cbSize           = sizeof NOTIFYICONDATA;
    NIData.hWnd             = hTrayWnd;
    NIData.uID              = 4711;
    NIData.uFlags           = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    NIData.hIcon            = ProviderDefinitions[ CurrentChecked ].ProviderIcon;
    NIData.uCallbackMessage = wm_iconmessage;
    _tcscpy(NIData.szTip, ProviderDefinitions[ CurrentChecked ].aProviderName );

    Shell_NotifyIcon( NIM_ADD, &NIData );
}

// Converts an Icon to a Bitmap compatible to a given window
HBITMAP setIcon( HWND hTrayWnd, HICON hIcon )
{
#if(WINVER >= 0x0500)
            ICONINFO IconInfo;
            GetIconInfo( hIcon, &IconInfo );

            BITMAP bmp; 
            // Retrieve the bitmap's color format, width, and height. 
            GetObject( IconInfo.hbmColor, sizeof(BITMAP), (LPSTR)&bmp);
            HDC     wndDC     = GetDC( hTrayWnd );
            HDC     memDC     = CreateCompatibleDC( wndDC );
            HBITMAP memBitmap = CreateCompatibleBitmap( wndDC, 20, 16 );
            ReleaseDC( hTrayWnd, wndDC );
            SelectObject( memDC, memBitmap );
            HBRUSH Brush = GetSysColorBrush( COLOR_MENU );
            SelectObject( memDC, Brush );
            FloodFill( memDC, 0, 0, GetSysColor(COLOR_MENU) );
            DrawIconEx( memDC, 0, 0, hIcon, 16, 16, 0, NULL, DI_NORMAL );
            DeleteDC( memDC );

    return memBitmap;
#else
    return 0;
#endif
}

// Main entrypoint for pgm
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	MSG         msg;
	HACCEL      hAccelTable;
    TCHAR       aWindowClass[ 1000 ];								// The title bar text
    DWORD       ValueType;

    // Get Path to this executable
    GetModuleFileName( hInstance, aPathToExecutable, sizeof aPathToExecutable / sizeof TCHAR );

    // Load classname of our window
	LoadString(hInstance, IDC_SCCSWITCHER, aWindowClass, sizeof aWindowClass / sizeof TCHAR );

    // Load prefix for Menuintems
	LoadString( hInst, IDS_STARTSCC_PREFIX, aStartSCCPrefix, sizeof aStartSCCPrefix / sizeof TCHAR );

    // Load Menutext to disable SCC Integration
	LoadString( hInst, IDS_DISABLE_INTEGRATION, aDisableSCCMenutext, sizeof aDisableSCCMenutext / sizeof TCHAR );

	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon( hInstance, (LPCTSTR)IDI_SCCSWITCHER);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= aWindowClass;
	wcex.hIconSm		= LoadIcon( wcex.hInstance, (LPCTSTR)IDI_SMALL);

    // Register classname
	RegisterClassEx( &wcex );

    // Store instance handle in our global variable
    hInst = hInstance;
    
    // Create hidden window to process notification messages
    hTrayWnd = CreateWindow( aWindowClass, _T(""), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL );
    if (!hTrayWnd)
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;
    
    // Load the default icon
    MyIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_SMALL) );
    if ( !MyIcon )
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;

    // Prepare popup menu ...
    MainMenu = LoadMenu( hInst, MAKEINTRESOURCE(IDC_SCCSWITCHER));
    if ( !MainMenu )
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;

    LeftButtonSubMenu  = CreatePopupMenu();
    RightButtonSubMenu = GetSubMenu( MainMenu, 0 );

    // To dismiss the menu after 10 sec
#if(WINVER >= 0x0500)
    MENUINFO MenuInfo;
    MenuInfo.fMask = MIM_STYLE;
    GetMenuInfo( RightButtonSubMenu, &MenuInfo );
    MenuInfo.fMask = MIM_APPLYTOSUBMENUS | MIM_STYLE;
    MenuInfo.dwStyle |= MNS_AUTODISMISS;
    SetMenuInfo( RightButtonSubMenu, &MenuInfo );
#endif

    if ( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, _T(""), 0, KEY_WRITE|KEY_READ, NULL, &WindowsRunKey, NULL ) )
    {
        TCHAR   aCurrentProgram[ 1000 ];
        DWORD   CurrentProgramLength = sizeof aCurrentProgram;
        if ( ERROR_SUCCESS == RegQueryValueEx( WindowsRunKey, _T("SCCSwitcher"), 0, &ValueType, reinterpret_cast<BYTE*>(aCurrentProgram), &CurrentProgramLength ) )
            Autostart = TRUE;

        CheckMenuItem( RightButtonSubMenu, IDM_AUTOSTART, MF_BYCOMMAND|(Autostart?MF_CHECKED:MF_UNCHECKED) );
    }
    else
        EnableMenuItem( RightButtonSubMenu, IDM_AUTOSTART, MF_BYCOMMAND|MF_GRAYED );
    
    // Open registy key, where current scc provider is specified
    if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("Software\\SourceCodeControlProvider"), 0, KEY_WRITE|KEY_READ, &ProviderKey ) )
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;

    // Get current provider
    TCHAR   aCurrentProviderRegistryPath[ 1000 ];
    DWORD   CurrentProviderRegistryPathLength = sizeof aCurrentProviderRegistryPath;
    RegQueryValueEx( ProviderKey, _T("ProviderRegKey"), 0, &ValueType, reinterpret_cast<BYTE*>(aCurrentProviderRegistryPath), &CurrentProviderRegistryPathLength );

    // Open registy key, where all installed scc providers are listed
    HKEY InstalledProviderKey;
    if ( ERROR_SUCCESS != RegOpenKeyEx( ProviderKey, _T("InstalledSCCProviders"), 0, KEY_READ, &InstalledProviderKey ) )
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;

    // # of subkeys is the # of installed providers
    DWORD NumberOfProviders;
    if ( ERROR_SUCCESS != RegQueryInfoKey( InstalledProviderKey, NULL, NULL, NULL, NULL, NULL, NULL, &NumberOfProviders, NULL, NULL, NULL, NULL ) )
        return ErrorMessageFromResource( IDS_ERROR_CANNOT_ACCESS_REGISTRY, 1 ), 1;

    // allocate them
    ProviderDefinitions = new ProviderDefinition[ NumberOfProviders + 1 ];

    DWORD   ProviderNameLength = sizeof ProviderDefinitions[0].aProviderName / sizeof TCHAR; // Characters
    DWORD   ProviderRegistryPathLength = sizeof ProviderDefinitions[0].aProviderRegistryPath;                  // Bytesize
    // Startindex of entries in popupmenu
    UINT    LeftButtonMenuStartIndex  = 0;
    UINT    RightButtonMenuStartIndex = 7;

    MENUITEMINFO    mii;
    mii.cbSize  = sizeof MENUITEMINFO;

    // Iterate thru provider subkeys
    for( DWORD Index = 0 ; ; Index++ )
    {
        if ( !Index )
        {
            memset( &ProviderDefinitions[ Index ], 0, sizeof ProviderDefinitions[0] );
            _tcscpy( ProviderDefinitions[ Index ].aProviderName, aDisableSCCMenutext );
            ProviderDefinitions[ Index ].ProviderIcon   = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_DISABLED_SCC ) );
            ProviderDefinitions[ Index ].ProviderBitmap = setIcon( hTrayWnd, ProviderDefinitions[ Index ].ProviderIcon );
        }
        else
        {
            if ( ERROR_SUCCESS != RegEnumValue( InstalledProviderKey, Index - 1, ProviderDefinitions[Index].aProviderName, &ProviderNameLength, NULL, &ValueType, reinterpret_cast<BYTE*>(ProviderDefinitions[Index].aProviderRegistryPath), &ProviderRegistryPathLength ) )
                break;

            ProviderNameLength = sizeof ProviderDefinitions[0].aProviderName / sizeof TCHAR; // Characters
            ProviderRegistryPathLength = sizeof ProviderDefinitions[0].aProviderRegistryPath; // Bytesize

            // Default is to use a default icon and no bitmap
            ProviderDefinitions[Index].ProviderIcon   = 0;
            ProviderDefinitions[Index].ProviderBitmap = 0;

            // Open realprovider key
            HKEY RealProviderKey;
            if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, ProviderDefinitions[Index].aProviderRegistryPath, 0, KEY_READ, &RealProviderKey ) )
            {
                DWORD   ProviderDllLength = sizeof ProviderDefinitions[0].aProviderDll;
                if ( ERROR_SUCCESS != RegQueryValueEx( RealProviderKey, _T("SCCServerPath"), 0, &ValueType, reinterpret_cast<BYTE*>(ProviderDefinitions[Index].aProviderDll), &ProviderDllLength ) )
                    _tcscpy( ProviderDefinitions[Index].aProviderDll, _T("This shouln't be so! but who cares?") );

                // Check if an Entry "IconDll" is available. If so, the entry is treated as 
                // a Path to a Modulename  - Exe or Dll -.
                // If a trailing ";<number>" is specified, <number> is used as a Resource index into the
                // Module. If unspecified, 1 is used
                TCHAR   anIconDll[ 1000 ];
                DWORD   IconDllLength = sizeof anIconDll;
                if ( ERROR_SUCCESS == RegQueryValueEx( RealProviderKey, _T("IconDll"), 0, &ValueType, reinterpret_cast<BYTE*>(anIconDll), &IconDllLength ) )
                {
                    TCHAR   *pFilename = _tcstok(anIconDll,_T(",;"));
                    TCHAR   *pIndex = _tcstok(NULL,_T(",;"));
                    if (!pIndex)
                        pIndex = _T("1");

                    // Load module
                    HMODULE IconInstance = LoadLibraryEx( anIconDll, NULL, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE );

                    // Load icon from module - first try the 16*16 version
                    HICON   anIcon = (HICON)LoadImage( IconInstance, MAKEINTRESOURCE(_ttoi(pIndex)), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );
                    if ( !anIcon )
                        anIcon = (HICON)LoadImage( IconInstance, MAKEINTRESOURCE(_ttoi(pIndex)), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE );

                    if ( anIcon )
                    {
                        // Assign it to provider info
                        ProviderDefinitions[ Index ].ProviderIcon   = anIcon;
                        ProviderDefinitions[ Index ].ProviderBitmap = setIcon( hTrayWnd, ProviderDefinitions[ Index ].ProviderIcon );
                    }
                    // time for library bye bye
                    FreeLibrary( IconInstance );
                }

                RegCloseKey( RealProviderKey );
            }
        }
        // If no icon available, provide default icon
        if ( !ProviderDefinitions[ Index ].ProviderIcon )
            ProviderDefinitions[ Index ].ProviderIcon = MyIcon;

#if(WINVER >= 0x0500)
        mii.fMask      = MIIM_ID|MIIM_DATA|MIIM_STATE;

        if ( ProviderDefinitions[ Index ].ProviderBitmap )
            mii.fMask |= MIIM_BITMAP | MIIM_STRING;
        else
            mii.fMask |= MIIM_STRING;

        mii.hbmpItem   = ProviderDefinitions[ Index ].ProviderBitmap;
#else
        mii.fMask      = MIIM_ID|MIIM_DATA|MIIM_STATE|MIIM_TYPE;
        mii.fType      = MFT_STRING;
#endif
        mii.dwTypeData = ProviderDefinitions[ Index ].aProviderName;

        // Is this the current provider?
        if ( _tcscmp( aCurrentProviderRegistryPath, ProviderDefinitions[Index].aProviderRegistryPath ) )
            // No -> unchecked
            mii.fState = 0;
        else
        {
            // Yes -> check item
            mii.fState = MFS_CHECKED;
            CurrentChecked = Index;
        }

        // The Id is 2000 plus the current index
        mii.wID = Index + LEFTBUTTONMENU_ID_BASE;

        // Insert it!
        InsertMenuItem( RightButtonSubMenu, RightButtonMenuStartIndex++, TRUE, &mii );

        if ( Index )
        {
            mii.fMask      = MIIM_ID|MIIM_DATA|MIIM_TYPE;
            mii.fType      = MFT_STRING;

            TCHAR aBuffer[ 200 ];
            _stprintf( aBuffer, aStartSCCPrefix, ProviderDefinitions[ Index ].aProviderName );

            mii.dwTypeData = aBuffer;

            // The Id is RIGHTBUTTONMENU_ID_BASE plus the current index
            mii.wID = Index + RIGHTBUTTONMENU_ID_BASE;
            InsertMenuItem( LeftButtonSubMenu, LeftButtonMenuStartIndex++, TRUE, &mii );
        }
    }

    // Mark current as the default
    if ( CurrentChecked )
        SetMenuDefaultItem( LeftButtonSubMenu, CurrentChecked + RIGHTBUTTONMENU_ID_BASE, FALSE );

    // Close it
    RegCloseKey( InstalledProviderKey );

    // Add icon to taskbar
    addTaskbarIcon();

    // Load Accelerators
	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SCCSWITCHER);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

    // Remove Icon from Tray
    NOTIFYICONDATA NIData;
    NIData.cbSize = sizeof NOTIFYICONDATA;
    NIData.hWnd = hTrayWnd;
    NIData.uID = 4711;

    Shell_NotifyIcon( NIM_DELETE, &NIData );

    // Cleanup
    RegCloseKey( ProviderKey );

    if ( WindowsRunKey )
        RegCloseKey( WindowsRunKey );
    
    delete [] ProviderDefinitions;

    DestroyMenu( LeftButtonSubMenu );
    DestroyMenu( MainMenu );

	return static_cast<int>(msg.wParam);
}

// Changes to the specified provider
// visual controls are changed to reflect internal state
void switchToProvider( UINT ProviderNo )
{
    MENUITEMINFO mii;
    mii.cbSize = sizeof MENUITEMINFO;

    // Uncheck old entry
    mii.fMask = MIIM_STATE;
    mii.fState = 0;
    SetMenuItemInfo( RightButtonSubMenu, LEFTBUTTONMENU_ID_BASE + CurrentChecked, FALSE, &mii );

    CurrentChecked = ProviderNo;

    // Check new entry
    mii.fState = MFS_CHECKED;
    SetMenuItemInfo( RightButtonSubMenu, LEFTBUTTONMENU_ID_BASE + CurrentChecked, FALSE, &mii );

    // Mark current as default
    SetMenuDefaultItem( LeftButtonSubMenu, CurrentChecked + RIGHTBUTTONMENU_ID_BASE, FALSE );

    // Change icon and tip
    NOTIFYICONDATA NIData;
    NIData.cbSize = sizeof NOTIFYICONDATA;
    NIData.hWnd   = hTrayWnd;
    NIData.uID    = 4711;
    NIData.uFlags = NIF_ICON | NIF_TIP;
    NIData.hIcon  = ProviderDefinitions[ CurrentChecked ].ProviderIcon;
    _tcscpy(NIData.szTip, ProviderDefinitions[ CurrentChecked ].aProviderName );

    Shell_NotifyIcon( NIM_MODIFY, &NIData );

    // Set registry value
    RegSetValueEx( ProviderKey, _T("ProviderRegKey"), 0, REG_SZ, reinterpret_cast<BYTE*>(ProviderDefinitions[ CurrentChecked ].aProviderRegistryPath), static_cast<DWORD>((_tcslen(ProviderDefinitions[ CurrentChecked ].aProviderRegistryPath)+1)*sizeof(TCHAR)) );
}

// Start userinterface of SCC provider
void startSCCUI( UINT ProviderNo )
{
    HINSTANCE SCCProvider = LoadLibrary( ProviderDefinitions[ ProviderNo ].aProviderDll );
    if ( SCCProvider )
    {
        tSccInitialize   pSccInitialize     = reinterpret_cast<tSccInitialize>(GetProcAddress(SCCProvider, "SccInitialize" ));
        tSccUninitialize pSccUninitialize   = reinterpret_cast<tSccUninitialize>(GetProcAddress(SCCProvider, "SccUninitialize" ));
        tSccRunScc       pSccRunScc         = reinterpret_cast<tSccRunScc>(GetProcAddress(SCCProvider, "SccRunScc" ));

        void *pContext;

        char    aProviderName[ SCC_max_name ];
        LONG    Caps;
        char    aProviderPath[ SCC_max_init_path ];
        DWORD   co_comment_len;
        DWORD   comment_len;

        pSccInitialize( &pContext, NULL, "SCCSwitcher", aProviderName, &Caps, aProviderPath, &co_comment_len, &comment_len );
        char *aFileArgs[] = { NULL };
        pSccRunScc( pContext, NULL, 0, aFileArgs );
        pSccUninitialize( pContext );
        FreeLibrary( SCCProvider );
    }
}

// Changes the autostart setting
void toggleAutostart()
{
    if ( Autostart )
    {
        // Remove
        if ( ERROR_SUCCESS == RegDeleteValue( WindowsRunKey, _T("SCCSwitcher") ) )
            Autostart = FALSE;
    }
    else
    {
        // Add
        if ( ERROR_SUCCESS == RegSetValueEx( WindowsRunKey, _T("SCCSwitcher"), 0, REG_SZ, reinterpret_cast<BYTE*>(aPathToExecutable), static_cast<DWORD>((_tcslen(aPathToExecutable)+1)*sizeof(TCHAR)) ) )
            Autostart = TRUE;
    }

    // Reflect change in menu
    CheckMenuItem( RightButtonSubMenu, IDM_AUTOSTART, MF_BYCOMMAND|(Autostart?MF_CHECKED:MF_UNCHECKED) );
}

// Main windows message loop
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int             wmId, wmEvent;

    // During desktop restart this message is broadcasted to all toplevel windows. 
    // The icon must be added again to be visible. 
    // (Some of MS programmers haven't read this chapter ;-) -  Watch most icons disappear when you kill and then restart explorer.exe )
    if ( message == wm_TaskbarRestart )
        addTaskbarIcon();

    // A notification for the taskbar icon is received
    if ( message == wm_iconmessage )
    {
        switch( lParam )
        {
        // It's a left button down event!
        case WM_LBUTTONDOWN:
            {
            POINT Point;
            // Get current position of mouse
            GetCursorPos( &Point );
            // And start tracking the menu

            // For the use of this and the WM_NULL Message below -> see Q135788 at MSDN
            SetForegroundWindow(hWnd);

            TrackPopupMenuEx( LeftButtonSubMenu, TPM_RIGHTALIGN|TPM_BOTTOMALIGN|TPM_LEFTBUTTON, Point.x, Point.y, hWnd, NULL );

            // see above
            PostMessage( hWnd, WM_NULL, 0, 0 );
            }
            break;

        // It's a right button down event!
        case WM_RBUTTONDOWN:
            {
            POINT Point;
            // Get current position of mouse
            GetCursorPos( &Point );
            // And start tracking the menu

            // For the use of this and the WM_NULL Message below -> see Q135788 at MSDN
            SetForegroundWindow(hWnd);

            TrackPopupMenuEx( RightButtonSubMenu, TPM_RIGHTALIGN|TPM_BOTTOMALIGN|TPM_RIGHTBUTTON, Point.x, Point.y, hWnd, NULL );

            // see above
            PostMessage( hWnd, WM_NULL, 0, 0 );
            }
            break;

        case WM_LBUTTONDBLCLK:
            // Start Userinterface of SCC provider via. SCC interface
            startSCCUI( CurrentChecked );
            break;

        default:
            break;
        }
        return 0;
    }

    switch (message) 
    {
    case WM_SETTINGCHANGE:
        break;

    case WM_COMMAND:
        wmId    = LOWORD(wParam); 
        wmEvent = HIWORD(wParam); 

        // Parse the menu selections:
        switch ( wmId )
        {
        case IDM_ABOUT:
            // Show an about box
            DialogBox( hInst, (LPCTSTR)IDD_ABOUTBOX, NULL, (DLGPROC)About );
            break;

        case IDM_EXIT:
            // TTL. Destruction triggers Quit message later
            DestroyWindow(hWnd);
            break;

        case IDM_START_SCC:
            // Start Userinterface of SCC provider via. SCC interface
            startSCCUI( CurrentChecked );
            break;

        case IDM_AUTOSTART:
            // Toggle the current autostart setting
            toggleAutostart();
            break;

        default:
            if ( wmId >= LEFTBUTTONMENU_ID_BASE &&
                 wmId < LEFTBUTTONMENU_ID_BASE_MAX )
            {
                // A new provider is selected -> Switch to it
                switchToProvider( wmId - LEFTBUTTONMENU_ID_BASE );
            }
            else
                if ( wmId >= RIGHTBUTTONMENU_ID_BASE &&
                     wmId < RIGHTBUTTONMENU_ID_BASE_MAX )
                {
                    // Start Userinterface of SCC provider via. SCC interface
                    startSCCUI( wmId - RIGHTBUTTONMENU_ID_BASE );
                }
                else
                    return DefWindowProc( hWnd, message, wParam, lParam );
        }
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
    }
    return 0;
}

// Message handler for about box.
LRESULT CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
    switch (message)
    {
    case WM_INITDIALOG:
        return TRUE;
        
    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
        {
            EndDialog(hDlg, LOWORD(wParam));
            return TRUE;
        }
        break;
    }
    return FALSE;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions