See the question and my original answer on StackOverflow

To hide columns, you must redefine the whole set of columns using the IColumnManager::SetColumns method.

Here is some sample code (I've used error checks and ATL's smart pointers to avoid possible memory leaks). In this code, I remove the "Title" column if it's the last one, so just make sure it's the last one in the first opened view before you test it:

#include <Windows.h>
#include <atlbase.h>
#include <exdisp.h>
#include <shobjidl_core.h>
#include <ShlGuid.h>

int main()
{
  CoInitialize(NULL);
  {
    CComPtr<IShellWindows> windows;
    ATLASSERT(SUCCEEDED(windows.CoCreateInstance(CLSID_ShellWindows)));

    CComPtr<IDispatch> first;
    ATLASSERT(SUCCEEDED(windows->Item(CComVariant(0), &first)));

    CComPtr<IColumnManager> mgr;
    ATLASSERT(SUCCEEDED(IUnknown_QueryService(first, SID_SFolderView, IID_PPV_ARGS(&mgr))));

    // get the visible columns
    auto flags = CM_ENUM_VISIBLE;
    UINT count = 0;
    ATLASSERT(SUCCEEDED(mgr->GetColumnCount(flags, &count)));

    CComHeapPtr<PROPERTYKEY> pks;
    pks.Allocate(count);
    ATLASSERT(SUCCEEDED(mgr->GetColumns(flags, pks, count)));

    // remove last if it's "Title"
    if (count > 1)
    {
      CM_COLUMNINFO ci{ sizeof(CM_COLUMNINFO) };
      ci.dwMask = CM_MASK_NAME;
      ATLASSERT(SUCCEEDED(mgr->GetColumnInfo(pks[count - 1], &ci)));

      if (!lstrcmp(ci.wszName, L"Title"))
      {
        ATLASSERT(SUCCEEDED(mgr->SetColumns(pks, count - 1)));
      }
    }
  }
  CoUninitialize();
  return 0;
}