Capesoft MessageBox select-and-copy?

I use Capesoft MessageBox in all my apps.
But I just ran into a need that I can’t address. Am I missing a setting somewhere?

I need to display a message to a user containing an insurance ID. It would be convenient for the user to highlight the ID, Ctrl-C, and then paste it into the medical software app.

Easy-peasy with the default Clarion MESSAGE.
But when I enable MessageBox, it seems the only option is Ctrl-C to copy the entire message, so not useful for the user to grab the ID he needs.

Am I missing a setting or is this just a limitation of CS MessageBox?

This is the code:

      message('This athena ID is already matched to|CenCal patient ZZZ, JANE|with ID of ZZZ12345','Wrong-O',ICON:Exclamation,,,2)

And the pic shows the results with and without the template.

Hi Jane,

Doesn’t appear so. The control is either a prompt or a string (if messagebox creates the control itself).
The Copy Key logic is

      if self.CopyKeyTemp
        if Keycode() = self.CopyKeyTemp

You might be able to play with editing the window in ds_Message and changing the control to a text control that is set to read-only and formatted to look like a string/prompt control (flat, transparent).
The the right-click options for select/copy would be available. Just a thought. I haven’t tried it.

Thanks, Rick.

Yeah, I saw the logic in the class file but was wondering whether there was something I’d missed.

For this particular app I created a separate window message procedure where the ID I want selectable is actually a read-only, flat, transparent entry field.

Works fine. But it’s kinda too bad that one needs to give up some functionality in order to gain the other functionality that MessageBox provides.

Thanks for checking!

Another option is to give them some choices and be done. :slight_smile:

CASE message('This athena ID is already matched to|CenCal patient ZZZ, JANE|with ID of ZZZ12345','Wrong-O',ICON:Exclamation,'OK|Copy This|Copy That',,2)
OF 2
OF 3

Good idea, Jeff.

You have the Message Procedure ds_Message() that you can change the code.

Here’s a Test Message using Capesoft:


