home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-08 | 24.8 KB | 712 lines | [TEXT/MPS ] |
- {••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••}
- {• MIDI SKELETON •}
- {•------------------------------------------------------------------------------•}
- {• MIDISHARE est un module logiciel conçu spécialement pour permettre le fonc- •}
- {• tionnement et le développement d'applications Midi dans un contexte multi- •}
- {• tâches et temps réel. •}
- {• •}
- {• MIDISHARE prend en charge la plupart des problèmes spécifiques liés au déve- •}
- {• loppement d'applications Midi: gestion des flux Midi, gestion du temps, •}
- {• gestion des tâches. En outre, MIDISHARE permet le fonctionnement simultané •}
- {• sous Multi-Finder de ces applications, ainsi que l'établissement de connec- •}
- {• tions Midi virtuelles entre celles-ci. •}
- {• •}
- {• SKELETON est un exemple d'application MidiShare minimale qui peut être •}
- {• utilisée comme base de développement pour de nouvelles applications. •}
- {• Par défaut, l'application renvoie tous les événements qu'elle reçoit, sans •}
- {• aucune modification. •}
- {• •}
- {• Les points qui peuvent être facilement modifiés sont les suivants : •}
- {• •}
- {• - ReceiveEvents : qui traite tous les événements reçus et qui réalise ici •}
- {• un simple MidiThru. •}
- {• •}
- {• - La constante wantRealTime : quand elle vaut 1, ReceiveEvents est appelée •}
- {• sous interruption et fonctionne donc en temps réel, mais ne peut pas •}
- {• utiliser les appels à la Toolbox; quand elle vaut 0, ReceiveEvents est •}
- {• appelée dans la boucle principale et peut donc utiliser la toolbox. •}
- {• •}
- {• - La constante wantFilter : quand elle vaut 1, un filtre sur les entrées •}
- {• Midi est installé, quand elle vaut 0, aucun filtre n'est installé et •}
- {• l'application reçoit tous les événements. •}
- {• •}
- {• - InstallFilter : qui configure le filtre d'entrée •}
- {• •}
- {• - La resource de dialogue 128 qui définit la fenêtre de l'application •}
- {• •}
- {• •}
- {•------------------------------------------------------------------------------•}
- {• © GRAME 1987-92, Yann Orlarey et Hervé Lequay •}
- {••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••}
-
- {$D+} { MacsBug symbols on }
- {$R-} { No range checking }
-
- Program SKELETON;
-
- USES Memtypes, Quickdraw, OSIntf, ToolIntf, PackIntf, Traps, MidiShareUnit;
-
- const AppleID = 128; AppleMenu = 1;
- FileID = 129; FileMenu = 2;
- EditID = 130; EditMenu = 3;
- UndoI = 1; CutI = 3; CopyI = 4; PasteI = 5; ClearI = 6;
-
- WindowID = 128;
- AboutID = 129;
- AlertID = 500;
-
- resumeMask = $01; { suspend/resume mask }
-
- wantRealTime= true; { je veux du temps réel }
- wantFilter = false; { sans filtrage des événements }
-
- var
- myRefNum: integer; { numéro d'appl. Midi }
- myFilter: TFilter; { filtre d'événements }
- myWindow: windowPtr; { fenêtre }
-
- doneFlag: boolean; { flag d'arrêt }
-
- gMac: SysEnvRec; { machine… }
- eventPending: boolean; { vrai si événement en attente }
- hasWNE: boolean; { vrai si WaitNextEvent implémenté }
- foreGround: boolean; { vrai si en foreGround }
-
- myEvent: eventRecord; { pour la main event loop }
- theChar: char; { pour la gestion des touches }
- dragRect: rect; { rect de déplacement de fenêtre }
- myMenus: array[AppleMenu..EditMenu] of MenuHandle;
- { les menus }
-
-
-
- (********************************************************************************)
- (* UTILITAIRES *)
- (*------------------------------------------------------------------------------*)
- (* *)
- (********************************************************************************)
-
- {$S Initialize}
- Function TRAPAVAILABLE (tNumber: integer; tType: trapType): boolean;
- (* Vérification de l'implémentation d'une trappe *)
- begin
- TrapAvailable:= NGetTrapAddress(tNumber,tType) <> GetTrapAddress(_Unimplemented)
- end;
-
- {$S Main}
- Function ISAPPWINDOW (aWind: windowPtr): boolean;
- (* vérifie si la fenêtre appartient à l'application *)
- begin
- if aWind = nil then
- IsAppWindow:= false
- else
- IsAppWindow:= windowPeek(aWind)^.windowKind >= 0
- end;
-
- {$S Main}
- Function ISDAWINDOW (aWind: windowPtr): boolean;
- (* vérifie si la fenêtre appartient à un accessoire de bureau *)
- begin
- if aWind = nil then
- IsDAWindow:= false
- else
- IsDAWindow:= windowPeek(aWind)^.windowKind < 0
- end;
-
- {$S Main}
- Procedure CenterRectOnScreen (var aRect: Rect);
- (* Centre un rectangle global sur l'écran principal (dragRect) *)
- var screenSize : Point;
- rectSize : Point;
- begin
- with dragRect do
- SetPt(screenSize,right - left,bottom - top);
- with aRect do begin
- SetPt(rectSize,right - left,bottom - top);
- left:= dragRect.left + (screenSize.h - rectSize.h) div 2;
- top:= dragRect.top + (screenSize.v - rectSize.v) div 5;
- topLeft:= point(PinRect(dragRect,topLeft));
- right:= left + rectSize.h;
- bottom:= top + rectSize.v;
- end;
- end;
-
- {$S Main}
- Function GetNewCenteredDialog (dialogID: integer): DialogPtr;
- (* Affiche une fenêtre de dialogue au centre de l'écran *)
- var dlogTemplate : DialogTHndl;
- begin
- GetNewCenteredDialog := nil;
- dlogTemplate := DialogTHndl(GetResource('DLOG', dialogID));
- if dlogTemplate <> nil then begin
- CenterRectOnScreen(dlogTemplate^^.boundsRect);
- GetNewCenteredDialog:= GetNewDialog(dialogID, nil, pointer(-1));
- end
- else SysBeep(2) { At least give some indication }
- end;
-
- {$S Main}
- Procedure AlertUser (alertID: integer);
- (* Affiche une alerte au centre de l'écran *)
- var alrtTemplate : AlertTHndl;
- temp : integer;
- begin
- alrtTemplate := AlertTHndl(GetResource('ALRT', alertID));
- if alrtTemplate <> nil then begin
- SetCursor(arrow);
- CenterRectOnScreen(alrtTemplate^^.boundsRect);
- temp:= Alert(alertID,nil)
- end
- else SysBeep(2) { At least give some indication }
- end;
-
-
- (*=============================== MidiShare Part ===============================*)
-
-
- (********************************************************************************)
- (* RECEIVE EVENTS *)
- (*------------------------------------------------------------------------------*)
- (* Cette procédure traite tous les événements reçus. Elle peut être appelée *)
- (* "manuellement" (wantRealTime 0) dans la boucle principale de l'application *)
- (* s'il n'y a pas de contraintes temps réel sur la réception. *)
- (* *)
- (* Dans le cas contraire (wantRealTime 1), grâce à MidiSetRcvAlarm, la routine *)
- (* peut être appelée automatiquement par MidiShare, sous interruptions, chaque *)
- (* fois que l'application reçoit de nouveaux événements (voir SetupMidi). *)
- (* *)
- (* Dans le code ci dessous, ReceiveEvents réalise un simple MidiThru sans *)
- (* aucun traitement. *)
- (* *)
- (* ReceiveEvents doit obligatoirement comporter un paramètre, qui est le *)
- (* numéro de référence MidiShare de l'application. *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* refNum: numéro de référence MidiShare de l'application. *)
- (* *)
- (********************************************************************************)
-
- {$ Main}
- Procedure RECEIVEEVENTS (refNum: integer);
- var e: midiEvPtr;
- n: longint;
- begin
- n := midiCountEvs(refNum); { compte les événements reçus }
- while n > 0 do begin { Pour chaque événement : }
- e := midiGetEv(refNum); { on récupère l'événement reçu }
- MidiSend(refNum,e); { et on le renvoie sans modification }
- n := n-1 { un de moins à traiter }
- end
- end;
-
-
- (********************************************************************************)
- (* INSTALL FILTER *)
- (*------------------------------------------------------------------------------*)
- (* Cette procédure définit les valeurs du filtre de l'application. Un filtre *)
- (* est composé de trois parties, qui sont trois tableaux de booléens : *)
- (* *)
- (* un tableau de 256 bits pour les ports Midi acceptés *)
- (* un tableau de 256 bits pour les types d'événements acceptés *)
- (* un tableau de 16 bits pour les canaux Midi acceptés *)
- (* *)
- (* Dans le code ci dessous, le filtre est paramétré pour accepter n'importe *)
- (* quel type d'événement. *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$ Initialize}
- Procedure INSTALLFILTER;
- var i: integer;
- begin
- for i:= 0 to 255 do begin
- myFilter.evType[i]:= true; { accepte tous les types d'événements }
- myFilter.port[i]:= true { en provenance de tous les ports }
- end;
-
- for i:= 0 to 15 do
- myFilter.channel[i]:= true; { et sur tous les canaux Midi }
-
- MidiSetFilter(myRefNum,@myFilter) { installe le filtre }
- end;
-
-
- (********************************************************************************)
- (* APPL ALARM *)
- (*------------------------------------------------------------------------------*)
- (* ALARM est la procédure passée à MidiShare comme alarme de changement de sta- *)
- (* tut des appl. Midi ou des ports. Comme il est possible qu'elle soit appelée *)
- (* sous interruptions, elle ne peut provoquer d'appel à des routines qui utili- *)
- (* sent le Memory Manager. Elle positionne seulement des flags, la Main Event *)
- (* Loop se chargeant d'appeler MAINALARM si ces flags sont positionnés. *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* refnum: numéro de l'application (de Midi Connection) *)
- (* code: HiWrd = refnum de l'application concernée *)
- (* LoWrd = code de la modification intervenue *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure APPLALARM (refnum: integer; code: longint);
- begin
- case LoWrd(code) of
- MIDIOpenAppl : ; { ouverture d'une application }
- MIDICloseAppl : ; { fermeture d'une application }
- MIDIChgName : ; { changement de nom d'une application }
- MIDIChgConnect : ; { modification d'une connexion }
- MIDIOpenModem : ; { ouverture du port Modem }
- MIDICloseModem : ; { fermeture du port Modem }
- MIDIOpenPrinter : ; { ouverture du port Printer }
- MIDIClosePrinter : ; { fermeture du port Printer }
- end;
- end;
-
-
- (********************************************************************************)
- (* SETUP MIDI *)
- (*------------------------------------------------------------------------------*)
- (* Vérifie la présence de MidiShare, la possibilité d'ouverture Midi, et *)
- (* installe la procédure d'alarme qui sera appelée par MidiShare lors des chan- *)
- (* gements de statut des applications ou des ports. *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Initialize}
- Procedure SETUPMIDI;
- var name: str255;
- apRefNum: integer;
- apParam: Handle;
- aRefNum: integer;
-
- Procedure FAILSETUP (strIndex: integer);
- var msgStr: str255;
- begin
- GetIndString (msgStr,AlertID,strIndex); { message d'alerte suivant erreur }
- ParamText(name,msgStr,'','');
- AlertUser(AlertID);
- ExitToShell { et quitte }
- end;
-
- begin
- GetAppParms(name,apRefNum,apParam); { récupérer le nom d'application }
- if not MidiShare then FailSetUp(1); { MidiShare n'est pas installé }
-
- myRefNum:= MidiOpen(name); { ouverture en Midi }
- if myRefNum = MidiErrSpace then FailSetUp(2); { impossible, plus de place }
-
- if wantRealTime then begin
- {MidiSetApplAlarm(myRefNum,@ApplAlarm);} { définit la tâche temps-réel de contexte }
- MidiSetRcvAlarm(myRefNum,@ReceiveEvents) { définit la tâche temps-réel de réception }
- end;
- if wantFilter then
- InstallFilter; { installe un filtre si nécessaire }
-
- MidiConnect(0,myRefNum,true); { connection avec les ports Midi d'entrées }
- MidiConnect(myRefNum,0,true) { connection avec les ports Midi de sortie }
- end;
-
-
- (********************************************************************************)
- (* DO IDLE *)
- (*------------------------------------------------------------------------------*)
- (* Execution des différentes tâches Midi : reception des événements Midi si *)
- (* cela n'est pas fait sous interruptions; Exécution des tâches différées en *)
- (* attente (tâches crées par MidiDTask). *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure DOIDLE;
- var n: longint;
- begin
- if not wantRealTime then
- ReceiveEvents(myRefNum);
- for n:= 1 to MidiCountDTasks(myRefNum) do
- MidiExec1DTask(myRefNum)
- end;
-
-
- (*=============================== Macintosh Part ===============================*)
-
- (********************************************************************************)
- (* SET UP MENUS *)
- (*------------------------------------------------------------------------------*)
- (* Installation de la barre de menus *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Initialize}
- Procedure SETUPMENUS;
- var i: integer;
- begin
- myMenus[AppleMenu] := GetMenu(AppleID); { menu Pomme }
- AddResMenu(myMenus[AppleMenu],'DRVR'); { ajout des accessoires de bureau }
- myMenus[FileMenu] := GetMenu(FileID); { menu Fichier }
- myMenus[EditMenu] := GetMenu(EditID); { menu Edit }
- for i := AppleMenu to EditMenu do
- InsertMenu(myMenus[i], 0);
- DrawMenuBar { affiche la barre des menus }
- end;
-
-
- (********************************************************************************)
- (* SETUP WINDOW *)
- (*------------------------------------------------------------------------------*)
- (* Ouvre la fenêtre *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Initialize}
- Procedure SETUPWINDOW;
- var r : rect;
- begin
- with screenBits.bounds do { rect max de déplacmt de fenêtre }
- SetRect(dragRect, 4, 24, right - 4, bottom - 4);
- myWindow := GetNewDialog(WindowID,nil,pointer(-1));
- SetPort(myWindow);
- r:= myWindow^.portRect;
- with r do begin
- LocalToGlobal(topLeft);
- LocalToGlobal(botRight)
- end;
- if not RectInRgn(r,GetGrayRgn) then begin { rect fenêtre hors écrans : }
- CenterRectOnScreen(r); { le centrer sur l'écran principal }
- MoveWindow(myWindow,r.left,r.top,true)
- end;
- ShowWindow(myWindow)
- end;
-
- {$S Main}
- Procedure SAVEWINDOWPOS;
- (* Sauvegarde dans la ressource DLOG de l'application la position de la fenêtre *)
- type rectPtr = ^rect;
- rectHdle = ^rectPtr;
- var windHdle: handle;
- begin
- windHdle:= Get1Resource('DLOG',WindowID);
- rectHdle(windHdle)^^:= windowPeek(myWindow)^.contRgn^^.rgnBBox;
- ChangedResource(windHdle);
- if ResError = noErr then
- WriteResource(windHdle)
- end;
-
-
- (********************************************************************************)
- (* INITIALIZE *)
- (*------------------------------------------------------------------------------*)
- (* Initialisations générales (hasWNE, foreGround, managers, fenêtre, Midi) *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Initialize}
- Procedure INITIALIZE;
- var err: OSErr;
- begin
- err:= SysEnvirons(1,gMac);
- hasWNE:= (gMac.machineType >= 0) & TrapAvailable(_WaitNextEvent,ToolTrap);
-
- InitGraf(@thePort); { initialisations standard }
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(NIL);
- InitCursor;
- SetUpMenus; { mise en place menus }
- SetUpMidi; { ouverture MidiShare }
- SetUpWindow; { initialisations fenêtre et listes }
- end;
-
-
- (********************************************************************************)
- (* ADJUST MENUS *)
- (*------------------------------------------------------------------------------*)
- (* Ajustement de la barre de menus suivant la fenêtre de premier plan, juste *)
- (* lors d'un click dans la barre des menus *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* aucun *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure ADJUSTMENUS;
- begin
- if IsAppWindow(FrontWindow) then begin
- DisableItem(myMenus[EditMenu],UndoI);
- DisableItem(myMenus[EditMenu],CutI);
- DisableItem(myMenus[EditMenu],CopyI);
- DisableItem(myMenus[EditMenu],PasteI);
- DisableItem(myMenus[EditMenu],ClearI)
- end
- else
- if IsDAWindow(FrontWindow) then begin
- EnableItem(myMenus[EditMenu],UndoI);
- EnableItem(myMenus[EditMenu],CutI);
- EnableItem(myMenus[EditMenu],CopyI);
- EnableItem(myMenus[EditMenu],PasteI);
- EnableItem(myMenus[EditMenu],ClearI)
- end
- end;
-
-
- (********************************************************************************)
- (* DO COMMAND *)
- (*------------------------------------------------------------------------------*)
- (* Gère les menus: Pomme (About), File (Quit) *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* mResult: numéro de menu et d'item retournés par MenuSelect et MenuKey *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure DOCOMMAND ( mResult: LONGINT);
- var theItem: integer;
- name: str255;
- sysEdit: boolean;
-
- Procedure SHOWABOUT;
- var myDialog : dialogPtr;
- hit : integer;
- begin
- myDialog:= GetNewCenteredDialog(AboutID);
- if myDialog <> nil then begin
- ModalDialog(nil,hit);
- DisposDialog(myDialog);
- end
- end;
-
- begin
- theItem := LoWord(mResult);
- case HiWord(mResult) of
- AppleID: { menu Pomme }
- if theItem <> 1 then begin
- GetItem(myMenus[AppleMenu], theItem, name);
- theItem := OpenDeskAcc(name) end
- else ShowAbout;
- FileID: { menu File }
- doneFlag := true;
- EditID: { menu Edit: uniquement pour DAs }
- sysEdit := SystemEdit(theItem-1);
- end;
- HiliteMenu(0)
- end;
-
-
- (********************************************************************************)
- (* TRACK DIALOG *)
- (*------------------------------------------------------------------------------*)
- (* Procédure chargée du suivi de la souris lors d'un click dans contenu *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* window: pointeur sur la fenêtre de dialogue. *)
- (* where: point où la souris a été cliquée. *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure TRACKDIALOG (window: windowPtr; where: point);
- begin
- SetPort(window);
- GlobalToLocal(where); { conversion du point en local }
- end;
-
-
- (********************************************************************************)
- (* DO MOUSE DOWN *)
- (*------------------------------------------------------------------------------*)
- (* Gère les clicks souris *)
- (* *)
- (* Les paramètres de l'appel : *)
- (* --------------------------- *)
- (* *)
- (* anEvent: l'événement *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure DOMOUSEDOWN (anEvent: eventRecord);
- var whichWind: windowPtr;
- part: integer;
- begin
- part:= FindWindow(anEvent.where, whichWind);
- case part of
- inMenuBar: begin
- AdjustMenus;
- DoCommand(MenuSelect(anEvent.where))
- end;
- inSysWindow: SystemClick(anEvent,whichWind);
- inDrag: DragWindow(whichWind,anEvent.where,dragRect);
- inGoAway: doneFlag:= TrackGoAway(whichWind,anEvent.where);
- inContent: if whichWind <> FrontWindow then
- SelectWindow(whichWind)
- else
- if IsAppWindow(whichWind) then
- TrackDialog(whichWind,anEvent.where);
- end
- end;
-
-
- (********************************************************************************)
- (* ADJUST CURSOR *)
- (*------------------------------------------------------------------------------*)
- (* Ajuste le curseur suivant région et fenêtre *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure ADJUSTCURSOR;
- begin
- if foreGround and IsAppWindow(FrontWindow) then
- SetCursor(arrow)
- end;
-
-
- (********************************************************************************)
- (* CLOSE WINDOWS *)
- (*------------------------------------------------------------------------------*)
- (* Pour terminer correctement l'application: fermeture de toutes les fenêtres *)
- (* (application et DA's) *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- Procedure CLOSEWIND (aWind: windowPtr);
- (* ferme une fenêtre *)
- begin
- if IsDAWindow(aWind) then
- CloseDeskAcc(windowPeek(aWind)^.windowKind)
- else if IsAppWindow(aWind) then
- DisposeWindow(aWind)
- end;
-
- Procedure CLOSEALLWINDS;
- (* ferme toutes les fenêtres *)
- var window: windowPtr;
- begin
- repeat
- window:= FrontWindow;
- if window <> nil then
- CloseWind(window);
- until window = nil;
- end;
-
-
- Procedure _DataInit; EXTERNAL;
-
- (********************************************************************************)
- (* Corps Principal *)
- (*------------------------------------------------------------------------------*)
- (* Initialisation des managers, ouverture fenêtre, initialisations diverses et *)
- (* tutti quanti, boucle principale. *)
- (* *)
- (********************************************************************************)
-
- {$S Main}
- begin
- UnLoadSeg(@_DataInit);
- MaxApplZone;
- Initialize;
- UnLoadSeg(@Initialize);
-
- DoneFlag:=false; { flag de terminaison }
- repeat { boucle principale typique }
- if hasWNE then
- eventPending:= WaitNextEvent(everyEvent, myEvent, 0, nil)
- { no sleep, no mouseRgn }
- else begin
- SystemTask;
- eventPending:= GetNextEvent(everyEvent, myEvent)
- end;
- AdjustCursor; { si ≠ curseurs ou mouseRgn, ici }
- with myEvent do
- case what of
- nullEvent:
- DoIdle; { do Idle }
- {
- activateEvt:
- if IsAppWindow(windowPtr(message)) then;
- if BAnd(modifiers,activeFlag) <> 0 then
- else
- }
- osEvt:
- case BSR(message,24) of
- suspendResumeMessage:
- begin
- foreGround:= BAnd(message,resumeMask) <> 0;
- {
- if IsAppWindow(FrontWindow) then
- }
- end;
- mouseMovedMessage:
- DoIdle { do Idle }
- end;
- keyDown, autoKey:
- begin
- theChar:= chr(BAnd(message,charCodeMask));
- IF BAnd(modifiers, cmdKey) <> 0 then begin
- AdjustMenus;
- DoCommand(MenuKey(theChar))
- end
- end;
- mouseDown:
- DoMouseDown(myEvent);
- updateEvt:
- if IsAppWindow(windowPtr(message)) then begin
- BeginUpdate(myWindow);
- if not EmptyRgn(myWindow^.visRgn) then begin
- SetPort(myWindow);
- DrawDialog(myWindow)
- end;
- EndUpdate(myWindow)
- end
- end
- until doneFlag;
- MidiClose(myRefNum); { fermeture MidiShare }
- SaveWindowPos;
- CloseAllWinds;
- ExitToShell
- end.
-