Team OS/2 Italia - Developer Assistant

------------------------------------------

INI Copier v1.00

Un esempio di programma PM Multi-Threaded

thread.c

/***************************************************************************
 
 Threads for INI Copier
 
 ****************************************************************************/

#define INCL_WINDIALOGS
#define INCL_WINSTDFILE
#define INCL_DOSPROCESS
#define INCL_WINLISTBOXES

#include "global.h"
#include "resource.h"
#include <string.h>

/* macro definitions */

/* global variables */

/* La variabile FileTypes serve come parametro per la WinFileDlg */
static char *FileTypes[]=
{
    "Plain Text",
    "Binary Data",
    "INI File",
    NULL
};

/* function prototypes */

/* OpenThreadException gestisce le eccezioni del thread di apertura dei
 profili */
ULONG APIENTRY OpenThreadException(PEXCEPTIONREPORTRECORD pReport,
                                   PEXCEPTIONREGISTRATIONRECORD pReg,
                                   PCONTEXTRECORD pContext,
                                   PVOID );

/* CloseThreadException gestisce le eccezioni dei thread di chiusura dei
 profili */
ULONG APIENTRY CloseThreadException(PEXCEPTIONREPORTRECORD pReport,
                                    PEXCEPTIONREGISTRATIONRECORD pReg,
                                    PCONTEXTRECORD pContext,
                                    PVOID );

/* Presenta la finestra di richiesta di un filename */
PSZ AskFileName(HWND hWnd,PSZ fName);
    
/* implementation */

/* Questa funzione si occupa di richiedere il filename del profilo, lo apre 
 e costruisce le liste in memoria. Comunica con il thread principale con dei 
 messaggi da me definiti */
VOID THREADFN OpenThread(ThreadData *pThread)
{
    /* Questa struttura e` necessaria per registrare il gestore delle 
     eccezioni del thread. E` importante che sia un variabile nello stack e
     deve essere la prima. */
    EXCEPTIONREGISTRATIONRECORD ExceptionReg={0,OpenThreadException};
    HAB         habOpenThread; /* HAB di questo thread */
    HMQ         hmqOpenQueue;  /* Handle della coda dei messaggi del thread */
    /* struttura che viene passata al thread principale quando viene aperto 
     un file profilo */
    PrfOpen     Opened;
    PSZ         pszFileName;  /* filename */
    HINI        hPrf;         /* handle del profilo */
    HWND        hList[2];     /* handle delle liste */
    
    /* Registro il gestore delle eccezioni */
    DosSetExceptionHandler(&ExceptionReg);
    
    /* Inizializzo il PM. Attenzione che il WinInitialize() e` importante,
    specialmente se si usa Merlin (Warp 4.0) */
    habOpenThread=WinInitialize(0);
    hmqOpenQueue=WinCreateMsgQueue(habOpenThread,0);
    
    /* Richiedo il nome del profilo da aprire */
    pszFileName=AskFileName(pThread->hWnd,pThread->fName);

    /* Se pszFileName e` diverso da NULL si procede aprendo il profilo
     altrimenti si segnala l'errore al thread principale */
    if(pszFileName != NULL)
    {
        /* Comunica al thread principale il nome del file */
        WinSendMsg(pThread->hWnd,WM_FILENAME,
                   (MPARAM)pThread->Profile,pszFileName);

        /* Apre il profilo per verificare che il nome sia valido */
        hPrf=PrfOpenProfile(habOpenThread,pszFileName);
        if(hPrf==NULLHANDLE)
        {
            /* Il nome non era valido e quindi mostra l'errore */
            ErrorBox(IDE_CANTOPEN,FALSE);
            /* Comunica l'errore al thread principale */
            WinSendMsg(pThread->hWnd,WM_FILENAME,
                       (MPARAM)FAILURE,(MPARAM)pThread->Profile);
        }
        else
        {
            /* riempie la struttura Opened e costruisce le liste in memoria */
            Opened.hWnd=pThread->hWnd;
            Opened.Profile=pThread->Profile;
            Opened.List=BuildLists(hPrf);
            
            /* Ottiene gli handle delle listBox in base al profilo */
            switch(pThread->Profile)
            {
                case PROFILE_A:
                    WinMultWindowFromIDs(pThread->hWnd,hList,
                                         LIST_A,SUBLIST_A);
                    break;
                case PROFILE_B:
                    WinMultWindowFromIDs(pThread->hWnd,hList,
                                         LIST_B,SUBLIST_B);
                    break;
            }

            /* Comunica al thread principale l'avvenuta apertura */
        	WinSendMsg(pThread->hWnd,WM_PROFILE,
                       (MPARAM)pThread->Profile,&Opened);

            /* Riempie le list box e chiude il profilo */
            FillLists(hList[0],hList[1],Opened.List);
            PrfCloseProfile(hPrf);
        }
    }
    else  /* Mando un mex per dire che non e` stato selezionato il file */
        WinSendMsg(pThread->hWnd,WM_FILENAME,
                   (MPARAM)FAILURE,(MPARAM)pThread->Profile);
    
    /* Distrugge le risorse PM (Queue & Anchor Block) */
    WinDestroyMsgQueue(hmqOpenQueue);
    WinTerminate(habOpenThread);

    MemFree(pThread);   /* Libera la struttura passata al Thread */
    /* rimuove il gestore delle eccezioni */
    DosUnsetExceptionHandler(&ExceptionReg);
}