The Message Window puts all the text into a PROMPT(''''),AT(118,32),USE(?MainTextPrompt). The ThisMessage class breaks it into lines and adds 13,10s.

I tested modifying it to use a TEXT control that would allow Select and Copy. To test it I added the TEXT to the right of the existing Prompt so I can see them side by side to know its correct. I run this in a Routine when F8 is pressed so normal Messages are not affected. It looks good so far.

The above is BOXED to see the size. Below is the without the Box. The Prompt and Text look identical to me … although I swear the TEXT on the right looks a little smaller. Both are Segoe 10.

Below is the code I run when F8 is pressed.
Editted 3/20/24 to be final code that is complete and ready to release. Will be using this for when I am running in “Dev mode”…

MakeCopyTextControlRtn  ROUTINE  !3/20/24 when F8 add TEXT so Jane can Select+Copy message  F9=OnTop
TextX LONG    
TextY LONG    
TextW LONG    
DbgOnTextSide   BOOL(False)
    IF KEYCODE()=F8Key THEN DbgOnTextSide=True. !F8 debug puts new TEXT to Right side
    IF LenPmt=0 THEN EXIT.                      !No Body Text then no need for TEXT Control
    GETPOSITION(?MainTextPrompt,TextX,TextY,TextW,TextH)   !<==Message Text Control is Prompt
    IF DbgOnTextSide THEN 
       TextX = WinWd + 10           !For Debug put TEXT() on Right of Prompt 
       TextY -= 1 
       SETPOSITION(0,,,WinWd*2+20)  !Make Window 2X wider and put TEXT on right
       TextX -= 2                   !TEXT needs X move left to be over Prompt
       TextY -= 1                   !TEXT needs Y move up   to be over Prompt
       HIDE(?MainTextPrompt)        !If ~Debug then Hide( Prompt ) and Leave TextX as is

    TextFEQ=CREATE(0,CREATE:TEXT)   !The TEXT control to replace the PROMPT
    SETPOSITION(TextFEQ,TextX,TextY,TextW+4+8,TextH+4)   !+8 for extra width, should be no problem
        ! +4 ? How much extra for Frameless? use GetSystemMetrics()?  SM_CXEdge CYEdge ?

    TextFEQ{PROP:Boxed}=0      !Set =1 to see control size for Debug / Design
    !No TextFEQ{PROP:Trn}=1    !TRN flickers, so below change color instead 
    TextFEQ{PROP:Color}    =CHOOSE(~0{PROP:Gray}, COLOR:Window    ,COLOR:BtnFace)
    TextFEQ{PROP:FontColor}=CHOOSE(~0{PROP:Gray}, COLOR:WindowText,COLOR:BtnText)   

    !The Prompt Text has && doubled by Class so change && to &
    PmtTxt &=NEW(STRING(LenPmt+9))
    PmtTxt = ?MainTextPrompt{PROP:Text}
    LOOP P=1 TO LenPmt
        IF PmtTxt[P]='&' AND PmtTxt[P+1]='&' THEN P+=1.  !Its && Skip 1 &
        M += 1
        IF M=P THEN CYCLE.
        PmtTxt[M]=PmtTxt[P] ; PmtTxt[P]=''
    TextFEQ{PROP:Text} = PmtTxt  !was ?MainTextPrompt{PROP:Text}

F9 positions the TEXT on top of the Prompt (and hides it) so this is the final result.

Oddly when I select with the mouse text it kind of bolds the other text on the line. You can see it in the below capture. Sometimes TRN messes with painting.

3/18 - Edited to remove TRN and instead set Font Colors to match Window, this fixed painting flicker when selecting text.


The size choices I made going from Prompt to Text look fine, but need review and checking.

Jane you should try my Gray/White Button Panel change. It is easy to add in one Routine. It makes the Message look more like the API.

1 Like

Thanks, Carl!

You are definitely the Window Dude. Rick’s suggestion of using a text control elegantly brought to life!
The wizards at Capesoft might want to consider a change like this.

Since I’ve already coded a dedicated message window for this particular procedure’s needs I’ll stick with that, but will definitely keep your code in mind if needed in the future.

And yes, I like the way your Gray/White Button Panel works.
Although I suffered 20 minutes of head-banging (yes, I’m that slow) on one app when I didn’t realize that the MessageBox import of the three procedures puts grad_bar.bmp as wallpaper on the ds_Message window, and that needs to be removed for your code to work.

Thanks for what looks like an elegant solution!


I just throw the ideas out like a gauntlet knowing that Carl can’t resist coding up actual examples. :rofl:


Confirmed that PROP:TRN=1 is the problem causing odd painting.

Revised code to not set TRN=1, instead set Text Control Colors to match the Window Colors. Below is revised code, and I edited my original post above:

       !No TextFEQ{PROP:Trn}=1                 !Flickers, so change color instead 
       TextFEQ{PROP:Color}    =CHOOSE(~0{PROP:Gray}, COLOR:Window    ,COLOR:BtnFace)
       TextFEQ{PROP:FontColor}=CHOOSE(~0{PROP:Gray}, COLOR:WindowText,COLOR:BtnText)   
       TextFEQ{PROP:Boxed}=0      !For Debug to see control size set =1       

One way this could be tested would be to only use the TEXT control if MSGMODE:CANCOPY is in the StylePar i.e. IF BAND(StylePar,MSGMODE:CaNCopy) . If that worked then either always do it, or check IF BAND(SYSTEM{PROP:MsgModeDefault},MSGMODE:CaNCopy) and rely on setting that for the feature some same what the RTL works.

Capesoft ds_Message() is easy to modify and make do new things. All of the complexity is in the Class that formats the Window controls for that procedure gets very far.

I have a Message “thing” I need to get published on GitHub that lets you press Ctrl+E to open a Message Box Editor. Often I want to tinker with the line breaks or wording so this makes it easy.

Can modify it, preview then generate new Message() Code:

What was more work was generating the Window code. Often a Message() gets too complicated and you want a Window, this makes it faster.

This Editor started like many things … how hard can it be … just a Window with an Entry for Caption and Text for the body :wink: