Win 32 API and Clarion versions 10 11 12 and Above

We are starting to replace good old clarion standard procedures with our linux ported binding emulation machine to windows 32.. with the goal of adding the binding machine to clarion template ABC apps with AI generated features…

Heres the call to file dialog as a UBS (universal Binding Machine) macro. Objects can also be bound to call win32 api and CPP bound code. we will demo these as we go and if UBS can live in windows land put it up later next year on GITHUB separate from our linux runtimes… Since this is only old window 32 it will be free.

CPP code updated for Threading.

void scriptFileDialog(ScriptInterface *ifc)
{

 // AI Generated Anthropic add in to UBS win32 version.
// This does not run on the Linux cloud Azure version and is win32 windows only.

void scriptFileDialog(ScriptInterface *ifc)
{
	REFSTART();
	int argc = ifc->getParamCount();
	if (argc < 2)
	{
		ifc->setReturnString("");
		REFEND();
		return;
	}

	string_t title = ifc->getParamAsString(0);
	string_t filter = ifc->getParamAsString(1);

	// Shared result storage
	std::string result;
	bool completed = false;
	std::mutex resultMutex;
	std::condition_variable cv;

	// Launch dialog on separate thread
	std::thread dialogThread([&]() {
		// Convert UBS filter format to Windows format
		char winFilter[1024];
		char *wp = winFilter;
		const char *fp = filter;
		// Convert "Description|*.ext|Description2|*.ext2" to "Description\0*.ext\0Description2\0*.ext2\0\0"
		while (*fp && (wp - winFilter) < 1020)
		{
			if (*fp == '|')
				*wp++ = '\0';
			else
				*wp++ = *fp;
			fp++;
		}
		*wp++ = '\0';
		*wp = '\0';

		char fileName[MAX_PATH] = "";
		OPENFILENAMEA ofn;
		ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.lpstrFilter = winFilter;
		ofn.lpstrFile = fileName;
		ofn.nMaxFile = MAX_PATH;
		ofn.lpstrTitle = (LPSTR)title;
		ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR;

		std::lock_guard<std::mutex> lock(resultMutex);
		if (GetOpenFileNameA(&ofn))
		{
			result = fileName;
		}
		else
		{
			result = "No File";
		}
		completed = true;
		cv.notify_one();
	});

	// Wait for completion
	std::unique_lock<std::mutex> lock(resultMutex);
	cv.wait(lock, [&] { return completed; });

	dialogThread.join();
	ifc->setReturnString(result.c_str());
	REFEND();
}

Callable from Clarion..
UBS App Module -

 cexpression = 'filedialog("Select File", "All Files |*.*");' 

UBSAppModule.IFileDialog.FileFolder          Procedure(string Titleselect,string defaultfilter)
Foldercontents     ANY
lcexpression       cstring(555)
    CODE
    Foldercontents = ''  
    if Self.folderdialoghandle  = FALSE    
       lcexpression = 'filedialog("Select File", "All Files|*.*");'    
       if len(Clip(lcexpression)) > FALSE
           ! Call UBS via the local clarion APP Module document interface. 
          Self.folderdialoghandle = self.AppiUBSref.Document(lcexpression)
       END
    END     
    !  message(' after document registered with universal binding service. ')
    if Self.folderdialoghandle> FALSE
       ! Execute scriptbindale handle.  
       Foldercontents = self.AppiUBSref.DocStrId(Self.folderdialoghandle)
     END
     return(Foldercontents)

! WIndow Control styling to come in a few weeks… very busy on linux Azure in the cloud… where the future of computing blues skys calls.

Seems to be working inside the clarion Accept loop as the CPP function uses its own thread… We will try for creating GUI controls in the coming months…

Note: This is ALL AI generated - Anthropic 4.0.

More WIN API Dialogs added for macro script execution from Clarion Windows and non window code . The Threading fences and protects the win API from the Clarion Accept loop. The Support for the WIN32 Dialogs is Anthropic Generated. Can AI take over CPP development of products and should venders consider that they cant keep there products closed off except in the case where IP is involved but with interfaces for allowing access. In the binding machine everything is a bindable and there is no need for a closed off Black BOX accept at the heart of the binding machine… Even what looks like code is nothing but a binding where program statements are nothing but emulation imaged as bindings. As AI says it really shines in the cloud where everything can be bound to everything.. A = B… A binding = B binding..

Where AI can generate software bindings on demand … AI generates and consumes its own creations…

/*
GLOBAL VARIABLES SET BY DIALOGS:

Color Dialog:

  • global.dlgrgbcolors.color (RGB value)
  • global.dlgrgbcolors.red (red component)
  • global.dlgrgbcolors.green (green component)
  • global.dlgrgbcolors.blue (blue component)

Font Dialog:

  • global.fontname (font family name)
  • global.fontsize (font size in points)
  • global.fontweight (font weight)
  • global.fontitalic (italic flag)

Print Dialog:

  • global.printfrom (start page)
  • global.printto (end page)
  • global.printcopies (number of copies)

USAGE EXAMPLES:
result = filedialog(“Open File”, “Text Files|.txt|All Files|.");
result = savefiledialog(“Save As”, "Documents|
.doc|All Files|.”, “doc”);
folder = folderdialog(“Select Directory”);
color = colordialog(“Pick Color”, 16777215); // Sets global.selectedcolor, etc.
font = fontdialog(“Choose Font”); // Sets global.fontname, global.fontsize, etc.
button = messagebox(“Save changes?”, “Confirm”, 4, 32); // MB_YESNO | MB_ICONQUESTION
printer = printdialog(“Print Document”); // Sets global.printfrom, etc.
setup = printsetupdialog();
text = inputdialog(“Enter name:”, “User Input”, “Default”);
*/

// Color Picker Dialog - WITH GLOBAL VARIABLE SETTING
void scriptColorDialog(ScriptInterface *ifc)
{
REFSTART();
int argc = ifc->getParamCount();
string_t title = (argc > 0) ? ifc->getParamAsString(0) : “Choose Color”;
long defaultColor = (argc > 1) ? ifc->getParamAsInteger(1) : RGB(255, 255, 255);

std::string result;
bool completed = false;
bool colorSelected = false;
COLORREF selectedColor = 0;
std::mutex resultMutex;
std::condition_variable cv;

std::thread dialogThread([&]() {
	static COLORREF customColors[16] = { 0 };
	CHOOSECOLORA cc;
	ZeroMemory(&cc, sizeof(cc));
	cc.lStructSize = sizeof(cc);
	cc.rgbResult = defaultColor;
	cc.lpCustColors = customColors;
	cc.Flags = CC_FULLOPEN | CC_RGBINIT;

	std::lock_guard<std::mutex> lock(resultMutex);
	if (ChooseColorA(&cc))
	{
		selectedColor = cc.rgbResult;
		colorSelected = true;
	}
	else
	{
		colorSelected = false;
	}
	completed = true;
	cv.notify_one();
});

std::unique_lock<std::mutex> lock(resultMutex);
cv.wait(lock, [&] { return completed; });
dialogThread.join();

// Set global variables on main thread
if (colorSelected)
{
	result = std::to_string(selectedColor);
	
	Script *scriptCore = (Script *)ifc;
	scriptString_t globalname = scriptStringFromString("global");
	var_t gv = scriptCore->findGlobal(globalname);
	if (gv != NULL)
	{
		BindVar *global = new BindVar(gv);
		
		bindable_t dlgColors = global->selectMember("dlgrgbcolors", 0, 0);
		
		bindable_t colorValue = dlgColors->selectMember("color", 0, 0);
		colorValue->setToInteger(selectedColor);
		colorValue->unShare();
		
		bindable_t redValue = dlgColors->selectMember("red", 0, 0);
		redValue->setToInteger(GetRValue(selectedColor));
		redValue->unShare();
		
		bindable_t greenValue = dlgColors->selectMember("green", 0, 0);
		greenValue->setToInteger(GetGValue(selectedColor));
		greenValue->unShare();
		
		bindable_t blueValue = dlgColors->selectMember("blue", 0, 0);
		blueValue->setToInteger(GetBValue(selectedColor));
		blueValue->unShare();
		
		dlgColors->unShare();
		delete global;
	}
	scriptStringUnShare(globalname);
}
else
{
	result = "No Color";
}

ifc->setReturnString(result.c_str());
REFEND();

}

// Binding everything to everything… AI hello world… is coming..to a cloud near you…

bindNative(“case”, baseOpCase, PRI_CASE, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative(“else”, baseOpElse, PRI_ELSEDEFAULT, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative(“default”, baseOpElse, PRI_ELSEDEFAULT, VARATTR_IMMEDIATE | VARATTR_ISOP);

bindNative("inherit", baseOpInherit, PRI_VAR, VARATTR_NONE); // operator so no new frame but priority 0 like a function
bindNative("data", baseOpData, PRI_VAR, VARATTR_IMMEDIATE | VARATTR_ISOP);
bindNative("args", baseOpArgs, PRI_VAR, VARATTR_IMMEDIATE);

bindNative("_compound", baseOpCompound, PRI_REPEAT, VARATTR_IMMEDIATE);       // internal !!!
bindNative("_again", baseOpAgain, PRI_REPEAT, VARATTR_IMMEDIATE);       // internal !!!

bindBindable("print", createBindBuiltin(scriptFuncPrint));
bindBindable("source", createBindBuiltin(scriptFuncSource));
bindBindable("assert", createBindBuiltin(scriptAssert));
bindBindable("exists", createBindBuiltin(scriptExists));
bindBindable("remove", createBindBuiltin(scriptRemove));
bindBindable("after", createBindBuiltin(scriptAfter));
bindBindable("addon", createBindBuiltin(scriptAddon));

bindBindable("filedialog", createBindBuiltin(scriptFileDialog));

bindBindable("savefiledialog", createBindBuiltin(scriptSaveFileDialog));

bindBindable(“colordialog”, createBindBuiltin(scriptColorDialog));
bindBindable(“fontdialog”, createBindBuiltin(scriptFontDialog));
bindBindable(“messagebox”, createBindBuiltin(scriptMessageBox));
bindBindable(“printdialog”, createBindBuiltin(scriptPrintDialog));
bindBindable(“printsetupdialog”, createBindBuiltin(scriptPrintSetupDialog));
bindBindable(“inputdialog”, createBindBuiltin(scriptInputDialog));

bindNativeObject("loop", new loopObject(this), PRI_STARTBLOCK, VARATTR_IMMEDIATE | VARATTR_ISOP);

Ai - has recently added over 150 functions to the window version of our linux binding software machine and is proposing the novel creation of a functions based approach to creating win 3 UI controls.

Threading Strategy
UI Thread Management:
Store DispatcherQueue reference in UBS global variable
All builtin functions marshal operations to UI thread using TryEnqueue
Handle cross-thread communication for property access
Example Implementation:
cpp
void scriptWinUISetProp(ScriptInterface ifc) {
// Get parameters from UBS
int controlID = ifc->getParamAsInteger(1);
string propName = ifc->getParamAsString(2);
// Get dispatcher from UBS global
bindable_t global = ifc->findglobalvar(“global”);
bindable_t dispatcherVar = global->selectMember(“winui_dispatcher”, 0, 0);
auto dispatcher = (winrt::DispatcherQueue
)(dispatcherVar->getAsInteger());
// Marshal to UI thread
dispatcher->TryEnqueue([=]{
// Get control from UBS global storage
bindable_t global = ifc->findglobalvar(“global”);
bindable_t controlVar = global->selectMember((“winui_control_” + std::to_string(controlID)).c_str(), 0, 0);
auto control = (winrt::IInspectable)(controlVar->getAsInteger());

// Set property using base class casting
SetControlProperty(control, propName, value);

}

WinUI 3 Integration Proposal for UBS.pdf (229.8 KB)