/* Chiede il nome del file da aprire */
PSZ AskFileName(HWND hWnd,PSZ fName)
{
    FILEDLG     DlgData;  /* struttura per la file dialog */
    HWND        hFileDlg; /* Handle della dialog */
    PSZ         pszName;  /* FileName */
    
    memset(&DlgData,0,sizeof(FILEDLG)); /* azzera la struttura */
    
    /* Riempie la struttura */
    DlgData.cbSize=sizeof(FILEDLG);
    DlgData.fl=FDS_OPEN_DIALOG;
    DlgData.pszIType=NULL;    /* Filtro sugli extended attributes */
    DlgData.papszITypeList=(PAPSZ)FileTypes; /* Lista dei tipi da selezionare */
    
	/* Se viene passato un filename si estrae la path */
    if(fName!=NULL)
    {
    	pszName=strrchr(fName,'\\'); /* Cerca la slash */
    	if(pszName==NULL)
        	pszName=strrchr(fName,':'); /* se non la trova cerca i due punti */
    	if(pszName!=NULL)  /* se ha trovato una path la copia */
            strncpy(DlgData.szFullFile,fName,pszName-fName+1);
    }
    strcat(DlgData.szFullFile,"*.INI");  /* aggiunge il filtro sull'estensione */
    
	/* Crea la dialog */
    hFileDlg=WinFileDlg(HWND_DESKTOP,NULLHANDLE,&DlgData);
    
	/* Se e` stato correttamente selezionato un file */
    if(hFileDlg && (DlgData.lReturn==DID_OK))
    {
        /* Restituisce una copia del filename */
    	pszName=(PSZ)Memory(strlen(DlgData.szFullFile)+1);
    	strcpy(pszName,DlgData.szFullFile);
        return pszName;
    }

    /* Non e` stato selezionato alcun file */
    return NULL;
}


/* Questa funzione si occupa di rimuovere tutte le strutture in memoria 
legate ad un profilo */
VOID THREADFN CloseThread(PrfOpen *pPrfData)
{
    /* Struttura per registrare il gestore delle eccezioni */
    EXCEPTIONREGISTRATIONRECORD ExceptionReg={0,CloseThreadException};
    HAB         habCloseThread;  /* handle dell'anchor block */
    HMQ         hmqCloseQueue;   /* handle della message queue */
    HWND        hList[2];    /* Handle delle list box */
    
    /* Registra il gestore delle eccezioni */
    DosSetExceptionHandler(&ExceptionReg);
    
    /* Inizializza il PM e crea la coda dei messaggi */
    habCloseThread=WinInitialize(0);
    hmqCloseQueue=WinCreateMsgQueue(habCloseThread,0);
    
    /* distrugge le liste */
    ClearLists(pPrfData->List);
    
    /* Ottiene gli handle delle listBox giuste */
    switch(pPrfData->Profile)
    {
        case PROFILE_A:
            WinMultWindowFromIDs(pPrfData->hWnd,hList,
                                 LIST_A,SUBLIST_A);
            break;
            
        case PROFILE_B:
            WinMultWindowFromIDs(pPrfData->hWnd,hList,
                                 LIST_B,SUBLIST_B);
            break;
    }

    /* Cancella il contenuto delle liste */
    WinSendMsg(hList[0],LM_DELETEALL,NULL,NULL);
    WinSendMsg(hList[1],LM_DELETEALL,NULL,NULL);
    
    /* comunica al thread principale che il profilo e` stato chiuso 
    correttamente */
    WinSendMsg(pPrfData->hWnd,WM_PROFILECLOSED,
               (MPARAM)pPrfData->Profile,(MPARAM)pPrfData);
    
    /* Distrugge la coda dei messaggi */
    WinDestroyMsgQueue(hmqCloseQueue);
    WinTerminate(habCloseThread);

    /* Libera la memoria della struttura pPrfData e rimuove il gestore delle
    eccezioni */
    MemFree(pPrfData);
    DosUnsetExceptionHandler(&ExceptionReg);
}


/* Gestore delle eccezioni del thread di apertura del profilo */
ULONG APIENTRY OpenThreadException(PEXCEPTIONREPORTRECORD pReport,
                                   PEXCEPTIONREGISTRATIONRECORD pReg,
                                   PCONTEXTRECORD pContext,
                                   PVOID pDispatcher)
{
   switch(pReport->ExceptionNum)
   {
       /* Il thread e` stato interrotto da un altro processo quindi 
       avverte il thread principale */
        case XCPT_ASYNC_PROCESS_TERMINATE:
            WinSendMsg(hMainWindow,WM_PROFILE,(MPARAM)FAILURE,
                       (MPARAM)(pReport->ExceptionNum));
            _endthread();
            break;
            
        /* E` avvenuto un errore quindi si avverte il thread principale
        e si mostrano i dati dell'eccezione */
        case XCPT_ACCESS_VIOLATION:
            WinSendMsg(hMainWindow,WM_PROFILE,(MPARAM)FAILURE,
                       (MPARAM)(pReport->ExceptionNum));
            ExcptBox(pReport);
            break;

        default:
            break;
    }
    return XCPT_CONTINUE_SEARCH;
}


/* gestisce le eccezioni del thread di chiusura */
ULONG APIENTRY CloseThreadException(PEXCEPTIONREPORTRECORD pReport,
                                    PEXCEPTIONREGISTRATIONRECORD pReg,
                                    PCONTEXTRECORD pContext,
                                    PVOID pDispatcher)
{
    switch(pReport->ExceptionNum)
    {
        case XCPT_ASYNC_PROCESS_TERMINATE:
            _endthread();
            break;

		/* Mostra un messaggio d'errore */
        case XCPT_ACCESS_VIOLATION:
            ErrorBox(IDE_CLOSEXCP,TRUE);
            break;

        default:
            break;
    }
    return XCPT_CONTINUE_SEARCH;
}

---------------------------------------------------

Torna alla nostra HomePage - Pagina a cura di: Giovanni Pagni
Last modified 27-10-97