---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- This text file contains four source files. Use your editor to cut this file into these: lc_samp.c lc_samp.h lc_samp.mak lc_samp.rc ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ------------------ HERE BEGINS THE LC_SAMP.C FILE ------------- /* Sample Non-DDE client program for LC.EXE Garry J. Vass [72307,3311] This program (cloned from generic.c) uses the LC.EXE Winapp to perform calculations on strings containing expressions of the form: 3+4+5+6 3*4 3/sin(3)*log(2) and so on. For locating code that is specific to this application (i.e., not generic), set your Search function for "COMMENT". Why not DDE? 1. This particular client-server relationship is straightforward, well structured, predictable, and requires expedience. 2. About 12 lines of code for this versus 300+ lines to implement DDE. 3. The downside is that the messages WM_USER+63 (request), and WM_USER+64 (reply) are looked upon as private channels. This is conceptually similar to the old-world situation where DOS resident programs argued over who owned what hotkey (sigh). I use a recognition signature 0x4C43, 'L'<<4 + 'C', in the message to establish ownership. */ /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ #include "windows.h" #include "lc_samp.h" int request_calculation( HWND sender, char *str ); /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ HANDLE hInst; FARPROC Lproc; char Inputstring[ 255 ] = "2+2"; char Resultstring[ 255 ] = "Result: 4"; char Anystring[ 255 ]; #define WAK( a ) MessageBox( GetFocus( ), a, "WIN-ACK", MB_OK ); /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ /* COMMENT: This variable is used to specify the handle (HWND) of the LC application. */ static HWND Lchwnd = -1; /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { MSG msg; if( !hPrevInstance ) { if( !InitApplication( hInstance ) ) return( FALSE ); /* COMMENT: This code starts the LC application. If Windows cannot start the program, she returns a value less than 32. */ if( WinExec( "LC", SW_SHOWMINNOACTIVE ) < 32 ) { MessageBox( GetFocus(), (LPSTR)"I cannot find my server", (LPSTR)"ShowStopper", MB_OK ); return( FALSE ); } } if( !InitInstance( hInstance, nCmdShow ) ) return( FALSE ); while( GetMessage( &msg, NULL, NULL, NULL ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return( msg.wParam ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ BOOL InitApplication( HANDLE hInstance ) { WNDCLASS wc; wc.style = NULL; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = "lcmenu"; wc.lpszClassName = "lcclass"; return( RegisterClass( &wc ) ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ BOOL InitInstance( HANDLE hInstance, int nCmdShow ) { HWND hWnd; hInst = hInstance; hWnd = CreateWindow( "lcclass", "LC Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if( !hWnd ) return( FALSE ); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); return( TRUE ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ long FAR PASCAL MainWndProc( HWND hWnd, unsigned message, WORD wParam, LONG lParam ) { switch( message ) { case WM_COMMAND: if( wParam == IDM_ABOUT ) { Lproc = MakeProcInstance( About, hInst ); DialogBox( hInst, "AboutBox", hWnd, Lproc ); FreeProcInstance( Lproc ); break; } else if( wParam == IDM_ABOUT+1 ) { /* COMMENT: This code opens the dialog box for entering expressions. */ Lproc = MakeProcInstance( Samp, hInst ); DialogBox( hInst, "LCSAMP", hWnd, Lproc ); FreeProcInstance( Lproc ); break; } else return( DefWindowProc( hWnd, message, wParam, lParam ) ); case WM_DESTROY: PostQuitMessage( 0 ); break; default: return( DefWindowProc( hWnd, message, wParam, lParam ) ); } return( NULL ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ BOOL FAR PASCAL About( HWND hDlg, unsigned message, WORD wParam, LONG lParam ) { switch( message ) { case WM_INITDIALOG: return( TRUE ); case WM_COMMAND: if( wParam == IDOK || wParam == IDCANCEL ) { EndDialog( hDlg, TRUE ); return( TRUE ); } break; } return( FALSE ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ BOOL FAR PASCAL Samp( HWND hDlg, unsigned message, WORD wParam, LONG lParam ) { static int grab; switch( message ) { case WM_INITDIALOG: SetDlgItemText( hDlg, 101, (LPSTR)Inputstring ); return( TRUE ); case WM_COMMAND: if( wParam == 100 ) { EndDialog( hDlg, TRUE ); return( TRUE ); } else if( wParam == 107 ) { /* calc button */ /* COMMENT: When the calculate button has been pressed, this code acquires the string and prepares it for calculation. */ GetDlgItemText( hDlg, 101, (LPSTR)Inputstring, 50 ); request_calculation( hDlg, Inputstring ); } break; case WM_USER+64: /* COMMENT: LC.EXE sends its results with the WM_USER+64 message. The format it uses is message: WM_USER+64 wParam: The handle (HWND) to LC's window. lParam: The low word contains a global atom with LC's result. The high word contains the handle (HWND) of the application that requested the service. The processing does not need to take place within a dialog callback, the reply message is sent to whatever handle requested the service. */ if( HIWORD( lParam ) == hDlg ) {/*Is it ours?*/ GlobalGetAtomName( LOWORD( lParam ), Anystring, 100 ); SetDlgItemText( hDlg, 103, (LPSTR)Anystring ); Lchwnd = (HWND)wParam; } break; } return( FALSE ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ int request_calculation( HWND sender, char *str ) { ATOM anyatom; /* COMMENT: This code prepares a string for calculation and sends it to the server. LC listens for WM_USER+63 messages in the following format: message: WM_USER+63 wParam: The handle (HWND) of the sending, or client, window. lParam: The low word contains a global atom with the string to be calculated. The high word contains a recognition signature, 0x4C43. */ anyatom = GlobalAddAtom( (LPSTR) str ); SendMessage( Lchwnd, WM_USER+63, sender, MAKELONG( anyatom, 0x4C43 ) ); GlobalDeleteAtom( anyatom ); } /**************************************************************/ /* */ /* */ /* */ /* */ /* */ /**************************************************************/ --------------------- HERE ENDS THE LC_SAMP.C FILE ----------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- --------------------- HERE BEGINS THE LC_SAMP MAKE FILE ------ all: lc_samp.exe lc_samp.res: lc_samp.rc lc_samp.h rc -r lc_samp.rc lc_samp.obj: lc_samp.c lc_samp.h erase lc_samp.exe cl -c -AS -Gsw -Oas -Zpe lc_samp.c lc_samp.exe: lc_samp.obj lc_samp.def link /NOD lc_samp,,, libw slibcew, lc_samp.def rc lc_samp.res lc_samp.exe: lc_samp.res rc lc_samp.res ----------------------- HERE ENDS THE LC_SAMP MAKE FILE ------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- --------------------- HERE BEGINS THE LC_SAMP.H FILE ---------- #define IDM_ABOUT 100 int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int); BOOL InitApplication(HANDLE); BOOL InitInstance(HANDLE, int); long FAR PASCAL MainWndProc(HWND, unsigned, WORD, LONG); BOOL FAR PASCAL About(HWND, unsigned, WORD, LONG); BOOL FAR PASCAL Samp(HWND, unsigned, WORD, LONG); ----------------------- HERE ENDS THE LC_SAMP.H FILE ---------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------- HERE BEGINS THE LC_SAMP.RC FILE -------- #include "windows.h" #include "lc_samp.h" lcmenu MENU BEGIN POPUP "About" BEGIN MENUITEM "&About...", IDM_ABOUT END MENUITEM "&Calculate", IDM_ABOUT+1 END LCSAMP DIALOG LOADONCALL MOVEABLE DISCARDABLE 11, 29, 258, 148 CAPTION "LC-Sample" STYLE WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SIZEBOX | WS_POPUP BEGIN CONTROL "", 101, "edit", ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD, 140, 20, 70, 20 CONTROL "Press here to calculate", 107, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 140, 50, 90, 20 CONTROL "Done", 100, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 200, 130, 36, 14 CONTROL "Enter an expression here", 102, "static", SS_LEFT | WS_CHILD, 40, 20, 90, 10 CONTROL "Result:", 103, "static", SS_LEFT | WS_CHILD, 140, 80, 110, 10 CONTROL "Samples", 104, "static", SS_LEFT | WS_CHILD, 10, 40, 30, 10 CONTROL "3+4/(5+6)*(7*8)", 105, "static", SS_LEFT | WS_CHILD, 10, 60, 50, 10 CONTROL "2*sin(3)^3*sqr(7)", 106, "static", SS_LEFT | WS_CHILD, 10, 70, 60, 10 END AboutBox DIALOG 22, 17, 144, 75 STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU CAPTION "About" BEGIN CTEXT "Sample LC-Client" -1, 0, 5, 144, 8 DEFPUSHBUTTON "OK" IDOK, 53, 59, 32, 14, WS_GROUP END ----------------------- HERE ENDS THE LC_SAMP.RC FILE -------- --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- ---------------------------------------------------------------