Tuesday, August 26, 2025

 Multi-Monitor Smudge

MS-Windows lost my Window...?

Apparently, it's not MS-Windows. It's me, when saving the program's last locations in an .INI file.

If I close the program. It saves the Top/Left so when run again it comes back where I left it. But if I change primary monitors, or orientation, before I run it again, I have a problem - if it was closed on any non-primary monitor. My Left = -1700 might now be +1700 and is now WAY off screen. Or too high/low, if the monitors were stacked and now side-by-side.

My multi-monitor solution was to put the following code in my On Show event.

//-------------------------------------
//reset form if primary monitor changed
int drL, drT, drR, drB;
TRect drect;
drect = Screen->DesktopRect;
drL = drect.Left;
drT = drect.Top;
drR =drect.Right;
drB = drect.Bottom;
if(Top < drT)//too high
     {Top = 0;}
if(Top > drB)//too low
     {Top = 0;}
if(Left < drL)//too far left
     {Left = 0;}
if(Left > drR)//too far right
     {Left = 0;}
//-------------------------------------


This would also help if I disconnected the secondary monitor.


 

Friday, August 22, 2025

Character smudges
Crystalfontz makes serial port and USB programmable LCD displays for your PC. Lots of uses... Monitor resources, core temps, playlists, mail notification, messages, gaming ...
Even bigger, the same type of applications that can print to these devices, can talk to billboards, gas pumps, numerous other devices. It's not as hard as it looks. I started on one twenty years ago, and recently found it on an old backup CD. I've been taking it out and playing with it regularly.

