Clipboard Interprocess Communications demo, an IPC Mechanism.
This program will run 4 instances of itself to show some clipboard interprocess functions.

Have fun...
Pierre

Code:
#COMPILE EXE '#Win 9.07#
#DIM ALL
#INCLUDE "Win32Api.inc"

%Listbox     = 101
%ButtonSend  = 102
%ButtonClear = 103
%ButtonExit  = 104

GLOBAL sCaption AS STRING
GLOBAL hDlg     AS DWORD
GLOBAL Bypass   AS LONG
'_____________________________________________________________________________

FUNCTION ExeName$() AS STRING
 LOCAL zFileName   AS ASCIIZ * %MAX_PATH
 LOCAL LenFileName AS LONG

 LenFileName = GetModuleFileName(0, zFileName, %MAX_PATH)
 zFileName   = MID$(zFileName, 1 + INSTR(-1, zFileName, "\"))
 FUNCTION    = LEFT$(zFileName, -4) 'Return fileName, no path and no extention

END FUNCTION
'______________________________________________________________________________

FUNCTION WriteToClipBoard(BYVAL sText AS STRING, ClipboardCustomFormat AS LONG) AS LONG
 LOCAL pz   AS ASCIIZ PTR
 LOCAL hMem AS DWORD

 Bypass = 1 'No need to read what we send
 hMem   = GlobalAlloc(%GHND, LEN(sText) + 1)
 pz     = GlobalLock(hMem)
 @pz    = sText
 GlobalUnlock(hMem)
 OpenClipboard(0)
 'EmptyClipboard
 SetClipboardData(ClipboardCustomFormat, hMem)
 CloseClipboard
 FUNCTION = 1

END FUNCTION
'_____________________________________________________________________________

CALLBACK FUNCTION DlgProc
 STATIC zClipboardCustomFormat AS ASCIIZ * 21
 LOCAL  pzClipboardData        AS ASCIIZ POINTER
 LOCAL  pzData                 AS ASCIIZ POINTER
 LOCAL  sClipboardData         AS STRING
 LOCAL  sOneLost               AS STRING
 STATIC hClipboardChain        AS DWORD
 STATIC ClipboardCustomFormat  AS LONG
 LOCAL  RetVal                 AS LONG

 SELECT CASE CBMSG

   CASE %WM_INITDIALOG
     hClipboardChain        = SetClipboardViewer(CBHNDL) 'Add ourselve to clipboard chain
     zClipboardCustomFormat = "CustomClipboardFormat"
     ClipboardCustomFormat  = RegisterClipboardFormat(zClipboardCustomFormat)

   CASE %WM_DRAWCLIPBOARD 'Here we know the clipboard content is beeing updated
     IF IsClipboardFormatAvailable(ClipboardCustomFormat) THEN
       IF Bypass THEN
         Bypass = 0
       ELSE
         OpenClipboard(0)
         pzClipboardData = GetClipboardData(ClipboardCustomFormat)
         pzData          = GlobalLock(pzClipboardData)
         sClipboardData  = @pzData
         GlobalUnlock(pzClipboardData)
         CloseClipboard
         CONTROL SEND hDlg, %Listbox, %LB_INSERTSTRING, -1, STRPTR(sClipboardData)
         CONTROL SEND hDlg, %Listbox, %LB_GETCOUNT, 0, 0 TO RetVal
         CONTROL SEND hDlg, %Listbox, %LB_SETCURSEL, RetVal - 1, 0
       END IF
     END IF
     SendMessage(hClipboardChain, CBMSG, CBWPARAM, CBLPARAM) 'Forward data to next clipboard chain

  CASE %WM_CHANGECBCHAIN
    sOneLost = "Some previous clipboard app. just ended!"
    CONTROL SEND hDlg, %Listbox, %LB_INSERTSTRING, -1, STRPTR(sOneLost)
    CONTROL SEND hDlg, %Listbox, %LB_GETCOUNT, 0, 0 TO RetVal
    CONTROL SEND hDlg, %Listbox, %LB_SETCURSEL, RetVal - 1, 0
    IF CBWPARAM = hClipboardChain THEN
      hClipboardChain = CBLPARAM
    ELSE
      IF hClipboardChain THEN
        SendMessage(hClipboardChain, CBMSG, CBWPARAM, CBLPARAM)
      END IF
    END IF

  CASE %WM_COMMAND
    SELECT CASE LOWRD(CBWPARAM)

      CASE %ButtonSend
        IF (CBCTLMSG = %BN_CLICKED) OR (CBCTLMSG = 1) THEN
          WriteToClipBoard(sCaption & "  " & TIME$, ClipboardCustomFormat)
        END IF

      CASE %ButtonClear
        IF (CBCTLMSG = %BN_CLICKED) OR (CBCTLMSG = 1) THEN
          LISTBOX RESET hDlg, %Listbox
        END IF

      CASE %ButtonExit
        IF (CBCTLMSG = %BN_CLICKED) OR (CBCTLMSG = 1) THEN
          DIALOG END CBHNDL, 0
        END IF

    END SELECT

   CASE %WM_DESTROY
     WriteToClipBoard(sCaption & " just past the way!!!", ClipboardCustomFormat) 'Tell everybody that we are ending
     ChangeClipboardChain(CBHNDL, hClipboardChain) 'Remove ourselve from clipboard chain

 END SELECT

END FUNCTION
'_____________________________________________________________________________

FUNCTION PBMAIN
 LOCAL ProcessCount AS LONG
 LOCAL ProcessIndex AS LONG
 LOCAL RetVal       AS LONG

 ProcessCount = 4
 ProcessIndex = 1
 sCaption     = ExeName$ & "-1"
 DO
   SLEEP 10
   IF FindWindow(BYVAL %NULL, BYCOPY sCaption) THEN
     ProcessIndex = VAL(RIGHT$(sCaption, 1)) + 1
     IF ProcessIndex > ProcessCount THEN EXIT FUNCTION
     sCaption = ExeName$ & "-" & FORMAT$(ProcessIndex)
   ELSE
     EXIT DO
   END IF
 LOOP
 IF ProcessIndex < ProcessCount THEN
   'This application will start another copy of itself until ProcessCount is reached
   RetVal = SHELL(ExeName$ & ".exe")
 END IF

 DIALOG NEW %HWND_DESKTOP, sCaption, 10 + (ProcessIndex - 1) * 170, 10, 160, 210, _
 %WS_POPUP OR %DS_MODALFRAME OR %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hDlg

 CONTROL ADD LISTBOX, hdlg, %Listbox, , 5, 5, 150, 190, _
 %WS_CHILD OR %WS_VISIBLE  OR %WS_VSCROLL OR %WS_TABSTOP, 0

 CONTROL ADD BUTTON, hDlg, %ButtonSend, "SEND", 20, 192, 35, 15, _
 %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP

 CONTROL ADD BUTTON, hdlg, %ButtonClear, "CLEAR", 60, 192, 35, 15, _
 %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP

 CONTROL ADD BUTTON, hDlg, %ButtonExit, "EXIT", 100, 192, 35, 15, _
 %WS_CHILD OR %WS_VISIBLE OR %BS_PUSHBUTTON OR %WS_TABSTOP

 DIALOG SHOW MODAL hDlg CALL DlgProc

END FUNCTION
'_____________________________________________________________________________
'