Announcement

Collapse
No announcement yet.

Mysterious GPF and Exception Handling

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael Mattias
    replied
    >Is there a list of "Blocking Functions"

    Sure, the entire PB keyword list. They either return, timeout and return, or block.

    e.g..
    COMM RECV
    ..returns on timeout or when something is received, not before, not after.

    And of course, all the Win32 synchronization functions, eg WaitForxxxx or Sleep[Ex].

    >Shouldn't a global variable be global across threads?

    You should know this by now.

    A global variable is global to the code module. If a thread function is in the code module, it has access to GLOBAL variables.

    Leave a comment:


  • Cliff Nichols
    replied
    MCM....My thoughts EXACTLY

    The only problem is, that it did not occur until I did away with the Do Loop and just called the function from the callback. So I am in a catch 22 unless I can find a way around.

    At least I now have a few things to look at. But unfortunately too many pieces (and a couple pieces that I can not verify if my guess is possible, until PB or others can get me documentation to if I may or may not be right)

    Anyways from my code above, maybe someone can extrapolate and give me something to look at (although I have a ton of avenues but SOMEONE has to have run into something as difficult as this one before)

    Testing Procedure: (Both in Exe and DLL form)
    1. Start the program, and have the Limits Viewer run
    2. While its running, kill the program (or parent process if run as Dll) and from there "SendMessage" to click the button

    Results:
    EXE: All ends fine, no GPF or known errors
    DLL: All ends fine, but GPF/Error (depending on parent process could be approx 5 seconds after closing)

    Testing Procedure2: (Both in Exe and DLL form)
    1. Start the program, and have the Limits Viewer run
    2. "Physically" Press the button to close the test

    Results:
    EXE: All ends fine, no GPF or known errors
    DLL: All ends fine, no GPF or known errors

    Common Results:
    EXE: Both tests are the same, whether I physically click the button, or SendMessage to push it
    DLL: Works if I "Physically" Click...GPF if I SendMessage to do it

    Either way...my best guesses to cause of problems? (Only guessing here)
    *** Remember by the way in all cases, I set a Global Variable = %True (meaning 1 and no other value) that if it is set to escape the DO LOOP
    • Programmatically press "Flag is not seen" within loop (not sure why)
    • Physically Click, "Flag is seen" (still don't know why different from program click"
    • "Streamin" may be a blocking function, but commenting this out does not get rid of the problem
    • "COMM" may be a blocking function but again commenting out does not fix the problem
    • DO LOOP with 1ms sleep by itself, I get the same problem.
    • I would have thought threading my COMM RECV could be a cause but since it was commented out, I have to almost ignore it (ALLLLMOSTTT)


    So I wonder for the missing peices, that I know exist, but no documentation (that I can find anyways)
    • Is there a list of "Blocking Functions" (and hopefully, what they do, why they block, how to disable the block etc) both on the SDK side and the DDT side?
    • Shouldn't a global variable be global across threads? (lets not get into the synch and thread aware and accessing in the middle of an update, because to my knowledge at SOME point any thread looking at the variable should see it changed (whether the same thread or a different one)


    Probably confusing, but at this point, my only answer to the user is ("1st Close all running pieces" and THEN close the parent program
    (Although I do not like leaving "Bugs known to me in my programs")

    On a side note...I do Not know about PB 8.04 but PB 8.03 has documented CancelIO and CancelIoEX but neither of which exists in the Win32Api.Inc file (which I tried to replicate from C++ definitions, hoping that was the solution)

    Leave a comment:


  • Michael Mattias
    replied
    >Turns out I run out of stack space and create an endless loop somewhere

    OUT OF STACK SPACE ===>>> MAJOR CLUE HERE!

    I have three dollars sixty-two cents says in one of your message processing code groups you are calling something which results in the same message being automatically generated... causing an endless recursion. Well, it's not really endless... it will end as soon as you run out of stack space and generate a Stack Fault GPF - but it sounds like you have already discovered this.

    Leave a comment:


  • Cliff Nichols
    replied
    Neverrrrrrrrmind.....BAAAAAAAD Idea

    Turns out I run out of stack space and create an endless loop somewhere.


    Back to the drawing board

    Leave a comment:


  • Michael Mattias
    replied
    >Look ma! No Do Loops

    Good for you.

    Next Stop: "Look Ma, no GLOBALs!"

    (e,g,GUI + Worker Thread + Abort Demo)

    Yes, that's right: no GLOBALs (or STATICs for that matter) in that code. It's cut and paste and compile and run.

    MCM

    Leave a comment:


  • Cliff Nichols
    replied
    Do loop blocking

    I think I just found a heck of an example why MCM dislikes globals (And I am starting to also now). I found my bug, it was my Do Loop in the "TroubleshootLimits".
    Even though I do a check for my Global Flag, to see if it = %True, and if it does then exit the loop. Somehow If I physically press the button, then the loop sees that the Flag = %True and exits the loop, but if I programmatically press the button, then the loop never sees the Flag changed from %False to %True.

    Still unsure as to why? But searching for a cause when I was at wits end finding the cause of the GPF I tripped into a post From back in 2003 where Bob Plymale as asking some Thread Question. Where he was using a Do Loop to wait for a Thread to complete, and MCM pointed out "WaitForSingleObject"

    Lance Edmonds comment below that sparked a thought in my head
    You should not hold up the message queue by blocking it waiting for the thread to finish. Doing so largely removes the point of using a secondary thread anyway.
    Although my problem had nothing to do with threads, I stopped and thought "Could the Do Loop be blocking? because I already started the loop before setting the flag to break out?" (Still not totally sure, because pushing the button Sets the Flag correctly)

    Anyways, I stopped and thought about the purpose of the loop. The core purpose is to keep sending and receiving certain codes until the button is pressed and the Window is closed. Lance had mentioned Starting and Stopping from the Callback function, and it hit me....I could get rid of my do loop and just call the function each loop of my Callback function (as deemed necessary) since the window is open as long as the test is running.

    Look ma! No Do Loops
    Well it certainly made the problem in this case go away. Now I have to figure out why it could not see the flag set to True in the 1st place?

    Leave a comment:


  • Michael Mattias
    replied
    > if there is a better definition for a modeless dialog in SDK I would love to see it.
    CreateDialog[Indirect][Param]

    Leave a comment:


  • Cliff Nichols
    replied
    With the discussion with Karl-Heinz Voltmann at DLL will not terminate I think it may have just hit me where some of my problems may be.

    In each of my functions if there is a do loop I have a flag in the loop (If ParentClosing = %True then exit do) and a flag to escape the loop based off a variable to stop that particular loop.

    I started thinking about "Forget the code.....think of what the code is DOING", and if I got it right what is happening is
    1. Once I enter my do loop, I am stuck there until either my Flag is set to escape, or I found what I am looking for
    2. Because my dialog is modeless I can push the button to set the flag to escape my loop, and it does because my loop is checking the state of my global variable
    3. If I close and my loop is no longer running then no crash

    So in this case (I may be WAYYYYyyyy off here but) would a modeless dialog be some sort of "Threaded Dialog"?

    But if I close, while the loop is running, and programmatically press the button, I get a crash (I assume because the loop never sees the flag set?), possibly because the the message to stop is on the stack waiting to be processed, and PostQuitMessage 0 stops my message pump to the message to stop is never seen?

    Forgive me if I am wrong (or just partially right) but gut feeling tells me the problem is in my loop because if it is running, I crash, if it is not running I do not crash

    Leave a comment:


  • Cliff Nichols
    replied
    I too dislike the mix of DDT and SDK, but when this all started, DDT was all I understood. But as time went on, I started understanding SDK and finding it much more useful in a lot of cases.

    Anyways, how would I go about a Modeless Dialog/Window using SDK? The closest I can find is
    GetClassInfoEx(GetModuleHandle(BYVAL %NULL), "#32770", twcx) 'copy dialog class (modeless)
    (I really do not get why modeless is marked as "#32770" though)

    so I made a function in my newer version (trying to avoid pitfalls of the past) as being:
    Code:
    FUNCTION Register_Modeless( _
              ClassName AS STRING, _        'Class Name
              BYVAL ClassCallBack AS DWORD, _     'Callback Function
              ClassInstance AS LONG, _      'Instance
              ClassIcon AS ASCIIZ, _        'Icon
              ClassBackGround AS LONG _    'Background
              ) AS LONG
         ON ERROR GOTO ErrHandler
        GetClassInfoEx(GetModuleHandle(BYVAL %NULL), "#32770", twcx)      'copy dialog class (modeless) into ports class
    
         szClassName        = ClassName
         twcx.cbSize        = SIZEOF(twcx)                               ' size of WNDCLASSEX structure
         twcx.style         = %CS_DBLCLKS                                ' class styles
         twcx.lpfnWndProc   = ClassCallBack                  ' address of window procedure used by class
         twcx.cbClsExtra    = 0                                          ' extra class bytes
         twcx.cbWndExtra    = %DLGWINDOWEXTRA                                          ' extra window bytes
         twcx.hInstance     = ClassInstance                                  ' instance of the EXE/DLL that is registering the window
         twcx.hIcon         = LoadIcon(ClassInstance, ClassIcon)    ' handle of class icon
         twcx.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)        ' handle of class cursor
         twcx.hbrBackground = ClassBackGround                    ' brush used to fill background of window's client area
         twcx.lpszMenuName  = %NULL                                      ' resource identifier of the class menu
         twcx.lpszClassName = VARPTR(szClassName)                        ' class name
         twcx.hIconSm       = LoadIcon(%NULL, ClassIcon)    ' handle of small icon shown in caption/system Taskbar
         SELECT CASE RegisterClassEx(twcx)
              CASE 0
                   FUNCTION = %FALSE
              CASE ELSE
                   FUNCTION = %TRUE
         END SELECT
         EXIT FUNCTION
    ErrHandler:
         LogError ERR, ERROR$(ERR)
         RESUME              'Resume once error has been handled
    END FUNCTION
    You can't call LoadCosmos on LibMain/Dll_Process_Attach since you are using functions other than those in KERNEL32.DLL
    I thought the whole purpose of the attach and detach was to setup and cleanup variables, arrays, dialogs, etc?????

    In this case SHowCosmos in the attach was solely for display purposes. But in real was debating on no matter what the 1st function called was (Lets say it was "SendToPort", then the window would automatically pop up when the dll was attached to the process.) Although I have already seen a reason not to show just because I called a function.)

    Anyways if there is a better definition for a modeless dialog in SDK I would love to see it.

    Leave a comment:


  • Michael Mattias
    replied
    I haven't gone thru this in deatil but I can tell you I don't like using a DDT MODELESS dialog with an SDK message loop.

    Try changing that DDTdialog to a SDK dialog and use CreateDialog to create the window and add the IsDialogMessage() call to your message loop in WinMain.

    For as little as that dialog does it shouldn't take you more than twenty minutes.

    Also..
    Code:
    FUNCTION LibMain .....
        ...
        LoadCosmos
    You can't call LoadCosmos on LibMain/Dll_Process_Attach since you are using functions other than those in KERNEL32.DLL

    Better you should set a STATIC flag in fucntion ShowCosmos
    Code:
    FUNCTION ShowCosmos....
    
     STATIC bLoaded AS LONG
    
     ....
     IF ISFALSE bLoaded THEN    ' load it on the first call. 
        CALL          LoadCosmos
        bLoaded  = %TRUE
     END IF

    MCM
    Last edited by Michael Mattias; 1 Dec 2007, 09:41 AM.

    Leave a comment:


  • Cliff Nichols
    replied
    Test conditions

    Now for the Test Conditions.
    The major one is if you do the following:
    1. Open the test program (it in turn opens the dll (so to speak). )
    2. Click "Tools-->Limits" and the dialog should pop up with the cancel button
    3. Close the parent testing Process without closing the dll interface


    What it should do since this is the only process with the dll loaded is to free all threads, and whatever else I can think of that could cause a memory corruption (but obviously not working for whatever reason)

    The minor test is if you do the following:
    1. Open the test program (it in turn opens the dll (so to speak). )
    2. Close the parent testing Process without closing the dll interface

    the results of this one may be just because I got wooped and tired of trying to tear down, so not a big deal at the moment.

    Barring things I am not noticing, or thinking of, the 2 core sections that I think may be causing the errors may be either or combined ideas?
    1. I have a variable "ParentClosing =" that I thought was a global flag to tell any threads to stop and break out (but maybe this is part of what MCM has been so gently trying to beat into my noggin in the 1st place about variables not available across threads? (But I think in this case each thread should see my flag?)
    2. StreaminString for the RichEdit...(I have no documentation on where, how, or what is happening with this callback so it could be of partial cause?)
    3. Less likely, but perhaps the "COMM" functions? maybe they were not built to handle a constant pounding of "Send/Receive" ......just guessing at the moment


    The interesting thing is the difference between running as an EXE vs running as a DLL (see #COMPILE to switch between the 2 ways)

    Anyways, I REALLY appreciate fresh eyes on what is obviously eluding me.
    (Hopefully my next version will be all SDK and I can avoid mistakes of the "Past/Present/ and hopefully Future"

    Thanx again to anyone helping

    Leave a comment:


  • Cliff Nichols
    replied
    Sorry Edwin and MCM, I am sure you guys get the feeling that when I say "Its buried deep" that its a phrase that I hear often when hearing the same questions from someone wanting my help, and my only reply is "I have to see the code" to even BEGIN to get a clue.

    I am sure it's the typical "i will not tell to much"..
    Not that I don't want to, but it truly is buried that deep in code (too bad I did not know then what I have learned since), as you will see from the code below that unfortunately took me about 8 hours to rip out and make functional by itself without the other thousands of lines of code.

    1) I am sure it's VB again?
    Actually yes to begin, but also under Labview, C++, and PB itself (each with their own "quirks" but I think the common flaw is a pointer gone bad? or something I have no knowledge that I may or may not have control over

    Anyways, like I said it took me over 8 hrs to rip down and make a "Functional" demonstration of the problem, so please forgive me the 2nd error I get from my demo (I think its just the migraine and me not thinking, why PB will not fire the close event, so I am not so worried about that problem just yet)

    Anyways, to make things simpler, you will see areas where I hard-coded things like "Assume Com1" rather than the real possibles and their error-checks, etc.

    Also for MCM...I know you hate me for all the Globals, but my next version I am hoping to eliminate the whole "Global - Local" debate, so please bear with me.

    I also stuck as much as I could into as few files as possible. Although my usual habit is to put all my "Declares" in separate *.h files and the associated code into *.inc files so I can just drop them into different projects and not have to re-do working code.

    Anyways, I appreciate some "Fresh-Eyes" over what I may be obviously missing.

    The main Program. Name it "COSMOS" or whatever
    Code:
    '#COMPILE EXE
    #COMPILE DLL
    #DIM ALL
    #DEBUG ERROR ON
    #TOOLS ON
    #INCLUDE "WIN32API.INC"       'Windows Api
    
    '------------------------------------------------------------------------------
    '*** Load all the header files
    '------------------------------------------------------------------------------
    '*** COSMOS.h
         DECLARE FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
         DECLARE FUNCTION LIBMAIN (BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) AS LONG
         DECLARE FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
         DECLARE FUNCTION LoadCosmos ALIAS "LoadCosmos"() AS LONG
         DECLARE FUNCTION UnloadCosmos ALIAS "UnloadCosmos"() AS LONG
         DECLARE FUNCTION GetWindowState ALIAS "GetWindowState"(WindowToCheck AS LONG) AS LONG
         DECLARE FUNCTION ShowCosmos ALIAS "ShowCosmos"() AS LONG
         DECLARE FUNCTION HideCosmos ALIAS "HideCosmos"() AS LONG
         DECLARE FUNCTION IsCosmosVisible ALIAS "IsCosmosVisible"() AS LONG
    
         GLOBAL IsExe            AS LONG
         GLOBAL ParentClosing AS LONG
         GLOBAL hInst        AS DWORD
         GLOBAL hWndMain     AS DWORD
         GLOBAL hWndClient   AS DWORD
         GLOBAL fClosed      AS LONG
         GLOBAL freezeMenu   AS LONG
    '------------------------------------------------------------------------------
    '*** Menubar.h
         GLOBAL hMenu AS LONG
         GLOBAL StatHeight  AS LONG
         %IDM_TOOLS                         = %WM_USER + 100
         %IDM_TRBLIMITSVIEWON               = %WM_USER + 942
    '------------------------------------------------------------------------------
    '*** Statusbar.h
         GLOBAL hStatus      AS DWORD
         %ID_STATUSBAR                      = %WM_USER + 1025&  ' statusbar
    '------------------------------------------------------------------------------
    '*** ErrorHandling.h
         DECLARE FUNCTION StartTrace ALIAS "StartTrace"() AS LONG
         DECLARE FUNCTION EndTrace ALIAS "EndTrace"() AS LONG
         DECLARE FUNCTION ErrorCheck ALIAS "ErrorCheck"(ErrorCode AS LONG)AS LONG     'Error Handling
    
         GLOBAL TraceLog AS STRING
         GLOBAL TraceLogNum AS LONG
         GLOBAL NumOfErrorsCosmos    AS LONG
    '------------------------------------------------------------------------------
    '*** Threading.h
         DECLARE FUNCTION OpenMdiThread ALIAS "OpenMdiThread"() AS LONG       'Added to re-enable the Mdi thread
         DECLARE FUNCTION CloseMdiThread ALIAS "CloseMdiThread"() AS LONG
    
         DECLARE FUNCTION OpenListenThread ALIAS "OpenListenThread"() AS LONG       'Added to re-enable the listen thread
         DECLARE FUNCTION CloseListenThread ALIAS "CloseListenThread"() AS LONG
    
         GLOBAL MdiThread AS LONG    'Added so that the MdiForm can run on its own, and return to parent caller
         GLOBAL MdiThreadDone AS LONG
    
         GLOBAL HwndThread       AS LONG         'Variable for the thread
         GLOBAL CloseThread      AS LONG
         GLOBAL ThreadDone       AS LONG
    '------------------------------------------------------------------------------
    '*** DlgIoState.h
         DECLARE SUB ShowIoStateWindow(TestToRun AS STRING)
         DECLARE SUB HideIoStateWindow()
    
         GLOBAL IoTest AS STRING
         GLOBAL IsDlgIoOpen AS LONG
         GLOBAL HwndDlgIoState  AS DWORD
    
         %Btn_Stop    = 102
    '------------------------------------------------------------------------------
    '*** History.h
         DECLARE CALLBACK FUNCTION HistoryChildrenCallback() AS LONG
         DECLARE CALLBACK FUNCTION HistoryCallBack () AS LONG
         DECLARE FUNCTION LoadHistory(BYVAL hParent&) AS LONG     'Load main program
         DECLARE FUNCTION ShowHistory ALIAS "ShowHistory"(BYVAL hParent&) AS LONG
         DECLARE FUNCTION HideHistory ALIAS "HideHistory"() AS LONG
         DECLARE FUNCTION IsHistoryOpen ALIAS "IsHistoryOpen"() AS LONG
         DECLARE SUB LstHistoryAddLine(FontType AS STRING, FontColor AS STRING, TextToAdd AS STRING, AppendCr AS LONG)    'MUST REMAIN HERE DUE TO CONFLICT OF LOADING PORT FUNCTION OR DLGHistory 1ST
         DECLARE SUB LstHistoryRestoreHistory()
         DECLARE SUB LstHistoryClearHistory()
         DECLARE SUB DefaultHistory()
    
         GLOBAL HistoryHeight AS LONG
         GLOBAL HistoryWidth AS LONG
         GLOBAL hLibHistory AS LONG
         GLOBAL RchEdHistory AS LONG
         GLOBAL hHistory AS LONG        'Handle for subclassed RichEdit
         GLOBAL OldDlgHistoryTxtProc AS LONG  'for address of original RichEdit procedure
         GLOBAL HistoryRtfText AS STRING
         %RchEdHistory = 100
    '------------------------------------------------------------------------------
    '*** Rtf.h
         DECLARE FUNCTION RichEditStreamInString (BYVAL dwCookie AS DWORD, BYVAL pbBuff AS BYTE PTR, _
                                          BYVAL cb AS LONG, pcb AS LONG) AS DWORD
    
         GLOBAL gPos AS LONG, gPtr AS LONG, gTxt AS STRING
    
         DECLARE FUNCTION RtfCommandsStart() AS STRING
         DECLARE FUNCTION RtfCommandsEnd() AS STRING
    
         DECLARE FUNCTION RtfCommandsEndOfLine() AS STRING
    
         DECLARE FUNCTION RtfReplaceCr(CommandString AS STRING) AS STRING
    
         DECLARE FUNCTION RtfFontCourier() AS STRING
         DECLARE FUNCTION RtfFontTimesNewRoman() AS STRING
         DECLARE FUNCTION RtfFontAndale() AS STRING
         DECLARE FUNCTION RtfFontLucidia() AS STRING
         DECLARE FUNCTION RtfFontGeorgia() AS STRING
    
         DECLARE FUNCTION RtfFontBold() AS STRING
         DECLARE FUNCTION RtfFontUnBold() AS STRING
         DECLARE FUNCTION RtfFontItalic() AS STRING
         DECLARE FUNCTION RtfFontUnItalic() AS STRING
         DECLARE FUNCTION RtfFontUnderline() AS STRING
         DECLARE FUNCTION RtfFontUnUnderline() AS STRING
    
         DECLARE FUNCTION RtfFontSize(SizeForFont AS LONG) AS STRING
    
         DECLARE FUNCTION RtfFontMaroon() AS STRING
         DECLARE FUNCTION RtfFontGreen() AS STRING
         DECLARE FUNCTION RtfFontOlive() AS STRING
         DECLARE FUNCTION RtfFontNavy() AS STRING
         DECLARE FUNCTION RtfFontPurple() AS STRING
         DECLARE FUNCTION RtfFontTeal() AS STRING
         DECLARE FUNCTION RtfFontGrey() AS STRING
         DECLARE FUNCTION RtfFontSilver() AS STRING
         DECLARE FUNCTION RtfFontRed() AS STRING
         DECLARE FUNCTION RtfFontLime() AS STRING
         DECLARE FUNCTION RtfFontYellow() AS STRING
         DECLARE FUNCTION RtfFontBlue() AS STRING
         DECLARE FUNCTION RtfFontFuchsia() AS STRING
         DECLARE FUNCTION RtfFontAqua() AS STRING
         DECLARE FUNCTION RtfFontWhite() AS STRING
         DECLARE FUNCTION RtfFontBlack() AS STRING
    '------------------------------------------------------------------------------
    '*** WaitForChar.h
         DECLARE FUNCTION WaitForChar ALIAS "WaitForChar"(CharToWaitFor AS ASCIIZ * %MAX_PATH, OPTIONAL BYVAL TimeOutTime AS LONG) AS LONG
         DECLARE FUNCTION WaitForCharWithMotorPosition ALIAS "WaitForCharWithMotorPosition"(CharToWaitFor AS ASCIIZ * %MAX_PATH, BYVAL MotorNumber AS LONG, OPTIONAL BYVAL ReportToWindowHwnd AS LONG, OPTIONAL BYVAL TimeOutTime AS LONG) AS LONG
    
         GLOBAL WaitingForChar AS LONG
    '------------------------------------------------------------------------------
    '*** PortFunctions.h
         DECLARE FUNCTION OpenPort ALIAS "OpenPort"(BYVAL ComPortNumber AS LONG, BYVAL ComPortBaudRate AS LONG) AS LONG  'Configure and open serial port
         DECLARE FUNCTION IsPortOpen ALIAS "IsPortOpen"() AS LONG    'Determine if port is already open (mostly for labview users)
         DECLARE FUNCTION ClosePort ALIAS "ClosePort"() AS LONG  'Close serial port
         DECLARE FUNCTION SendToPort ALIAS "SendToPort" (CommandOut AS STRING) AS LONG 'Send Command to device via Cptr or actual string
         DECLARE FUNCTION WaitReply(MinNumOfChars AS LONG, TimeoutTime AS LONG)AS LONG
         DECLARE FUNCTION ReadAndThenClearFromPort ALIAS "ReadAndThenClearFromPort"() AS STRING  'Get reply from device
         DECLARE FUNCTION CountCharsAtPort ALIAS "CountCharsAtPort"() AS LONG 'Count Number of Chars at port
         DECLARE FUNCTION SearchForChars ALIAS "SearchForChars"(CharsToFind AS ASCIIZ) AS LONG
         DECLARE FUNCTION ClearPort ALIAS "ClearPort"() AS LONG  'Clear buffer
         DECLARE FUNCTION RemoveFromPort ALIAS "RemoveFromPort"(StringToRemove AS ASCIIZ) AS LONG  'Clear buffer chars
    
         DECLARE FUNCTION ReceiveData(BYVAL HwndTerminal AS DWORD) AS LONG
         DECLARE FUNCTION ReadFromPort ALIAS "ReadFromPort"() AS STRING  'Get reply from device
    
         DECLARE FUNCTION VerifyIfVxm() AS LONG
         DECLARE SUB CheckVxmConnected ALIAS "CheckVxmConnected"()
    
         GLOBAL ErrPort AS LONG
         GLOBAL Buffer           AS STRING       'ComPort Buffer
         GLOBAL CharsInBuffer    AS LONG         'Number of Chars at buffer
         GLOBAL OpeningPort AS LONG          'If opening the port dont show the reply from the verify
         GLOBAL DetectingVxm AS LONG         'If Detecting then continue till false. (Verify Status will make false if passed in as true)
         GLOBAL TracePort AS LONG
         GLOBAL TracePortLog AS STRING
         GLOBAL TracePortLogNum AS LONG
    
         GLOBAL hWndPort AS LONG
    '------------------------------------------------------------------------------
    '*** TroubleshootIo.h
         DECLARE SUB TroubleshootLimits()
         DECLARE SUB StopTroubleshootLimits()
         DECLARE SUB RunningLimitsView()
         DECLARE SUB StoppedLimitsView()
         GLOBAL IoView AS LONG
         GLOBAL LimitState AS STRING
         GLOBAL ChangeIoDisplay AS LONG
    '------------------------------------------------------------------------------
    '*** RTF.inc and RichEdit.inc should be their own Inc files due to size
    #INCLUDE "RichEdit.inc"
    #INCLUDE "Rtf.inc"
    '*** InitControls.inc and Mdi32.inc should be their own Inc files due to size
    #INCLUDE "Mdi32.inc"
    #INCLUDE "COMMCTRL.INC"
    #INCLUDE "InitControls.inc"
    '------------------------------------------------------------------------------
    
    '*** Load the resource file
    #RESOURCE "COSMOS.pbr"
    '------------------------------------------------------------------------------
    '*** If compiling as Exe
    FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
         ON ERROR GOTO ErrHandler
    '     TRACE NEW "MyExeTrace.txt"
    '     TRACE ON
         IsExe = %True
         hInst = hInstance 'store module handle in global variable for later use
         LoadCosmos
    '     TRACE OFF
    '     TRACE CLOSE
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION  ' end WinMain
    
    '*** If compiling as Dll
    FUNCTION LIBMAIN (BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) AS LONG
         ON ERROR GOTO ErrHandler
         SELECT CASE fwdReason
              CASE %DLL_PROCESS_ATTACH
                   FUNCTION = 1   'success!
                   'FUNCTION = 0   'failure!  This will prevent the EXE from running.
    '               TRACE NEW "MyDllTrace.txt"
    '               TRACE ON
                   IsExe = %False      'Flag for Exe
                   hInst = hInstance
                   LoadCosmos
              CASE %DLL_PROCESS_DETACH
                   UnloadCosmos
                   FUNCTION = 1   'success!
                   'FUNCTION = 0   'failure!
    '               TRACE OFF
    '               TRACE CLOSE
              CASE %DLL_THREAD_ATTACH
                   FUNCTION = 1   'success!
                   'FUNCTION = 0   'failure!
              CASE %DLL_THREAD_DETACH
                   FUNCTION = 1   'success!
                   'FUNCTION = 0   'failure!
         END SELECT
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    '------------------------------------------------------------------------------
    ' Main procedure
    '------------------------------------------------------------------------------
    FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
                      BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
         ON ERROR GOTO ErrHandler
         LOCAL tRect       AS RECT
         LOCAL cc          AS CLIENTCREATESTRUCT
         LOCAL rc AS RECT
         LOCAL zText AS ASCIIZ * %MAX_PATH
         SELECT CASE wMsg
              CASE %WM_INITDIALOG     'If initializing (opening the TerminalSimple)
              CASE %WM_CREATE
                   ParentClosing = %False
                   '------------------------------------------------------------------------
                   ' some of CommCtrl.dll's controls, messages and styles were not included
                   ' in standard Win95A release, so we need to see how to initiate the dll.
                   '------------------------------------------------------------------------
    '               NewComCtl = InitComctl32 (%ICC_BAR_CLASSES)
                   '------------------------------------------------------------------------
    ''*** Create the status bar window
                   hStatus = CreateStatusWindow(%WS_CHILD OR %WS_VISIBLE OR %SBS_SIZEGRIP, "", hWnd, %ID_STATUSBAR)
                   DIM prts(0 TO 11) AS LONG
                   GetClientRect hStatus, rc
    '*** Dimension the parts
                   prts(0) = rc.nRight * 0.05     : prts(1) = rc.nRight * 0.15     'Port:Portnum
                   prts(2) = rc.nRight * 0.16     : prts(3) = rc.nRight * 0.25     'Space:Baud
                   prts(4) = rc.nRight * 0.35     : prts(5) = rc.nRight * 0.36     'Baudratenum:Space
                   prts(6) = rc.nRight * 0.43     : prts(7) = rc.nRight * 0.78     'Status:PortStatus
                   prts(8) = rc.nRight * 0.79     : prts(9) = rc.nRight * 0.85     'Space:VXM
                   prts(10) = rc.nRight * 0.95     : prts(11) = rc.nRight * 1      'VXMStatus:Space
                   Sendmessage hStatus, %SB_SETPARTS, 12, VARPTR(prts(0))
    '*** Port
                   zText = " Port: " : SendMessage hStatus, %SB_SETTEXT, 0, VARPTR(zText)
                   zText = " Not Set" : SendMessage hStatus, %SB_SETTEXT, 1, VARPTR(zText)
    '*** BaudRate
                   zText = " Baudrate: " : SendMessage hStatus, %SB_SETTEXT, 3, VARPTR(zText)
                   zText = " Not Set" : SendMessage hStatus, %SB_SETTEXT, 4, VARPTR(zText)
    '*** Port Status
                   zText = " Status: " : SendMessage hStatus, %SB_SETTEXT, 6, VARPTR(zText)
                   zText = " Not Set" : SendMessage hStatus, %SB_SETTEXT, 7, VARPTR(zText)
    '*** Create MDI Client window
    '               cc.idFirstChild = 1
    '               cc.hWindowMenu  = hMenuWindow  'for file list in Window menu
                   hWndClient = CreateWindowEx(%WS_EX_CLIENTEDGE, "MDICLIENT", BYVAL %NULL, _
                                                 %WS_CHILD OR %WS_CLIPCHILDREN OR _
                                                 %WS_VISIBLE OR %WS_VSCROLL OR %WS_HSCROLL  , _
                                                 0, 0, 0, 0, hWnd, 1, hInst, cc)
                   EXIT FUNCTION
              CASE %WM_SIZE
                   IF wParam <> %SIZE_MINIMIZED THEN
    '*** Get Toolbar and statusbar height
                        GetWindowRect hStatus, tRect
                        StatHeight = tRect.nBottom - tRect.nTop  'statusbar height
                        GetWindowRect RchEdHistory, tRect
                        HistoryHeight = tRect.nBottom - tRect.nTop
    '*** Set Toolbar and statusbar height
                        SendMessage hStatus, wMsg, wParam, lParam
                        MoveWindow hWndClient, -2, 0, LOWRD(lParam)+ 5 , HIWRD(lParam) - (StatHeight + HistoryHeight) - 10, %TRUE
                        GetWindowRect hWndClient, tRect
                        HistoryWidth = tRect.nRight - tRect.nLeft '- 10
                        SetWindowPos RchEdHistory, 0, 0, HIWRD(lParam) - (StatHeight + HistoryHeight) - 10, HistoryWidth, HistoryHeight, %SWP_NOZORDER
                        InvalidateRect hStatus, BYVAL 0, %TRUE  'now redraw window
                        UpdateWindow hStatus       'Redraw the dialog
                   END IF
                   EXIT FUNCTION
    '*** Form Notifications
              CASE %WM_NOTIFY
                   EXIT FUNCTION
    '*** Menu Select
              CASE %WM_MENUSELECT
                   LoadString hInst, wParam, zText, SIZEOF(zText)
                   EXIT FUNCTION
    '*** Paint the form
              CASE %WM_NCPAINT 'if flag is set, return zero to avoid menu update
                   IF freezeMenu THEN EXIT FUNCTION
    '*** Determine which menu or command was clicked
              CASE %WM_COMMAND
                   SELECT CASE LOWRD(wParam)          'Equivelant to CBCTL in a callback function
    '****************************************** TROUBLESHOOTING ROUTINES ***************************************************
                        CASE %IDM_TRBLIMITSVIEWON
                             TroubleshootLimits
                   END SELECT
              CASE %WM_SYSCOLORCHANGE
    '*** Forward this message to common controls so that they will be properly updated if the user changes the color settings.
                   SendMessage hStatus,  %WM_SYSCOLORCHANGE, wParam, lParam
              CASE %WM_CLOSE
                   SELECT CASE IsExe
                        CASE %True
                             UnloadCosmos
                        CASE %False
                             SELECT CASE ParentClosing          '<--- Only End if the parent process is closing
                                  CASE %True
                                       UnloadCosmos
                                  CASE %False
                                       HideCosmos
                                       EXIT FUNCTION
                             END SELECT
                   END SELECT
              CASE %WM_DESTROY
                   SELECT CASE IsExe
                        CASE %True
                             PostQuitMessage 0                  '<--- Escape message pump if still running
                             EXIT FUNCTION
                        CASE %False
                   END SELECT
         END SELECT
         FUNCTION = DefFrameProc(hWnd, hWndClient, wMsg, wParam, lParam)
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION LoadCosmos ALIAS "LoadCosmos"()EXPORT AS LONG
         ON ERROR GOTO ErrHandler
    ''*** Window variables
         LOCAL hAccel       AS DWORD
         LOCAL Msg          AS TAGMSG
         LOCAL wce          AS WNDCLASSEX
         LOCAL szClassName  AS ASCIIZ * 80
    '*** Desktop variables
         LOCAL DeskTopX AS LONG
         LOCAL DeskTopY AS LONG
         LOCAL AppX AS LONG
         LOCAL AppY AS LONG
    '*** Register Main Window Class
    '     GetClassInfoEx(hInst, "#32770", wce)      'copy dialog class (modeless) into ports class
         szClassName       = "COSMOS"
         wce.cbSize        = SIZEOF(wce)
         wce.style         = %CS_HREDRAW OR %CS_VREDRAW
         wce.lpfnWndProc   = CODEPTR(WndProc)
         wce.cbClsExtra    = 0
         wce.cbWndExtra    = 0
         wce.hInstance     = hInst
         wce.hIcon         = LoadIcon(hInst, "APPICON")
         wce.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
         wce.hbrBackground = %NULL       'LoadImage(%Null, ".\COSMOS Intro.bmp" , %IMAGE_BITMAP, 0, 0,%LR_LOADFROMFILE)
         wce.lpszMenuName  = %NULL
         wce.lpszClassName = VARPTR(szClassName)
         wce.hIconSm       = LoadIcon(hInst, BYVAL %IDI_APPLICATION)
         IF RegisterClassEx(wce) = 0 THEN
              RegisterClass BYVAL (VARPTR(wce) + 4)
         END IF
    '*** Setup main menu
         hMenu       = LoadMenu(hInst, "MAINMENU")           'main menu        '<--- Involves Res File
    '*** Get Desktop properties
         DeskTopX = GetSystemMetrics(%SM_CXSCREEN)
         DeskTopY = GetSystemMetrics(%SM_CYSCREEN)
         SELECT CASE DesktopX
              CASE < 800
                   AppX = 640
              CASE 800 TO 1024
                   AppX = 800
              CASE > 1024
                   AppX = 1024
         END SELECT
         SELECT CASE DesktopY
              CASE < 600
                   AppY = 480
              CASE 600 TO 768
                   AppY = 600
              CASE > 768
                   AppY = 768
         END SELECT
    
    '*** Create main window using the registered class
         LOCAL CurrentVersion AS STRING
         CurrentVersion = "3.1.1"
         hWndMain = CreateWindow("COSMOS", _              ' window class name
                                  "COSMOS (version " + CurrentVersion + ")", _              ' window caption
                                  %WS_OVERLAPPEDWINDOW, _   ' window style
                                  (DeskTopX - AppX) / 2, _  ' initial x position
                                  (DeskTopY - AppY) / 2, _  ' initial y position
                                  AppX, _                    ' initial x size
                                  AppY, _                    ' initial y size
                                  %NULL, _                  ' parent window handle
                                  hMenu, _                  ' window menu handle
                                  hInst, _              ' program instance handle
                                  BYVAL %NULL)              ' creation parameters
         LoadHistory HwndMain
    '*** Load Dialogs
    '            ShowIoStateWindow                         '<--- Breaks the rules list only for keeping track of whats loaded
    OpenPort 1, 9600
         OpenListenThread
         ShowCosmos
    '*** Message handler loop
         SELECT CASE IsExe
              CASE %False
              CASE %True
                   WHILE GetMessage(Msg, BYVAL %NULL, 0, 0)
                        IF TranslateMDISysAccel(hWndClient, Msg) = 0 THEN
                             IF TranslateAccelerator(hWndMain, hAccel, Msg) = 0 THEN
                                  TranslateMessage Msg
                                  DispatchMessage Msg
                             END IF
                        END IF
                   WEND
         END SELECT
         FUNCTION = msg.wParam
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    FUNCTION UnloadCosmos ALIAS "UnloadCosmos"()EXPORT AS LONG
         LOCAL lResult AS LONG
         LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
         ClosePort
         ParentClosing = %True
    '     SendMessage(GetDlgCtrlId(%Btn_Stop), %BM_CLICK, 0, 0)
    '     DIALOG END HwndDlgIoState
    '     HideIoStateWindow
    '     DestroyWindow HwndDlgIoState
    '     SendMessage hWndClient, %WM_CLOSE, HwndDlgAbout&, 0
    '     SendMessage(HwndDlgIoState, %WM_SYSCOMMAND, %SC_CLOSE, 0)
         SendMessage(GetDlgItem(HwndDlgIoState, %Btn_Stop), %BM_CLICK, 0, 0)
    '     lResult = GetLastError()           'Check for the error
    '     FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL  'Format the message
    'MSGBOX ErrorBuff + $CR + STR$(GetDlgItem(HwndDlgIoState, %Btn_Stop)) + $CR + STR$(GetDlgCtrlId(%Btn_Stop))
    
         IF HwndThread THEN CloseListenThread
         DestroyMenu hMenu
         DestroyWindow HwndClient
         DestroyWindow RchEdHistory
         DestroyWindow HwndMain
    '     DestroyWindow GetWindow(HwndMain, %GW_HWNDFIRST)
    '     lResult = GetLastError()           'Check for the error
    '     FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL  'Format the message
    'MSGBOX ErrorBuff + str$(HwndMain)
              IF hLibHistory THEN FreeLibrary hLibHistory
    '     lResult = GetLastError()           'Check for the error
    '     FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL  'Format the message
    'MSGBOX ErrorBuff
    ''MSGBOX "Thread Count = " + STR$(THREADCOUNT) + $CR + "Thread Id = " + STR$(THREADID) + $CR + "MDI Thread = " + STR$(MdiThread)
    END FUNCTION
    
    FUNCTION GetWindowState ALIAS "GetWindowState"(WindowToCheck AS LONG) AS LONG
         SELECT CASE IsWindowVisible(WindowToCheck)
              CASE 0         'Not Visible = 0
                   FUNCTION = %SW_HIDE
              CASE ELSE      'Visible
                   SELECT CASE IsZoomed(WindowToCheck)
                       CASE 0         'Not Maximized
                             SELECT CASE IsIconic(WindowToCheck)
                                  CASE 0    'Not Minimized (Normal) = 1
                                       FUNCTION = %SW_SHOWNORMAL
                                  CASE ELSE      'Minimized = 6
                                       FUNCTION = %SW_MINIMIZE
                             END SELECT
                        CASE ELSE      'Maximized = 3
                             FUNCTION = %SW_MAXIMIZE
                   END SELECT
         END SELECT
    END FUNCTION
    
    FUNCTION ShowCosmos ALIAS "ShowCosmos"()EXPORT AS LONG
         SELECT CASE IsWindow(HwndMain)
              CASE 0         'If COSMOS not loaded then load it
                   LoadCosmos
              CASE ELSE
         END SELECT
         SELECT CASE GetWindowState(HwndMain)
              CASE %SW_SHOWNORMAL
              CASE ELSE
                   ShowWindow HwndMain, %SW_SHOWNORMAL
                   SLEEP 100         'Need this for some reason so window will stay in forground
                   UpdateWindow HwndMain
                   DefaultHistory
         END SELECT
         FUNCTION = %True
    END FUNCTION
    
    FUNCTION HideCosmos ALIAS "HideCosmos"()EXPORT AS LONG
         SELECT CASE IsWindow(HwndMain)
              CASE 0    'Cosmos does not exist
              CASE ELSE 'Cosmos exists
                   SELECT CASE GetWindowState(HwndMain)
                        CASE %SW_HIDE
                        CASE ELSE
                             ShowWindow HwndMain, %SW_HIDE
                   END SELECT
         END SELECT
         FUNCTION = %False
    END FUNCTION
    
    FUNCTION IsCosmosVisible ALIAS "IsCosmosVisible"() EXPORT AS LONG
         SELECT CASE IsWindow(HwndMain)
              CASE 0
                   FUNCTION = %False
              CASE ELSE
                   FUNCTION = GetWindowState(HwndMain)
         END SELECT
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------------------------------------
    '*** ErrorHandling.inc
    FUNCTION StartTrace ALIAS "StartTrace"() AS LONG
         TRACE NEW "Error Testing Trace"
         TRACE ON
         TraceLogNum = FREEFILE
         TraceLog = "COSMOS Serial Driver Trace " + DATE$ + ".txt"
         REPLACE ":" WITH "-" IN TraceLog
         OPEN TraceLog FOR APPEND AS #TraceLogNum
         NumOfErrorsCosmos = 0
    END FUNCTION
    
    FUNCTION EndTrace ALIAS "EndTrace"() AS LONG
         TRACE ON
         TRACE CLOSE
         CLOSE TraceLogNum
         SLEEP 100           'Just to slow things down
         SELECT CASE NumOfErrorsCosmos
              CASE > 0        'Errors occured
              CASE ELSE       'No errors so kill the log
                   KILL TraceLog
         END SELECT
    END FUNCTION
    
    FUNCTION ErrorCheck ALIAS "ErrorCheck"(ErrorCode AS LONG) AS LONG
         LOCAL i AS LONG
         LOCAL CallStack AS STRING
         TRACE ON
         SELECT CASE ErrorCode
              CASE 0
              CASE 1 TO 150, 241 TO 255       'PowerBasic Runtime Errors
                   NumOfErrorsCosmos = NumOfErrorsCosmos + 1
                   FOR i = CALLSTKCOUNT TO 1 STEP -1
                        CallStack = CallStack + CALLSTK$(i) + $CRLF
                   NEXT i
                   PRINT #TraceLogNum, "Thread ID = " + STR$(THREADID)
                   PRINT #TraceLogNum, "Error Number = " + STR$(ErrorCode) + " Error Description = " + ERROR$(ErrorCode)
                   PRINT #TraceLogNum, "Call Stack at Error = " + CallStack
                   PRINT #TraceLogNum, "Errors in Session = " + STR$(NumOfErrorsCosmos) + $CRLF + $CRLF + $CRLF
                   ERRCLEAR
         END SELECT
         TRACE OFF
         FUNCTION = %True
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------------------------------------
    '*** Threading.inc
    FUNCTION OpenListenThread ALIAS "OpenListenThread"() AS LONG       'Added to re-enable the listen thread
         ON ERROR GOTO ErrHandler
         CloseThread = %False
         ERRCLEAR
         IF HwndThread = 0 THEN THREAD CREATE ReceiveData(1) TO HwndThread  'Create a "listen" thread to monitor input from device
         FUNCTION = %True
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    FUNCTION CloseListenThread ALIAS "CloseListenThread"() AS LONG
         CloseThread = %True
         IF HwndThread THEN THREAD CLOSE HwndThread TO ThreadDone
         WaitForSingleObject HwndThread, %INFINITE
         IF HwndThread THEN HwndThread = 0
         FUNCTION = ThreadDone
         EXIT FUNCTION
    END FUNCTION
    '-------------------------------------------------------------------------------------------------------------------------
    '*** DlgIoState.inc
    CALLBACK FUNCTION IoStateCallback()
        LOCAL BtnState AS LONG
        LOCAL StatusFlag AS LONG
        LOCAL StatusText AS STRING
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_MDIACTIVATE
                 SELECT CASE CBWPARAM                 'Deactivated window
                      CASE HwndDlgIoState
                             LstHistoryClearHistory
                 END SELECT
                 SELECT CASE CBLPARAM                 'Activated window
                      CASE HwndDlgIoState
                             LstHistoryClearHistory
                 END SELECT
                 CONTROL SEND HwndMain, %RchEdHistory, %EM_SETSEL, 1, 1
                 FUNCTION = %False          '%WM_MDIACTIVATE needs 0 (or %False) returned to indicate the message was processed
            CASE %WM_INITDIALOG       'initialise stuff before dialog is drawn
                StatusFlag = %True '%False      'e.g.
                LimitState = ""     'Just to get the status screen to refresh
    
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
                    CASE %Btn_Stop
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                             SELECT CASE UCASE$(IoTest)
                                CASE "TROUBLESHOOTLIMITS"
                                    StopTroubleshootLimits
                            END SELECT
                            EnableMenuItem hMenu, %IDM_TRBLIMITSVIEWON, %MF_ENABLED
                        END IF
                END SELECT
            CASE %WM_SYSCOMMAND
                IF (CBWPARAM AND &HFFF0) = %SC_CLOSE THEN   'Must get the CBWPARAM first or this query-unload equiv will not work
                    SELECT CASE ParentClosing
                        CASE %False
                            FUNCTION = %True        'Blocks the close by not allowing the next call to destroy
                             DefaultHistory
                     SELECT CASE UCASE$(IoTest)
                        CASE "TROUBLESHOOTLIMITS"
                            StopTroubleshootLimits
                    END SELECT
                    EnableMenuItem hMenu, %IDM_TRBLIMITSVIEWON, %MF_ENABLED
                        CASE %True
                            FUNCTION = %False        'Allows the close on the next call with the destroy
                    END SELECT
                END IF
            CASE %WM_CLOSE
            CASE %WM_DESTROY
        END SELECT
    '     FUNCTION = DefMDIChildProc(CBHNDL, CBMSG, CBWPARAM, CBLPARAM)           'Need this if Window is to show
    '     FUNCTION = DefFrameProc(HwndClient, CBHNDL, CBMSG, CBWPARAM, CBLPARAM)           'Need this if Window is to show
    END FUNCTION
    
    SUB ShowIoStateWindow(TestToRun AS STRING)
        IsDlgIoOpen = %True
        IoTest = TestToRun
        DIM x&, y&
        DIALOG GET LOC HwndMain TO x&, y&
        LOCAL Style&, ExStyle&
        Style& = %WS_CHILD OR %WS_CAPTION OR %WS_SYSMENU OR %WS_CLIPSIBLINGS  'OR %WS_SYSMENU  %WS_CAPTION OR %WS_SYSMENU OR %DS_CENTER
        ExStyle& = 0
        DIALOG NEW HwndClient, "Limits Viewer", x& - 115, y&, 115, 25, Style&, ExStyle&  TO HwndDlgIoState
        CONTROL ADD BUTTON, HwndDlgIoState, %Btn_Stop, "Exit", 30, 5, 50, 15, %WS_CHILD OR _
                              %WS_VISIBLE OR %WS_TABSTOP OR %BS_AUTOCHECKBOX OR %BS_PUSHLIKE
        DIALOG SHOW MODELESS HwndDlgIoState, CALL IoStateCallback
    END SUB
    
    SUB HideIoStateWindow()
        ON ERROR GOTO ErrHandler
        ERRCLEAR
        LOCAL Result AS LONG
        SELECT CASE IsWindow(HwndDlgIoState  )
            CASE 0
            CASE ELSE
                DIALOG SHOW STATE HwndDlgIoState, %SW_HIDE TO Result  'Hide the TerminalSimple
        END SELECT
        EXIT SUB
    ErrHandler:
        StartTrace
        ErrorCheck ERR
        EndTrace
    END SUB
    '-------------------------------------------------------------------------------------------------------------------------
    '*** History.inc
    CALLBACK FUNCTION HistoryChildrenCallback() AS LONG
         ON ERROR GOTO ErrHandler
         LOCAL tRect       AS RECT
         LOCAL ActiveWindow AS LONG
         LOCAL MainHeight AS LONG
         LOCAL MainWidth AS LONG
         SELECT CASE CBMSG
              CASE %WM_SETFOCUS
                   ActiveWindow = SendMessage(HwndClient, %WM_MDIGETACTIVE, BYVAL %NULL, BYVAL %NULL)
                   CALL HideCaret (CBCTL)
                   FUNCTION = 0 : EXIT FUNCTION
              CASE %WM_KILLFOCUS
              CASE %WM_MOVE, %WM_SIZE, %WM_CLOSE, %WM_QUERYENDSESSION
                   GetWindowRect HwndMain, tRect
                   MainHeight = tRect.nBottom - tRect.nTop
                   MainWidth = tRect.nRight - tRect.nLeft
                   GetWindowRect hStatus, tRect
                   StatHeight = tRect.nBottom - tRect.nTop  'statusbar height
                   SendMessage HwndMain, %WM_SIZE, %SIZE_RESTORED, MAK(DWORD, MainWidth - 10 , MainHeight - StatHeight - 20)
                   InvalidateRect hStatus, BYVAL %NULL, %True
                   UpdateWindow hStatus
              CASE %WM_SIZING
         END SELECT
         FUNCTION = CallWindowProc(OldDlgHistoryTxtProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM) 'Pass back to original
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    CALLBACK FUNCTION HistoryCallBack () AS LONG
        ON ERROR GOTO ErrHandler
        SELECT CASE CBMSG           'Determine what the event is
            CASE %WM_INITDIALOG     'If initializing (opening the History)
                FUNCTION = %FALSE   ' Return 0 to stop the dialog box engine setting focus
            CASE %WM_MDIACTIVATE
                 FUNCTION = %False          '%WM_MDIACTIVATE needs 0 (or %False) returned to indicate the message was processed
            CASE %WM_KEYDOWN        'In this case re-set focus because of loss of focus
            CASE %WM_MOUSEACTIVATE
            CASE %WM_DROPFILES
                FUNCTION = %True
            CASE %WM_MOVE
            CASE %WM_SETREDRAW
            CASE  %WM_MOUSEWHEEL
            CASE %WM_COMMAND
            CASE %WM_SIZE
                FUNCTION = %True
            CASE %WM_SYSCOMMAND
                IF (CBWPARAM AND &HFFF0) = %SC_CLOSE THEN   'Must get the CBWPARAM first or this query-unload equiv will not work
                   SELECT CASE ParentClosing
                        CASE %False
                            FUNCTION = %True        'Blocks the close by not allowing the next call to destroy
                        CASE %True
                            FUNCTION = %False        'Allows the close on the next call with the destroy
                    END SELECT
                END IF
            CASE %WM_DESTROY
            CASE ELSE
         END SELECT
    '     FUNCTION = DefMDIChildProc(CBHNDL, CBMSG, CBWPARAM, CBLPARAM)           'Need this if Window is to show
         FUNCTION = DefFrameProc(CBHNDL, HwndClient, CBMSG, CBWPARAM, CBLPARAM)
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    FUNCTION LoadHistory(BYVAL hParent&) AS LONG     'Load main program
         ON ERROR GOTO ErrHandler
         hLibHistory = LoadLibrary("RICHED32.DLL")      'Load the Richedit Dll
         RchEdHistory = CreateWindowEx(%NULL, _                                             ' extended styles
                        $RICHEDIT_CLASS, _                                        ' class name
                        "", _                                              ' caption
                        %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_VSCROLL OR %WS_HSCROLL OR %WS_EX_MDICHILD  OR %WS_EX_CLIENTEDGE     _         ' window styles
                        OR %WS_SIZEBOX OR %ES_DISABLENOSCROLL _    'To allow resizing the History window
                        OR %ES_MULTILINE OR %ES_AUTOVSCROLL OR %ES_AUTOHSCROLL _   ' class styles
                        OR %ES_WANTRETURN OR %ES_NOHIDESEL  OR %ES_LEFT OR %ES_READONLY, _      ' OR %EM_SETREADONLY' class styles
                        0, 0, _                                           ' left, top
                        680, 180, _                                            ' width, height
                        hParent&, %RchEdHistory, _                                       ' handle of parent, control ID
                        hInst, BYVAL %NULL)                             ' handle of instance, creation parameters
    '*** Subclass the RichEditBox
         CONTROL HANDLE HwndMain, %RchEdHistory TO hHistory
         OldDlgHistoryTxtProc = SetWindowLong(hHistory, %GWL_WNDPROC, CODEPTR(HistoryChildrenCallback )) 'Subclass Edit control
         CONTROL SEND HwndMain, %RchEdHistory, %EM_SETBKGNDCOLOR, 0, RGB(255,254,209)    'Post-it Note Color
         FUNCTION=%True
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    SUB LstHistoryAddLine(FontType AS STRING, FontColor AS STRING, TextToAdd AS STRING, AppendCr AS LONG)
         ON ERROR GOTO ErrHandler
         LOCAL LineCount AS LONG
         LOCAL i AS LONG
         LOCAL TempRtfText AS STRING
         LOCAL RemoveRtfText AS STRING
         LOCAL TempText AS STRING
         LOCAL eStream AS EDITSTREAM
         LOCAL ret AS LONG
         SELECT CASE FontColor
              CASE "Red"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontRed + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontRed + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontRed + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Yellow"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontYellow + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontYellow + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontYellow + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Auqua", "Aqua"    'In the case of typo's in code
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontAqua + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontAqua + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontAqua + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Blue"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlue + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlue + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlue + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Green"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontGreen + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontGreen + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontGreen + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Black"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlack + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlack + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontBlack + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "White"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontWhite + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontWhite + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontWhite + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Teal"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontTeal + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontTeal + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontTeal + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Lime"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontLime + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontLime + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontLime + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Fuchsia"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontFuchsia + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontFuchsia + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontFuchsia + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Olive"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontOlive + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontOlive + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontOlive + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
              CASE "Maroon"
                   SELECT CASE AppendCr
                        CASE %False
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontMaroon + TextToAdd
                        CASE %True
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontMaroon + RtfCommandsEndOfLine + TextToAdd
                        CASE 2
                             REPLACE $CR WITH $CR + RtfCommandsEndOfLine IN TextToAdd
                             HistoryRtfText = HistoryRtfText + RtfFontMaroon + TextToAdd + RtfCommandsEndOfLine
                   END SELECT
         END SELECT
    '*** KEEP THE WINDOW FROM GETTING TOO BIG
         SELECT CASE LEN(HistoryRtfText)
              CASE > = 20000
                   TempRtfText = HistoryRtfText
                   DO WHILE INSTR(TempRtfText, RtfCommandsEndOfLine)
                        LineCount = LineCount + 1
                        TempRtfText = MID$(TempRtfText, INSTR(TempRtfText, RtfCommandsEndOfLine) + LEN(RtfCommandsEndOfLine))
                        IF ParentClosing = %True THEN EXIT DO
                   LOOP
    'Loop through to determine how much to remove then remove it
                   RemoveRtfText = ""
                   TempRtfText = HistoryRtfText
                   FOR i = 1 TO ROUND(((LineCount * .1) + .5), 0)  'Round to the truly closets whole number
                        RemoveRtfText = RemoveRtfText + MID$(TempRtfText, 1, INSTR(TempRtfText, RtfCommandsEndOfLine) + LEN(RtfCommandsEndOfLine))
                        TempRtfText = MID$(TempRtfText, INSTR(TempRtfText, RtfCommandsEndOfLine) + LEN(RtfCommandsEndOfLine))
                   NEXT i
                   HistoryRtfText = MID$(HistoryRtfText, LEN(RemoveRtfText))
                   SLEEP 1         'JUST TO GIVE THE PROCESSOR A BREAK
              CASE ELSE
         END SELECT
         eStream.pfnCallback = CODEPTR(RichEditStreamInString) 'pointer to RichEdit callback procedure
         gPos = 1
         gTxt = RtfCommandsStart + RtfFontCourier + RtfFontSize(12) + HistoryRtfText + RtfCommandsEnd
         gPtr = STRPTR(gTxt)
         IF IsWindow(RchEdHistory) THEN ret = SendMessage(RchEdHistory, %EM_STREAMIN, %SF_RTF, VARPTR(eStream)) 'stream in text
         InvalidateRect HwndMain, BYVAL %NULL, %True
         UpdateWindow HwndMain
         CONTROL GET TEXT HwndMain, %RchEdHistory TO TempText
         CONTROL SEND HwndMain, %RchEdHistory, %EM_SETSEL,LEN(TempText), LEN(TempText)
         SELECT CASE TracePort
              CASE %False
              CASE %True
                   PRINT #TracePortLogNum, TempText
         END SELECT
         EXIT SUB
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END SUB
    
    SUB LstHistoryRestoreHistory()
         LOCAL TempText AS STRING
         LOCAL eStream AS EDITSTREAM
         eStream.pfnCallback = CODEPTR(RichEditStreamInString) 'pointer to RichEdit callback procedure
         gPos = 1
         gTxt = RtfCommandsStart + RtfFontCourier + RtfFontSize(12) + HistoryRtfText + RtfCommandsEnd
         gPtr = STRPTR(gTxt)
         SendMessage RchEdHistory, %EM_STREAMIN, %SF_RTF, VARPTR(eStream) 'stream in text
         CONTROL GET TEXT HwndMain, %RchEdHistory TO TempText
         CONTROL SEND HwndMain, %RchEdHistory, %EM_SETSEL,LEN(TempText), LEN(TempText)
    END SUB
    
    SUB LstHistoryClearHistory()
         HistoryRtfText = ""
         CONTROL SET TEXT HwndMain, %RchEdHistory, ""
         InvalidateRect HwndMain, BYVAL %NULL, %True
         UpdateWindow HwndMain
    END SUB
    
    SUB DefaultHistory()
         LOCAL LongStr AS LONG
         LstHistoryClearHistory
         LstHistoryAddLine "fontc12", "Blue", "COSMOS", %False
         LstHistoryAddLine "fontc12", "Maroon", $TAB + "Select a Tool or File to edit from menu above", %True
    
         LstHistoryAddLine "fontc12", "Blue", "", %True
         LstHistoryAddLine "fontc12", "Blue", "Tools Available", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + "File" + $TAB + "---> Create, Edit, Send and Recieve program scripts to, and from the VXM", %True
    
         LongStr = LEN("|- Troubleshooting")
         LstHistoryAddLine "fontc12", "Blue", "", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + "Tools -", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Tools -")) + "|- QuickMoves" + SPACE$(LongStr - LEN("|- QuickMoves")) + " ---> Virtual Jog, Quick Move motor (absolute or relative position), TeachMode", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Tools -")) + "|- Code Creator" + SPACE$(LongStr - LEN("|- Code Creator")) + " ---> Create program scripts without needing to know VXM commands", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Tools -")) + "|- Terminal" + SPACE$(LongStr - LEN("|- Terminal")) + " ---> Communicate directly with VXM via Terminal", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Tools -")) + "|- Tutorials" + SPACE$(LongStr - LEN("|- Tutorials")) + " ---> Tutorials on VXM commands, and common uses", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Tools -")) + "|- Troubleshooting" + " ---> Got a problem? Troubleshooting tools should solve the problem", %True
    
         LongStr = LEN("|- Program Selector Switch (Thumbwheel)")
         LstHistoryAddLine "fontc12", "Blue", "", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + "Setup -", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Wizard" + SPACE$(LongStr - LEN("|- Wizard")) + " ---> Walks you through the complete setup necessary to start using the VXM", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Port" + SPACE$(LongStr - LEN("|- Port")) + " ---> Setup communication directly, or auto-detect what port your VXM is connected to", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Axis" + SPACE$(LongStr - LEN("|- Axis")) + " ---> Setup each axis so the motors move properly", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Joystick and Jog" + SPACE$(LongStr - LEN("|- Joystick and Jog")) + " ---> Set VXM to allow Joystick and Jog control", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Program Selector Switch (Thumbwheel)"  + " ---> Set VXM to allow 'stand-alone' program selection", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Multi-Function User Inputs" + SPACE$(LongStr - LEN("|- Multi-Function User Inputs")) + " ---> Set VXM to allow various options depending on input", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Setup -")) + "|- Controller Mode" + SPACE$(LongStr - LEN("|- Controller Mode")) + " ---> Set VXM mode, invert motor direction, home motor 1st time run after power-up", %True
    
         LstHistoryAddLine "fontc12", "Blue", "", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + "Help -", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Help -")) + "|- Documentation " + $TAB + "---> VXM Users Manual, QuickStarts, Application Notes", %True
         LstHistoryAddLine "fontc12", "Maroon", $TAB + SPACE$(LEN("Help -")) + "|- Online Support" + $TAB + "---> Various websites with information not covered here", %True
         CONTROL SEND HwndMain, %RchEdHistory, %EM_SETSEL, 1, 1
    END SUB
    '-------------------------------------------------------------------------------------------------------------------------
    
    
    '***************************************************************************
    '*** RTF.inc and RichEdit.inc should be their own *.inc files due to size
    '***************************************************************************
    
    
    '-------------------------------------------------------------------------------------------------------------------------
    '*** WaitForChar.inc
    FUNCTION WaitForChar ALIAS "WaitForChar"(CharToWaitFor AS ASCIIZ * %MAX_PATH, OPTIONAL BYVAL TimeOutTime AS LONG) EXPORT AS LONG
         ON ERROR GOTO ErrHandler
         LOCAL SendText AS STRING
         LOCAL HoldBuffer AS STRING
         LOCAL TempBuffer AS STRING
         LOCAL RemoveChar AS ASCIIZ * %MAX_PATH
         LOCAL TempSearchString AS ASCIIZ * %MAX_PATH
         LOCAL CharWaitingFor AS ASCIIZ * %MAX_PATH
         LOCAL StartTime AS CURRENCY
         IF TimeOutTime <> 0 THEN StartTime = TIMER
         CharWaitingFor = CharToWaitFor
         WaitingForChar = %True
         DO
              TempSearchString = ReadFromPort
              SLEEP 10
              TempSearchString = STRREVERSE$(TempSearchString)
              SELECT CASE TimeOutTime
                   CASE 0
    '*** Add routine to stop user lockout if waiting forever and control not on or will never return
                        ReadFromPort
                        HoldBuffer = Buffer
                        SendText = "V"
                        SendToPort SendText
                        SLEEP 10
                        ReadFromPort
                        TempBuffer = Buffer
                        REPLACE HoldBuffer WITH "" IN TempBuffer
                        RemoveChar = TempBuffer      'Change to Asciiz to remove from port
                        SELECT CASE TempBuffer       'If no response then exit the wait
                             CASE ""                     'Just in case try one more time
                                  ReadFromPort
                                  HoldBuffer = Buffer
                                  SendText = "V"
                                  SendToPort SendText
                                  SLEEP 10
                                  ReadFromPort
                                  TempBuffer = Buffer
                                  REPLACE HoldBuffer WITH "" IN TempBuffer
                                  RemoveChar = TempBuffer      'Change to Asciiz to remove from port
                                  SELECT CASE TempBuffer       'If no response then exit the wait
                                       CASE ""                     'Still nothing so break out
                                            FUNCTION = %True               'Changed to true just to shut labview up
                                            WaitingForChar = %False
                                            EXIT DO
                                       CASE ELSE
                                  END SELECT
                             CASE ELSE
                        END SELECT
    '*** Put error checks 1st then check for replies that normally dont appear
                        SELECT CASE INSTR(TempBuffer, "Ë")
                             CASE 0
                             CASE ELSE
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
    
                        SELECT CASE INSTR(TempBuffer, "b")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
                        SELECT CASE INSTR(TempBuffer, "R")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
                        SELECT CASE INSTR(TempBuffer, "J")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
                   CASE ELSE
                        SELECT CASE TIMER
                             CASE < StartTime + (TimeOutTime/1000)
                             CASE >= StartTime + (TimeoutTime/1000) + (1/1000)        'Added extra ms so msg below not shown unless char not found
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
              END SELECT
              IF ParentClosing = %True THEN TempSearchString = TempSearchString + CharToWaitFor
              IF ParentClosing = %True THEN EXIT DO
         LOOP UNTIL INSTR(TempSearchString, CharToWaitFor) 'Dont use "OR EscapeFunction = %True" cause a Binary OR is used
         SELECT CASE INSTR(TempSearchString,CharToWaitFor)
              CASE 0
                   FUNCTION = %False
              CASE ELSE
                   RemoveFromPort(CharToWaitFor)
                   FUNCTION = %True
         END SELECT
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    
    FUNCTION WaitForCharWithMotorPosition ALIAS "WaitForCharWithMotorPosition"(CharToWaitFor AS ASCIIZ * %MAX_PATH, BYVAL MotorNumber AS LONG, OPTIONAL BYVAL ReportToWindowHwnd AS LONG, OPTIONAL BYVAL TimeOutTime AS LONG) EXPORT AS LONG
         ON ERROR GOTO ErrHandler
         LOCAL SendText AS STRING
         LOCAL HoldBuffer AS STRING
         LOCAL TempBuffer AS STRING
         LOCAL RemoveChar AS ASCIIZ * %MAX_PATH
         LOCAL TempSearchString AS ASCIIZ * %MAX_PATH
         LOCAL CharWaitingFor AS ASCIIZ * %MAX_PATH
         LOCAL MotorPosition AS STRING
         LOCAL HandleMotorPosition AS LONG
         LOCAL StartTime AS CURRENCY
         HandleMotorPosition = ReportToWindowHwnd
    '     Buffer = ""
         IF TimeOutTime <> 0 THEN StartTime = TIMER
         CharWaitingFor=CharToWaitFor
         DO
              TempSearchString = ReadFromPort
              SLEEP 100
              TempSearchString = STRREVERSE$(TempSearchString)
              SELECT CASE TimeOutTime
                   CASE 0
                        ReadFromPort
                        HoldBuffer = Buffer
                        SendText = "V"
                        SendToPort SendText
                        SLEEP 100
                        ReadFromPort
                        TempBuffer = Buffer
                        REPLACE HoldBuffer WITH "" IN TempBuffer
                        RemoveChar = TempBuffer      'Change to Asciiz to remove from port
                        SELECT CASE TempBuffer       'If no response then exit the wait
                             CASE ""                     'Just in case try one more time
                                  ReadFromPort
                                  HoldBuffer = Buffer
                                  SendText = "V"
                                  SendToPort SendText
                                  SLEEP 100
                                  ReadFromPort
                                  TempBuffer = Buffer
                                  REPLACE HoldBuffer WITH "" IN TempBuffer
                                  RemoveChar = TempBuffer      'Change to Asciiz to remove from port
                                  SELECT CASE TempBuffer       'If no response then exit the wait
                                       CASE ""                     'Still nothing so break out
                                            FUNCTION = %True               'Changed to true just to shut labview up
                                            WaitingForChar = %False
                                            EXIT FUNCTION
                                       CASE ELSE
                                  END SELECT
                             CASE ELSE
                        END SELECT
    '*** Put error checks 1st then check for replies that normally dont appear
                        SELECT CASE INSTR(TempBuffer, "Ë")
                             CASE 0
                             CASE ELSE
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT FUNCTION
                        END SELECT
                        SELECT CASE INSTR(TempBuffer, "b")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT FUNCTION
                        END SELECT
                        SELECT CASE INSTR(TempBuffer, "R")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT FUNCTION
                        END SELECT
                        SELECT CASE INSTR(TempBuffer, "J")
                             CASE 0
                             CASE ELSE
                                  RemoveFromPort RemoveChar
                                  FUNCTION = %True               'Changed to true just to shut labview up
                                  WaitingForChar = %False
                                  EXIT FUNCTION
                        END SELECT
                   CASE ELSE
                        SELECT CASE TIMER
                             CASE < StartTime + (TimeOutTime/1000)
                             CASE >= StartTime + (TimeoutTime/1000) + (1/1000)        'Added extra ms so msg below not shown unless char not found
                                  WaitingForChar = %False
                                  EXIT DO
                        END SELECT
              END SELECT
              Buffer = ""
              SELECT CASE MotorNumber
                   CASE 3 TO 4           'Cant get motor 3 or 4 positions while VXM is busy
                   CASE 1 TO 2
    '                    MotorPosition = GetMotorPosition(MotorNumber)
                      MotorPosition = "+00000000"                      '<--- Purposely faked for demo
                        IF HandleMotorPosition THEN SendMessage HandleMotorPosition, %WM_SETTEXT, 0, BYVAL STRPTR(MotorPosition)  'Send position back to parent caller
              END SELECT
              IF ParentClosing = %True THEN TempSearchString = TempSearchString + CharToWaitFor
              IF ParentClosing = %True THEN EXIT DO
         LOOP UNTIL INSTR(TempSearchString, CharToWaitFor) 'Dont use "OR EscapeFunction = %True" cause a Binary OR is used
         SELECT CASE INSTR(TempSearchString,CharToWaitFor)
              CASE 0
                   FUNCTION = %False
              CASE ELSE
                   RemoveFromPort(CharToWaitFor)
                   FUNCTION = %True
         END SELECT
         EXIT FUNCTION
    ErrHandler:
         StartTrace
         ErrorCheck ERR
         EndTrace
    END FUNCTION
    '-------------------------------------------------------------------------------------------------------------------------
    '*** PortFunctions.inc
    FUNCTION OpenPort ALIAS "OpenPort"(BYVAL ComPortNumber AS LONG, BYVAL ComPortBaudRate AS LONG) EXPORT AS LONG  'Configure and open serial port
         LOCAL ComPort AS STRING
         LOCAL BaudRate AS STRING
         LOCAL Dummy AS STRING
         ComPort = "\\.\COM1"                                                    '<--- Purposely set for debug demo
    '     BaudRate = STR$(ComPortBaudRate)          'For Display Purposes
          BaudRate = "9600"                                                    '<--- Purposely set for debug demo
         HwndPort = FREEFILE               'Handle to the file (aka ComPort)
         COMM OPEN ComPort AS HwndPort  'Open the port
         ErrPort = ERR
         SELECT CASE HwndPort          'If Error then
              CASE 0
                 FUNCTION = %False        'Return false to function call
                   ClosePort
                   EXIT FUNCTION             'Exit if port cannot be opened
              CASE ELSE
          END SELECT
         SELECT CASE FILEATTR(HwndPort, 0)   'Check if the port is truly Open
              CASE 0
                   FUNCTION = %False        'Return false to function call
                   ClosePort
                   EXIT FUNCTION
              CASE ELSE
         END SELECT
         COMM SET HwndPort, BAUD      = ComPortBaudRate  'Set the BaudRate
         COMM SET HwndPort, BYTE      = 8                    ' 8 bits
         COMM SET HwndPort, PARITY   = %False             ' No parity
         COMM SET HwndPort, STOP      = 0                    ' 1 stop bit
         COMM SET HwndPort, TXBUFFER = 2048               ' 4096                ' 4k transmit buffer
         COMM SET HwndPort, RXBUFFER = 2048               ' 4096                ' 4k receive buffer
         COMM SET HwndPort, NULL      = %False               'Do not toss the null valued bytes due to the $ for reading the Output States
         COMM PRINT HwndPort, $NUL       'Issue a CR/LF and flush the receive buffer
         SLEEP 1
         IF FILEATTR(HwndPort, 0) THEN COMM RECV HwndPort, COMM(HwndPort, RXQUE), dummy   'If anything is on the port, then remove it and put it in dummy variable
         FUNCTION = %TRUE          'If it made it this far then return True to function call
         DIALOG DOEVENTS
         OpeningPort = %False
    END FUNCTION
    
    FUNCTION IsPortOpen ALIAS "IsPortOpen"() EXPORT AS LONG
         SELECT CASE FILEATTR(HwndPort, 0)   'Check if the port is truly Open
              CASE 0
                   FUNCTION = %False        'Return false to function call
              CASE ELSE
                   FUNCTION = %True
         END SELECT
    END FUNCTION
    
    FUNCTION ClosePort ALIAS "ClosePort"() EXPORT AS LONG  'Close serial port
          LOCAL Dummy AS STRING
         OpeningPort = %False
         IF FILEATTR(HwndPort, 0) THEN COMM RECV HwndPort, COMM(HwndPort, RXQUE), dummy  'Get it
         IF FILEATTR(HwndPort, 0) THEN COMM CLOSE HwndPort               'Close the port (Handle#)
         FUNCTION = %True          'Return True to function call
         HwndPort = %False
         DIALOG DOEVENTS
    END FUNCTION
    
    FUNCTION SendToPort ALIAS "SendToPort" (CommandOut AS STRING) EXPORT AS LONG 'Send Command to device via Cptr or actual string
         ON ERROR GOTO ErrHandler
         LOCAL SendText AS STRING
         LOCAL lResult AS LONG
    '     local StringPointer AS ASCIIZ PTR      'Setup a pointer in case commandout is a pointer
    '     StringPointer = VARPTR(CommandOut)  'Get the location of the pointer
    '     SendText = @StringPointer
         SendText = CommandOut
         IF ParentClosing = %True THEN EXIT FUNCTION
         IF FILEATTR(HwndPort, 0) THEN COMM SEND HwndPort, SendText
         DIALOG DOEVENTS                          'Message Pump for DLL version of the form to react
         FUNCTION = %True
         EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION ReceiveData(BYVAL HwndTerminal AS DWORD) AS LONG
         WHILE ISFALSE CloseThread
               IF ParentClosing = %True THEN EXIT DO
              IF FILEATTR(HwndPort, 0) THEN CharsInBuffer = COMM(HwndPort, RXQUE) ' Test the RX buffer
              SELECT CASE CharsInBuffer
                   CASE< 1
                         SLEEP 1
                    CASE ELSE
                        ReadFromPort
              END SELECT
         WEND
    END FUNCTION
    
    FUNCTION ReadFromPort ALIAS "ReadFromPort"() EXPORT AS STRING  'Get reply from device
         LOCAL lResult AS LONG
         LOCAL TempBuffer        AS STRING        'Temp ComPort Buffer
         IF ParentClosing = %True THEN EXIT FUNCTION
         IF FILEATTR(HwndPort, 0) THEN CharsInBuffer = COMM(HwndPort, RXQUE) ' Test the RX buffer
         SELECT CASE CharsInBuffer
              CASE< 1
                      SLEEP 1
              CASE ELSE
                   IF FILEATTR(HwndPort, 0) THEN COMM RECV HwndPort, CharsInBuffer, TempBuffer        ' Read incoming characters.
                   Buffer = Buffer & TempBuffer
         END SELECT
         FUNCTION = Buffer     'Return the buffer value to function call
    END FUNCTION
    
    FUNCTION WaitReply(MinNumOfChars AS LONG, TimeoutTime AS LONG)AS LONG
         LOCAL StartTime AS CURRENCY
         StartTime = TIMER
         DO
              SELECT CASE CountCharsAtPort
                   CASE > = MinNumOfChars
                        EXIT DO
                   CASE ELSE
              END SELECT
              IF TIMER > = StartTime + (TimeOutTime/1000) THEN EXIT DO
          IF ParentClosing = %True THEN EXIT DO
         LOOP
         FUNCTION = %True
    END FUNCTION
    
    FUNCTION ReadAndThenClearFromPort ALIAS "ReadAndThenClearFromPort"() EXPORT AS STRING  'Get reply from device
         TRACE ON
         ON ERROR GOTO ErrHandler
         ERRCLEAR
         FUNCTION = ReadFromPort
         ClearPort
         EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION CountCharsAtPort ALIAS "CountCharsAtPort"() EXPORT AS LONG 'Count Number of Chars at port
         TRACE ON
         ON ERROR GOTO ErrHandler
         ERRCLEAR
         IF FILEATTR(HwndPort, 0) THEN CharsInBuffer = COMM(HwndPort, RXQUE) ' Test the RX buffer
         SELECT CASE CharsInBuffer
              CASE< 1
              CASE ELSE
                   ReadFromPort
         END SELECT
         FUNCTION = LEN(Buffer)
         EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION SearchForChars ALIAS "SearchForChars"(CharsToFind AS ASCIIZ) EXPORT AS LONG
         TRACE ON
         ON ERROR GOTO ErrHandler
         ERRCLEAR
         LOCAL TempString AS STRING
         LOCAL StringPointer AS ASCIIZ PTR      'Setup a pointer in case commandout is a pointer
         StringPointer = VARPTR(CharsToFind)  'Get the location of the pointer
         SELECT CASE StringPointer
              CASE 0
                   FUNCTION = %False
                   EXIT FUNCTION
              CASE ELSE
         END SELECT
         [email protected]
    '     @StringPointer = STRREVERSE$(@StringPointer)
         TempString = STRREVERSE$(TempString)
         IF FILEATTR(HwndPort, 0) THEN CharsInBuffer = COMM(HwndPort, RXQUE) ' Test the RX buffer
         SELECT CASE CharsInBuffer
              CASE< 1
              CASE ELSE
                   ReadFromPort
         END SELECT
         Buffer = STRREVERSE$(Buffer)
         SELECT CASE INSTR(Buffer,@StringPointer)
              CASE 0
                   FUNCTION = %False
              CASE ELSE
                   FUNCTION = %True
         END SELECT
    '     @StringPointer = STRREVERSE$(@StringPointer)
         TempString = STRREVERSE$(TempString)
         Buffer = STRREVERSE$(Buffer)
         EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION ClearPort ALIAS "ClearPort"() EXPORT AS LONG  'Clear buffer
         TRACE ON
         ON ERROR GOTO ErrHandler
         ERRCLEAR
         Buffer = ""
         FUNCTION = %True
         EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION RemoveFromPort ALIAS "RemoveFromPort"(StringToRemove AS ASCIIZ) EXPORT AS LONG  'Clear buffer chars
         TRACE ON
         ON ERROR GOTO ErrHandler
         ERRCLEAR
         LOCAL TempString AS STRING
         LOCAL StringPointer AS ASCIIZ PTR      'Setup a pointer in case commandout is a pointer
         StringPointer = VARPTR(StringToRemove)  'Get the location of the pointer
         SELECT CASE StringPointer
              CASE 0
                   FUNCTION = %False
                   EXIT FUNCTION
              CASE ELSE
         END SELECT
         [email protected]
         TempString = STRREVERSE$(TempString)
         SELECT CASE Buffer  'If buffer is empty then read in case buffer wasnt filled yet
              CASE ""
                   FUNCTION = %False
                   EXIT FUNCTION
              CASE ELSE
         END SELECT
         SELECT CASE TempString
              CASE ""
                   FUNCTION = %False
                   EXIT FUNCTION
              CASE ELSE
         END SELECT
    '     IF Updating = %False THEN
              Buffer = STRREVERSE$(Buffer)
              Buffer = STRDELETE$(Buffer, INSTR(Buffer, TempString), LEN(TempString))
              TempString = STRREVERSE$(TempString)
              Buffer = STRREVERSE$(Buffer)
    '     END IF
          EXIT FUNCTION
    ErrHandler:
         ErrorCheck ERR
    END FUNCTION
    
    FUNCTION VerifyIfVxm() AS LONG
    '     ClearPort
    '     SendToPort "ATZ"
    '     SLEEP 100
    '     ReadFromPort
    '     SELECT CASE INSTR(UCASE$(Buffer), "OK")
    '          CASE %False
                   ClearPort
                   SendToPort "K,Q,F,V"  'Force a Kill Offline and back Online
                   SLEEP 100
                   ReadFromPort
                   SELECT CASE LEFT$(Buffer,1)
                        CASE "R","J","B","b"
                             FUNCTION = %True
                        CASE ELSE
                             FUNCTION = %False
                   END SELECT
    '          CASE ELSE
    '               FUNCTION = %False
    '     END SELECT
    END FUNCTION
    
    SUB CheckVxmConnected ALIAS "CheckVxmConnected"()
    
         LOCAL TempReply AS STRING
         ClearPort
         IF FILEATTR(HwndPort, 0) THEN COMM SEND HwndPort, "V"
         SLEEP 100
         TempReply = ReadFromPort
         SELECT CASE TempReply
              CASE ""
                   LstHistoryAddLine "fontc12", "Red", "*** VXM Not turned on or not connected ***", %True
              CASE ELSE
         END SELECT
    
    END SUB
    '-------------------------------------------------------------------------------------------------------------------------
    '*** TroubleshootIo.inc
    '*** Limits
    SUB TroubleshootLimits()
        LOCAL lResult AS LONG
        LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
         ON ERROR GOTO ErrHandler
    '*** Ensure nothing is already running
        StopTroubleshootLimits
        HideIoStateWindow
        EnableMenuItem hMenu, %IDM_TRBLIMITSVIEWON, %MF_ENABLED
        IoView = %True
        ShowIoStateWindow(FUNCNAME$)
        DO
            IF IoView = %False THEN EXIT DO
            IF ParentClosing = %True THEN EXIT DO
    '*** Check if change display
            Buffer = ""
    ''*** Limits
            SendToPort "?"
            WaitReply 1, 100    'Wait for 1 char or 100ms
              ReadFromPort
              IF Buffer = "" THEN Buffer = "0"
            Buffer = BIN$(ASC(Buffer), 8)
            SELECT CASE Buffer
                 CASE ""
                CASE = Limitstate
                    ChangeIoDisplay = %False
                CASE ELSE
                    ChangeIoDisplay = %True
            END SELECT
            Limitstate = Buffer
    ''*** If Stopping Viewer then update screen
            SELECT CASE IoView
                CASE %False
                    StoppedLimitsView
                CASE %True
                    RunningLimitsView
            END SELECT
              DIALOG DOEVENTS
            SLEEP 1
            IF IoView = %False THEN EXIT DO
            IF ParentClosing = %True THEN EXIT DO
        LOOP
        StoppedLimitsView   'When triggered to escape update the stopped view
        EXIT SUB
    ErrHandler:
        StartTrace
        ErrorCheck ERR
        EndTrace
    END SUB
    
    SUB StopTroubleshootLimits()
        IoView = %False
    END SUB
    
    SUB RunningLimitsView()
        DIM Msg AS STRING
        DIM i AS LONG
    '*** User Limits
        SELECT CASE ChangeIoDisplay
            CASE %False
            CASE %True
                LstHistoryClearHistory
                Msg = "Limits Viewer" + $CR
                LstHistoryAddLine "fontc12", "Blue", Msg, %False
    
                Msg = $TAB + "Press limit switches to see if state changes" + $CR
                LstHistoryAddLine "fontc12", "Maroon", Msg, %False
                Msg = $TAB + "Low = 0" + $TAB + "High = 1" + $CR
                LstHistoryAddLine "fontc12", "Maroon", Msg, %False
    
                Msg = "Limit 4+" + $TAB + "Limit 4-" + $TAB + "Limit 3+" + $TAB + "Limit 3-" + $TAB + _
                      "Limit 2+" + $TAB + "Limit 2-" + $TAB + "Limit 1+" + $TAB + "Limit 1-" + $CR
                LstHistoryAddLine "fontc12", "Blue", Msg, %True
                Msg = ""
                FOR i = 1 TO LEN(Limitstate)
                    SELECT CASE i
                        CASE 1
                            Msg = Msg + SPACE$(LEN("Limit 4+") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 4+") / 2) + $TAB
                        CASE 2
                            Msg = Msg + SPACE$(LEN("Limit 4-") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 4-") / 2) + $TAB
                        CASE 3
                            Msg = Msg + SPACE$(LEN("Limit 3+") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 3+") / 2) + $TAB
                        CASE 4
                            Msg = Msg + SPACE$(LEN("Limit 3-") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 3-") / 2) + $TAB
                        CASE 5
                            Msg = Msg + SPACE$(LEN("Limit 2+") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 2+") / 2) + $TAB
                        CASE 6
                            Msg = Msg + SPACE$(LEN("Limit 2-") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 2-") / 2) + $TAB
                        CASE 7
                            Msg = Msg + SPACE$(LEN("Limit 1+") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 1+") / 2) + $TAB
                        CASE 8
                            Msg = Msg + SPACE$(LEN("Limit 1-") / 2) + MID$(Limitstate, i, 1) + SPACE$(LEN("Limit 1-") / 2) + $TAB
                    END SELECT
                NEXT i
                Msg = Msg + $CR
                LstHistoryAddLine "fontc12", "Green", Msg, %False
        END SELECT
    END SUB
    
    SUB StoppedLimitsView()
        LstHistoryClearHistory
    END SUB
    '-------------------------------------------------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------------------------------------------------
    These files should be in your PB folders already, so it should "Just Compile", but if not, let me know and I will post a copy
    Code:
    '*** RTF.inc and RichEdit.inc should be their own Inc files due to size
    #INCLUDE "RichEdit.inc"
    #INCLUDE "Rtf.inc"
    '*** InitControls.inc and Mdi32.inc should be their own Inc files due to size
    #INCLUDE "Mdi32.inc"
    #INCLUDE "COMMCTRL.INC"
    #INCLUDE "InitControls.inc"
    The Ripped down version of my resource file - Name it "COSMOS.rc"
    Code:
    #include "resource.h"
    
    //TOOLS
         #define IDM_TOOLS             WM_USER + 100 //TOOLS MENU
         #define IDM_TRBLIMITSVIEWON        WM_USER + 942
    
    MAINMENU MENU LOADONCALL MOVEABLE
    BEGIN
    //*** TOOLS ***
         POPUP "Tools"
         BEGIN
                   MENUITEM "Limits"                                IDM_TRBLIMITSVIEWON
         END
    //*** END TOOLS ***
    END
    My PB test code (sorry so sloppy, but by the end of the day I got a wicked migraine)
    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"       'Windows Api
    '*** Prototype for LoadLibrary call function
         DECLARE FUNCTION DllShowCosmos() AS LONG
    '***
    
    GLOBAL hDlg  AS DWORD
    %IDD_DIALOG1  =  101
    
    CALLBACK FUNCTION ShowDIALOG1Proc()
         SELECT CASE AS LONG CBMSG
              CASE %WM_INITDIALOG
              CASE %WM_NCACTIVATE
              CASE %WM_COMMAND
              CASE %WM_CLOSE
                   PostQuitMessage 0             'Stop the message pump
    'MSGBOX FUNCNAME$ + " %WM_CLOSE fired"
        END SELECT
    END FUNCTION
    
    '------------------------------------------------------------------------------
    FUNCTION WINMAIN ( _
                        BYVAL hInstance     AS LONG, _     ' handle of current instance
                        BYVAL hPrevInstance AS LONG, _     ' handle of previous instance(not used in Win32)
                        BYVAL pszCmdLine    AS ASCIIZ PTR, _     ' address of command line
                        BYVAL nCmdShow      AS LONG _      ' show state of window
                     ) AS LONG
         DIALOG NEW %HWND_DESKTOP, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
              OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
              %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
              %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
              %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
         DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc
         LOCAL tmsg AS TagMsg
         LOCAL hLib AS DWORD
         LOCAL AddrShowCosmos AS DWORD
         hLib = LoadLibrary( "COSMOS.dll")
         AddrShowCosmos=GetProcAddress(BYVAL hLib, "ShowCosmos")
         IF AddrShowCosmos THEN CALL DWORD AddrShowCosmos USING DllShowCosmos
    '*** Acquire and dispatch messages until a WM_QUIT message is received.
         WHILE ISTRUE GetMessage(tmsg, BYVAL %NULL, 0, 0)
              TranslateMessage tmsg
              DispatchMessage tmsg
         WEND
    MSGBOX FUNCNAME$ + " has escaped messagepump"
    END FUNCTION

    Leave a comment:


  • Edwin Knoppert
    replied
    I am sure it's the typical "i will not tell to much"..

    1) I am sure it's VB again?

    2) If so, an unhandled error in VB crashes PB code as well.

    Leave a comment:


  • Michael Mattias
    replied
    Not to be "too" simple, but perhaps you could make the source code available along with any required data files and instructions on "how to make it fail" and you might get some 'fresh eyes' on the problem.

    I remember I had a dumb mistake in one of my programs once, and I got to the point where I was sure there was a compiler problem. So I bundled up the source and data files and mailed in to the PB support dept.

    In less than an hour someone had replied that leaving an orphan underscore at the end of a source code line changes a single-line if into a multi-line IF..END IF block, and if I simply fixed that and added the (now) required END IF the program would work just fine.

    This, too, could be something 'fresh eyes' could spot almost instantly.

    Hell, it's a thought.

    MCM

    Leave a comment:


  • Cliff Nichols
    started a topic Mysterious GPF and Exception Handling

    Mysterious GPF and Exception Handling

    I was trying to track down a mysterious GPF in my dll that only occurs when I do a precise step of sequences, and have spent days verifying that pointers are good, and all threads are closed, and anything I could think of that might cause the crash, and still can not find it.

    Then I was searching the forums for what else could be a corrupted memory location, or anything else that could GPF, and ran into one that MCM wrote about a year ago Sure its a GPF but....
    In it the point was made that you could raise your own exceptions, so I started thinking. If you can raise one, then there must be a way to read one and act on it?

    Sure enough looking in the Win32 help files, I found "GetExceptionInformation" which I think may be my answer, but could not find any examples to show me just how to use it (or if I even understand the documentation correctly)

    Does anyone have some examples or point me the right direction? I would like to be able to build into my dll that when an unhandled exception occurs I can either take care of it, or log it when it occurs, and not later on (like when closing the program)

    Side Note: Compiled as EXE I get no GPF, Compiled as DLL I get no GPF if I push a button that does my cleanup, but if I programmatically press the button from code, then I get a GPF when closing. (Which is really starting to make me think, that where I am looking is NOT where the exception occurred.
Working...
X