There are a few bumps with these things. For example, some ansi characters didn't display properly. Those are ~ ` $ { } [ ] | \ These  nine are reserved control chars built into the ROM and are substituted with random upper-ansi chars. But they were nice enough to give you eight spare character slots on the ROM, you can insert your own into. Yeah... and it's binary... it's either black or backlit.
So lately, after I hard-coded replacements for the replacement, I've been working on alternate sets of characters, I can call on demand - stuffed in a file, called up, displayed, and dumped, if needed. I mean, I have two hundred and fifty-five slots I can, fill 8 at a time.
The basic character array is an declared as :  static unsigned char [ ] [8] [8] = ...
________________________________________
using this| shows as| so assign new char
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 `            ¿           n/a (not used)
 ~           Ü            '\000'
 $            ¤            '\001'
 {            ä            '\002'
 }            ñ            '\003'
 [            Ä            '\004'
 ]            Ñ            '\005'
 |            ö            '\006'
 \            Ö            '\007'
________________________________________
static unsigned defaultcustchar [][8][8] =
{
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,1,1,0,0,1},
    {0,0,1,0,0,1,1,0},// ~
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,0,0,0}
  },
    {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,1,0,0},
    {0,0,0,0,1,1,1,0},// $
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,0,1,0,0},
    {0,0,0,0,0,0,1,0},
    {0,0,0,0,1,1,1,0},
    {0,0,0,0,0,1,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,1,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},// {
    {0,0,0,1,0,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,0,1,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,1,0,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},// }
    {0,0,0,0,0,1,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,1,0,0,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,1,1,0,0,0},
    {0,0,0,1,0,0,0,0},
    {0,0,0,1,0,0,0,0},// [
    {0,0,0,1,0,0,0,0},
    {0,0,0,1,0,0,0,0},
    {0,0,0,1,1,0,0,0},
    {0,0,0,0,0,0,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,0,1,1,0},
    {0,0,0,0,0,0,1,0},
    {0,0,0,0,0,0,1,0},// ]
    {0,0,0,0,0,0,1,0},
    {0,0,0,0,0,0,1,0},
    {0,0,0,0,0,1,1,0},
    {0,0,0,0,0,0,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},// |
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,0,0}
  },
  {
    {0,0,0,0,0,0,0,0},
    {0,0,1,0,0,0,0,0},
    {0,0,0,1,0,0,0,0},
    {0,0,0,0,1,0,0,0},// backslash
    {0,0,0,0,0,1,0,0},
    {0,0,0,0,0,0,1,0},
    {0,0,0,0,0,0,0,1},
    {0,0,0,0,0,0,0,0}
  }
};

I'll assign them to the device with a button click (labeled "Default")
if(bRunning){
     unsigned char cData[8];
    int i, j;
    for (i = 0; i < TOTAL_CUSTS; i++)//fill the array
    {
        for (j = 0; j < 8; j++)
        {
        cData[j] = (unsigned char) ((128 * defaultcustchar[i-1][j][0]) +
        (64 * defaultcustchar[i][j][1]) + (32 * defaultcustchar[i][j][2]) +
        (16 * defaultcustchar[i][j][3]) + (8 * defaultcustchar[i][j][4]) +
        (4 * defaultcustchar[i][j][5]) + (2 * defaultcustchar[i][j][6]) +
        defaultcustchar[i][j][7]);
        }
        if (LCD_RESULT_NOERROR != lcdSetCustomChar(i, cData))
        {
        lcdFree();               
        }
    }
          lcdClearDisplay();
          lcdSetCursorPos(7,2);//LCD third line gets the first 8 chars
          lcdSendCharacter('\000');
          lcdSendCharacter('\001');
          lcdSendCharacter('\002');
          lcdSendCharacter('\003');
          lcdSendCharacter('\004');
          lcdSendCharacter('\005');
          lcdSendCharacter('\006');
          lcdSendCharacter('\007');
          TestBtn->Enabled = true;
          }//end of if(bRunning)


Pretty good likeness.
Okay, so those are hard into the .exe file. What about your artistic nature when you need, bars for graphs, inverse characters, sparkly things, or a battery indicator:
const unsigned char battery[8] =
{
0x0E,               // .###.          .
0x1F,               // #####          .
0x11,               // #___#          .
0x11,               // #___#          .
0x1F,               // #####          .
0x1F,               // #####          .
0x1F,               // #####          .
0x1F                // ##### cursor row
};


So there's this character generator (dialog) I'm been working on. A matrix of 64 clickable TPanel objects - click=ON, click=OFF ...  Each sets one of 64 declared booleans,  pixal1-64. They also change color, and a second set of panels sized 2x2 in an "actual size" demo array. I added a TEdit control set with an alphanumeric font to mimic the device - wysiwyg, sort of.
void __fastcall TCharGenerator::Panel18Click(TObject *Sender)
{
//
TPanel *thispanel = (TPanel*)Sender;
if(thispanel->Color == clBlack)
    {
     thispanel->Color = Edit3->Color;
     pixal17 = false;
     thispanel->Hint = "|Off";
     P18->Color= Edit3->Color;
     }
     else
     {
     thispanel->Color = clBlack;
     pixal17 = true;
     thispanel->Hint = "|On";
     P18->Color = clBlack;
          }

After the 64 OnClicks.... 


That monster of a piece I wrote a few days ago has something to do with that grid. You can see the return values in the right hand column. Those numbers are what I save to the disk and call up as needed:
TIniFile *CharsINI = new TIniFile(ExtractFilePath(Application->ExeName)+ "chars.ini");
if(Edit1->Text != "")//Character Name
     {
     unsigned char custchar[8] = {0,0,0,0,0,0,0,0};//initialize blank char

     //read matrix data from panel1
     custchar[0] = (unsigned char)GetCharLine(pixal49,pixal50,pixal1,pixal2,pixal3,pixal4,pixal5,pixal6);
     custchar[1] = (unsigned char)GetCharLine(pixal51,pixal52,pixal7,pixal8,pixal9,pixal10,pixal11,pixal12);
     custchar[2] = (unsigned char)GetCharLine(pixal53,pixal54,pixal13,pixal14,pixal15,pixal16,pixal17,pixal18);
     custchar[3] = (unsigned char)GetCharLine(pixal55,pixal56,pixal19,pixal20,pixal21,pixal22,pixal23,pixal24);
     custchar[4] = (unsigned char)GetCharLine(pixal57,pixal58,pixal25,pixal26,pixal27,pixal28,pixal29,pixal30);
     custchar[5] = (unsigned char)GetCharLine(pixal59,pixal60,pixal31,pixal32,pixal33,pixal34,pixal35,pixal36);
     custchar[6] = (unsigned char)GetCharLine(pixal61,pixal62,pixal37,pixal38,pixal39,pixal40,pixal41,pixal42);
     custchar[7] = (unsigned char)GetCharLine(pixal63,pixal64,pixal43,pixal44,pixal45,pixal46,pixal47,pixal48);

 
    CharsINI->WriteInteger(Edit1->Text, "line0",custchar[0]);
    CharsINI->WriteInteger(Edit1->Text, "line1",custchar[1]);
    CharsINI->WriteInteger(Edit1->Text, "line2",custchar[2]);
    CharsINI->WriteInteger(Edit1->Text, "line3",custchar[3]);
    CharsINI->WriteInteger(Edit1->Text, "line4",custchar[4]);
    CharsINI->WriteInteger(Edit1->Text, "line5",custchar[5]);
    CharsINI->WriteInteger(Edit1->Text, "line6",custchar[6]);
    CharsINI->WriteInteger(Edit1->Text, "line7",custchar[7]);
    CharsINI->ReadSections(ListBox1->Items);//reload listbox

    Edit1->Text = "";
    ListBox1->SetFocus();
    Button3->Click();// next slide please

    Label10->Caption =  IntToStr( custchar[0]);// IntToStr((char)GetCharLine(pixal1,pixal2,pixal3,pixal4,pixal5,pixal6));
    }
else
    {
    ShowMessage("You gotta name it first");
    }

AnsiString s;
AnsiString sCustChar;
AnsiString s0,s1,s2,s3,s4,s5,s6,s7;
int iIndex;
iint i0,i1,i2,i3,i4,i5,i6,i7;
int ih0,ih1,ih2,ih3,ih4,ih5,ih6,ih7;
int iline0, iline1, iline2, iline3, iline4, iline5, iline6, iline7;
int iCount = ListBox1->Items->Count;
int iHex = iline0;


if(bRunning){
for(int iFill=0;iFill < iCount; ++iFill)
        {
        if(iCount >= 0)
            {
            if(ListBox1->ItemIndex >= 0)
                {
                s = ListBox1->Items->Strings[iFill];
                //get the ints from the file
                iline0 = CharsINI->ReadInteger(s,"line0",0);
                iline1 = CharsINI->ReadInteger(s,"line1",0);
                iline2 = CharsINI->ReadInteger(s,"line2",0);
                iline3 = CharsINI->ReadInteger(s,"line3",0);
                iline4 = CharsINI->ReadInteger(s,"line4",0);
                iline5 = CharsINI->ReadInteger(s,"line5",0);
                iline6 = CharsINI->ReadInteger(s,"line6",0);
                iline7 = CharsINI->ReadInteger(s,"line7",0);
                                iIndex = ListBox1->Items->IndexOf(s);
                }
            }

            sCustChar = IntToStr(iline0) + "," + IntToStr(iline1) +
             "," + IntToStr(iline2) + "," + IntToStr(iline3) +
            "," + IntToStr(iline4) + "," + IntToStr(iline5) +
            "," + IntToStr(iline6) + "," + IntToStr(iline7);

            iHex = iline0;
                i0 = iline0;
            i1 = iline1;
            i2 = iline2;
            i3 = iline3;
            i4 = iline4;
            i5 = iline5;
            i6 = iline6;
            i7 = iline7;
            s0 = "0x"+  sCustChar.IntToHex(i0, 8);
            s1 = "0x"+  sCustChar.IntToHex(i1, 8);
            s2 = "0x"+  sCustChar.IntToHex(i2, 8);
            s3 = "0x"+  sCustChar.IntToHex(i3, 8);
            s4 = "0x"+  sCustChar.IntToHex(i4, 8);
            s5 = "0x"+  sCustChar.IntToHex(i5, 8);
            s6 = "0x"+  sCustChar.IntToHex(i6, 8);
            s7 = "0x"+  sCustChar.IntToHex(i7, 8);
            ih0 = StrToInt(s0);
            ih1 = StrToInt(s1);
            ih2 = StrToInt(s2);
            ih3 = StrToInt(s3);
            ih4 = StrToInt(s4);
            ih5 = StrToInt(s5);
            ih6 = StrToInt(s6);
            ih7 = StrToInt(s7);
 


//----------------------------Now, lets make a custom char                   .
unsigned char custchar [8]  = {ih0,ih1,ih2,ih3,ih4,ih5,ih6,ih7};
*custchar = (unsigned char)  ( ih0,ih1,ih2,ih3,ih4,ih5,ih6,ih7 );
  lcdSetCustomChar(iFill, custchar);

}//end of for 


lcdClearDisplay();
lcdSetCursorPos(0,1);
lcdSendCharacter('\000');
lcdSendCharacter('\001');
lcdSendCharacter('\002');
lcdSendCharacter('\003');
lcdSendCharacter('\004');
lcdSendCharacter('\005');
lcdSendCharacter('\006');
lcdSendCharacter('\007');
String sHex2 = IntToHex(*custchar,8);
Edit3->Text = sHex2;//the big yellow label at the bottom
delete custchar;
TestBtn->Enabled = true;
} //end of if(bRunning)

      
delete CharsINI;

And out pops another character set for display

Next step - read them back into the panel array, ListBox-> OnClick, for editing. I'll blog some more about the LCD Controller next time.




Wednesday, August 20, 2025

Typing Practice

 Today's smudge

There's gotta be an easier way..... I still have the "Setter "to write:

int TCharGenerator::GetCharLine(bool g, bool h, bool a, bool b, bool c, bool d, bool e, bool f)

{
//jeex = 256 test posibilities

if(!g && !h && !a && !b && !c && !d && !e && !f)
    {
     return  0;
     }  //00000000

if(!g && !h && !a && !b && !c && !d && !e && f)   {return    1;}      //00000001
if(!g && !h && !a && !b && !c && !d && e && !f)   {return    2;}      //00000010
if(!g && !h && !a && !b && !c && !d && e && f)    {return    3;}      //00000011
if(!g && !h && !a && !b && !c && d && !e && !f)   {return    4;}      //00000100
if(!g && !h && !a && !b && !c && d && !e && f)    {return    5;}      //00000101
if(!g && !h && !a && !b && !c && d && e && !f)    {return    6;}      //00000110
if(!g && !h && !a && !b && !c && d && e && f)     {return    7;}      //00000111
if(!g && !h && !a && !b && c && !d && !e && !f)   {return    8;}      //00001000
if(!g && !h && !a && !b && c && !d && !e && f)    {return    9;}      //00001001
if(!g && !h && !a && !b && c && !d && e && !f)    {return   10;}      //00001010
if(!g && !h && !a && !b && c && !d && e && f)     {return   11;}      //00001011
if(!g && !h && !a && !b && c && d && !e && !f)    {return   12;}      //00001100
if(!g && !h && !a && !b && c && d && !e && f)     {return   13;}      //00001101
if(!g && !h && !a && !b && c && d && e && !f)     {return   14;}      //00001110
if(!g && !h && !a && !b && c && d && e && f)      {return   15;}      //00001111
if(!g && !h && !a && b && !c && !d && !e && !f)   {return   16;}      //00010000
if(!g && !h && !a && b && !c && !d && !e && f)    {return   17;}      //00010001
if(!g && !h && !a && b && !c && !d && e && !f)    {return   18;}      //00010010
if(!g && !h && !a && b && !c && !d && e && f)     {return   19;}      //00010011
if(!g && !h && !a && b && !c && d && !e && !f)    {return   20;}      //00010100
if(!g && !h && !a && b && !c && d && !e && f)     {return   21;}      //00010101
if(!g && !h && !a && b && !c && d && e && !f)     {return   22;}      //00010110
if(!g && !h && !a && b && !c && d && e && f)      {return   23;}      //00010111
if(!g && !h && !a && b && c && !d && !e && !f)    {return   24;}      //00011000
if(!g && !h && !a && b && c && !d && !e && f)     {return   25;}      //00011001
if(!g && !h && !a && b && c && !d && e && !f)     {return   26;}      //00011010
if(!g && !h && !a && b && c && !d && e && f)      {return   27;}      //00011011
if(!g && !h && !a && b && c && d && !e && !f)     {return   28;}      //00011100
if(!g && !h && !a && b && c && d && !e && f)      {return   29;}      //00011101
if(!g && !h && !a && b && c && d && e && !f)      {return   30;}      //00011110
if(!g && !h && !a && b && c && d && e && f)       {return   31;}      //00011111
if(!g && !h && a && !b && !c && !d && !e && !f)   {return   32;}      //00100000
//typing rest area .....pant pant pant.............
if(!g && !h && a && !b && !c && !d && !e && f)    {return   33;}      //00100001
if(!g && !h && a && !b && !c && !d && e && !f)    {return   34;}      //00100010
if(!g && !h && a && !b && !c && !d && e && f)     {return   35;}      //00100011
if(!g && !h && a && !b && !c && d && !e && !f)    {return   36;}      //00100100
if(!g && !h && a && !b && !c && d && !e && f)     {return   37;}      //00100101
if(!g && !h && a && !b && !c && d && e && !f)     {return   38;}      //00100110
if(!g && !h && a && !b && !c && d && e && f)      {return   39;}      //00100111
if(!g && !h && a && !b && c && !d && !e && !f)    {return   40;}      //00101000
if(!g && !h && a && !b && c && !d && !e && f)     {return   41;}      //00101001
if(!g && !h && a && !b && c && !d && e && !f)     {return   42;}      //00101010
if(!g && !h && a && !b && c && !d && e && f)      {return   43;}      //00101011
if(!g && !h && a && !b && c && d && !e && !f)     {return   44;}      //00101100
if(!g && !h && a && !b && c && d && !e && f)      {return   45;}      //00101101
if(!g && !h && a && !b && c && d && e && !f)      {return   46;}      //00101110
if(!g && !h && a && !b && c && d && e && f)       {return   47;}      //00101111
if(!g && !h && a && b && !c && !d && !e && !f)    {return   48;}      //00110000
if(!g && !h && a && b && !c && !d && !e && f)     {return   49;}      //00110001
if(!g && !h && a && b && !c && !d && e && !f)     {return   50;}      //00110010
if(!g && !h && a && b && !c && !d && e && f)      {return   51;}      //00110011
if(!g && !h && a && b && !c && d && !e && !f)     {return   52;}      //00110100
if(!g && !h && a && b && !c && d && !e && f)      {return   53;}      //00110101
if(!g && !h && a && b && !c && d && e && !f)      {return   54;}      //00110110
if(!g && !h && a && b && !c && d && e && f)       {return   55;}      //00110111
if(!g && !h && a && b && c && !d && !e && !f)     {return   56;}      //00111000
if(!g && !h && a && b && c && !d && !e && f)      {return   57;}      //00111001
if(!g && !h && a && b && c && !d && e && !f)      {return   58;}      //00111010
if(!g && !h && a && b && c && !d && e && f)       {return   59;}      //00111011
if(!g && !h && a && b && c && d && !e && !f)      {return   60;}      //00111100
if(!g && !h && a && b && c && d && !e && f)       {return   61;}      //00111101
if(!g && !h && a && b && c && d && e && !f)       {return   62;}      //00111110
if(!g && !h && a && b && c && d && e && f)        {return   63;}      //00111111
//typing rest area .....pant pant pant.............
if(!g && h && !a && !b && !c && !d && !e && !f)   {return   64;}      //01000000
if(!g && h && !a && !b && !c && !d && !e && f)    {return   65;}      //01000001
if(!g && h && !a && !b && !c && !d && e && !f)    {return   66;}      //01000010
if(!g && h && !a && !b && !c && !d && e && f)     {return   67;}      //01000011
if(!g && h && !a && !b && !c && d && !e && !f)    {return   68;}      //01000100
if(!g && h && !a && !b && !c && d && !e && f)     {return   69;}      //01000101
if(!g && h && !a && !b && !c && d && e && !f)     {return   70;}      //01000110
if(!g && h && !a && !b && !c && d && e && f)      {return   71;}      //01000111
if(!g && h && !a && !b && c && !d && !e && !f)    {return   72;}      //01001000
if(!g && h && !a && !b && c && !d && !e && f)     {return   73;}      //01001001
if(!g && h && !a && !b && c && !d && e && !f)     {return   74;}      //01001010
if(!g && h && !a && !b && c && !d && e && f)      {return   75;}      //01001011
if(!g && h && !a && !b && c && d && !e && !f)     {return   76;}      //01001100
if(!g && h && !a && !b && c && d && !e && f)      {return   77;}      //01001101
if(!g && h && !a && !b && c && d && e && !f)      {return   78;}      //01001110
if(!g && h && !a && !b && c && d && e && f)       {return   79;}      //01001111
if(!g && h && !a && b && !c && !d && !e && !f)    {return   80;}      //01010000
if(!g && h && !a && b && !c && !d && !e && f)     {return   81;}      //01010001
if(!g && h && !a && b && !c && !d && e && !f)     {return   82;}      //01010010
if(!g && h && !a && b && !c && !d && e && f)      {return   83;}      //01010011
if(!g && h && !a && b && !c && d && !e && !f)     {return   84;}      //01010100
if(!g && h && !a && b && !c && d && !e && f)      {return   85;}      //01010101
if(!g && h && !a && b && !c && d && e && !f)      {return   86;}      //01010110
if(!g && h && !a && b && !c && d && e && f)       {return   87;}      //01010111
if(!g && h && !a && b && c && !d && !e && !f)     {return   88;}      //01011000
if(!g && h && !a && b && c && !d && !e && f)      {return   89;}      //01011001
if(!g && h && !a && b && c && !d && e && !f)      {return   90;}      //01011010
if(!g && h && !a && b && c && !d && e && f)       {return   91;}      //01011011
if(!g && h && !a && b && c && d && !e && !f)      {return   92;}      //01011100
if(!g && h && !a && b && c && d && !e && f)       {return   93;}      //01011101
if(!g && h && !a && b && c && d && e && !f)       {return   94;}      //01011110
if(!g && h && !a && b && c && d && e && f)        {return   95;}      //01011111
if(!g && h && a && !b && !c && !d && !e && !f)    {return   96;}      //01100000
//typing rest area .....pant pant pant.............
if(!g && h && a && !b && !c && !d && !e && f)     {return   97;}      //01100001
if(!g && h && a && !b && !c && !d && e && !f)     {return   98;}      //01100010
if(!g && h && a && !b && !c && !d && e && f)      {return   99;}      //01100011
if(!g && h && a && !b && !c && d && !e && !f)     {return  100;}      //01100100
if(!g && h && a && !b && !c && d && !e && f)      {return  101;}      //01100101
if(!g && h && a && !b && !c && d && e && !f)      {return  102;}      //01100110
if(!g && h && a && !b && !c && d && e && f)       {return  103;}      //01100111
if(!g && h && a && !b && c && !d && !e && !f)     {return  104;}      //01101000
if(!g && h && a && !b && c && !d && !e && f)      {return  105;}      //01101001
if(!g && h && a && !b && c && !d && e && !f)      {return  106;}      //01101010
if(!g && h && a && !b && c && !d && e && f)       {return  107;}      //01101011
if(!g && h && a && !b && c && d && !e && !f)      {return  108;}      //01101100
if(!g && h && a && !b && c && d && !e && f)       {return  109;}      //01101101
if(!g && h && a && !b && c && d && e && !f)       {return  110;}      //01101110
if(!g && h && a && !b && c && d && e && f)        {return  111;}      //01101111
if(!g && h && a && b && !c && !d && !e && !f)     {return  112;}      //01110000
if(!g && h && a && b && !c && !d && !e && f)      {return  113;}      //01110001
if(!g && h && a && b && !c && !d && e && !f)      {return  114;}      //01110010
if(!g && h && a && b && !c && !d && e && f)       {return  115;}      //01110011
if(!g && h && a && b && !c && d && !e && !f)      {return  116;}      //01110100
if(!g && h && a && b && !c && d && !e && f)       {return  117;}      //01110101
if(!g && h && a && b && !c && d && e && !f)       {return  118;}      //01110110
if(!g && h && a && b && !c && d && e && f)        {return  119;}      //01110111
if(!g && h && a && b && c && !d && !e && !f)      {return  120;}      //01111000
if(!g && h && a && b && c && !d && !e && f)       {return  121;}      //01111001
if(!g && h && a && b && c && !d && e && !f)       {return  122;}      //01111010
if(!g && h && a && b && c && !d && e && f)        {return  123;}      //01111011
if(!g && h && a && b && c && d && !e && !f)       {return  124;}      //01111100
if(!g && h && a && b && c && d && !e && f)        {return  125;}      //01111101
if(!g && h && a && b && c && d && e && !f)        {return  126;}      //01111110
if(!g && h && a && b && c && d && e && f)         {return  127;}      //01111111
//typing rest area .....pant pant pant.............
if(g && !h && !a && !b && !c && !d && !e && !f)   {return  128;}      //10000000
if(g && !h && !a && !b && !c && !d && !e && f)    {return  129;}      //10000001
if(g && !h && !a && !b && !c && !d && e && !f)    {return  130;}      //10000010
if(g && !h && !a && !b && !c && !d && e && f)     {return  131;}      //10000011
if(g && !h && !a && !b && !c && d && !e && !f)    {return  132;}      //10000100
if(g && !h && !a && !b && !c && d && !e && f)     {return  133;}      //10000101
if(g && !h && !a && !b && !c && d && e && !f)     {return  134;}      //10000110
if(g && !h && !a && !b && !c && d && e && f)      {return  135;}      //10000111
if(g && !h && !a && !b && c && !d && !e && !f)    {return  136;}      //10001000
if(g && !h && !a && !b && c && !d && !e && f)     {return  137;}      //10001001
if(g && !h && !a && !b && c && !d && e && !f)     {return  138;}      //10001010
if(g && !h && !a && !b && c && !d && e && f)      {return  139;}      //10001011
if(g && !h && !a && !b && c && d && !e && !f)     {return  140;}      //10001100
if(g && !h && !a && !b && c && d && !e && f)      {return  141;}      //10001101
if(g && !h && !a && !b && c && d && e && !f)      {return  142;}      //10001110
if(g && !h && !a && !b && c && d && e && f)       {return  143;}      //10001111
if(g && !h && !a && b && !c && !d && !e && !f)    {return  144;}      //10010000
if(g && !h && !a && b && !c && !d && !e && f)     {return  145;}      //10010001
if(g && !h && !a && b && !c && !d && e && !f)     {return  146;}      //10010010
if(g && !h && !a && b && !c && !d && e && f)      {return  147;}      //10010011
if(g && !h && !a && b && !c && d && !e && !f)     {return  148;}      //10010100
if(g && !h && !a && b && !c && d && !e && f)      {return  149;}      //10010101
if(g && !h && !a && b && !c && d && e && !f)      {return  150;}      //10010110
if(g && !h && !a && b && !c && d && e && f)       {return  151;}      //10010111
if(g && !h && !a && b && c && !d && !e && !f)     {return  152;}      //10011000
if(g && !h && !a && b && c && !d && !e && f)      {return  153;}      //10011001
if(g && !h && !a && b && c && !d && e && !f)      {return  154;}      //10011010
if(g && !h && !a && b && c && !d && e && f)       {return  155;}      //10011011
if(g && !h && !a && b && c && d && !e && !f)      {return  156;}      //10011100
if(g && !h && !a && b && c && d && !e && f)       {return  157;}      //10011101
if(g && !h && !a && b && c && d && e && !f)       {return  158;}      //10011110
if(g && !h && !a && b && c && d && e && f)        {return  159;}      //10011111
if(g && !h && a && !b && !c && !d && !e && !f)    {return  160;}      //10100000
//typing rest area .....pant pant pant.............
if(g && !h && a && !b && !c && !d && !e && f)     {return  161;}      //10100001
if(g && !h && a && !b && !c && !d && e && !f)     {return  162;}      //10100010
if(g && !h && a && !b && !c && !d && e && f)      {return  163;}      //10100011
if(g && !h && a && !b && !c && d && !e && !f)     {return  164;}      //10100100
if(g && !h && a && !b && !c && d && !e && f)      {return  165;}      //10100101
if(g && !h && a && !b && !c && d && e && !f)      {return  166;}      //10100110
if(g && !h && a && !b && !c && d && e && f)       {return  167;}      //10100111
if(g && !h && a && !b && c && !d && !e && !f)     {return  168;}      //10101000
if(g && !h && a && !b && c && !d && !e && f)      {return  169;}      //10101001
if(g && !h && a && !b && c && !d && e && !f)      {return  170;}      //10101010
if(g && !h && a && !b && c && !d && e && f)       {return  171;}      //10101011
if(g && !h && a && !b && c && d && !e && !f)      {return  172;}      //10101100
if(g && !h && a && !b && c && d && !e && f)       {return  173;}      //10101101
if(g && !h && a && !b && c && d && e && !f)       {return  174;}      //10101110
if(g && !h && a && !b && c && d && e && f)        {return  175;}      //10101111
if(g && !h && a && b && !c && !d && !e && !f)     {return  176;}      //10110000
if(g && !h && a && b && !c && !d && !e && f)      {return  177;}      //10110001
if(g && !h && a && b && !c && !d && e && !f)      {return  178;}      //10110010
if(g && !h && a && b && !c && !d && e && f)       {return  179;}      //10110011
if(g && !h && a && b && !c && d && !e && !f)      {return  180;}      //10110100
if(g && !h && a && b && !c && d && !e && f)       {return  181;}      //10110101
if(g && !h && a && b && !c && d && e && !f)       {return  182;}      //10110110
if(g && !h && a && b && !c && d && e && f)        {return  183;}      //10110111
if(g && !h && a && b && c && !d && !e && !f)      {return  184;}      //10111000
if(g && !h && a && b && c && !d && !e && f)       {return  185;}      //10111001
if(g && !h && a && b && c && !d && e && !f)       {return  186;}      //10111010
if(g && !h && a && b && c && !d && e && f)        {return  187;}      //10111011
if(g && !h && a && b && c && d && !e && !f)       {return  188;}      //10111100
if(g && !h && a && b && c && d && !e && f)        {return  189;}      //10111101
if(g && !h && a && b && c && d && e && !f)        {return  190;}      //10111110
if(g && !h && a && b && c && d && e && f)         {return  191;}      //10111111
//typing rest area .....pant pant pant.............
if(g && h && !a && !b && !c && !d && !e && !f)    {return  192;}      //11000000
if(g && h && !a && !b && !c && !d && !e && f)     {return  193;}      //11000001
if(g && h && !a && !b && !c && !d && e && !f)     {return  194;}      //11000010
if(g && h && !a && !b && !c && !d && e && f)      {return  195;}      //11000011
if(g && h && !a && !b && !c && d && !e && !f)     {return  196;}      //11000100
if(g && h && !a && !b && !c && d && !e && f)      {return  197;}      //11000101
if(g && h && !a && !b && !c && d && e && !f)      {return  198;}      //11000110
if(g && h && !a && !b && !c && d && e && f)       {return  199;}      //11000111
if(g && h && !a && !b && c && !d && !e && !f)     {return  200;}      //11001000
if(g && h && !a && !b && c && !d && !e && f)      {return  201;}      //11001001
if(g && h && !a && !b && c && !d && e && !f)      {return  202;}      //11001010
if(g && h && !a && !b && c && !d && e && f)       {return  203;}      //11001011
if(g && h && !a && !b && c && d && !e && !f)      {return  204;}      //11001100
if(g && h && !a && !b && c && d && !e && f)       {return  205;}      //11001101
if(g && h && !a && !b && c && d && e && !f)       {return  206;}      //11001110
if(g && h && !a && !b && c && d && e && f)        {return  207;}      //11001111
if(g && h && !a && b && !c && !d && !e && !f)     {return  208;}      //11010000
if(g && h && !a && b && !c && !d && !e && f)      {return  209;}      //11010001
if(g && h && !a && b && !c && !d && e && !f)      {return  210;}      //11010010
if(g && h && !a && b && !c && !d && e && f)       {return  211;}      //11010011
if(g && h && !a && b && !c && d && !e && !f)      {return  212;}      //11010100
if(g && h && !a && b && !c && d && !e && f)       {return  213;}      //11010101
if(g && h && !a && b && !c && d && e && !f)       {return  214;}      //11010110
if(g && h && !a && b && !c && d && e && f)        {return  215;}      //11010111
if(g && h && !a && b && c && !d && !e && !f)      {return  216;}      //11011000
if(g && h && !a && b && c && !d && !e && f)       {return  217;}      //11011001
if(g && h && !a && b && c && !d && e && !f)       {return  218;}      //11011010
if(g && h && !a && b && c && !d && e && f)        {return  219;}      //11011011
if(g && h && !a && b && c && d && !e && !f)       {return  220;}      //11011100
if(g && h && !a && b && c && d && !e && f)        {return  221;}      //11011101
if(g && h && !a && b && c && d && e && !f)        {return  222;}      //11011110
if(g && h && !a && b && c && d && e && f)         {return  223;}      //11011111
if(g && h && a && !b && !c && !d && !e && !f)     {return  224;}      //11000000
//typing rest area .....pant pant pant.............
if(g && h && a && !b && !c && !d && !e && f)      {return  225;}      //11100001
if(g && h && a && !b && !c && !d && e && !f)      {return  226;}      //11100010
if(g && h && a && !b && !c && !d && e && f)       {return  227;}      //11100011
if(g && h && a && !b && !c && d && !e && !f)      {return  228;}      //11100100
if(g && h && a && !b && !c && d && !e && f)       {return  229;}      //11100101
if(g && h && a && !b && !c && d && e && !f)       {return  230;}      //11100110
if(g && h && a && !b && !c && d && e && f)        {return  231;}      //11100111
if(g && h && a && !b && c && !d && !e && !f)      {return  232;}      //11101000
if(g && h && a && !b && c && !d && !e && f)       {return  233;}      //11101001
if(g && h && a && !b && c && !d && e && !f)       {return  234;}      //11101010
if(g && h && a && !b && c && !d && e && f)        {return  235;}      //11101011
if(g && h && a && !b && c && d && !e && !f)       {return  236;}      //11101100
if(g && h && a && !b && c && d && !e && f)        {return  237;}      //11101101
if(g && h && a && !b && c && d && e && !f)        {return  238;}      //11101110
if(g && h && a && !b && c && d && e && f)         {return  239;}      //11101111
if(g && h && a && b && !c && !d && !e && !f)      {return  240;}      //11110000
if(g && h && a && b && !c && !d && !e && f)       {return  241;}      //11110001
if(g && h && a && b && !c && !d && e && !f)       {return  242;}      //11110010
if(g && h && a && b && !c && !d && e && f)        {return  243;}      //11110011
if(g && h && a && b && !c && d && !e && !f)       {return  244;}      //11110100
if(g && h && a && b && !c && d && !e && f)        {return  245;}      //11110101
if(g && h && a && b && !c && d && e && !f)        {return  246;}      //11110110
if(g && h && a && b && !c && d && e && f)         {return  247;}      //11110111
if(g && h && a && b && c && !d && !e && !f)       {return  248;}      //11111000
if(g && h && a && b && c && !d && !e && f)        {return  249;}      //11111001
if(g && h && a && b && c && !d && e && !f)        {return  250;}      //11111010
if(g && h && a && b && c && !d && e && f)         {return  251;}      //11111011
if(g && h && a && b && c && d && !e && !f)        {return  252;}      //11111100
if(g && h && a && b && c && d && !e && f)         {return  253;}      //11111101
if(g && h && a && b && c && d && e && !f)         {return  254;}      //11111110
if(g && h && a && b && c && d && e && f)          {return  255;}      //11111111
//typing rest area .....pant pant pant.............






//unreachable code? sure - so what?
return 0;
}


Tuesday, August 19, 2025

A simple batch file runner.

 

Smudge for today   
Written using C++ Builder 6
A simple program that writes a short batch file, runs it and deletes the .bat.Use it to send messages to other users on your local network, no other files or libraries required. It uses msg.exe, which I found was not installed by default in Windows 11. But it is stashed in one of Windows sub directories (..\syswow64\) Run a search "msg.exe", find it, and "copy" it to ..\system32 (where it belongs)

 
 //---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MsgForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMsgDlg *MsgDlg;
//---------------------------------------------------------------------------
__fastcall TMsgDlg::TMsgDlg(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMsgDlg::ExitBtnClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TMsgDlg::SendBtnClick(TObject *Sender)
{
TStringList *MyStrings = new TStringList();
AnsiString s1,s2;//temp strings
s1 = AnsiQuotedStr(Edit1->Text,'"');//user
s2 = AnsiQuotedStr(Edit2->Text,'"');//message

try{
MyStrings->Clear();
MyStrings->Add("msg " + s1 + " " + s2);//command
MyStrings->Add("del SendMsg.bat");//cleanup
MyStrings->Add("exit");//close batch program
MyStrings->SaveToFile("SendMsg.bat");
}
__finally{ delete MyStrings;}
if(s1 != "\"\"")//we have a user
{
if(s2 != "\"\"")//we have a message
{
if(FileExists("SendMsg.bat"))//we have a batfile
{
AnsiString sExe = "SendMsg.bat";
SHELLEXECUTEINFO execinfo ;
memset (&execinfo, 0, sizeof (execinfo)) ;
execinfo.cbSize = sizeof (execinfo) ;
execinfo.lpVerb = "open" ;
execinfo.lpFile = sExe.c_str() ;
execinfo.lpParameters = "" ;
execinfo.fMask = SEE_MASK_NOCLOSEPROCESS ;
execinfo.nShow = SW_HIDE;
if (! ShellExecuteEx (&execinfo))//didn't execute
{
ShowMessage("ERROR::0x\\0010\nCould not create process - SendMsg");
return ;//error value
}
Label3->Caption = "Message sent.";//did execute
Label3->Visible = true;
}
if(bBeep)//confirmation menu item checked
{
ShowMessage("message: " + s2 + "\nsent to: " + s1);
}
}
if(s2 == "\"\"")//no message
{
Label3->Caption = "No message to send.";
}
}
Edit2->SetFocus();
Edit2->Clear();//ready for another message to same user
}
//---------------------------------------------------------------------------
void __fastcall TMsgDlg::Edit2KeyPress(TObject *Sender, char &Key)
{
Label3->Visible = false;
}
//---------------------------------------------------------------------------
void __fastcall TMsgDlg::FormClose(TObject *Sender, TCloseAction &Action)
{
DeleteFile("sendmsg.bat");//dbl-checking
}
//---------------------------------------------------------------------------
void __fastcall TMsgDlg::Beep1Click(TObject *Sender)
{
if(Beep1->Checked) //bool bBeep declared in .h
{
bBeep = true;
}
else
{
bBeep = false;
}
}
//---------------------------------------------------------------------------

Monday, August 18, 2025

Run...

 

Snip of the week   
Written using C++ Builder 6 ENT 

ShellExecuteEx( ) - When you want to launch another program from your program.



I have a program I test my code snips from. One of the features is a custom "launch" menu. Some of the items are predefined, some are user defined.
OnClick for these menu items, I set the program's name and parameter, and send them to a function that runs ShellExecuteEx( ). For example:


void __fastcall TShellWnd::Calculator1Click(TObject *Sender)//MenuItem
{
//calculator
AnsiString sProg = "c:\\windows\\system32\\calc.exe";//path to calculator
AnsiString sParams = "";//usually null
LaunchProgram(Sender, sProg, sParams);
}
I can send all my "Launch" clicks to the same function

bool __fastcall TShellWnd::LaunchProgram(TObject *Sender, AnsiString Program, AnsiString Params)
{
//------------------------ Launch Menu Click--------------//
if(FileExists(Program))
	{
     AnsiString sExe = Program.c_str();
     MessageBeep(0);
     SHELLEXECUTEINFO execinfo ;
     memset (&execinfo, 0, sizeof (execinfo)) ;
     execinfo.cbSize = sizeof (execinfo) ;
     execinfo.lpVerb = "Open" ;// [  |   |  ]
     execinfo.lpFile = sExe.c_str() ;
     execinfo.lpParameters = "Params" ;//as needed
     execinfo.fMask = SEE_MASK_NOCLOSEPROCESS ;// see shellapi.h (lines 346-368)
     execinfo.nShow = SW_SHOW;// [ SW_HIDE | SW_SHOWMINNOACTIVE | SW_MINIMIZE ]
     if (! ShellExecuteEx (&execinfo))
          {
          ShowMessage("ERROR::0x0020\nCould not create process : " + Program);
          return -1 ;//change to your error value
          }
     }
return true;
}

 
For the custom menu items, I use an INI file to store the information I need, that I set from a preferences dialog.

The INI reads like this:


[Menu]
----snip----
Custom5Caption=PhotoShop 5.5
Custom5Path=C:\Program Files\Adobe\Photoshop 5.5\Photoshp.exe
----snip----
The main form's OnCreate event:

TIniFile *ini;
          ini = new TIniFile( ChangeFileExt( Application->ExeName,".ini") );
----snip----
	     Custom51->Caption   =  ini->ReadString( "Menu", "Custom5Caption",  "");
	     sCustomPath5        =  ini->ReadString( "Menu", "Custom5Path",     "");
----snip----
		delete ini;

MenuItem - "Custom51" OnClick:


void __fastcall TShellWnd::Custom51Click(TObject *Sender)//MenuItem
{
// Custom5
if(Custom51->Caption != "")//invisible
     {
     if(Custom51->Caption != "Custom 5")//designtime text
          {
          if(sCustomPath5 != "")//blank lpfile (command string)
               {
               LaunchProgram(Sender, sCustomPath5, NULL);
               }
          }
     }
}

The lpfile doesn't have to be an executable program. ShellExecuteEx( ) will take files with registered extentions and open them in their associated applications (.txt, .doc, .wav, etc)
On the other hand, if there is no association, or you want to do something different with the file, to can usually use the "filename.ext" as a parameter. For example, Windows 7 associates .jpg files to Internet Explorer, but I want to edit the image... so:


SetCurrentDir(sWorkingDir);
OpenPicDlg->InitialDir = sWorkingDir;
if(OpenPicDlg->Execute())
     {
     AnsiString sFile = OpenPicDlg->FileName;
     if(FileExists(sFile))
     	{
          AnsiString sExe = "mspaint.exe";//open  ms-paint
          SHELLEXECUTEINFO execinfo ;
          memset (&execinfo, 0, sizeof (execinfo)) ;
          execinfo.cbSize = sizeof (execinfo) ;
          execinfo.lpVerb = "Open" ;
          execinfo.lpFile = sExe.c_str() ;
          execinfo.lpParameters = sFile.c_str() ;//file to open in ms-paint
          execinfo.fMask = SEE_MASK_NOCLOSEPROCESS ;
          execinfo.nShow = SW_SHOW;
          if (! ShellExecuteEx (&execinfo))
               {
               ShowMessage("ERROR::0x0022\nCould not create process - Open (Image)");
               return  ;
               }
          }
     }


You'll find the definition in shellapi.h (line numbers)
Include\shellapi.h(321): ////  Begin ShellExecuteEx and family
Include\shellapi.h(324): /* ShellExecute() and ShellExecuteEx() error codes */
Include\shellapi.h(346-368) fmask defined (#define SEE_MASK_CLASSNAME 0x00000001) for example
Include\shellapi.h(442): SHSTDAPI_(BOOL) ShellExecuteExA(LPSHELLEXECUTEINFOA lpExecInfo);
Include\shellapi.h(443): SHSTDAPI_(BOOL) ShellExecuteExW(LPSHELLEXECUTEINFOW lpExecInfo);
Include\shellapi.h(445): #define ShellExecuteEx  ShellExecuteExW
Include\shellapi.h(447): #define ShellExecuteEx  ShellExecuteExA
Include\shellapi.h(479): ////  End ShellExecuteEx and family


typedef struct _SHELLEXECUTEINFOA
{
        					// Required fields
        DWORD 		cbSize;
        ULONG 		fMask;
        HWND 		hwnd;
        LPCSTR		lpVerb;
        LPCSTR  	lpFile;
        LPCSTR		lpParameters;
        int 		nShow;
        HINSTANCE	hInstApp;
        					// Optional fields
        LPCSTR		lpDirectory;
        LPVOID		lpIDList;
        LPCSTR		lpClass;
        HKEY		hkeyClass;
        DWORD		dwHotKey;
        union
		{
		HANDLE	hIcon;
		HANDLE	hMonitor;
		} DUMMYUNIONNAME;
        HANDLE		hProcess;
} SHELLEXECUTEINFOA, *LPSHELLEXECUTEINFOA;


to the top