windows-nt/Source/XPSP1/NT/shell/osshell/ep/freecell/dialog.c
2020-09-26 16:20:57 +08:00

591 lines
17 KiB
C

/****************************************************************************
Dialog.c
June 91, JimH initial code
Oct 91, JimH port to Win32
Contains dialog box callback procedures.
****************************************************************************/
#include "freecell.h"
#include "freecons.h"
static void CentreDialog(HWND hDlg);
/****************************************************************************
MoveColDlg
If there is ambiguity about whether the user intends to move a single card
or a column to an empty column, this dialog lets the user decide.
The return code in EndDialog tells the caller the user's choice:
-1 user chose cancel
FALSE user chose to move a single card
TRUE user chose to move a column
****************************************************************************/
INT_PTR APIENTRY MoveColDlg(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
CentreDialog(hDlg);
return TRUE;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDCANCEL:
EndDialog(hDlg, -1);
return TRUE;
break;
case IDC_SINGLE:
EndDialog(hDlg, FALSE);
return TRUE;
break;
case IDC_MOVECOL:
EndDialog(hDlg, TRUE);
return TRUE;
break;
}
break;
}
return FALSE; /* Didn't process a message */
}
/****************************************************************************
GameNumDlg
The variable gamenumber must be set with a default value before this
dialog is invoked. That number is placed in an edit box where the user
can accept it by pressing Enter or change it. EndDialog returns TRUE
if the user chose a valid number (1 to MAXGAMENUMBER) and FALSE otherwise.
****************************************************************************/
INT_PTR APIENTRY GameNumDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
// For context sensitive help
static DWORD aIds[] = {
IDC_GAMENUM, IDH_GAMENUM,
0,0 };
switch (message) {
case WM_INITDIALOG: // set default gamenumber
CentreDialog(hDlg);
SetDlgItemInt(hDlg, IDC_GAMENUM, gamenumber, FALSE);
return TRUE;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDCANCEL:
gamenumber = CANCELGAME;
EndDialog(hDlg, TRUE);
return TRUE;
case IDOK:
gamenumber = (int) GetDlgItemInt(hDlg, IDC_GAMENUM, NULL, TRUE);
// negative #s are special cases -- unwinnable shuffles
if (gamenumber < -2 || gamenumber > MAXGAMENUMBER)
gamenumber = 0;
EndDialog(hDlg, gamenumber != 0);
return TRUE;
}
break;
// context sensitive help.
case WM_HELP:
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
HELP_WM_HELP, (ULONG_PTR) aIds);
break;
case WM_CONTEXTMENU:
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
(ULONG_PTR) aIds);
break;
}
return FALSE;
}
/****************************************************************************
YouWinDlg(HWND, unsigned, UINT, LONG)
****************************************************************************/
INT_PTR APIENTRY YouWinDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hSelect; // handle to check box
switch (message) {
case WM_INITDIALOG: // initialize checkbox
hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
SendMessage(hSelect, BM_SETCHECK, bSelecting, 0);
return TRUE;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDYES:
hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
bSelecting = (BOOL) SendMessage(hSelect, BM_GETCHECK, 0, 0);
EndDialog(hDlg, IDYES);
return TRUE;
case IDNO:
case IDCANCEL:
EndDialog(hDlg, IDNO);
return TRUE;
}
break;
}
return FALSE; // didn't process a message
}
/****************************************************************************
YouLoseDlg
The user can choose to play a new game (same shuffle or new shuffle) or not.
****************************************************************************/
INT_PTR APIENTRY YouLoseDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hSameGame; // handle to check box
BOOL bSame; // value of check box
switch (message) {
case WM_INITDIALOG:
CentreDialog(hDlg);
bGameInProgress = FALSE;
UpdateLossCount();
hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
SendMessage(hSameGame, BM_SETCHECK, TRUE, 0); // default to same
return TRUE;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDYES:
case IDOK:
hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
bSame = (BOOL) SendMessage(hSameGame, BM_GETCHECK, 0, 0);
if (bSame)
PostMessage(hMainWnd,WM_COMMAND,IDM_RESTART,gamenumber);
else
{
if (bSelecting)
PostMessage(hMainWnd, WM_COMMAND, IDM_SELECT, 0);
else
PostMessage(hMainWnd, WM_COMMAND, IDM_NEWGAME, 0);
}
EndDialog(hDlg, TRUE);
return TRUE;
case IDNO:
case IDCANCEL:
gamenumber = 0;
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
#define ARRAYSIZE(a) ( sizeof(a) / sizeof(a[0]) )
/****************************************************************************
StatsDlg
This dialog box shows current wins and losses, as well as total stats
including data from .ini file.
The IDC_CLEAR message clears out the entire section from the .ini file.
****************************************************************************/
INT_PTR APIENTRY StatsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hText; // handle to text control with stats
UINT cTLost, cTWon; // total losses and wins
UINT cTLosses, cTWins; // streaks
UINT wPct; // winning % this session
UINT wTPct; // winning % including .ini data
UINT wStreak; // current streak amount
UINT wSType; // current streak type
TCHAR sbuffer[40]; // streak buffer
int nResp; // messagebox response
TCHAR buffer[256]; // extra buffer needed for loadingstrings.
LONG lRegResult; // used to store return code from registry call
// for context sensitive help
static DWORD aIds[] = {
IDC_CLEAR, IDH_CLEAR,
IDC_STEXT1, IDH_STEXT1,
IDC_STEXT2, IDH_STEXT2,
IDC_STEXT3, IDH_STEXT3,
0,0 };
switch (message) {
case WM_INITDIALOG:
CentreDialog(hDlg);
wPct = CalcPercentage(cWins, cLosses);
/* Get cT... data from the registry */
lRegResult = REGOPEN
if (ERROR_SUCCESS == lRegResult)
{
cTLost = GetInt(pszLost, 0);
cTWon = GetInt(pszWon, 0);
wTPct = CalcPercentage(cTWon, cTLost);
cTLosses = GetInt(pszLosses, 0);
cTWins = GetInt(pszWins, 0);
wStreak = GetInt(pszStreak, 0);
if (wStreak != 0)
{
wSType = GetInt(pszSType, 0);
if (wStreak == 1)
{
LoadString(hInst, (wSType == WON ? IDS_1WIN : IDS_1LOSS),
sbuffer, ARRAYSIZE(sbuffer));
}
else
{
LoadString(hInst, (wSType == WON ? IDS_WINS : IDS_LOSSES),
smallbuf, SMALL);
wsprintf(sbuffer, smallbuf, wStreak);
}
}
else
wsprintf(sbuffer, TEXT("%u"), 0);
// set the dialog text.
LoadString(hInst, IDS_STATS1, buffer, ARRAYSIZE(buffer));
wsprintf(bigbuf, buffer, wPct, cWins, cLosses);
hText = GetDlgItem(hDlg, IDC_STEXT1);
SetWindowText(hText, bigbuf);
LoadString(hInst, IDS_STATS2, buffer, ARRAYSIZE(buffer));
wsprintf(bigbuf, buffer, wTPct, cTWon, cTLost);
hText = GetDlgItem(hDlg, IDC_STEXT2);
SetWindowText(hText, bigbuf);
LoadString(hInst, IDS_STATS3, buffer, ARRAYSIZE(buffer));
wsprintf(bigbuf, buffer, cTWins, cTLosses, (LPTSTR) sbuffer);
hText = GetDlgItem(hDlg, IDC_STEXT3);
SetWindowText(hText, bigbuf);
REGCLOSE;
}
return TRUE;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlg, TRUE);
return TRUE;
case IDC_CLEAR:
LoadString(hInst, IDS_APPNAME, smallbuf, SMALL);
LoadString(hInst, IDS_RU_SURE, bigbuf, BIG);
MessageBeep(MB_ICONQUESTION);
nResp = MessageBox(hDlg, bigbuf, smallbuf,
MB_YESNO | MB_ICONQUESTION);
if (nResp == IDNO)
break;
lRegResult = REGOPEN
if (ERROR_SUCCESS == lRegResult)
{
DeleteValue(pszWon);
DeleteValue(pszLost);
DeleteValue(pszWins);
DeleteValue(pszLosses);
DeleteValue(pszStreak);
DeleteValue(pszSType);
REGCLOSE
}
cWins = 0;
cLosses = 0;
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
// context sensitive help.
case WM_HELP:
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
HELP_WM_HELP, (ULONG_PTR) aIds);
break;
case WM_CONTEXTMENU:
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
(ULONG_PTR) aIds);
break;
}
return FALSE;
}
/****************************************************************************
CalcPercentage
Percentage is rounded off, but never up to 100.
****************************************************************************/
UINT CalcPercentage(UINT cWins, UINT cLosses)
{
UINT wPct = 0;
UINT lDenom; // denominator
lDenom = cWins + cLosses;
if (lDenom != 0L)
wPct = (((cWins * 200) + lDenom) / (2 * lDenom));
if (wPct >= 100 && cLosses != 0)
wPct = 99;
return wPct;
}
/****************************************************************************
GetHelpFileName()
Puts the full path name of the helpfile in bigbuf
side effect: contents of bigbuf are altered
****************************************************************************/
CHAR *GetHelpFileName()
{
CHAR *psz; // used to construct pathname
psz = bighelpbuf + GetModuleFileNameA(hInst, bighelpbuf, BIG-1);
if (psz - bighelpbuf > 4)
{
while (*psz != '.')
--psz;
}
strcpy(psz, ".chm");
return bighelpbuf;
}
/****************************************************************************
Options Dlg
****************************************************************************/
INT_PTR OptionsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hMessages; // handle to messages checkbox
HWND hQuick; // quick checkbox
HWND hDblClick; // double click checkbox
// For context sensitive help
static DWORD aIds[] = {
IDC_MESSAGES, IDH_OPTIONS_MESSAGES,
IDC_QUICK, IDH_OPTIONS_QUICK,
IDC_DBLCLICK, IDH_OPTIONS_DBLCLICK,
0,0 };
switch (message) {
case WM_INITDIALOG:
CentreDialog(hDlg);
hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
SendMessage(hMessages, BM_SETCHECK, bMessages, 0);
hQuick = GetDlgItem(hDlg, IDC_QUICK);
SendMessage(hQuick, BM_SETCHECK, bFastMode, 0);
hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
SendMessage(hDblClick, BM_SETCHECK, bDblClick, 0);
return TRUE;
case WM_COMMAND:
switch (wParam) {
case IDYES:
case IDOK:
hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
bMessages = (BOOL)SendMessage(hMessages, BM_GETCHECK, 0, 0);
hQuick = GetDlgItem(hDlg, IDC_QUICK);
bFastMode = (BOOL)SendMessage(hQuick, BM_GETCHECK, 0, 0);
hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
bDblClick = (BOOL)SendMessage(hDblClick, BM_GETCHECK, 0, 0);
EndDialog(hDlg, TRUE);
return TRUE;
case IDNO:
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
// context sensitive help.
case WM_HELP:
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
HELP_WM_HELP, (ULONG_PTR) aIds);
break;
case WM_CONTEXTMENU:
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
(ULONG_PTR) aIds);
break;
}
return FALSE;
}
/****************************************************************************
ReadOptions and WriteOptions retrieve and update .ini file
****************************************************************************/
VOID ReadOptions()
{
LONG lRegResult = REGOPEN
if (ERROR_SUCCESS == lRegResult)
{
bMessages = GetInt(pszMessages, TRUE);
bFastMode = GetInt(pszQuick, FALSE);
bDblClick = GetInt(pszDblClick, TRUE);
REGCLOSE
}
}
VOID WriteOptions()
{
LONG lRegResult = REGOPEN
if (ERROR_SUCCESS == lRegResult)
{
if (bMessages)
DeleteValue(pszMessages);
else
SetInt(pszMessages, 0);
if (bFastMode)
SetInt(pszQuick, 1);
else
DeleteValue(pszQuick);
if (bDblClick)
DeleteValue(pszDblClick);
else
SetInt(pszDblClick, 0);
RegFlushKey(hkey);
REGCLOSE
}
}
/****************************************************************************
Registry helper functions
These all assume that REGOPEN has been called first.
Remember to REGCLOSE when you're done.
DeleteValue is implemented as a macro.
****************************************************************************/
int GetInt(const TCHAR *pszValue, int nDefault)
{
DWORD dwType = REG_BINARY;
DWORD dwSize = sizeof(LONG_PTR);
LONG_PTR dwNumber, ret;
if (!hkey)
return nDefault;
ret = RegQueryValueEx(hkey, pszValue, 0, &dwType, (LPBYTE)&dwNumber,
&dwSize);
if (ret)
return nDefault;
return (int)dwNumber;
}
long SetInt(const TCHAR *pszValue, int n)
{
long dwNumber = (long)n;
if (hkey)
return RegSetValueEx(hkey, pszValue, 0, REG_BINARY,
(unsigned char *)&dwNumber, sizeof(dwNumber));
else
return 1;
}
/****************************************************************************
CentreDialog
****************************************************************************/
void CentreDialog(HWND hDlg)
{
RECT rcDlg, rcMainWnd, rcOffset;
GetClientRect(hMainWnd, &rcMainWnd);
GetClientRect(hDlg, &rcDlg);
GetWindowRect(hMainWnd, &rcOffset);
rcOffset.top += GetSystemMetrics(SM_CYCAPTION);
rcOffset.top += GetSystemMetrics(SM_CYMENU);
SetWindowPos(hDlg, 0,
((rcMainWnd.right - rcDlg.right) / 2) + rcOffset.left,
((rcMainWnd.bottom - rcDlg.bottom) / 2) + rcOffset.top,
0, 0, SWP_NOSIZE | SWP_NOZORDER);
}