#if 1

    #include "project.h"

    CONTYPE MENUHId = SOB_CONTAINER_NO;
SOBDATA* MENUHLastCreated;

HMENU sob_get_HMENU(SOBID sobId)
{
    if (sobId > MAX_NBR_SOBS)
    {
        swprintf_s(txtBuffer, szTxtBuffer, L"SOB index out of range %04x \n", sobId);

        ReportError(txtBuffer);
        return NULL;
    }
    SOBDATA* pSobData = sob_get_base(sobId);
    if (pSobData NEQU NULL)  return  pSobData->hMenu;

    return NULL;
}
SOBID sob_find_hmenu(HMENU hMenu)
{

    SOBID i;
    SOBDATA* cData;
    for (i = 0; i < MAX_NBR_SOBS; i++)
    {
        cData = sob_get_base((SOBID)i);

        if ((cData->sIndex)   LAND(cData->hMenu EQU hMenu)) return  i;
    }
    return SOBID_ERROR;
}

TCHAR* sob_menu_title_get(SOBID  sobId)
{
    SOBDATA* sData = sob_get_base(sobId);
    if (sData EQU NULL) return NULL;

    SOBDATA* pData = sob_get_base(sData->pIndex);

    #define menuTitleMax 255
    static TCHAR title[menuTitleMax + 1] = { 0 };

    MENUITEMINFO menuinfo = { 0 };
    menuinfo.cbSize = sizeof(menuinfo);
    menuinfo.fMask = MIIM_TYPE;
    menuinfo.fType = MFT_STRING;
    menuinfo.dwTypeData = (LPWSTR)&title;
    menuinfo.cch = menuTitleMax;

    GetMenuItemInfo
    (pData->hMenu
    , (UINT)sobId
    , FALSE
    , &menuinfo
    );
    return title;
}

CONTAINERGETSOBDATA GetChecked_MENUH;
SOBDATA * GetChecked_MENUH(SOBDATA * sData)
{
    if (sData EQU NULL) return  NULL;
    if (sData->subType NEQU MENUHId)    return NULL;

    SOBDATA *  childObj =  CONTAINER.FirstChild(sData);
    while (childObj)
    {
        if ((childObj->type EQU MENUVId) LAND(MENUV.GetState((MENUVOBJECT*)childObj)))  return childObj;
        childObj = sob_get_next_child(childObj);
    }
    return NULL;
}

// ---------------------------------

static  myUInt ReSize_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER

    swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.ReSize method not supported\n"));  ReportError(txtBuffer);
    return SOB_NOK;
}

// ---------------------------------

CONTAINERINFORM Display_MENUH;
static  myUInt Display_MENUH(SOBDATA* conData)
{   // conData   = & SOBDATA for the CONTAINER   being displayed

    swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Display method not supported\n"));  ReportError(txtBuffer);
    return SOB_NOK;
}

// ---------------------------------

CONTAINERCREATE LastWidget_MENUH;
static SOBDATA* LastWidget_MENUH()
{
    return  MENUHLastCreated;
}

// ---------------------------------

SOBFNC_GETTEXT MENUH_SOB_GetTypeText;
static TCHAR* MENUH_SOB_GetTypeText(SOBDATA* thisSob)
{
    static TCHAR objType[] = TEXT("MENUH");
    return  objType;
}

CONTAINERGETTEXT GetTypeText_MENUH;
static  TCHAR* GetTypeText_MENUH(SOBDATA* conData)
{

    if (fnInvalidSobGeneric(conData))
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.GetTypeText given an invalid SOBOBJ\n"));  ReportError(txtBuffer);
        return NULL;
    }

    if (conData->subType NEQU MENUHId)
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.GetTypeText given a non MENUH object\n"));  ReportError(txtBuffer);
        SOB.Report(conData);
        return NULL;
    }

    //  swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.GetTypeText\n"));  ReportError(txtBuffer);

    return   MENUH_SOB_GetTypeText(conData);
}

// ---------------------------------

CONTAINERINFORM  UpDateChildren_MENUH;

static  myUInt UpDateChildren_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER   that is UPDATING it's children

    //  swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.UpDateChildren method not supported\n"));  ReportError(txtBuffer);
    return SOB_NOK;
}

// ---------------------------------

