Clarion 11.1, ABC. I’m writing a procedure #EXTENSION template that should inject a few lines into a browse’s ResetQueue method (to DISABLE/ENABLE the Insert button based on a record count). The template registers fine, installs on the procedure fine, prompts accept values fine — but it generates NOTHING into the browse method. No error; the code simply never appears.
Here is the embed section:
#AT(%BrowserMethodCodeSection, %ActiveTemplateInstance, ‘ResetQueue’, ‘(BYTE ResetMode)’), PRIORITY(5000)
#IF(%UseEditionGuard)
IF %EditionGuard
IF RECORDS(%BrowseClass) >= %RecordLimit
DISABLE(%InsertControl)
%BrowseObject.InsertControl = False
ELSE
%BrowseObject.InsertControl = %InsertControl
ENABLE(%InsertControl)
END
DISPLAY(%InsertControl)
END
#ELSE
IF RECORDS(%BrowseClass) >= %RecordLimit
DISABLE(%InsertControl)
%BrowseObject.InsertControl = False
ELSE
%BrowseObject.InsertControl = %InsertControl
ENABLE(%InsertControl)
END
DISPLAY(%InsertControl)
#ENDIF
#ENDAT
The embed code: BRW1.ResetQueue PRIORITY 2500
IF Glo:Edition = 1
IF RECORDS(Queue:Browse) >= 10
DISABLE(?Insert)
ELSE
ENABLE(?Insert)
END
END
What I’ve already verified:
-
The embed point exists and is reachable. If I hand-type “!here” directly into the BRW1.ResetQueue embed in the Embeditor, it generates into the .clw correctly, and the method BRW1.ResetQueue PROCEDURE(BYTE ResetMode) appears.
-
The signature is exact. I used the EmbedInfo / “create #AT from embed” template inside that same ResetQueue embed, and it printed:
!#AT(%BrowserMethodCodeSection,%ActiveTemplateInstance,‘ResetQueue’,‘(BYTE ResetMode)’),PRIORITY(5000)
which matches my template’s #AT character-for-character.
-
It’s not a caching/stale-generation issue — a fresh app, a brand-new simple browse (single sort order, ResetQueue present in the generated class), same result: nothing generates from the extension.
My working theory: because this is a procedure #EXTENSION, %ActiveTemplateInstance refers to the EXTENSION’s own instance, not the browse (BRW1) instance — so the #AT has no browse method to match and silently generates nothing. The EmbedInfo output showing that signature was presumably generated in the context of the BrowseBox control template, where %ActiveTemplateInstance DOES mean the browse.
My questions:
Q1. Is that theory correct — that a procedure #EXTENSION cannot use %ActiveTemplateInstance to target a specific browse’s method?
Q2. If so, what is the correct way, FROM A PROCEDURE #EXTENSION, to embed code into a specific browse’s ResetQueue method? Is there a symbol for the browse instance I should use instead, or do I need to #FOR/loop over the browse control instances (e.g. over %Control or a browse-instance symbol) and reference that instance in the #AT?
Q3. If a procedure #EXTENSION genuinely can’t do this cleanly, is the accepted approach to make it a BrowseBox #CONTROL template instead? If so, how is such a control template ATTACHED to an existing browse list control in the app (the step-by-step in the IDE), since it isn’t a visual control I’d drop on the window?
Context on why an extension is preferred: I want to add this limiter to ~12 browse procedures across an app (and reuse across other apps), toggling behavior via a single global (Glo:Edition). Hand-placing works but I’d like the template to manage placement. Whichever mechanism is correct (extension with the right instance reference, or control template), a short example of the working #AT line plus how it’s installed would be hugely appreciated.
DataLimiter.tpl (3.3 KB)
Thanks in advance.