home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- trace.c
- -------
-
- This module is an example of how you could use the TextView DLL to add
- a trace system to your application. The code here manages the 'Trace'
- menu set up in the application's main window, and also contains a
- routine that can be called to write a message to the trace window with
- an arbitrary number of arguments.
-
- Copyright (c) Alan Phillips 1991
-
- This source may be freely used and adapted for use in non-commercial
- applications. Those wishing to include it, and the TextView DLL in
- commercial or ShareWare packages should first obtain the written agreement
- of the author.
-
- The source has been edited using a tab width of 4 characters.
-
- *****************************************************************************/
-
- #include "stdhead.h"
- #include "menu.h"
-
- #include <stdarg.h>
-
- /*****************************************************************************
-
- Local Procedures
- ----------------
-
- *****************************************************************************/
-
- static void handle_file_menu(HWND,WORD);
- static void window_closed(HWND);
-
- /*****************************************************************************
-
- Local Data
- ----------
-
- *****************************************************************************/
-
- static FARPROC lpMenuHandler; /* instance of menu handler function */
- static HFONT hFont; /* handle to font used */
-
-
- /*****************************************************************************
-
- start_tracing
- -------------
-
- This routine is called when the user clicks 'start tracing' in the
- main window's 'Trace' menu. If a trace window does not already exist
- it creates one, updating the menu accordingly. Otherwise, it simply
- sets the application's 'tracing' flag to TRUE so that the trace() routine
- will actually record messages
-
- start_tracing(hWnd)
-
- HWND hWnd; Handle to main window
-
- *****************************************************************************/
-
- void start_tracing(HWND hWnd)
-
- {
- HMENU hMenu; /* handle to main menu window */
-
- /* If we have a trace window already, just set the 'tracing' flag to
- * be TRUE and adjust the menu a bit
- */
-
- if ( hTraceWnd != NULL )
- {
- tracing = TRUE;
- EnableMenuItem(GetMenu(hWnd),IDM_TRACE_OFF,MF_ENABLED|MF_BYCOMMAND);
- EnableMenuItem(GetMenu(hWnd),IDM_TRACE_ON,MF_GRAYED|MF_BYCOMMAND);
- return;
- }
-
- /* We don't have a trace window, so we'll create one. If you want to use
- * your own font in the window, you need to define OWN_FONT above, and
- * alter the arguments to the CreateFont function here as required
- */
-
- #ifdef OWN_FONT
- hFont = CreateFont( 18,
- 0,
- 0,
- 0,
- 700,
- FALSE,
- FALSE,
- FALSE,
- ANSI_CHARSET,
- OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- DEFAULT_PITCH | FF_DONTCARE,
- "Helv");
-
- if ( hFont == NULL )
- message("Cannot create font",NULL,MB_ICONSTOP);
- #endif
-
- /* Set up a procedure instance to our routine that handles clicks in the
- * trace window's menu. The DLL will call back into that routine to
- * notify us when the user does things. Note that you must specify this
- * routine as a procedure instance, and it must be exported in the
- * application's .DEF file
- */
-
- lpMenuHandler = MakeProcInstance(menu_handler,hInst);
-
- /* And create the TextView window we'll use for tracing */
-
- hTraceWnd = TVCreateWindow("TRACE_WINDOW",
- "Trace Window",
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- 300,
- 200,
- hInst,
- #ifdef OWN_FONT
- hFont,
- #else
- NULL,
- #endif
- TVS_TIMESTAMP | TVS_VSCROLL | TVS_HSCROLL |
- TVS_SYSMENU | TVS_MINIMIZE |
- TVS_FILESAVE | TVS_FILESAVEAS |
- TVS_FILEPRINT | TVS_SCROLLMENU,
- 0,
- 4,
- TRW_SIZE,
- lpMenuHandler);
-
- /* You should always check that the window has in fact been created. If
- * you specified inconsistent arguments to the TVCreateWindow call the
- * DLL would return a NULL handle
- */
-
- if ( hTraceWnd == NULL )
- {
- message("Cannot create trace window",NULL,MB_ICONSTOP);
- return;
- }
-
- /* The window now exists. We can now adjust the main window's 'Trace'
- * menu to make the appropriate items enabled
- */
-
- hMenu = GetMenu(hWnd);
- EnableMenuItem(hMenu,IDM_TRACE_KILLWND,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_OFF,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_ON,MF_GRAYED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_RESET,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SHOW,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SCR_MAN,MF_ENABLED | MF_BYCOMMAND);
- CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_CHECKED|MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_COPY,MF_ENABLED | MF_BYCOMMAND);
-
- /* And now, with everything set up, we can set our own global flag to
- * mark that tracing is active. Once this is done, calls to the trace()
- * routine lower down will actually write to the TextView window
- */
-
- tracing = TRUE;
- }
-
- /*****************************************************************************
-
- kill_trace_window
- -----------------
-
- This routine is entered when the user clicks the 'kill window' item in the
- main window's 'Trace' menu. It destroys the TextView window, and resets
- the 'Trace' menu so that inappropriate items are no longer enabled.
-
- stop_tracing(hWnd)
-
- HWND hWnd; Main window handle
-
- *****************************************************************************/
-
- void kill_trace_window(HWND hWnd)
-
- {
- /* Call the TextView DLL to destroy the window. It's recommended that you
- * don't simply send a WM_DESTROY message to the handle, as in this case
- * the DLL will act as if the action was initiated from the system menu
- * close option, and will call back into the application to tell it
- */
-
- TVDestroyWindow(hTraceWnd);
-
- /* Then call our tidy up routine to mark that tracing has stopped and
- * bring the 'Trace' menu into line
- */
-
- window_closed(hWnd);
-
- }
-
-
- /*****************************************************************************
-
- reset_tracing
- -------------
-
- This routine is called when the user clicks the 'reset' item in the
- main window's 'Trace' menu. It calls the TextView DLL to discard all
- the lines stored so far in the trace window.
-
- reset_tracing(hWnd)
-
- HWND hWnd; Handle to main window
-
- *****************************************************************************/
-
- void reset_tracing(HWND hWnd)
-
- {
- /* Simply call the 'reset window' routine in the TextView DLL to reset
- * the trace window
- */
-
- TVResetWindow(hTraceWnd);
- }
-
- /*****************************************************************************
-
- report_trace_status
- -------------------
-
- This routine is entered when the user clicks the 'report status' item in
- the main window's 'Trace' menu. If the global variable hTraceWnd is NULL
- there is no trace window; if not, it calls the TextView DLL to obtain
- details of what the trace window is currently doing.
-
- report_trace_status()
-
- *****************************************************************************/
-
- void report_trace_status()
-
- {
- TVWSTATUS stats; /* status block for window */
-
- if ( hTraceWnd == NULL )
- {
- /* The global window handle is NULL, so the trace window does not
- * exist
- */
-
- message("No trace window open","Info",NULL);
- return;
- }
- else
- {
- /* There is a trace window, so we ask the DLL for details about it */
-
- if ( TVGetWindowStatus(hTraceWnd,&stats) == NULL )
- message("Cannot get trace window status",NULL,MB_ICONSTOP);
- else
- message("Tracing is %sactive\nLines stored\t%d/%d\nScroll state\t%s\nRedrawing\t%s",
- "Info",
- NULL,
- (tracing) ? (LPSTR)"" : (LPSTR)"in",
- stats.nLinesStored,
- stats.nMaxLines,
- (stats.nScrollState == TV_SCR_AUTO) ? (LPSTR)"auto"
- : (LPSTR)"manual",
- (stats.nRedraw) ? (LPSTR)"enabled"
- : (LPSTR)"disabled");
-
- }
- }
-
-
- /*****************************************************************************
-
- menu_handler
- -------------
-
- This routine is called by the TextView DLL whenever the user clicks on
- a menu item in the window (including the 'close' option in the system
- menu).
-
- You use a routine such as this to keep the application informed of what
- the user is doing in the TextView window. It's mandatory to have the routine
- if the TextView window has been created with a 'File' menu or can be
- closed from its 'System' menu; otherwise you need only have it if you want
- to keep keep track, for example, of the window's scroll state.
-
- This routine must be in the EXPORT list in the application's .DEF file
- and must be declared FAR PASCAL.
-
- menu_handler(hWnd,nMenuItem)
-
- HWND hWnd; Window handle
- WORD nMenuItem; Code for the menu item clicked
-
- *****************************************************************************/
-
- void FAR PASCAL menu_handler(HWND hWnd,WORD nMenuItem)
-
- {
- HMENU hMenu; /* handle to main window menu */
-
- /* The DLL passes back a code indicating the menu item that the user has
- * clicked on. Here we handle all the possible items for release 1.00.xxx
- * of the TextView DLL
- */
-
- switch (nMenuItem)
- {
- case TVMI_CLOSE: /* System menu close */
-
- /* Call our handler function to clear out the window handle
- * and do any other tidying up
- */
-
- window_closed(hWnd);
- break;
-
- case TVMI_FILESAVE: /* File save */
- case TVMI_FILESAVEAS: /* File save as */
- case TVMI_FILEPRINT: /* File print */
-
- /* Pass this to a function that handles each of the menu
- * items
- */
-
- handle_file_menu(hWnd,nMenuItem);
- break;
-
- case TVMI_AUTOSCROLL: /* Scroll auto */
-
- /* Adjust the scroll items in our own menu so that they are
- * step with the trace window's state
- */
-
- hMenu = GetMenu(hMainWnd);
-
- CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_CHECKED|MF_BYCOMMAND);
- CheckMenuItem(hMenu,IDM_TRACE_SCR_MAN,MF_UNCHECKED|MF_BYCOMMAND);
- break;
-
- case TVMI_MANUALSCROLL: /* Scroll manual */
-
- /* Adjust the scroll items in our own menu so that they are
- * step with the trace window's state
- */
-
- hMenu = GetMenu(hMainWnd);
-
- CheckMenuItem(hMenu,IDM_TRACE_SCR_MAN,MF_CHECKED|MF_BYCOMMAND);
- CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_UNCHECKED|MF_BYCOMMAND);
- break;
-
- default: /* unknown item */
-
- /* Anything else we don't handle. Later releases of the
- * TextView DLL may add further menu items to those processed
- * above, so this is not necessarily an error.
- */
-
- message("Unknown menu item (%d) clicked",NULL,
- MB_ICONSTOP,nMenuItem);
- break;
- }
-
- }
-
- /*****************************************************************************
-
- trace
- -----
-
- This routine can be called in your application to write one line to
- the trace window. You pass it a FAR pointer to a null-terminated string,
- and a value giving the color to use when writing the text. Optionally,
- you can include arguments to be substituted in the text string with a
- wsprintf call.
-
- Note that you must cast string pointers to LPSTR explicitly if you pass
- them in the optional arguments.
-
- If the trace window does not exist, or if the global variable 'tracing'
- is FALSE, the routine does nothing.
-
- Of course, there are an infinite number of other ways of writing a trace
- routine; this merely demonstrates one possible approach.
-
- The technique used here to handle a variable number of arguments will
- not work from within a DLL.
-
- reply = trace(format,color,...)
-
- BOOL reply; TRUE if message was written, else FALSE.
- FALSE is returned only if the actual call
- to TVOutputText fails
- LPSTR *format; Message format string
- COLORREF color; Color to use
- ... Optional arguments
-
- *****************************************************************************/
-
- BOOL trace(LPSTR format,COLORREF color,...)
-
- {
- char buffer[256]; /* text assembly buffer */
- va_list arg_ptr; /* argument list pointer */
-
- /* So that you can control tracing within the program either by destroying
- * the trace window and setting the handle to NULL, or by setting a
- * global flag to FALSE to inhibit it, we do something here only if we
- * are actually supposed to.
- *
- * (Note that there is another way to control whether something appears
- * in the trace window. You can call the DLL's TVSuspendWindow function
- * to mark the window as suspended, and in this state any attempt to
- * write a line to the window will also be ignored. However, that approach
- * will always call into the DLL, so that this technique is more efficient)
- */
-
- if ( !tracing || hTraceWnd == NULL )
- return(TRUE);
-
- /* Build the text to include any optional arguments. Note that any string
- * pointers in the list must have been cast to FAR pointers
- */
-
- va_start(arg_ptr,color);
- wvsprintf(buffer,format,arg_ptr);
-
- /* Call the DLL to write the line to the TextView window. Note that if
- * the window has been marked as suspended, or if it's in manual scroll
- * state, the line will be discarded.
- */
-
- TVSetTextColor(hTraceWnd,color);
- return( TVOutputText(hTraceWnd,buffer,lstrlen(buffer)) );
- }
-
-
- /*****************************************************************************
-
- handle_file_menu
- -----------------
-
- This routine is called from the menu handler function to process
- actions in the file menu. This has been put into a separate function to
- keep the menu handler getting too large.
-
- handle_file_menu(hWnd,type)
-
- HWND hWnd; Handle of the TextView window concerned
- WORD nMenuItem; Identity of the menu item clicked
-
- *****************************************************************************/
-
- static void handle_file_menu(HWND hWnd,WORD nMenuItem)
-
- {
- char *ptr; /* ptr to message text */
-
- /* In this procedure you can take whatever you like. You might choose to
- * run a dialog to ask the user for a file name; then, using the
- * TVReturnData function, you could read back all the lines stored for
- * the window and write them to the file. For saving to file, you could
- * call the TVSaveWindowToFile function after asking the user for a
- * file name.
- *
- * Here we simply put up a message box to report what the user clicked
- * on, and nothing else. Set up a string to identify the action to start
- * with...
- */
-
- switch ( nMenuItem )
- {
- case TVMI_FILESAVE: /* 'File save' clicked */
-
- ptr = "File Save";
- break;
-
- case TVMI_FILESAVEAS: /* 'File save as' clicked */
-
- ptr = "File Save As";
- break;
-
- case TVMI_FILEPRINT: /* 'File Print' clicked */
-
- ptr = "File Print";
- break;
-
- default: /* this shouldn't happen... */
-
- ptr = "Unknown";
- break;
- }
-
- /* Now report in a message box */
-
- message("User clicked '%s' menu item","Info",NULL,(LPSTR)ptr);
-
- }
-
- /*****************************************************************************
-
- window_closed
- -------------
-
- This routine is called from the menu handler function to take the necessary
- steps when the window has been closed. It is also called from the
- application when it decides to close the trace window itself.
-
- window_closed(hWnd)
-
- HWND hWnd; Window handler
-
- *****************************************************************************/
-
- static void window_closed(HWND hWnd)
-
- {
- HMENU hMenu; /* handle to main window menu */
-
- /* Set the trace state to be off */
-
- tracing = FALSE;
-
- /* And set our copy of the trace window handle to NULL */
-
- hTraceWnd = NULL;
-
- /* Then adjust our trace menu so that the items reflect the fact that there
- * is now no trace window
- */
-
- hMenu = GetMenu(hMainWnd);
- EnableMenuItem(hMenu,IDM_TRACE_ON,MF_ENABLED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_KILLWND,MF_GRAYED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_RESET,MF_GRAYED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SHOW,MF_GRAYED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_GRAYED | MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_SCR_MAN,MF_GRAYED | MF_BYCOMMAND);
- CheckMenuItem(hMenu,IDM_TRACE_SCR_AUTO,MF_UNCHECKED|MF_BYCOMMAND);
- CheckMenuItem(hMenu,IDM_TRACE_SCR_MAN,MF_UNCHECKED|MF_BYCOMMAND);
- EnableMenuItem(hMenu,IDM_TRACE_COPY,MF_GRAYED | MF_BYCOMMAND);
-
- /* Free the proc instance to the menu handler function, if there is one */
-
- if ( lpMenuHandler != NULL )
- FreeProcInstance(lpMenuHandler);
-
- /* And delete the font we were using if we didn't let TextView use the
- * default non-proportional system font
- */
-
- #ifdef OWN_FONT
- DeleteObject(hFont);
- #endif
-
- }
-
-
-
-