CONTAINERINFORM  Open_MENUH;
static  myUInt Open_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER   being Opened
    // i.e. made the parent of container of subsequent children

    // ---------------------------------

    if (fnInvalidSobGeneric(conData))
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Open given an invalid SOBOBJ\n"));  ReportError(txtBuffer);
        return SOB_NOK;
    }

    if (conData->subType NEQU MENUHId)
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Open given a non MENUH object\n"));  ReportError(txtBuffer);
        return SOB_NOK;
    }

    // swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Open\n"));  ReportError(txtBuffer);

    sob_set_pSobObj(conData);

    return SOB_OK;
}

CONTAINERINFORM  Update_MENUH;
static  myUInt Update_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER   being UPDATED

    //    swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.UpDate method not supported\n"));  ReportError(txtBuffer);
    return SOB_NOK;
}

// ---------------------------------
CONTAINERCREATE1T   UpDateParent_MENUH;

static  SOBDATA*  UpDateParent_MENUH(TCHAR * pName)
{   // childObject   = address of the SOBDATA of the CHILD object   being added

    //  swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.UpDateParent method not supported\n"));  ReportError(txtBuffer);
    return NULL;
}
// ---------------------------------

CONTAINERGETSOBDATA FirstChild_MENUH;
static  SOBDATA* FirstChild_MENUH(SOBDATA* conData)
{
    if (fnInvalidSobGeneric(conData))
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.FirstChild given an invalid SOBOBJ\n"));  ReportError(txtBuffer);
        return NULL;
    }

    if (conData->subType NEQU MENUHId)
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.FirstChild given a non MENUH object\n"));  ReportError(txtBuffer);
        SOB.Report(conData);
        return NULL;
    }

    return  conData->headLink;
}

// ---------------------------------

static myUInt MENUH_SOB_Delete(SOBDATA* thisSob)
{
    // we need this function so that when a CONTAINER is deleted
    // it can trigger a delete of any widget related things of it's child
    // SOB OBJECTs here:-

    if (fnInvalidSobGeneric(thisSob))
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Delete given an invalid SOBOBJ\n"));  ReportError(txtBuffer);
        return SOB_NOK;
    }

    if (thisSob->type NEQU MENUVId)
    {
        swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Delete given a non MENUV object\n"));  ReportError(txtBuffer);
        return SOB_NOK;
    }

    SOBDATA* childObject = NULL;

    childObject = MENUH.FirstChild(thisSob);
    while (childObject)
    {
        childObject->fncCustomDelete(childObject);

        childObject = sob_get_next_child(childObject);
    }

    DeleteMenu(thisSob->hMenu, thisSob->sIndex, MF_BYCOMMAND);

    DrawMenuBar((HWND)appHWND);

    sobObj_delete(thisSob);
    return SOB_OK;
}

CONTAINERINFORM   Delete_MENUH;

static  myUInt Delete_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUV CONTAINER   being DELETED

    return MENUH_SOB_Delete(conData);
}

CONTAINERINFORM   DeleteChildren_MENUH;

static  myUInt DeleteChildren_MENUH(SOBDATA* conData)
{   // conData   = address of the SOBDATA of the MENUV CONTAINER   being DELETED

    return CONTAINER.DeleteChildren(conData);
}

// ---------------------------------

CONTAINERSETEVENTHANDLER SetEventHandler_MENUH;
static myUInt SetEventHandler_MENUH(SOBDATA* conData, EVENTHANDLER  value)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER

    SOB.SetEventHandler(conData, value);
    return SOB_NOK;
}

// ---------------------------------

CONTAINERSETVALUE Stretch_MENUH;
static myUInt Stretch_MENUH(SOBDATA* conData, myUInt value)
{   // conData   = address of the SOBDATA of the MENUH CONTAINER

    swprintf_s(txtBuffer, szTxtBuffer, _TEXT("MENUH.Stretch method not supported\n"));  ReportError(txtBuffer);
    return SOB_NOK;
}

// ---------------------------------
CONTAINERCREATE1T Create_MENUH;

static  PVTBLMENUH* MENUH_get_container_vtbl()
{
    static PVTBLMENUH conTable;
    static int  conTableFlag = 0;

    if (!conTableFlag)
    {
        // only need to initialise this table once since it is common to all containers of type   MENUH

        conTable.AddChild = UpDateParent_MENUH;
        conTable.Update = Update_MENUH;
        conTable.Delete = Delete_MENUH;
        conTable.Display = Display_MENUH;
        conTable.TypeText = GetTypeText_MENUH;
        conTable.Stretch = Stretch_MENUH;
        conTable.Create = Create_MENUH;
        conTable.UpDateChildren = UpDateChildren_MENUH;
        conTable.ReSize = ReSize_MENUH;
        conTable.Open = Open_MENUH;
        conTable.LastWidget = LastWidget_MENUH;
        conTable.FirstChild = FirstChild_MENUH;

        conTable.DeleteChildren = DeleteChildren_MENUH;
        conTable.SetEventHandler = SetEventHandler_MENUH;
        conTable.GetChecked = GetChecked_MENUH;

        conTableFlag = 1;
    }
    return &conTable;
}

// ----------------------------------------------------------------
// the MENUH "constructor" function
// ----------------------------------------------------------------
// some   containers do not need any parameters
// Modify this to suit your needs

static SOBDATA* internalCreate_MENUH( TCHAR * pName)
{
    if (MENUHId EQU SOB_CONTAINER_NO)
    {
        MENUHId = SOB_CONTAINER_MENU_H;

    }
    // the current PARENT MUST BE a MENUBAR or another  MENUH

    SOBID pSobId = sob_get_pSobIndex();
    MAINTYPE type = sob_get_type(pSobId);
    CONTYPE conType = sob_get_subtype(pSobId);

    if ((conType NEQU MENUBARId) LAND (conType NEQU MENUHId))
    {
        swprintf_s(txtBuffer, szTxtBuffer, L"Parent %x not a MENU BAR or MENU H but a %ws & %ws.\n", pSobId, sob_type_to_text(type), sob_container_to_text(conType));
        ReportError(txtBuffer);
        return NULL;
    }

    HMENU pMenu = sob_get_HMENU(pSobId);
    int loop = 0;
    SOBID wSobId = pSobId;
    while (1)
    {
        if (wSobId EQU SOBID_ERROR) break;

        if (sob_get_subtype(wSobId) EQU TOPWINDOWId)   break;

        wSobId = sob_get_pIndex(wSobId);

    }

    HWND  wHWND = sob_get_HWND(wSobId);
    HMENU  wMenu = GetMenu(wHWND);
    // SOBID sobId = sob_new(SOB_TYPE_CONTAINER, SOB_CONTAINER_MENU_H);

    SOBDATA* sData = sob_new_new(SOB_TYPE_CONTAINER, SOB_CONTAINER_MENU_H, 0, 0);

    sData->pVtbl = (MNGR_METHOD_TABLE_GENERIC*)MENUH_get_container_vtbl();

    // ---------------------------------
    // overwrite some of the default SOB  handlers with  custom ones for a MENUV
    sData->fncCustomDelete = MENUH_SOB_Delete;

    sData->fncCustomGetTypeText = MENUH_SOB_GetTypeText;

    // ---------------------------------

    // -----------------------------

    int menu_style = 0;  // for later use

    HMENU childHMENU = CreatePopupMenu();
    if (!childHMENU)
    {
        swprintf_s(txtBuffer, szTxtBuffer, L"Could not create a MENU H\n");
        ReportError(txtBuffer);
        return NULL;
    }

    sData->hWnd = wHWND;
    sData->hMenu = childHMENU;

    if (!AppendMenu(pMenu, MF_STRING BOR MF_POPUP BOR menu_style, (UINT_PTR)childHMENU, pName))
    {
        swprintf_s(txtBuffer, szTxtBuffer, L"Could not APPEND a MENU H %ws\n", pName);
        ReportError(txtBuffer);
        return NULL;
    }

    if (!DrawMenuBar(wHWND))
    ReportError((TCHAR*)L"DrawMenuBar fail");

    MENUHLastCreated = sData;

    return sData;

    // -----------------------------
}

static  SOBDATA* Create_MENUH (TCHAR* name)
{
    return internalCreate_MENUH(name);
}

// ---------------------------------

PVTBLMENUH  MENUH =
{
    UpDateParent_MENUH
    , Update_MENUH
    , Delete_MENUH
    , Display_MENUH
    , GetTypeText_MENUH
    , Stretch_MENUH

    , ReSize_MENUH
    , UpDateChildren_MENUH
    , Open_MENUH
    , LastWidget_MENUH

    , FirstChild_MENUH

    , DeleteChildren_MENUH
    , Create_MENUH
    ,  SetEventHandler_MENUH
    ,  GetChecked_MENUH
};

#endif
