VirtualBox

Ignore:
Timestamp:
Jul 20, 2010 1:27:46 PM (15 years ago)
Author:
vboxsync
Message:

VBoxTray: Modularized tray icon handling, fixed icon leak.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp

    r28800 r30928  
    44
    55/*
    6  * Copyright (C) 2006-2009 Oracle Corporation
     6 * Copyright (C) 2006-2010 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4040HINSTANCE             gInstance;
    4141HWND                  gToolWindow;
     42NOTIFYICONDATA        gNotifyIconData;
     43DWORD                 gMajorVersion;
    4244
    4345/* Prototypes */
     
    8587};
    8688
    87 static int vboxStartServices (VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
     89static BOOL vboxTrayIconAdd()
     90{
     91    HICON hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_VIRTUALBOX));
     92    if (hIcon == NULL)
     93    {
     94        Log(("Could not load tray icon, err %08X\n", GetLastError()));
     95        return FALSE;
     96    }
     97
     98    /* Prepare the system tray icon. */
     99    RT_ZERO(gNotifyIconData);
     100    gNotifyIconData.cbSize           = NOTIFYICONDATA_V1_SIZE; // sizeof(NOTIFYICONDATA);
     101    gNotifyIconData.hWnd             = gToolWindow;
     102    gNotifyIconData.uID              = ID_TRAYICON;
     103    gNotifyIconData.uFlags           = NIF_ICON | NIF_MESSAGE | NIF_TIP;
     104    gNotifyIconData.uCallbackMessage = WM_VBOX_TRAY;
     105    gNotifyIconData.hIcon            = hIcon;
     106
     107    sprintf(gNotifyIconData.szTip, "%s Guest Additions %d.%d.%dr%d",
     108            VBOX_PRODUCT, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
     109
     110    BOOL fCreated = Shell_NotifyIcon(NIM_ADD, &gNotifyIconData);
     111    if (!fCreated)
     112    {
     113        Log(("Could not create tray icon, err %08X\n", GetLastError()));
     114        RT_ZERO(gNotifyIconData);
     115    }
     116
     117    if (hIcon)
     118        DestroyIcon(hIcon);
     119    return fCreated;
     120}
     121
     122static void vboxTrayIconRemove()
     123{
     124    if (gNotifyIconData.cbSize > 0)
     125    {
     126        /* Remove the system tray icon and refresh system tray. */
     127        Shell_NotifyIcon(NIM_DELETE, &gNotifyIconData);
     128        HWND hTrayWnd = FindWindow("Shell_TrayWnd", NULL); /* We assume we only have one tray atm. */
     129        if (hTrayWnd)
     130        {
     131            HWND hTrayNotifyWnd = FindWindowEx(hTrayWnd, 0, "TrayNotifyWnd", NULL);
     132            if (hTrayNotifyWnd)
     133                SendMessage(hTrayNotifyWnd, WM_PAINT, 0, NULL);
     134        }
     135        RT_ZERO(gNotifyIconData);
     136    }
     137}
     138
     139static int vboxStartServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
    88140{
    89141    Log(("VBoxTray: Starting services...\n"));
     
    159211}
    160212
    161 static void vboxStopServices (VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
     213static void vboxStopServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
    162214{
    163215    if (!pEnv->hStopEvent)
     
    236288    DWORD status = NO_ERROR;
    237289
    238     /* open VBox guest driver */
     290    /* Open VBox guest driver. */
    239291    gVBoxDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
    240292                             GENERIC_READ | GENERIC_WRITE,
     
    254306    if (status == NO_ERROR)
    255307    {
    256         /* create a custom window class */
     308        /* Create a custom window class. */
    257309        WNDCLASS windowClass = {0};
    258310        windowClass.style         = CS_NOCLOSE;
     
    269321    if (status == NO_ERROR)
    270322    {
    271         /* create our window */
     323        /* Create our (invisible) tool window. */
    272324        gToolWindow = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
    273325                                     "VirtualBoxTool", "VirtualBoxTool",
     
    282334    Log(("VBoxTray: Window Handle = %p, Status = %p\n", gToolWindow, status));
    283335
    284     OSVERSIONINFO           info;
    285     DWORD                   dwMajorVersion = 5; /* default XP */
     336    OSVERSIONINFO info;
     337    gMajorVersion = 5; /* default XP */
    286338    info.dwOSVersionInfoSize = sizeof(info);
    287339    if (GetVersionEx(&info))
    288340    {
    289         Log(("VBoxTray: Windows version major %d minor %d\n", info.dwMajorVersion, info.dwMinorVersion));
    290         dwMajorVersion = info.dwMajorVersion;
     341        Log(("VBoxTray: Windows version major %d minor %d.\n", info.dwMajorVersion, info.dwMinorVersion));
     342        gMajorVersion = info.dwMajorVersion;
    291343    }
    292344
     
    314366
    315367        /* For Vista and up we need to change the integrity of the security descriptor too */
    316         if (dwMajorVersion >= 6)
     368        if (gMajorVersion >= 6)
    317369        {
    318370            HMODULE hModule;
     
    349401        }
    350402
    351         if (dwMajorVersion >= 5)        /* Only for W2K and up ... */
     403        if (gMajorVersion >= 5)        /* Only for W2K and up ... */
    352404        {
    353405            ghSeamlessNotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
     
    369421    status = VBoxDispIfInit(&svcEnv.dispIf);
    370422#ifdef VBOXWDDM
    371     /* for now the display mode will be adjusted to WDDM mode if needed
    372      * on display service initialization when it detects the display driver type */
     423    /*
     424     * For now the display mode will be adjusted to WDDM mode if needed
     425     * on display service initialization when it detects the display driver type.
     426     */
    373427#endif
    374428
    375429    if (status == NO_ERROR)
    376430    {
    377         int rc = vboxStartServices (&svcEnv, vboxServiceTable);
     431        int rc = vboxStartServices(&svcEnv, vboxServiceTable);
    378432
    379433        if (RT_FAILURE (rc))
     
    386440    if (status != NO_ERROR)
    387441    {
    388         vboxStopServices (&svcEnv, vboxServiceTable);
     442        vboxStopServices(&svcEnv, vboxServiceTable);
    389443        return;
    390444    }
    391445
    392     BOOL fTrayIconCreated = false;
    393 
    394     /* prepare the system tray icon */
    395     NOTIFYICONDATA ndata;
    396     RT_ZERO (ndata);
    397     ndata.cbSize           = NOTIFYICONDATA_V1_SIZE; // sizeof(NOTIFYICONDATA);
    398     ndata.hWnd             = gToolWindow;
    399     ndata.uID              = ID_TRAYICON;
    400     ndata.uFlags           = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    401     ndata.uCallbackMessage = WM_VBOX_TRAY;
    402     ndata.hIcon            = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_VIRTUALBOX));
    403     sprintf(ndata.szTip, "%s Guest Additions %d.%d.%dr%d", VBOX_PRODUCT, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
    404     Log(("VBoxTray: ndata.hWnd %08X, ndata.hIcon = %p\n", ndata.hWnd, ndata.hIcon));
     446    if (   vboxTrayIconAdd()
     447        && gMajorVersion >= 5) /* Only for W2K and up ... */
     448    {
     449        /* We're ready to create the tooltip balloon. */
     450        /* Check in 10 seconds (@todo make seconds configurable) ... */
     451        SetTimer(gToolWindow,
     452                 WM_VBOX_CHECK_HOSTVERSION,
     453                 10 * 1000, /* 10 seconds */
     454                 NULL       /* No timerproc */);
     455    }
    405456
    406457    /* Boost thread priority to make sure we wake up early for seamless window notifications (not sure if it actually makes any difference though) */
     
    419470
    420471    Log(("VBoxTray: Number of events to wait in main loop: %ld\n", dwEventCount));
    421 
    422     while(true)
     472    while (true)
    423473    {
    424474        DWORD waitResult = MsgWaitForMultipleObjectsEx(dwEventCount, hWaitEvent, 500, QS_ALLINPUT, 0);
    425475        waitResult = waitResult - WAIT_OBJECT_0;
    426476
    427         Log(("VBoxTray: Wait result  = %ld.\n", waitResult));
     477        /* Only enable for message debugging, lots of traffic! */
     478        //Log(("VBoxTray: Wait result  = %ld.\n", waitResult));
    428479
    429480        if (waitResult == 0)
     
    433484            break;
    434485        }
    435         else if ((waitResult == 1) && (ghSeamlessNotifyEvent!=0))       /* Only jump in, if seamless is active! */
     486        else if (   (waitResult == 1)
     487                 && (ghSeamlessNotifyEvent!=0)) /* Only jump in, if seamless is active! */
    436488        {
    437489            Log(("VBoxTray: Event 'Seamless' triggered.\n"));
     
    456508                DispatchMessage(&msg);
    457509            }
    458             /* we might have to repeat this operation because the shell might not be loaded yet */
    459             if (!fTrayIconCreated)
    460             {
    461                 fTrayIconCreated = Shell_NotifyIcon(NIM_ADD, &ndata);
    462                 Log(("VBoxTray: fTrayIconCreated = %d, err %08X\n", fTrayIconCreated, GetLastError ()));
    463 
    464                 /* We're ready to create the tooltip balloon. */
    465                 if (fTrayIconCreated && dwMajorVersion >= 5)
    466                 {
    467                     /* Check in 10 seconds (@todo make seconds configurable) ... */
    468                     SetTimer(gToolWindow,
    469                              WM_VBOX_CHECK_HOSTVERSION,
    470                              10000, /* 10 seconds */
    471                              NULL   /* no timerproc */);
    472                 }
    473             }
    474510        }
    475511    }
     
    477513    Log(("VBoxTray: Returned from main loop, exiting ...\n"));
    478514
    479     /* remove the system tray icon and refresh system tray */
    480     Shell_NotifyIcon(NIM_DELETE, &ndata);
    481     HWND hTrayWnd = FindWindow("Shell_TrayWnd", NULL); /* We assume we only have one tray atm */
    482     HWND hTrayNotifyWnd = FindWindowEx(hTrayWnd, 0, "TrayNotifyWnd", NULL);
    483     if (hTrayNotifyWnd)
    484         SendMessage(hTrayNotifyWnd, WM_PAINT, 0, NULL);
    485 
    486     Log(("VBoxTray: waiting for display change thread ...\n"));
    487 
    488     vboxStopServices (&svcEnv, vboxServiceTable);
     515    vboxTrayIconRemove();
     516
     517    Log(("VBoxTray: Waiting for display change thread ...\n"));
     518
     519    vboxStopServices(&svcEnv, vboxServiceTable);
    489520
    490521    Log(("VBoxTray: Destroying tool window ...\n"));
    491522
    492     /* destroy the tool window */
     523    /* Destroy the tool window. */
    493524    DestroyWindow(gToolWindow);
    494525
     
    551582LRESULT CALLBACK VBoxToolWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    552583{
     584    static UINT s_uTaskbarCreated = 0;
     585
    553586    switch (msg)
    554587    {
     588        case WM_CREATE:
     589            Log(("VBoxTray: Tool window created.\n"));
     590            s_uTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));
     591            if (!s_uTaskbarCreated)
     592                Log(("VBoxTray: Cannot register message \"TaskbarCreated\"! Error = %ld\n", GetLastError()));
     593            break;
     594
    555595        case WM_CLOSE:
    556596            break;
    557597
    558598        case WM_DESTROY:
     599            Log(("VBoxTray: Tool window destroyed.\n"));
    559600            KillTimer(gToolWindow, WM_VBOX_CHECK_HOSTVERSION);
    560601            break;
     
    609650
    610651        default:
    611             return DefWindowProc(hwnd, msg, wParam, lParam);
    612     }
    613     return 0;
     652
     653            if(msg == s_uTaskbarCreated)
     654            {
     655                Log(("VBoxTray: Taskbar (re-)created, installing tray icon ...\n"));
     656                vboxTrayIconAdd();
     657            }
     658            break;
     659    }
     660    return DefWindowProc(hwnd, msg, wParam, lParam);
    614661}
    615662
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette