Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
TopLevel Form Problem
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
Gestionnaire d'écran & Écrans
Divers
Thread ID:
00808026
Message ID:
00808038
Vues:
17
Here is the rest of the code:
DEFINE CLASS Tform As Form 
    Width=520 
    Height=280 
    Caption="LAN Messenger" 
    BorderStyle=2 
    MaxButton=.F. 
    MinButton=.T. 
    Autocenter=.T.
    WindowState=1
    ShowWindow=2
    Desktop=.t.
    ADD OBJECT msg As Tmsg WITH Left=5, Top=5 

PROCEDURE Init 
    * a mailslot name automatically keeps all LAN users together in a group; 
    * currently "foxapp" name is used, in fact it might be any valid file name 
    * except some reserved names like "Messngr" or "BROWSE" 
    THIS.msg.TurnOn("foxapp") 
ENDDEFINE 

DEFINE CLASS Tmsg As Container 
#DEFINE INVALID_HANDLE_VALUE -1 
#DEFINE OPEN_EXISTING         3 
#DEFINE GENERIC_WRITE         0x40000000 
#DEFINE FILE_SHARE_READ       1 
#DEFINE FILE_ATTRIBUTE_NORMAL 128 
#DEFINE REFRESH_INTERVAL      1000  && timer interval 
#DEFINE MAX_MESSAGE_SIZE      250 
#DEFINE READ_TIMEOUT          500 
#DEFINE NAME_SIZE             24 
#DEFINE MSGID_SIZE            12 
#DEFINE MSGHEADER_SIZE        NAME_SIZE+MSGID_SIZE+2 

    Width=510 
    Height=340 
    BorderWidth=0 
    csLog="" 
    msHandle=INVALID_HANDLE_VALUE 
    msName="" 
    localname="" 
    lastmessage="" 
    msgID=0 

    ADD OBJECT lstIn As ListBox WITH Left=2, Top=2, Width=506,; 
        Height=160, ColumnCount=2, ColumnWidths="70, 630" 
    ADD OBJECT lbl1 As Label WITH; 
        Left=5, Top=180, Autosize=.T., Caption="Talk to:" 
    ADD OBJECT cmbOnline As ComboBox WITH; 
        Left=54, Top=178, Width=136, Style=2 
    ADD OBJECT cmdRefresh As CommandButton WITH; 
        Left=196, Top=178, Width=80, Height=27, Caption="Refresh" 
    ADD OBJECT txtOut As EditBox WITH; 
        Left=2, Top=215, Width=420, Height=50, Scrollbars=0 
    ADD OBJECT cmdSend As CommandButton WITH Default=.T.,; 
        Left=436, Top=235, Width=68, Height=27, Caption="Send", Enabled=.F. 

    * timer is used to check for incoming messages 
    ADD OBJECT tm As Timer WITH Interval=0 

PROCEDURE Init 
    THIS.decl 
    THIS.csLog = "log" + SUBSTR(SYS(2015), 3,10) && log cursor 
    THIS.localname = SUBS(SYS(0), 1,AT(" ",SYS(0))-1) && machine name 
    THIS.msgID = GetTickCount() && initial message ID 

PROCEDURE Destroy 
    THIS.TurnOff 

PROCEDURE tm.Timer 
    IF THIS.Parent.msHandle <> INVALID_HANDLE_VALUE 
        THIS.Parent.GetMessages  && checking for incoming messages 
    ENDIF 

PROCEDURE cmdRefresh.Click 
    THIS.Parent.SendMessage("*", "DETECT", .T., .T.) 

PROCEDURE cmdSend.Click 
    THIS.Parent.OnSendMessage 
    THIS.Enabled=.F. 

PROCEDURE txtOut.InteractiveChange 
    THIS.Parent.cmdSend.Enabled = THIS.Parent.ReadyToSend() 

PROCEDURE ReadyToSend 
RETURN THIS.msHandle <> INVALID_HANDLE_VALUE; 
    And Not EMPTY(THIS.txtOut.Value); 
    And Not EMPTY(THIS.cmbOnline.Value) 

PROCEDURE OnUserStatus(cUsername, lActive) 
    WITH THIS.cmbOnline 
        .Value = m.cUsername 
        IF m.lActive 
            IF .ListIndex = 0 
                .AddItem(m.cUsername) 
                .ListIndex = .ListCount 
            ENDIF 
        ELSE 
            IF .ListIndex <> 0 
                .RemoveItem(.ListIndex) 
                .ListIndex = 1 
            ENDIF 
        ENDIF 
    ENDWITH     
    THIS.cmdSend.Enabled = THIS.ReadyToSend() 

PROCEDURE OnSendMessage 
    THIS.SendMessage(THIS.cmbOnline.Value,; 
        ALLTRIM(THIS.txtOut.Value), .T., .F.) 
    THIS.txtOut.Value = "" 
    THIS.txtOut.SetFocus 

PROCEDURE TurnOff 
* disconnecting from the group 
    THIS.tm.Interval = 0 
    IF THIS.msHandle <> INVALID_HANDLE_VALUE 
        THIS.SendMessage("*", "OFFLINE", .F., .T.) 
        = CloseHandle(THIS.msHandle) 
        THIS.msHandle = INVALID_HANDLE_VALUE 
    ENDIF 

PROCEDURE TurnOn(cMailslot) 
* connecting to the group defined by cMailslot 
    THIS.TurnOff 

    cMailslot = UPPER(ALLTRIM(m.cMailslot)) 
    THIS.msHandle = CreateMailslot("\\.\mailslot\" + m.cMailslot,; 
        MAX_MESSAGE_SIZE, READ_TIMEOUT, 0) 

    IF THIS.msHandle <> INVALID_HANDLE_VALUE 
        THIS.msName = cMailslot 
        * sending ONLINE and DETECT messages to everyone -- * 
        THIS.SendMessage("*", "DETECT", .T., .T.) 
        THIS.SendMessage("*", "ONLINE", .F., .T.) 
        THIS.tm.Interval = REFRESH_INTERVAL 
    ENDIF 
RETURN (THIS.msHandle <> INVALID_HANDLE_VALUE) 

PROCEDURE CheckLog 
    IF Not USED(THIS.csLog) 
        CREATE CURSOR (THIS.csLog) (sender C(NAME_SIZE),; 
            recipient C(NAME_SIZE), msgid I, dt T, confreq L, sysmsg L,; 
            confirmed L, msgbody C(250)) 
    ENDIF 
    SELECT (THIS.csLog) 

PROCEDURE DisplayMessage(cSender, cMsgBody) 
    WITH THIS.lstIn 
        .AddItem(m.cSender) 
        .List(.ListCount, 2) = m.cMsgBody 
        .ListIndex = .ListCount 
    ENDWITH 

PROCEDURE SendMessage(cRecipient, cMsgBody, lConfReq, lSysMsg) 
* params: recipient, message body, needs confirmation, system message 
    LOCAL cTargetName, hFile, cMsg, nBytesWritten 
    nBytesWritten = 0 
     
    * mailslot name for the recipient 
    cTargetName = "\\" + ALLTRIM(UPPER(cRecipient)) +; 
        "\mailslot\" + THIS.msName 

    * obtaining a handle to mailslot, same as for a regular file 
    hFile = CreateFile(cTargetName, GENERIC_WRITE, FILE_SHARE_READ,; 
        0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) 

    IF hFile <> INVALID_HANDLE_VALUE 
        THIS.msgID = THIS.msgID + 1 

        * assembling a message: 
        * sender, message ID, body, needs to be confirmed, system message 
        cMsg = PADR(THIS.localname, NAME_SIZE) +; 
            STR(THIS.msgID, MSGID_SIZE) +; 
            Iif(m.lConfReq, "1","0") + Iif(m.lSysMsg, "1","0") +; 
            m.cMsgBody 

        * writing to the mailslot using the handle obtained with CreateFile 
        = WriteFile(hFile, m.cMsg, Len(m.cMsg), @nBytesWritten, 0) 
        = CloseHandle(hFile) 
         
        * saving sent message in a log 
        THIS.CheckLog 
        APPEND BLANK 
        REPLACE sender WITH THIS.localname, recipient WITH m.cRecipient,; 
            msgid WITH THIS.msgID, dt WITH datetime(),; 
            confreq WITH m.lConfReq, sysmsg WITH m.lSysMsg,; 
            msgbody WITH m.cMsgBody, confirmed WITH .F. 

        IF Not m.lSysMsg 
            THIS.DisplayMessage(THIS.localname, m.cMsgBody) 
        ENDIF 
    ENDIF 

