📄 chapt15.cpp
字号:
AnsiTapiTerm *pTerm;
MySimpleTapi *pTapi;
pTerm = (AnsiTapiTerm *) GetWindowLong( hWnd, 0 );
pTapi = (MySimpleTapi *) GetWindowLong( hWnd, 4 );
switch ( message )
{
//
// When my window is first created, I immediately
// create the terminal window as a child window. I
// get the pointer to the C++ object and store it as
// a window long word, giving me access to it whenever
// I need it without using a global variable.
//
case WM_CREATE:
pTerm = new AnsiTapiTerm( hWnd, "AnsiTerm Window", 25, 80 );
SetWindowLong( hWnd, 0, (LONG) pTerm );
if ( pTerm->m_hWnd == NULL )
MessageBox( hWnd, "Can't open child window", "Chapter 15", MB_OK );
SetFocus( hWnd );
break;
//
// When I am being destroyed, I take it upon myself
// to destroy both the terminal object and the Tapi
// object, if one exists.
//
case WM_DESTROY:
delete pTerm;
pTerm = 0;
if ( pTapi ) {
delete pTapi;
pTapi = 0;
}
PostQuitMessage( 0 );
break;
//
// Just for the sake of esthetics, I respond to this message
// with a minimum size large enough to prevent somebody from
// resizing me down to the point of ridiculousness.
//
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lp = (LPMINMAXINFO) lParam;
POINT ptTemp = {
lp->ptMinTrackSize.x,
GetSystemMetrics( SM_CYMENU ) +
GetSystemMetrics( SM_CYCAPTION ) +
2 * GetSystemMetrics( SM_CYFRAME )
};
lp->ptMinTrackSize = ptTemp;
}
break;
//
// When the frame window is resized, I immediately
// resize the terminal window. Size the terminal window
// is supposed to completely fill my client area, I
// can figure out what size it is supposed to be by
// simply getting the size of my client rect. When
// the terminal window processes this command it will
// potentially add scroll bars and offset the display.
//
case WM_SIZE:
{
RECT rc;
::GetClientRect( hWnd, &rc );
if ( lParam != 0 )
::MoveWindow( pTerm->m_hWnd,
0, 0,
rc.right - rc.left + 1,
rc.bottom - rc.top + 1,
TRUE );
}
break;
//
// I don't want the framing window to get the focus,
// so whenever I get it, I immediately foist it upon
// the terminal window.
//
case WM_SETFOCUS :
SetFocus( pTerm->m_hWnd );
return 0;
//
// The rest of the code in the message loop
// is the set of command handlers for menu
// items.
//
case WM_COMMAND:
switch ( LOWORD( wParam ) ) {
//
// Telling a window to close itself is a fast way
// of shutting the program down, so that's how
// we deal with the File|Exit menu item.
//
case ID_FILE_EXIT :
PostMessage( hWnd, WM_CLOSE, 0, 0 );
break;
//
// The base class, SimpleTapi, has a trace object
// that receives various messages as the object
// does its TAPI stuff. This trace window can be
// open or closed. This command toggles it back
// and forth between these two states. Since the
// trace object is static, we don't even need to
// use a pointer to the TAPI object. When the
// object is opened, a completely separate
// console window is opened up to receive trace
// information.
//
case ID_TAPI_OPEN_TRACE_WINDOW :
if ( SimpleTapi::m_Trace.IsOpen() )
SimpleTapi::m_Trace.Close();
else
SimpleTapi::m_Trace.Open();
UpdateMenu( hWnd, pTapi );
break;
//
// We can't do much of anything interesting
// with this program until the simple TAPI
// object is created. This command handler
// will either create or destroy the object,
// depending on whether or not it currently
// exists. The value of the pTapi after the
// operation has to be stuffed in the window
// storage area so it will persist past the
// end of this command processing.
//
case ID_TAPI_CREATE_TAPI_OBJECT :
if ( pTapi ) {
delete pTapi;
pTapi = 0;
} else
pTapi = new MySimpleTapi( hWnd );
SetWindowLong( hWnd, 4, (LONG) pTapi );
UpdateMenu( hWnd, pTapi );
break;
//
// This menu object should be grayed out unless
// the pTapi object has been created. If it has,
// we can either open or close the line. Note
// that this call is hard coded to open the first
// TAPI line. A better program would let you
// select from among the available lines via
// some sort of selection dialog. Note that the
// two functions called here both return
// immediately, we don't have to wait for a
// delayed response.
//
case ID_TAPI_OPEN_LINE :
if ( pTapi->IsOpen() )
pTapi->CloseLine();
else
pTapi->OpenLine( 0 );
UpdateMenu( hWnd, pTapi );
break;
//
// This menu item should only be enabled if a
// line has been opened. It will then either
// place a call or drop a call, depending on
// whether a call is active. This is a little
// bit tricky, because we have to deal with the
// fact that both of these calls don't return
// an immediate result
//
case ID_TAPI_PLACE_CALL :
if ( pTapi->CallActive() )
pTapi->DropCall();
else
pTapi->MakeCall( pTapi->m_NumberToDial );
break;
//
// The followign three menu items are enabled as
// long as a TAPI object is alive. All three are
// used to configure the parameters surrounding
// a TAPI call. The first two just invoke the
// standard dialogs supplied by TAPI to configure
// modems and the way they place calls. The final
// of the three pops up a dialog that optionally
// modifies the current outbound phone number.
//
case ID_TAPI_CONFIGURE_LINE :
pTapi->ConfigureDevice( 0 );
break;
case ID_TAPI_CONFIGURE_CALL :
pTapi->ConfigureCall( 0, pTapi->m_NumberToDial );
break;
case ID_TAPI_SET_PHONE_NUMBER :
DialogBox( GetModuleHandle( NULL ),
MAKEINTRESOURCE(IDD_GET_PHONE_NUMBER),
hWnd,
(DLGPROC) DlgProc );
break;
}
break;
//
// My specialized class derived from SimpleTapi
// is called MySimpleTapi. I've configured it to
// send the following Windows messages to a specific
// window as part of its notification process. I use
// the notification event to update the UI, mostly
// by printing a message on the terminal screen and
//
case WM_TAPI_CONNECTED_NOTIFY :
*pTerm << "\r\nConnected\r\n";
UpdateMenu( hWnd, pTapi );
break;
case WM_TAPI_DISCONNECTED_NOTIFY :
*pTerm << "\r\nDisconnected\r\n";
UpdateMenu( hWnd, pTapi );
break;
case WM_TAPI_STATE_CHANGE_NOTIFY :
UpdateMenu( hWnd, pTapi );
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0L;
}
//
// This program was written without the use of MFC or any
// other application framework, which means that using a
// dialog box to get a text string is a bit of trouble. The
// sole use of a dialog box in this program is to get the
// phone number that is to be dialed upon selection of the
// Place Call menu item.
//
// This dialog box assumes that its parent is the Chapter 15
// main window. Because of that, it can extract a pointer to
// the TAPI object from the storage area associated with that
// window. The phone number is stored in that structure,
// which means we can preload the text box with the number,
// then update the structure with the new value if the user
// clicks on the OK box to exit.
//
BOOL CALLBACK DlgProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
HWND hParent = GetParent( hWnd );
MySimpleTapi *pTapi;
pTapi = (MySimpleTapi *) GetWindowLong( hParent, 4 );
switch ( uMsg ) {
//
// When the dialog is first being created, we load up
// the edit text box with a copy of the phone number
// currently loaded into the text box.
//
case WM_INITDIALOG :
SetDlgItemText( hWnd,
IDC_PHONE_NUMBER,
pTapi->m_NumberToDial.c_str() );
return TRUE;
case WM_COMMAND :
switch ( LOWORD( wParam ) ) {
//
// If the user clicks on the cancel button, we just
// exit without updating any data.
//
case IDCANCEL :
EndDialog( hWnd, 0 );
return TRUE;
//
// If the user clicks OK, we update the phone number
// field in the TAPI object with whatever was typed
// into the field. No checks are made to ensure that
// it is a legal number.
//
case IDOK :
{
char number[ 25 ];
::GetDlgItemText( hWnd,
IDC_PHONE_NUMBER,
number,
24 );
pTapi->m_NumberToDial = number;
EndDialog( hWnd, 0 );
}
return TRUE;
}
}
return FALSE;
}
// End of CHAPT15.CPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -