//---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation 1993-1995
//
// File: ring.c
//
// This files contains the dialog code for the Voice settings
// property pages.
//
// History:
// 07-05-95 ScottH Created
//
//---------------------------------------------------------------------------
#include "proj.h" // common headers
#if defined(WIN95) && defined(CS_HELP)
#include "..\..\..\..\win\core\inc\help.h"
#endif
#define CX_PATTERN 40
#define CY_PATTERN 5
typedef struct tagRING
{
HWND hdlg; // dialog handle
LPMODEMINFO pmi; // modeminfo struct passed into dialog
HBITMAP hbmStrip;
HDC hdcStrip;
HFONT hfont;
int cyText;
} RING, FAR * PRING;
typedef struct tagRINGPAT
{
DWORD dwPattern;
LPARAM lParam;
} RINGPAT, FAR * PRINGPAT;
static RINGPAT s_rgrp[] =
{
{ DRP_NONE, 0 },
{ DRP_SHORT, 0 },
{ DRP_LONG, 0 },
{ DRP_SHORTSHORT, 0 },
{ DRP_SHORTLONG, 0 },
{ DRP_LONGSHORT, 0 },
{ DRP_LONGLONG, 0 },
{ DRP_SHORTSHORTLONG, 0 },
{ DRP_SHORTLONGSHORT, 0 },
{ DRP_LONGSHORTSHORT, 0 },
{ DRP_LONGSHORTLONG, 0 },
};
#pragma data_seg(DATASEG_READONLY)
const static UINT c_rgidcPattern[] =
{
IDC_ADDR_PRI,
IDC_ADDR1,
IDC_ADDR2,
IDC_ADDR3,
IDC_PRI_CALLERS,
IDC_CALLBACK,
};
const static UINT c_rgidcTypeOfCalls[] =
{
IDC_TYPE_ADDR_PRI,
IDC_TYPE_ADDR1,
IDC_TYPE_ADDR2,
IDC_TYPE_ADDR3,
IDC_TYPE_PRI_CALLERS,
IDC_TYPE_CALLBACK,
};
static DWORD c_rgdwCheapPatterns[] =
{
DRP_SINGLE,
DRP_DOUBLE,
DRP_TRIPLE,
};
const static UINT c_rgidcTypeOfCheapCalls[] =
{
IDC_TYPE_RING1,
IDC_TYPE_RING2,
IDC_TYPE_RING3,
};
TCHAR const FAR c_szUnimdmHelpFile[] = TEXT("unimdm.hlp");
#pragma data_seg()
#define Ring_GetPtr(hwnd) (PRING)GetWindowLong(hwnd, DWL_USER)
#define Ring_SetPtr(hwnd, lp) (PRING)SetWindowLong(hwnd, DWL_USER, (LONG)(lp))
//-----------------------------------------------------------------------------------
// Voice settings dialog code
//-----------------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: Initialize the bitmap strip
Returns: --
Cond: --
*/
void PRIVATE Ring_InitStrip(
PRING this,
HDC hdc)
{
ASSERT(hdc);
this->hbmStrip = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_PATTERNS));
ASSERT(this->hbmStrip);
this->hdcStrip = CreateCompatibleDC(hdc);
if (this->hdcStrip)
{
SelectObject(this->hdcStrip, this->hbmStrip);
}
}
/*----------------------------------------------------------
Purpose: Initialize the specified Pattern combobox.
Returns: --
Cond: --
*/
void PRIVATE Ring_InitPattern(
PRING this,
HWND hwndCB,
DWORD dwPattern)
{
int i;
int iSel = 0;
int n;
// Fill the listbox
for (i = 0; i < ARRAY_ELEMENTS(s_rgrp); i++)
{
n = ComboBox_AddString(hwndCB, &s_rgrp[i]);
// Keep our eyes peeled for the selected type
if (dwPattern == s_rgrp[i].dwPattern)
{
iSel = n;
}
}
ComboBox_SetCurSel(hwndCB, iSel);
}
/*----------------------------------------------------------
Purpose: Initialize the specified Type of Call combobox.
Returns: --
Cond: --
*/
void PRIVATE Ring_InitTypeOfCall(
PRING this,
HWND hwndCB,
DWORD dwType)
{
#pragma data_seg(DATASEG_READONLY)
static const struct
{
UINT ids;
DWORD dwType; // DRT_*
} s_rgTypes[] =
{
{ IDS_UNSPECIFIED, DRT_UNSPECIFIED },
{ IDS_DATA, DRT_DATA },
{ IDS_FAX, DRT_FAX },
{ IDS_VOICE, DRT_VOICE },
};
#pragma data_seg()
int i;
int iSel = 0;
int n;
TCHAR sz[MAXMEDLEN];
// Fill the listbox
for (i = 0; i < ARRAY_ELEMENTS(s_rgTypes); i++)
{
n = ComboBox_AddString(hwndCB, SzFromIDS(g_hinst, s_rgTypes[i].ids, sz, SIZECHARS(sz)));
ComboBox_SetItemData(hwndCB, n, s_rgTypes[i].dwType);
// Keep our eyes peeled for the selected type
if (dwType == s_rgTypes[i].dwType)
{
iSel = n;
}
}
ComboBox_SetCurSel(hwndCB, iSel);
}
/*----------------------------------------------------------
Purpose: Enable/disable all the controls
Returns: --
Cond: --
*/
void PRIVATE Ring_EnableControls(
PRING this,
BOOL bEnable)
{
HWND hwnd = this->hdlg;
EnableWindow(GetDlgItem(hwnd, IDC_LBL_ADDR_PRI), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_ADDR_PRI), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_ADDR_PRI), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_ADDR1), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_ADDR1), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_ADDR1), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_ADDR2), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_ADDR2), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_ADDR2), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_ADDR3), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_ADDR3), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_ADDR3), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_PRI_CALLERS), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_PRI_CALLERS), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_PRI_CALLERS), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_CALLBACK), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_CALLBACK), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_CALLBACK), bEnable);
}
/*----------------------------------------------------------
Purpose: WM_INITDIALOG Handler
Returns: FALSE when we assign the control focus
Cond: --
*/
BOOL PRIVATE Ring_OnInitDialog(
PRING this,
HWND hwndFocus,
LPARAM lParam) // expected to be PROPSHEETINFO
{
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HWND hwnd = this->hdlg;
HWND hwndCtl;
LPDWORD lpdw;
BOOL bEnable;
int i;
PVOICEFEATURES pvs;
HDC hdc;
LOGFONT lf;
ASSERT((LPTSTR)lppsp->lParam);
this->pmi = (LPMODEMINFO)lppsp->lParam;
pvs = &this->pmi->pglobal->vs;
// Determine some font things
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
this->hfont = CreateFontIndirect(&lf);
// Create bitmap strip
hdc = GetDC(hwnd);
if (hdc)
{
Ring_InitStrip(this, hdc);
ReleaseDC(hwnd, hdc);
}
// Enable/disable controls
bEnable = IsFlagSet(this->pmi->pglobal->vs.dwFlags, VSF_DIST_RING);
Button_SetCheck(GetDlgItem(hwnd, IDC_RING_CHECK), bEnable);
Ring_EnableControls(this, bEnable);
// Initialize controls
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcPattern); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcPattern[i]);
lpdw = &pvs->DistRing[i].dwPattern;
Ring_InitPattern(this, hwndCtl, *lpdw);
}
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcTypeOfCalls); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcTypeOfCalls[i]);
lpdw = &pvs->DistRing[i].dwMediaType;
Ring_InitTypeOfCall(this, hwndCtl, *lpdw);
}
return TRUE; // default initial focus
}
/*----------------------------------------------------------
Purpose: WM_COMMAND Handler
Returns: --
Cond: --
*/
void PRIVATE Ring_OnCommand(
PRING this,
int id,
HWND hwndCtl,
UINT uNotifyCode)
{
BOOL bCheck;
switch (id)
{
case IDC_RING_CHECK:
bCheck = Button_GetCheck(hwndCtl);
Ring_EnableControls(this, bCheck);
break;
default:
break;
}
}
/*----------------------------------------------------------
Purpose: Validate the user's settings.
The ring patterns must be unique, except that
any/all may be set to DRP_NONE.
Returns: TRUE if valid
Cond: --
*/
BOOL PRIVATE Ring_ValidateSettings(
PRING this)
{
HWND hwnd = this->hdlg;
int i;
int iSel;
HWND hwndCtl;
PRINGPAT prp;
for (i = 0; i < ARRAY_ELEMENTS(s_rgrp); i++)
{
// Initialize lParam to 0
s_rgrp[i].lParam = 0;
}
// Get the ring pattern settings
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcPattern); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcPattern[i]);
iSel = ComboBox_GetCurSel(hwndCtl);
ASSERT(LB_ERR != iSel);
ComboBox_GetLBText(hwndCtl, iSel, &prp);
// Is this pattern already selected,
// and is it something other than none?
if (DRP_NONE != prp->dwPattern && prp->lParam)
{
// Yes; can't have duplicate values
MsgBox(g_hinst,
hwnd,
MAKEINTRESOURCE(IDS_ERR_DUP_PATTERN),
MAKEINTRESOURCE(IDS_CAP_RING),
NULL,
MB_ERROR);
// Set the focus on the offending control
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndCtl, (LPARAM)TRUE);
return FALSE;
}
prp->lParam = TRUE;
}
return TRUE;
}
/*----------------------------------------------------------
Purpose: PSN_APPLY handler
Returns: TRUE if validation succeeded
FALSE if not
Cond: --
*/
BOOL PRIVATE Ring_OnApply(
PRING this)
{
BOOL bRet;
HWND hwnd = this->hdlg;
HWND hwndCtl;
LPDWORD lpdw;
int i;
int iSel;
PVOICEFEATURES pvs = &this->pmi->pglobal->vs;
PRINGPAT prp;
bRet = Ring_ValidateSettings(this);
// Are the user's settings valid?
if (bRet)
{
// Yes
if (Button_GetCheck(GetDlgItem(hwnd, IDC_RING_CHECK)))
{
SetFlag(pvs->dwFlags, VSF_DIST_RING);
}
else
{
ClearFlag(pvs->dwFlags, VSF_DIST_RING);
}
// Get the ring pattern settings
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcPattern); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcPattern[i]);
lpdw = &pvs->DistRing[i].dwPattern;
iSel = ComboBox_GetCurSel(hwndCtl);
ASSERT(LB_ERR != iSel);
ComboBox_GetLBText(hwndCtl, iSel, &prp);
*lpdw = prp->dwPattern;
}
// Get the type of call settings
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcTypeOfCalls); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcTypeOfCalls[i]);
lpdw = &pvs->DistRing[i].dwMediaType;
iSel = ComboBox_GetCurSel(hwndCtl);
ASSERT(LB_ERR != iSel);
*lpdw = ComboBox_GetItemData(hwndCtl, iSel);
}
}
return bRet;
}
/*----------------------------------------------------------
Purpose: WM_NOTIFY handler
Returns: varies
Cond: --
*/
LRESULT PRIVATE Ring_OnNotify(
PRING this,
int idFrom,
NMHDR FAR * lpnmhdr)
{
LRESULT lRet = 0;
switch (lpnmhdr->code)
{
case PSN_SETACTIVE:
break;
case PSN_KILLACTIVE:
// N.b. This message is not sent if user clicks Cancel!
// N.b. This message is sent prior to PSN_APPLY
//
break;
case PSN_APPLY:
lRet = Ring_OnApply(this) ? PSNRET_NOERROR : PSNRET_INVALID;
break;
default:
break;
}
return lRet;
}
/*----------------------------------------------------------
Purpose: WM_DESTROY handler
Returns: --
Cond: --
*/
void PRIVATE Ring_OnDestroy(
PRING this)
{
if (this->hdcStrip)
DeleteDC(this->hdcStrip);
if (this->hbmStrip)
DeleteObject(this->hbmStrip);
if (this->hfont)
DeleteFont(this->hfont);
}
/*----------------------------------------------------------
Purpose: WM_MEASUREITEM handler
Returns: --
Cond: !!! WM_MEASUREITEM is received before WM_INITDIALOG !!!
The contents of 'this' will be uninitialized.
*/
void PRIVATE Ring_OnMeasureItem(
PRING this,
LPMEASUREITEMSTRUCT lpmis)
{
HWND hwnd = this->hdlg;
HDC hdc;
ASSERT(ODT_COMBOBOX == lpmis->CtlType);
hdc = GetDC(hwnd);
if (hdc)
{
TEXTMETRIC tm;
GetTextMetrics(hdc, &tm);
lpmis->itemHeight = max(tm.tmHeight, CY_PATTERN);
ReleaseDC(hwnd, hdc);
}
}
/*----------------------------------------------------------
Purpose: WM_DRAWITEM handler
Returns: --
Cond: --
*/
void PRIVATE Ring_OnDrawCBItem(
PRING this,
const DRAWITEMSTRUCT FAR * lpcdis)
{
HWND hwnd = this->hdlg;
PRINGPAT prp = (PRINGPAT)lpcdis->itemData;
ASSERT(ODT_COMBOBOX == lpcdis->CtlType);
ASSERT(prp);
if (prp)
{
HDC hdc = lpcdis->hDC;
RECT rc = lpcdis->rcItem;
RECT rcFrame;
POINT ptSav;
int x;
int y;
int nBkMode;
COLORREF crText;
COLORREF crBk;
COLORREF crTextSav;
COLORREF crBkSav;
ASSERT(hdc);
SetViewportOrgEx(hdc, rc.left, rc.top, &ptSav);
rcFrame.top = 0;
rcFrame.left = 0;
rcFrame.bottom = rc.bottom - rc.top;
rcFrame.right = rc.right - rc.left;
// Set the colors
nBkMode = SetBkMode(hdc, TRANSPARENT);
TextAndBkCr(lpcdis, &crText, &crBk);
crTextSav = SetTextColor(hdc, crText);
crBkSav = SetBkColor(hdc, crBk);
// Do we need to redraw everything?
if (IsFlagSet(lpcdis->itemAction, ODA_DRAWENTIRE) ||
IsFlagSet(lpcdis->itemAction, ODA_SELECT))
{
// Yes
TCHAR sz[MAXSHORTLEN];
LPTSTR psz = sz;
int cch;
HFONT hfontSav;
// Show bitmap or text?
if (DRP_NONE == prp->dwPattern)
{
// Text
hfontSav = SelectFont(hdc, this->hfont);
SzFromIDS(g_hinst, IDS_AUTOMATIC, sz, SIZECHARS(sz));
cch = lstrlen(sz);
}
else
{
// Bitmap
hfontSav = NULL;
*psz = 0;
cch = 0;
}
ASSERT(rc.right - rc.left >= CX_PATTERN);
ASSERT(rc.bottom - rc.top >= CY_PATTERN);
x = (rc.right - rc.left - CX_PATTERN) / 2;
y = (rc.bottom - rc.top - CY_PATTERN) / 2;
// Fill background (with optional text)
ExtTextOut(hdc, 2, 2, ETO_OPAQUE, &rcFrame, psz, cch, NULL);
if (DRP_NONE != prp->dwPattern)
{
// Draw bitmap
BitBlt(hdc, x, y, CX_PATTERN, CY_PATTERN,
this->hdcStrip, ((int)prp->dwPattern - 1) * CX_PATTERN, 0,
SRCCOPY);
}
if (hfontSav)
SelectFont(hdc, hfontSav);
}
// Draw the caret?
if (IsFlagSet(lpcdis->itemAction, ODA_FOCUS) ||
IsFlagSet(lpcdis->itemState, ODS_FOCUS))
{
// Yes
DrawFocusRect(hdc, &rcFrame);
}
// Clean up
SetTextColor(hdc, crTextSav);
SetBkColor(hdc, crBkSav);
SetBkMode(hdc, nBkMode);
SetViewportOrgEx(hdc, ptSav.x, ptSav.y, NULL);
}
}
/*----------------------------------------------------------
Purpose: WM_DRAWITEM handler
Returns: --
Cond: --
*/
void PRIVATE Ring_OnDrawStaticItem(
PRING this,
const DRAWITEMSTRUCT FAR * lpcdis)
{
HWND hwnd = this->hdlg;
HDC hdc = lpcdis->hDC;
RECT rc = lpcdis->rcItem;
int x;
int y;
int nBkMode;
COLORREF crText;
COLORREF crBk;
COLORREF crTextSav;
COLORREF crBkSav;
ASSERT(ODT_STATIC == lpcdis->CtlType);
ASSERT(hdc);
// Set the colors
nBkMode = SetBkMode(hdc, TRANSPARENT);
TextAndBkCr(lpcdis, &crText, &crBk);
crTextSav = SetTextColor(hdc, crText);
crBkSav = SetBkColor(hdc, crBk);
ASSERT(rc.right - rc.left >= CX_PATTERN);
ASSERT(rc.bottom - rc.top >= CY_PATTERN);
x = (rc.right - rc.left - CX_PATTERN) / 2;
y = (rc.bottom - rc.top - CY_PATTERN) / 2;
// Fill background (with optional text)
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, TEXT(""), 0, NULL);
// Draw bitmap
BitBlt(hdc, x, y, CX_PATTERN, CY_PATTERN,
this->hdcStrip, (int)(DRP_LONG - 1) * CX_PATTERN, 0,
SRCCOPY);
// Clean up
SetTextColor(hdc, crTextSav);
SetBkColor(hdc, crBkSav);
SetBkMode(hdc, nBkMode);
}
/*----------------------------------------------------------
Purpose: WM_DRAWITEM handler
Returns: --
Cond: --
*/
void PRIVATE Ring_OnDrawItem(
PRING this,
const DRAWITEMSTRUCT FAR * lpcdis)
{
switch (lpcdis->CtlType)
{
case ODT_COMBOBOX:
Ring_OnDrawCBItem(this, lpcdis);
break;
case ODT_STATIC:
Ring_OnDrawStaticItem(this, lpcdis);
break;
default:
ASSERT(0);
break;
}
}
/*----------------------------------------------------------
Purpose: WM_DELETEITEM handler
Returns: --
Cond: !!! WM_DELETEITEM is received after WM_DESTROY !!!
*/
void Ring_OnDeleteItem(
PRING this,
const DELETEITEMSTRUCT FAR * lpcdis)
{
PRINGPAT prp = (PRINGPAT)lpcdis->itemData;
ASSERT(NULL == this); // this will be NULL
ASSERT(ODT_COMBOBOX == lpcdis->CtlType);
ASSERT(prp);
}
static BOOL s_bRingRecurse = FALSE;
LRESULT INLINE Ring_DefProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
ENTER_X()
{
s_bRingRecurse = TRUE;
}
LEAVE_X()
return DefDlgProc(hDlg, msg, wParam, lParam);
}
/*----------------------------------------------------------
Purpose: Real dialog proc
Returns: varies
Cond: --
*/
LRESULT Ring_DlgProc(
PRING this,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
#ifdef CS_HELP
// UE used the control IDs as help IDs. To prevent mix-ups in
// the future (ie, when the control IDs change), here are the
// help IDs.
#define IDH_UNI_RING_SERVICES 1069
#define IDH_UNI_RING_LBL_ADDR_PRI 1070
#define IDH_UNI_RING_ADDR_PRI 1073
#define IDH_UNI_RING_TYPE_ADDR_PRI 1082
#define IDH_UNI_RING_LBL_ADDR1 1071
#define IDH_UNI_RING_ADDR1 1074
#define IDH_UNI_RING_TYPE_ADDR1 1083
#define IDH_UNI_RING_LBL_ADDR2 1072
#define IDH_UNI_RING_ADDR2 1075
#define IDH_UNI_RING_TYPE_ADDR2 1084
#define IDH_UNI_RING_LBL_ADDR3 1076
#define IDH_UNI_RING_ADDR3 1077
#define IDH_UNI_RING_TYPE_ADDR3 1085
#define IDH_UNI_RING_LBL_PRI_CALLERS 1078
#define IDH_UNI_RING_PRI_CALLERS 1079
#define IDH_UNI_RING_TYPE_PRI_CALLERS 1086
#define IDH_UNI_RING_LBL_CALLBACK 1080
#define IDH_UNI_RING_CALLBACK 1081
#define IDH_UNI_RING_TYPE_CALLBACK 1087
#pragma data_seg(DATASEG_READONLY)
const static DWORD rgHelpIDs[] = {
IDC_RING_CHECK, IDH_UNI_RING_SERVICES,
IDC_LBL_ADDR_PRI, IDH_UNI_RING_LBL_ADDR_PRI,
IDC_ADDR_PRI, IDH_UNI_RING_ADDR_PRI,
IDC_TYPE_ADDR_PRI, IDH_UNI_RING_TYPE_ADDR_PRI,
IDC_LBL_ADDR1, IDH_UNI_RING_LBL_ADDR1,
IDC_ADDR1, IDH_UNI_RING_ADDR1,
IDC_TYPE_ADDR1, IDH_UNI_RING_TYPE_ADDR1,
IDC_LBL_ADDR2, IDH_UNI_RING_LBL_ADDR2,
IDC_ADDR2, IDH_UNI_RING_ADDR2,
IDC_TYPE_ADDR2, IDH_UNI_RING_TYPE_ADDR2,
IDC_LBL_ADDR3, IDH_UNI_RING_LBL_ADDR3,
IDC_ADDR3, IDH_UNI_RING_ADDR3,
IDC_TYPE_ADDR3, IDH_UNI_RING_TYPE_ADDR3,
IDC_LBL_PRI_CALLERS, IDH_UNI_RING_LBL_PRI_CALLERS,
IDC_PRI_CALLERS, IDH_UNI_RING_PRI_CALLERS,
IDC_TYPE_PRI_CALLERS, IDH_UNI_RING_TYPE_PRI_CALLERS,
IDC_LBL_CALLBACK, IDH_UNI_RING_LBL_CALLBACK,
IDC_CALLBACK, IDH_UNI_RING_CALLBACK,
IDC_TYPE_CALLBACK, IDH_UNI_RING_TYPE_CALLBACK,
0, 0 };
#pragma data_seg()
#endif
switch (message)
{
HANDLE_MSG(this, WM_INITDIALOG, Ring_OnInitDialog);
HANDLE_MSG(this, WM_COMMAND, Ring_OnCommand);
HANDLE_MSG(this, WM_NOTIFY, Ring_OnNotify);
HANDLE_MSG(this, WM_DESTROY, Ring_OnDestroy);
HANDLE_MSG(this, WM_MEASUREITEM, Ring_OnMeasureItem);
HANDLE_MSG(this, WM_DRAWITEM, Ring_OnDrawItem);
HANDLE_MSG(this, WM_DELETEITEM, Ring_OnDeleteItem);
#ifdef CS_HELP
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szUnimdmHelpFile, HELP_WM_HELP, (DWORD)(LPVOID)rgHelpIDs);
return 0;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, c_szUnimdmHelpFile, HELP_CONTEXTMENU, (DWORD)(LPVOID)rgHelpIDs);
return 0;
#endif
default:
return Ring_DefProc(this->hdlg, message, wParam, lParam);
}
}
/*----------------------------------------------------------
Purpose: Dialog Wrapper
Returns: varies
Cond: --
*/
BOOL CALLBACK Ring_WrapperProc(
HWND hDlg, // std params
UINT message,
WPARAM wParam,
LPARAM lParam)
{
PRING this;
// Cool windowsx.h dialog technique. For full explanation, see
// WINDOWSX.TXT. This supports multiple-instancing of dialogs.
//
ENTER_X()
{
if (s_bRingRecurse)
{
s_bRingRecurse = FALSE;
LEAVE_X()
return FALSE;
}
}
LEAVE_X()
this = Ring_GetPtr(hDlg);
if (this == NULL)
{
// (WM_SETFONT is the first message received by dialogs)
if (WM_SETFONT == message)
{
this = (PRING)LocalAlloc(LPTR, sizeof(RING));
if (!this)
{
MsgBox(g_hinst,
hDlg,
MAKEINTRESOURCE(IDS_OOM_SETTINGS),
MAKEINTRESOURCE(IDS_CAP_RING),
NULL,
MB_ERROR);
EndDialog(hDlg, IDCANCEL);
return (BOOL)Ring_DefProc(hDlg, message, wParam, lParam);
}
this->hdlg = hDlg;
Ring_SetPtr(hDlg, this);
}
else
{
return (BOOL)Ring_DefProc(hDlg, message, wParam, lParam);
}
}
if (message == WM_DESTROY)
{
Ring_DlgProc(this, message, wParam, lParam);
LocalFree((HLOCAL)OFFSETOF(this));
Ring_SetPtr(hDlg, NULL);
return 0;
}
return SetDlgMsgResult(hDlg, message, Ring_DlgProc(this, message, wParam, lParam));
}
//-----------------------------------------------------------------------------------
// Cheap ring dialog code
//-----------------------------------------------------------------------------------
#define CheapRing_GetPtr(hwnd) (PRING)GetWindowLong(hwnd, DWL_USER)
#define CheapRing_SetPtr(hwnd, lp) (PRING)SetWindowLong(hwnd, DWL_USER, (LONG)(lp))
/*----------------------------------------------------------
Purpose: Initialize the specified Type of Call combobox.
Returns: --
Cond: --
*/
void PRIVATE CheapRing_InitTypeOfCall(
PRING this,
HWND hwndCB,
DWORD dwType)
{
#pragma data_seg(DATASEG_READONLY)
static const struct
{
UINT ids;
DWORD dwType; // DRT_*
} s_rgTypes[] =
{
{ IDS_UNSPECIFIED, DRT_UNSPECIFIED },
{ IDS_DATA, DRT_DATA },
{ IDS_FAX, DRT_FAX },
{ IDS_VOICE, DRT_VOICE },
};
#pragma data_seg()
int i;
int iSel = 0;
int n;
TCHAR sz[MAXMEDLEN];
// Fill the listbox
for (i = 0; i < ARRAY_ELEMENTS(s_rgTypes); i++)
{
n = ComboBox_AddString(hwndCB, SzFromIDS(g_hinst, s_rgTypes[i].ids, sz, SIZECHARS(sz)));
ComboBox_SetItemData(hwndCB, n, s_rgTypes[i].dwType);
// Keep our eyes peeled for the selected type
if (dwType == s_rgTypes[i].dwType)
{
iSel = n;
}
}
ComboBox_SetCurSel(hwndCB, iSel);
}
/*----------------------------------------------------------
Purpose: Enable/disable all the controls
Returns: --
Cond: --
*/
void PRIVATE CheapRing_EnableControls(
PRING this,
BOOL bEnable)
{
HWND hwnd = this->hdlg;
EnableWindow(GetDlgItem(hwnd, IDC_LBL_RING1), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_RING1), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_RING2), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_RING2), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_LBL_RING3), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_TYPE_RING3), bEnable);
}
/*----------------------------------------------------------
Purpose: WM_INITDIALOG Handler
Returns: FALSE when we assign the control focus
Cond: --
*/
BOOL PRIVATE CheapRing_OnInitDialog(
PRING this,
HWND hwndFocus,
LPARAM lParam) // expected to be PROPSHEETINFO
{
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HWND hwnd = this->hdlg;
HWND hwndCtl;
LPDWORD lpdw;
BOOL bEnable;
int i;
PVOICEFEATURES pvs;
ASSERT((LPTSTR)lppsp->lParam);
this->pmi = (LPMODEMINFO)lppsp->lParam;
pvs = &this->pmi->pglobal->vs;
// Enable/disable controls
bEnable = IsFlagSet(this->pmi->pglobal->vs.dwFlags, VSF_DIST_RING);
Button_SetCheck(GetDlgItem(hwnd, IDC_RING_CHECK), bEnable);
CheapRing_EnableControls(this, bEnable);
// Initialize controls
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcTypeOfCheapCalls); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcTypeOfCheapCalls[i]);
lpdw = &pvs->DistRing[i].dwMediaType;
CheapRing_InitTypeOfCall(this, hwndCtl, *lpdw);
}
return TRUE; // default initial focus
}
/*----------------------------------------------------------
Purpose: WM_COMMAND Handler
Returns: --
Cond: --
*/
void PRIVATE CheapRing_OnCommand(
PRING this,
int id,
HWND hwndCtl,
UINT uNotifyCode)
{
BOOL bCheck;
switch (id)
{
case IDC_RING_CHECK:
bCheck = Button_GetCheck(hwndCtl);
CheapRing_EnableControls(this, bCheck);
break;
default:
break;
}
}
/*----------------------------------------------------------
Purpose: PSN_APPLY handler
Returns: TRUE if validation succeeded
FALSE if not
Cond: --
*/
BOOL PRIVATE CheapRing_OnApply(
PRING this)
{
HWND hwnd = this->hdlg;
HWND hwndCtl;
LPDWORD lpdw;
int i;
int iSel;
PVOICEFEATURES pvs = &this->pmi->pglobal->vs;
if (Button_GetCheck(GetDlgItem(hwnd, IDC_RING_CHECK)))
{
SetFlag(pvs->dwFlags, VSF_DIST_RING);
}
else
{
ClearFlag(pvs->dwFlags, VSF_DIST_RING);
}
// Get the ring pattern settings
for (i = 0; i < ARRAY_ELEMENTS(c_rgdwCheapPatterns); i++)
{
pvs->DistRing[i].dwPattern = c_rgdwCheapPatterns[i];
}
// Get the type of call settings
for (i = 0; i < ARRAY_ELEMENTS(c_rgidcTypeOfCheapCalls); i++)
{
hwndCtl = GetDlgItem(hwnd, c_rgidcTypeOfCheapCalls[i]);
lpdw = &pvs->DistRing[i].dwMediaType;
iSel = ComboBox_GetCurSel(hwndCtl);
ASSERT(LB_ERR != iSel);
*lpdw = ComboBox_GetItemData(hwndCtl, iSel);
}
return TRUE;
}
/*----------------------------------------------------------
Purpose: WM_NOTIFY handler
Returns: varies
Cond: --
*/
LRESULT PRIVATE CheapRing_OnNotify(
PRING this,
int idFrom,
NMHDR FAR * lpnmhdr)
{
LRESULT lRet = 0;
switch (lpnmhdr->code)
{
case PSN_SETACTIVE:
break;
case PSN_KILLACTIVE:
// N.b. This message is not sent if user clicks Cancel!
// N.b. This message is sent prior to PSN_APPLY
//
break;
case PSN_APPLY:
lRet = CheapRing_OnApply(this) ? PSNRET_NOERROR : PSNRET_INVALID;
break;
default:
break;
}
return lRet;
}
static BOOL s_bCheapRingRecurse = FALSE;
LRESULT INLINE CheapRing_DefProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
ENTER_X()
{
s_bCheapRingRecurse = TRUE;
}
LEAVE_X()
return DefDlgProc(hDlg, msg, wParam, lParam);
}
/*----------------------------------------------------------
Purpose: Real dialog proc
Returns: varies
Cond: --
*/
LRESULT CheapRing_DlgProc(
PRING this,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
#ifdef CS_HELP
// UE used the control IDs as help IDs. To prevent mix-ups in
// the future (ie, when the control IDs change), here are the
// help IDs.
#define IDH_UNI_RING_LBL_RING1 1088
#define IDH_UNI_RING_TYPE_RING1 1091
#define IDH_UNI_RING_LBL_RING2 1089
#define IDH_UNI_RING_TYPE_RING2 1092
#define IDH_UNI_RING_LBL_RING3 1090
#define IDH_UNI_RING_TYPE_RING3 1093
#pragma data_seg(DATASEG_READONLY)
const static DWORD rgHelpIDs[] = {
IDC_RING_CHECK, IDH_UNI_RING_SERVICES,
IDC_LBL_RING1, IDH_UNI_RING_LBL_RING1,
IDC_TYPE_RING1, IDH_UNI_RING_TYPE_RING1,
IDC_LBL_RING2, IDH_UNI_RING_LBL_RING2,
IDC_TYPE_RING2, IDH_UNI_RING_TYPE_RING2,
IDC_LBL_RING3, IDH_UNI_RING_LBL_RING3,
IDC_TYPE_RING3, IDH_UNI_RING_TYPE_RING3,
0, 0 };
#pragma data_seg()
#endif
switch (message)
{
HANDLE_MSG(this, WM_INITDIALOG, CheapRing_OnInitDialog);
HANDLE_MSG(this, WM_COMMAND, CheapRing_OnCommand);
HANDLE_MSG(this, WM_NOTIFY, CheapRing_OnNotify);
#ifdef CS_HELP
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szUnimdmHelpFile, HELP_WM_HELP, (DWORD)(LPVOID)rgHelpIDs);
return 0;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, c_szUnimdmHelpFile, HELP_CONTEXTMENU, (DWORD)(LPVOID)rgHelpIDs);
return 0;
#endif
default:
return CheapRing_DefProc(this->hdlg, message, wParam, lParam);
}
}
/*----------------------------------------------------------
Purpose: Dialog Wrapper
Returns: varies
Cond: --
*/
BOOL CALLBACK CheapRing_WrapperProc(
HWND hDlg, // std params
UINT message,
WPARAM wParam,
LPARAM lParam)
{
PRING this;
// Cool windowsx.h dialog technique. For full explanation, see
// WINDOWSX.TXT. This supports multiple-instancing of dialogs.
//
ENTER_X()
{
if (s_bCheapRingRecurse)
{
s_bCheapRingRecurse = FALSE;
LEAVE_X()
return FALSE;
}
}
LEAVE_X()
this = CheapRing_GetPtr(hDlg);
if (this == NULL)
{
// (WM_SETFONT is the first message received by dialogs)
if (WM_SETFONT == message)
{
this = (PRING)LocalAlloc(LPTR, sizeof(RING));
if (!this)
{
MsgBox(g_hinst,
hDlg,
MAKEINTRESOURCE(IDS_OOM_SETTINGS),
MAKEINTRESOURCE(IDS_CAP_RING),
NULL,
MB_ERROR);
EndDialog(hDlg, IDCANCEL);
return (BOOL)CheapRing_DefProc(hDlg, message, wParam, lParam);
}
this->hdlg = hDlg;
CheapRing_SetPtr(hDlg, this);
}
else
{
return (BOOL)CheapRing_DefProc(hDlg, message, wParam, lParam);
}
}
if (message == WM_DESTROY)
{
CheapRing_DlgProc(this, message, wParam, lParam);
LocalFree((HLOCAL)OFFSETOF(this));
CheapRing_SetPtr(hDlg, NULL);
return 0;
}
return SetDlgMsgResult(hDlg, message, CheapRing_DlgProc(this, message, wParam, lParam));
}
//-----------------------------------------------------------------------------------
// DTMF edit box proc
//-----------------------------------------------------------------------------------
/*----------------------------------------------------------
Purpose: Handle WM_CHAR
Returns: TRUE to let the characters by
FALSE to prohibit
Cond: --
*/
BOOL PRIVATE DTMFEditProc_OnChar(
HWND hwnd,
UINT ch,
int cRepeat)
{
BOOL bRet;
// Is this a numerical digit,
// a backspace,
// or a valid DTMF digit?
if (IsCharAlphaNumeric((TCHAR)ch) && !IsCharAlpha((TCHAR)ch) ||
VK_BACK == LOBYTE(VkKeyScan((TCHAR)ch)) ||
'A' == ch || 'B' == ch || 'C' == ch || 'D' == ch ||
'*' == ch || '#' == ch)
{
// Yes
bRet = TRUE;
}
else
{
// No
MessageBeep(MB_OK);
bRet = FALSE;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Number proc. Only allow numbers to be entered into this edit box.
Returns: varies
Cond: --
*/
LRESULT CALLBACK DTMFEditProc(
HWND hwnd, // std params
UINT message,
WPARAM wParam,
LPARAM lParam)
{
WNDPROC pfn = (WNDPROC)GetWindowLong(hwnd, GWL_USERDATA);
// BUGBUG: doesn't handle paste correctly!
switch (message)
{
case WM_CHAR:
if (!DTMFEditProc_OnChar(hwnd, (UINT)wParam, LOWORD(lParam)))
return 1; // Don't process this character
break;
}
return CallWindowProc(pfn, hwnd, message, wParam, lParam);
}
//-----------------------------------------------------------------------------------
// Call forwarding dialog code
//-----------------------------------------------------------------------------------
typedef struct tagCALLFWD
{
HWND hdlg; // dialog handle
LPMODEMINFO pmi; // modeminfo struct passed into dialog
} CALLFWD, FAR * PCALLFWD;
#define CallFwd_GetPtr(hwnd) (PCALLFWD)GetWindowLong(hwnd, DWL_USER)
#define CallFwd_SetPtr(hwnd, lp) (PCALLFWD)SetWindowLong(hwnd, DWL_USER, (LONG)(lp))
/*----------------------------------------------------------
Purpose: Enable/disable all the controls
Returns: --
Cond: --
*/
void PRIVATE CallFwd_EnableControls(
PCALLFWD this,
BOOL bEnable)
{
HWND hwnd = this->hdlg;
EnableWindow(GetDlgItem(hwnd, IDC_FWD_ACT), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_ACT), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_FWD_DEACT), bEnable);
EnableWindow(GetDlgItem(hwnd, IDC_DEACT), bEnable);
}
/*----------------------------------------------------------
Purpose: WM_INITDIALOG Handler
Returns: FALSE when we assign the control focus
Cond: --
*/
BOOL PRIVATE CallFwd_OnInitDialog(
PCALLFWD this,
HWND hwndFocus,
LPARAM lParam) // expected to be PROPSHEETINFO
{
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HWND hwnd = this->hdlg;
HWND hwndCtl;
BOOL bEnable;
PVOICEFEATURES pvs;
WNDPROC pfn;
ASSERT((LPTSTR)lppsp->lParam);
this->pmi = (LPMODEMINFO)lppsp->lParam;
pvs = &this->pmi->pglobal->vs;
// Subclass the edit boxes that only accept DTMF digits
hwndCtl = GetDlgItem(hwnd, IDC_ACT);
pfn = SubclassWindow(hwndCtl, DTMFEditProc);
SetWindowLong(hwndCtl, GWL_USERDATA, (LONG)pfn);
hwndCtl = GetDlgItem(hwnd, IDC_DEACT);
pfn = SubclassWindow(hwndCtl, DTMFEditProc);
SetWindowLong(hwndCtl, GWL_USERDATA, (LONG)pfn);
// Enable/disable controls
bEnable = IsFlagSet(pvs->dwFlags, VSF_CALL_FWD);
Button_SetCheck(GetDlgItem(hwnd, IDC_FWD_CHECK), bEnable);
CallFwd_EnableControls(this, bEnable);
// Initialize controls
hwndCtl = GetDlgItem(hwnd, IDC_ACT);
Edit_SetText(hwndCtl, pvs->szActivationCode);
Edit_LimitText(hwndCtl, SIZECHARS(pvs->szActivationCode)-1);
hwndCtl = GetDlgItem(hwnd, IDC_DEACT);
Edit_SetText(hwndCtl, pvs->szDeactivationCode);
Edit_LimitText(hwndCtl, SIZECHARS(pvs->szDeactivationCode)-1);
return TRUE; // default initial focus
}
/*----------------------------------------------------------
Purpose: WM_COMMAND Handler
Returns: --
Cond: --
*/
void PRIVATE CallFwd_OnCommand(
PCALLFWD this,
int id,
HWND hwndCtl,
UINT uNotifyCode)
{
BOOL bCheck;
switch (id)
{
case IDC_FWD_CHECK:
bCheck = Button_GetCheck(hwndCtl);
CallFwd_EnableControls(this, bCheck);
break;
default:
break;
}
}
/*----------------------------------------------------------
Purpose: Validate the user's settings.
The call forwarding fields must be filled in if the
service is turned on.
Returns: TRUE if valid
Cond: --
*/
BOOL PRIVATE CallFwd_ValidateSettings(
PCALLFWD this)
{
HWND hwnd = this->hdlg;
HWND hwndCtl;
// Is the service turned on?
if (Button_GetCheck(GetDlgItem(hwnd, IDC_FWD_CHECK)))
{
// Yes; are the fields filled in?
hwndCtl = GetDlgItem(hwnd, IDC_ACT);
if (0 == Edit_GetTextLength(hwndCtl))
{
// No; this is naughty
MsgBox(g_hinst,
hwnd,
MAKEINTRESOURCE(IDS_ERR_NEED_VALUE),
MAKEINTRESOURCE(IDS_CAP_CALLFWD),
NULL,
MB_ERROR);
// Set the focus on the offending control
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndCtl, (LPARAM)TRUE);
return FALSE;
}
hwndCtl = GetDlgItem(hwnd, IDC_DEACT);
if (0 == Edit_GetTextLength(hwndCtl))
{
// No; this is naughty
MsgBox(g_hinst,
hwnd,
MAKEINTRESOURCE(IDS_ERR_NEED_VALUE),
MAKEINTRESOURCE(IDS_CAP_CALLFWD),
NULL,
MB_ERROR);
// Set the focus on the offending control
PostMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndCtl, (LPARAM)TRUE);
return FALSE;
}
}
return TRUE;
}
/*----------------------------------------------------------
Purpose: PSN_APPLY handler
Returns: --
Cond: --
*/
BOOL PRIVATE CallFwd_OnApply(
PCALLFWD this)
{
BOOL bRet;
HWND hwnd = this->hdlg;
HWND hwndCtl;
PVOICEFEATURES pvs = &this->pmi->pglobal->vs;
bRet = CallFwd_ValidateSettings(this);
if (bRet)
{
if (Button_GetCheck(GetDlgItem(hwnd, IDC_FWD_CHECK)))
{
SetFlag(pvs->dwFlags, VSF_CALL_FWD);
}
else
{
ClearFlag(pvs->dwFlags, VSF_CALL_FWD);
}
hwndCtl = GetDlgItem(hwnd, IDC_ACT);
Edit_GetText(hwndCtl, pvs->szActivationCode, SIZECHARS(pvs->szActivationCode));
hwndCtl = GetDlgItem(hwnd, IDC_DEACT);
Edit_GetText(hwndCtl, pvs->szDeactivationCode, SIZECHARS(pvs->szDeactivationCode));
}
return bRet;
}
/*----------------------------------------------------------
Purpose: WM_NOTIFY handler
Returns: varies
Cond: --
*/
LRESULT PRIVATE CallFwd_OnNotify(
PCALLFWD this,
int idFrom,
NMHDR FAR * lpnmhdr)
{
LRESULT lRet = 0;
switch (lpnmhdr->code)
{
case PSN_SETACTIVE:
break;
case PSN_KILLACTIVE:
// N.b. This message is not sent if user clicks Cancel!
// N.b. This message is sent prior to PSN_APPLY
//
break;
case PSN_APPLY:
lRet = CallFwd_OnApply(this) ? PSNRET_NOERROR : PSNRET_INVALID;
break;
default:
break;
}
return lRet;
}
static BOOL s_bCallFwdRecurse = FALSE;
LRESULT INLINE CallFwd_DefProc(
HWND hDlg,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
ENTER_X()
{
s_bCallFwdRecurse = TRUE;
}
LEAVE_X()
return DefDlgProc(hDlg, msg, wParam, lParam);
}
/*----------------------------------------------------------
Purpose: Real dialog proc
Returns: varies
Cond: --
*/
LRESULT CallFwd_DlgProc(
PCALLFWD this,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
#ifdef CS_HELP
// UE used the control IDs as help IDs. To prevent mix-ups in
// the future (ie, when the control IDs change), here are the
// help IDs.
#define IDH_UNI_CALLFWD_SERVICES 1062
#define IDH_UNI_CALLFWD_FWD_ACT 1063
#define IDH_UNI_CALLFWD_ACT 1068
#define IDH_UNI_CALLFWD_FWD_DEACT 1064
#define IDH_UNI_CALLFWD_DEACT 1067
#pragma data_seg(DATASEG_READONLY)
const static DWORD rgHelpIDs[] = {
IDC_FWD_CHECK, IDH_UNI_CALLFWD_SERVICES,
IDC_FWD_ACT, IDH_UNI_CALLFWD_FWD_ACT,
IDC_ACT, IDH_UNI_CALLFWD_ACT,
IDC_FWD_DEACT, IDH_UNI_CALLFWD_FWD_DEACT,
IDC_DEACT, IDH_UNI_CALLFWD_DEACT,
0, 0 };
#pragma data_seg()
#endif
switch (message)
{
HANDLE_MSG(this, WM_INITDIALOG, CallFwd_OnInitDialog);
HANDLE_MSG(this, WM_COMMAND, CallFwd_OnCommand);
HANDLE_MSG(this, WM_NOTIFY, CallFwd_OnNotify);
#ifdef CS_HELP
case WM_HELP:
WinHelp(((LPHELPINFO)lParam)->hItemHandle, c_szUnimdmHelpFile, HELP_WM_HELP, (DWORD)(LPVOID)rgHelpIDs);
return 0;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, c_szUnimdmHelpFile, HELP_CONTEXTMENU, (DWORD)(LPVOID)rgHelpIDs);
return 0;
#endif
default:
return CallFwd_DefProc(this->hdlg, message, wParam, lParam);
}
}
/*----------------------------------------------------------
Purpose: Dialog Wrapper
Returns: varies
Cond: --
*/
BOOL CALLBACK CallFwd_WrapperProc(
HWND hDlg, // std params
UINT message,
WPARAM wParam,
LPARAM lParam)
{
PCALLFWD this;
// Cool windowsx.h dialog technique. For full explanation, see
// WINDOWSX.TXT. This supports multiple-instancing of dialogs.
//
ENTER_X()
{
if (s_bCallFwdRecurse)
{
s_bCallFwdRecurse = FALSE;
LEAVE_X()
return FALSE;
}
}
LEAVE_X()
this = CallFwd_GetPtr(hDlg);
if (this == NULL)
{
if (message == WM_INITDIALOG)
{
this = (PCALLFWD)LocalAlloc(LPTR, sizeof(CALLFWD));
if (!this)
{
MsgBox(g_hinst,
hDlg,
MAKEINTRESOURCE(IDS_OOM_SETTINGS),
MAKEINTRESOURCE(IDS_CAP_RING),
NULL,
MB_ERROR);
EndDialog(hDlg, IDCANCEL);
return (BOOL)CallFwd_DefProc(hDlg, message, wParam, lParam);
}
this->hdlg = hDlg;
CallFwd_SetPtr(hDlg, this);
}
else
{
return (BOOL)CallFwd_DefProc(hDlg, message, wParam, lParam);
}
}
if (message == WM_DESTROY)
{
CallFwd_DlgProc(this, message, wParam, lParam);
LocalFree((HLOCAL)OFFSETOF(this));
CallFwd_SetPtr(hDlg, NULL);
return 0;
}
return SetDlgMsgResult(hDlg, message, CallFwd_DlgProc(this, message, wParam, lParam));
}