PROCEDURE GetMessages  && reads inbound messages from a buffer 
    LOCAL nResult, nMsgSize, nNextSize, nMsgCount, nTimeout,; 
        cBuffer, nBytesRead 
    DO WHILE .T. 
        STORE 0 TO nMsgSize, nNextSize, nMsgCount, nTimeout 
        nResult = GetMailslotInfo(THIS.msHandle, @nMsgSize,; 
            @nNextSize, @nMsgCount, @nTimeout) 

        IF nResult <= 0 Or nMsgCount = 0 
            EXIT 
        ENDIF 
         
        cBuffer = Repli(Chr(0), nNextSize) 
        nBytesRead = 0 
        nResult = ReadFile(THIS.msHandle, @cBuffer, nNextSize, @nBytesRead, 0) 
        IF nResult <> 0 And Len(m.cBuffer) >= MSGHEADER_SIZE 
            THIS.lastmessage = m.cBuffer 
            THIS.OnInboundMsg 
        ENDIF 
    ENDDO 

PROCEDURE OnInboundMsg 
    LOCAL cSender, nMsgId, lConfReq, lSysMsg, cMsgBody, nConfId 
    cSender = SUBSTR(THIS.lastmessage, 1, NAME_SIZE) 
    IF m.cSender = THIS.localname 
        RETURN 
    ENDIF 

    nMsgId = VAL(SUBSTR(THIS.lastmessage, NAME_SIZE+1, MSGID_SIZE)) 
    lConfReq = (SUBSTR(THIS.lastmessage, NAME_SIZE+MSGID_SIZE+1, 1) = "1") 
    lSysMsg = (SUBSTR(THIS.lastmessage, NAME_SIZE+MSGID_SIZE+2, 1) = "1") 
    cMsgBody = SUBSTR(THIS.lastmessage, MSGHEADER_SIZE+1) 

    * storing inbound message in a log 
    THIS.CheckLog 
    LOCATE ALL FOR sender = m.cSender And msgid = m.nMsgId 
    IF Not FOUND() 
        APPEND BLANK 
        REPLACE sender WITH m.cSender, recipient WITH THIS.localname,; 
            msgid WITH m.nMsgId, dt WITH datetime(),; 
            confreq WITH m.lConfReq, sysmsg WITH m.lSysMsg,; 
            msgbody WITH m.cMsgBody 

        DO CASE 
        CASE Not m.lSysMsg 
            THIS.SendMessage(m.cSender, "CONF "+LTRIM(STR(m.nMsgId)), .F., .T.) 
            THIS.DisplayMessage(m.cSender, m.cMsgBody) 

        CASE AT("CONF", m.cMsgBody) = 1 
            nConfId = VAL(SUBSTR(m.cMsgBody, Len("CONF")+2)) 
            THIS.CheckLog 
            LOCATE ALL FOR sender = THIS.localname; 
                And msgid = m.nConfId And Not confirmed 
            IF FOUND() 
                REPLACE confirmed WITH .T. 
            ENDIF 

        CASE INLIST(m.cMsgBody, "ONLINE", "OFFLINE") 
            THIS.DisplayMessage(m.cSender, m.cMsgBody) 

        CASE m.cMsgBody = "DETECT" 
            THIS.SendMessage(m.cSender, "ONLINE", .F., .T.) 
        ENDCASE 
         
        THIS.OnUserStatus(m.cSender, (m.cMsgBody <> "OFFLINE")) 
    ENDIF 

PROCEDURE decl 
    DECLARE INTEGER CloseHandle IN kernel32 INTEGER 
    DECLARE INTEGER GetTickCount IN kernel32 
    DECLARE INTEGER GetLastError IN kernel32 

    DECLARE INTEGER CreateMailslot IN kernel32; 
        STRING lpName, INTEGER nMaxMessageSize,; 
        INTEGER lReadTimeout, INTEGER lpSecurityAttributes 

    DECLARE INTEGER GetMailslotInfo IN kernel32; 
        INTEGER hMailslot, INTEGER @lpMaxMessageSize,; 
        INTEGER @lpNextSize, INTEGER @lpMessageCount,; 
        INTEGER @lpReadTimeout 

    DECLARE INTEGER CreateFile IN kernel32; 
        STRING lpFileName, INTEGER dwDesiredAccess,; 
        INTEGER dwShareMode, INTEGER lpSecurityAttr,; 
        INTEGER dwCreationDisp, INTEGER dwFlagsAndAttr, INTEGER hTplFile 

    DECLARE INTEGER WriteFile IN kernel32; 
        INTEGER hFile, STRING lpBuffer, INTEGER nBt2Write,; 
        INTEGER @lpBtWritten, INTEGER lpOverlapped 

    DECLARE INTEGER ReadFile IN kernel32; 
        INTEGER hFile, STRING @lpBuffer, INTEGER nBytesToRead,; 
        INTEGER @lpBytesRead, INTEGER lpOverlapped 

ENDDEFINE 
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform