Friday
Platform: Windows 11, ArchiCAD 27 (build 6020)
DevKit: API.Development.Kit.WIN.27.6003
Toolchain: Visual Studio 2019 (v142), CMake, Ninja
I want to be upfront: this add-on is vibe coded — meaning it was written with AI assistance without deep prior knowledge of the ArchiCAD C++ API. I'm an architect, not a developer. The goal is a simple launcher add-on that opens a Python GUI application from ArchiCAD's menubar.
CheckEnvironment called! RegisterInterface called! RegisterMenu OK ← ACAPI_MenuItem_RegisterMenu returns 0 Initialize called! InstallMenuHandler OK ← ACAPI_MenuItem_InstallMenuHandler returns 0
No menu entry appears anywhere in the menubar or any submenu.
I've been trying to get a custom top-level menu ("Layout Manager") to appear in the menubar using MenuCode_UserDef.
During debugging I discovered my hand-rolled enum had the wrong value — I wasn't including ACAPinc.h (see note below), so I had defined it manually:
// What I had (WRONG — this is actually MenuCode_Image): MenuCode_UserDef = 8 // Correct value from APIdefs_Registration.h: MenuCode_UserDef = 0
I have now corrected this and rebuilt. The menu still does not appear.
I also noticed this note in the Add-On Manager dialog:
"The visibility and menu location of Add-Ons in the Archicad interface depend on Work Environment settings. These can be customized in Work Environment → Command Layout Schemes."
When searching for "Layout Manager" in Work Environment → Menus, the command does not appear in the available commands list.
I'm not sure what I'm missing. It could be the enum value, the resource structure, the Work Environment, the APIAddon_Preload return value, the struct layouts, the way I'm forward-declaring the API functions — or something else entirely that I haven't thought of.
Rather than assuming I know what the problem is, I'd really appreciate a fresh set of eyes. What would you check first? Is there something fundamentally wrong with this approach that would explain why RegisterMenu returns NoError but nothing shows up?
#include <windows.h> #include <shellapi.h> #include <stdio.h> typedef int GSErrCode; typedef unsigned int GSFlags; #define NoError 0 typedef enum { APIAddon_DontRegister = 0, APIAddon_Normal = 1, APIAddon_Preload = 2 } API_AddonType; typedef enum { MenuCode_UserDef = 0 // from APIdefs_Registration.h } APIMenuCodeID; #define MenuFlag_Default 0 struct API_MenuItemRef { short menuResID; short itemIndex; }; struct API_ServerApplicationInfo { short mainVersion; short releaseVersion; char pad[508]; }; struct API_EnvirParams { API_ServerApplicationInfo serverInfo; char pad[1024]; }; struct API_MenuParams { API_MenuItemRef menuItemRef; }; GSErrCode __cdecl ACAPI_MenuItem_RegisterMenu( short menuStrResID, short promptStrResID, APIMenuCodeID menuPosCode, GSFlags menuFlags); GSErrCode __cdecl ACAPI_MenuItem_InstallMenuHandler( short menuStrResID, GSErrCode (__cdecl* handlerProc)(const API_MenuParams*)); static void WriteLog(const wchar_t* msg) { /* logs to file */ } static void LaunchLayoutManager() { /* ShellExecuteW to .exe */ } static GSErrCode __cdecl MenuCommandHandler(const API_MenuParams*) { LaunchLayoutManager(); return NoError; } extern "C" { __declspec(dllexport) API_AddonType __cdecl CheckEnvironment(API_EnvirParams*) { return APIAddon_Preload; } __declspec(dllexport) GSErrCode __cdecl RegisterInterface(void) { return ACAPI_MenuItem_RegisterMenu(32001, 0, MenuCode_UserDef, MenuFlag_Default); } __declspec(dllexport) GSErrCode __cdecl Initialize(void) { return ACAPI_MenuItem_InstallMenuHandler(32001, MenuCommandHandler); } __declspec(dllexport) GSErrCode __cdecl FreeData(void) { return NoError; } } // extern "C"
'STR#' 32001 "Menu strings" { "Layout Manager" "Layout Manager..." }
'MDID' 32500 "Add-On Identifier" { 944270126 /* developer ID */ 1113797136 /* local ID */ }
I am intentionally not using ACAPinc.h because including it caused linker conflicts with the Module libraries in my CMake setup. Instead I forward-declare the two API functions I need (ACAPI_MenuItem_RegisterMenu and ACAPI_MenuItem_InstallMenuHandler) with their C++ name-mangled signatures as exported by ACAP_STAT.lib. Both functions return NoError at runtime.
I'm open to the possibility that this approach is flawed in a way I don't understand. Any guidance appreciated.
Thank you.
Operating system used: Windows 12