Problem while detecting delay using virtualwire.h and LiquidCrystal.h

I am Wokrking on a project which uses UNO and MEGA

The MEGA is the transmitter , UNO the receiver.
MEGA has a 3x4 keypad and rf 433 mhz module which sends the keypresses via VIRTUALWIRE
The UNO has the receiver connected and a 16,2 LCD connected.

The motto of my project is to receive the keypress and print it on the LCD. However I also want a feature in the receiver where "IT PRINTS A SPACE OR A DOT ’ . ’ if no key is received for 3 seconds.
It should print the space or dot only once i.e.
Suppose I send 1234 and then wait for a few seconds, if the receiver does not get any keypresss from tx for 3 seconds it will print the dot once (not every 3 seconds)
then if i press after say 10 seconds 567, then the display should look like this
"“1234.567"”

Now here is the code of the receiver that i tried.
The question is shouldd i put this feature in tx that it should transmit the space ifi no key is pressed for 3 seconds or i should implement this in the receiver end .
and How?
the code is as follows for tx and rx

TRANSMITTER

#include <Keypad.h>
#include <VirtualWire.h>
#define ledPin 13

const byte ROWS = 4; 
const byte COLS = 4; 
char keys[ROWS][COLS] =
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {32,34,36,38}; //connect to row pinouts 
byte colPins[COLS] = {40,42,44,46}; //connect to column pinouts

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  Serial.begin(9600);
  vw_setup(2000);
}

void loop()
{
  char msg[0];
  char key=keypad.getKey();
  if( key!=NO_KEY)
  {
     msg[0]=key;                            // load the array with the key character
     msg[1]=NULL;                           // Rx side seems to work without this

    digitalWrite(10,HIGH);               // Flash a light to show transmitting

    vw_send((uint8_t *)msg, strlen(msg));     // send the character out

    Serial.println(key);                // for debugging only

    vw_wait_tx();                             // Wait until the whole message is gone
  
    digitalWrite(10,LOW);
  }
    delay(50);                               // need some delay or seem to miss key presses
}

RECEIVER

#include <VirtualWire.h>
#include<LiquidCrystal.h>
const int receiver_pin = 12;

LiquidCrystal lcd(6,7,8,9,10,11);
void setup()
{
   Serial.begin(9600);
   vw_set_rx_pin(receiver_pin);
   vw_setup(2000);
   vw_rx_start();
   lcd.begin(16,2);
}

void loop()
{
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    
    
    
    if(vw_get_message(buf, &buflen))
    {
       digitalWrite(13,HIGH);
       
       
for(int i=0;i<buflen;i++)
       {
         Serial.print((char)buf[i]); 
         lcd.print((char)buf[i]);
          delay(100);
       }
       digitalWrite(13,LOW);
       
       
    } 
}

Now i tried to edit the receiver part which only test the code for serial print rather than lcd.print(i will add the LCD later)

#include <VirtualWire.h>
#include<LiquidCrystal.h>
const int receiver_pin = 12;

LiquidCrystal lcd(6,7,8,9,10,11);
void setup()
{
   Serial.begin(9600);
   vw_set_rx_pin(receiver_pin);
   vw_setup(2000);
   vw_rx_start();
   lcd.begin(16,2);
}

void loop()
{
    
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    
    int null;int i;
    if(vw_get_message(buf, &buflen))
    {
       digitalWrite(13,HIGH);
       
       for(int i=0;i<buflen;i++)
       {
       
             Serial.print((char)buf[i]); 
            // lcd.print((char)buf[i]);
            //delay(100);
             digitalWrite(13,LOW);
       }
    }
    if(delay(3000))
    { 
       Serial.print(".");
    }
    
}

Please help me if you understood the question as i think i have not explained perfectly .But may be you will understand my problem.

However I also want a feature in the receiver where "IT PRINTS A SPACE OR A DOT ' . ' if no key is received for 3 seconds.

The receiver doesn't receive keys. It receives data.

     msg[0]=key;                            // load the array with the key character
     msg[1]=NULL;                           // Rx side seems to work without this

    digitalWrite(10,HIGH);               // Flash a light to show transmitting

    vw_send((uint8_t *)msg, strlen(msg));     // send the character out

The use of an array to send one byte is silly. Just send the one byte.

    vw_send((uint8_t *)key, 1);
  char msg[0];

There is not room to store the 2 characters in the 0 element array!

    delay(50);                               // need some delay or seem to miss key presses

Nonsense.

    if(delay(3000))

More nonsense. The delay() function does not return a value.

You need to keep track of when the receiver receives data, using millis(). You absolutely must NOT use ANY delay() calls. If now minus then (the last time you received a character) is greater than the desired interval AND you haven't printed the special character, print it and set a flag that indicates that you have.

When a character arrives, clear that flag.

By the way, all that nonsense on the receiver, when you are sending only one character, is not needed. You KNOW how many characters there should be in the packet.