When we last left our hero, we were wondering how to invoke the default verb programmatically. Now that we've learned a lot about how IContextMenu is used in the interactive case, we can use that information to guide us in its use in the noninteractive case.

The key here is using the HMENU to identify the default menu item and just invoke it directly. Go back to the program from part 1 where we left it and make these changes:

void OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos)
{
  IContextMenu *pcm;
  if (SUCCEEDED(GetUIObjectOfFile(hwnd, L"C:\\Windows\\clock.avi",
                   IID_IContextMenu, (void**)&pcm))) {
    HMENU hmenu = CreatePopupMenu();
    if (hmenu) {
      if (SUCCEEDED(pcm->QueryContextMenu(hmenu, 0,
                             SCRATCH_QCM_FIRST, SCRATCH_QCM_LAST,
                             CMF_NORMAL))) {
        UINT id = GetMenuDefaultItem(hmenu, FALSE, 0);
        if (id != (UINT)-1) {
          CMINVOKECOMMANDINFO info = { 0 };
          info.cbSize = sizeof(info);
          info.hwnd = hwnd;
          info.lpVerb = MAKEINTRESOURCEA(id - SCRATCH_QCM_FIRST);
          pcm->InvokeCommand(&info);
        }
      }
      DestroyMenu(hmenu);
    }
    pcm->Release();
  }
}

We added the call to GetMenuDefaultItem to obtain the default menu item and then set the verb in the form of a menu identifier offset. (I.e., we subtract the starting point we passed to IContextMenu::QueryContextMenu.)

This code works but could be better. Next time, we'll make a minuscule tweak that improves the performance.