|
Source listing: echo $file; ?>. Return to
the main page
/* -*- C++ -*-
*******************************************************************
*
*
* Shisen-Sho for Windows
*
* dialogs.cpp - Dialog implementations
*
*
*******************************************************************
*
* A japanese game similar to mahjongg
*
*******************************************************************
*
* Created 2000-12-28 by Jim Mason <jmason@sirius.com>
*
* Game engine ported from Mario Weilguni's <mweilguni@sime.com>
* original game for KDE, KSHISEN. If you are interested in the
* KDE version of the game, see http://www.kde.org/kdegames/
*
*******************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*******************************************************************
*/
#include "stdafx.h"
#include "dialogs.h"
#include <windowsx.h>
#include <commctrl.h>
#include <commdlg.h>
#include "shisen.h"
#include "registry.h"
#include "bmputil.h"
/////////////////////////////////////////////////////////////////////////////
// PlayerName dialog
PlayerName::PlayerName(Window* pParent) :
Dialog(IDD, pParent) {
}
BOOL PlayerName::OnCommand(UINT nID, UINT nEvent, HWND hSource) {
if(nID == IDOK) {
// Save dialog item data
GetDlgItemText(m_hWnd, IDC_NAME, m_szName.GetBuffer(256), 256);
m_szName.ReleaseBuffer();
}
return Dialog::OnCommand(nID, nEvent, hSource);
}
/////////////////////////////////////////////////////////////////////////////
// ShowScores dialog
ShowScores::ShowScores(Window* pParent) :
Dialog(IDD, pParent) {
}
#define FUDGE_FACTOR 8
BOOL ShowScores::OnInitDialog() {
// Let superclass do its thing
Dialog::OnInitDialog();
// Create MS San Serif bold 12 point font
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
HDC hDC = GetDC();
lf.lfHeight = -MulDiv(12/*pt size*/, GetDeviceCaps(hDC, LOGPIXELSY), 72);
lf.lfWeight = FW_BOLD;
_tcscpy(lf.lfFaceName, _T("MS Sans Serif"));
HFONT hBigBold = CreateFontIndirect(&lf);
// Setup caption control with the font
m_caption.SetFont(hBigBold, TRUE); // m_caption destructor will delete font
m_caption.SubclassDlgItem(IDC_CAPTION, this);
// Setup columns
// Column geometry policy is as follows:
// Rank and Score are sized to label width
// Time and Size each get 1/4 the remaining list width
// Name gets the remainder (roughly 1/2 the list width)
HWND hList = GetDlgItem(IDC_LIST1);
CStdString szRank, szScore, szLabel;
int nRank, nScore, nRem, nTime, nSize;
RECT rcList, rcText;
::GetClientRect(hList, &rcList);
szRank.LoadString(IDS_RANK);
DrawText(hDC, szRank, -1, &rcText, DT_CALCRECT|DT_LEFT);
nRank = rcText.right - rcText.left + FUDGE_FACTOR;
szScore.LoadString(IDS_SCORE);
DrawText(hDC, szScore, -1, &rcText, DT_CALCRECT|DT_LEFT);
nScore = rcText.right - rcText.left + FUDGE_FACTOR*2;
nRem = rcList.right - rcList.left - nRank - nScore;
nTime = nSize = nRem/4;
nRem -= nTime + nSize;
ReleaseDC(hDC);
LVCOLUMN lvCol;
lvCol.mask = LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
lvCol.fmt = LVCFMT_RIGHT;
lvCol.pszText = (LPTSTR)(LPCTSTR)szRank;
lvCol.cx = nRank;
ListView_InsertColumn(hList, 0, &lvCol); // Rank
szLabel.LoadString(IDS_NAME);
lvCol.pszText = (LPTSTR)(LPCTSTR)szLabel;
lvCol.cx = nRem;
ListView_InsertColumn(hList, 1, &lvCol); // Name
szLabel.LoadString(IDS_TIME);
lvCol.cx = nTime;
ListView_InsertColumn(hList, 2, &lvCol); // Time
szLabel.LoadString(IDS_SIZE);
lvCol.cx = nSize;
ListView_InsertColumn(hList, 3, &lvCol); // Size
lvCol.pszText = (LPTSTR)(LPCTSTR)szScore;
lvCol.cx = nScore;
ListView_InsertColumn(hList, 4, &lvCol); // Score
// Populate the list
if(m_pHighScore)
for(int i = 0; i < 10; i++)
if(i < (*m_pHighScore).size()) {
LVITEM item;
CStdString s;
HighScore hs = (*m_pHighScore)[i];
// Add the item
s.Format("%d", i+1);
item.mask = LVIF_TEXT;
item.iItem = i;
item.iSubItem = 0;
item.pszText = (LPTSTR)(LPCTSTR)s;
ListView_InsertItem(hList, &item);
// insert name
ListView_SetItemText(hList, i, 1, hs.name);
// insert time
s.Format("%02d:%02d:%02d", hs.seconds/3600,
(hs.seconds/60)%60, hs.seconds%60);
ListView_SetItemText(hList, i, 2, (LPTSTR)(LPCTSTR)s);
// insert size
s.Format("%d x %d", hs.x, hs.y);
ListView_SetItemText(hList, i, 3, (LPTSTR)(LPCTSTR)s);
// insert score
s.Format("%d%c", Frame::GetScore(hs), hs.gravity?'*':' ');
ListView_SetItemText(hList, i, 4, (LPTSTR)(LPCTSTR)s);
}
// Optionally highlight an item
if(m_iHotItem >= 0)
ListView_SetHotItem(hList, m_iHotItem);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// SelectTileset dialog
SelectTileset::SelectTileset(Window* pParent) :
Dialog(IDD, pParent) {
}
BOOL SelectTileset::OnCommand(UINT nID, UINT nEvent, HWND hSource) {
switch(nEvent) {
case CBN_SELCHANGE:
switch(nID) {
case IDC_TILESET:
OnChangeTileset();
break;
case IDC_BACKGROUND:
OnChangeBackground();
break;
}
break;
case BN_CLICKED:
switch(nID) {
case IDC_BROWSETILESET:
OnBrowseTileset();
break;
case IDC_BROWSEBACKGROUND:
OnBrowseBackground();
break;
case IDOK:
OnOK();
break;
}
break;
default:
return Dialog::OnCommand(nID, nEvent, hSource);
}
Dialog::OnCommand(nID, nEvent, hSource);
return TRUE;
}
BOOL SelectTileset::OnInitDialog() {
// Let superclass do its thing
Dialog::OnInitDialog();
// Setup the board
RECT rc;
SetRect(&rc, 0, 0, 0, 0);
if (!m_board.Create(0, _T("Shisen Board"), _T("Shisen Tile Selector"),
WS_CHILD|WS_VISIBLE, rc, m_hWnd, IDW_MAIN)) {
// Failed to create board window; bail
EndDialog(m_hWnd, IDCANCEL);
return TRUE;
}
m_board.setNoEvents();
m_board.setSolvableFlag(FALSE);
m_board.setShuffle(4);
m_board.setSize(4, 2);
// Position the board
RECT rcFrame;
SIZE sizeBoard = m_board.sizeHint();
::GetWindowRect(GetDlgItem(IDC_FRAME), &rcFrame);
MapWindowPoints(HWND_DESKTOP, m_hWnd, (LPPOINT)&rcFrame, 2);
m_board.MoveWindow(rcFrame.left, rcFrame.top,
sizeBoard.cx, sizeBoard.cy, TRUE);
m_imageFiles.resize(0);
// Setup the tileset combo
m_tileset = GetDlgItem(IDC_TILESET);
// Add default item
ComboBox_AddString(m_tileset, _T("Default"));
ComboBox_SetItemData(m_tileset, 0, -1);
CStdString szCurrent = App::GetProfile()->GetProfileString(_T("Tilesets"),
_T("Tileset"), _T(""));
if(szCurrent.IsEmpty())
// Current tileset is the default, otherwise...
ComboBox_SetCurSel(m_tileset, 0);
else
// ...prime board with the current tileset
m_board.loadMahjonggTileset(szCurrent);
// Populate tileset combo
for(int i=1; TRUE; i++) {
CStdString s, e;
s.Format("Tileset_%d", i);
e = App::GetProfile()->GetProfileString(_T("Tilesets"), s, _T(""));
// Have we enumerated all the cached tilesets?
if(e.IsEmpty())
break;
// Skip this image if it is invalid
if(!CBmpUtil::LoadBmpImage(e))
continue;
// Add image pathname to the imageFiles array
m_imageFiles.push_back(e);
int iArrayPos = m_imageFiles.size()-1;
// Extract and nicely format the basename for the combo
int iStart = e.ReverseFind('\\');
int iEnd = e.ReverseFind('.');
s = e.Mid(iStart<0?0:iStart+1,
(iEnd>0 && iEnd>iStart)?iEnd-iStart-1:e.GetLength());
s.SetAt(0, toupper(s.GetAt(0)));
// Set the basename in the combo, selecting it if appropriate
int iComboPos = ComboBox_AddString(m_tileset, s);
ComboBox_SetItemData(m_tileset, iComboPos, iArrayPos);
if(!szCurrent.CompareNoCase(e))
ComboBox_SetCurSel(m_tileset, iComboPos);
}
// Remember the index of the last tileset. This is where we will
// begin adding any new tileset which needs to be flushed.
m_iNextTileset = i;
// Setup the background combo
m_background = GetDlgItem(IDC_BACKGROUND);
// Add default item
ComboBox_AddString(m_background, _T("Default"));
ComboBox_SetItemData(m_background, 0, -1);
szCurrent = App::GetProfile()->GetProfileString(_T("Tilesets"),
_T("Background"), _T(""));
if(szCurrent.IsEmpty())
// Current background is the default, else...
ComboBox_SetCurSel(m_background, 0);
else
// ...prime board with the current background
m_board.loadBackground(szCurrent);
// Populate background combo
for(i=1; TRUE; i++) {
CStdString s, e;
s.Format("Background_%d", i);
e = App::GetProfile()->GetProfileString(_T("Tilesets"), s, _T(""));
// Have we enumerated all the cached backgrounds?
if(e.IsEmpty())
break;
// Skip this image if it is invalid
if(!CBmpUtil::LoadBmpImage(e))
continue;
// Add image pathname to the imageFiles array
m_imageFiles.push_back(e);
int iArrayPos = m_imageFiles.size()-1;
// Extract and nicely format the basename for the combo
int iStart = e.ReverseFind('\\');
int iEnd = e.ReverseFind('.');
s = e.Mid(iStart<0?0:iStart+1,
(iEnd>0 && iEnd>iStart)?iEnd-iStart-1:e.GetLength());
s.SetAt(0, toupper(s.GetAt(0)));
// Set the basename in the combo, selecting it if appropriate
int iComboPos = ComboBox_AddString(m_background, s);
ComboBox_SetItemData(m_background, iComboPos, iArrayPos);
if(!szCurrent.CompareNoCase(e))
ComboBox_SetCurSel(m_background, iComboPos);
}
// Remember the index of the last background. This is where
// we will being adding any new background which needs to be
// flushed.
m_iNextBkgnd = i;
// Remember the last cached image file. This will allow us
// to figure out later whether a new tileset or bitmap needs
// to be flushed.
m_iNewFile = m_imageFiles.size();
return TRUE;
}
void SelectTileset::OnChangeTileset() {
CStdString szFileName;
int iSel;
if((iSel = ComboBox_GetCurSel(m_tileset)) != -1) {
int iIndex =ComboBox_GetItemData(m_tileset, iSel);
if(iIndex == -1) {
// Load default tileset
m_board.loadMahjonggTileset("");
m_board.InvalidateRect(NULL, TRUE);
return;
} else {
szFileName = m_imageFiles.at(iIndex);
// Test whether image file is valid
if(!CBmpUtil::LoadBmpImage(szFileName)) {
// Error
return;
}
// Select tileset into board
m_board.loadMahjonggTileset(szFileName);
m_board.InvalidateRect(NULL, TRUE);
}
}
}
void SelectTileset::OnBrowseTileset() {
int iPos;
CStdString e, szAppDir;
GetModuleFileName(NULL, szAppDir.GetBuffer(1024), 1024);
szAppDir.ReleaseBuffer(-1);
if((iPos = szAppDir.ReverseFind('\\')) > 0)
szAppDir = szAppDir.Left(iPos);
// Setup the Open dialog
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.hInstance = App::GetHInstance();
ofn.lpstrFilter = _T("Tileset Files (*.tileset)\0*.tileset\0\0");
ofn.lpstrInitialDir = szAppDir;
ofn.lpstrFile = e.GetBuffer(1024);
ofn.nMaxFile = 1024;
ofn.Flags = OFN_FILEMUSTEXIST;
int iSuccess = GetOpenFileName(&ofn);
e.ReleaseBuffer(-1);
if(iSuccess) {
// Is file valid?
HBITMAP hBmp;
if(CBmpUtil::LoadBmpImage(e, &hBmp)) {
BITMAP bm;
GetObject(hBmp, sizeof(BITMAP), &bm);
DeleteObject(hBmp);
if(!(bm.bmWidth == 360 && bm.bmHeight == 280)) {
// Tileset has incorrect dimensions
e.Format(IDS_INVALID_FILE);
MessageBox(m_hWnd, e, App::GetAppName(), MB_OK|MB_ICONEXCLAMATION);
return;
}
} else {
// File does not exist or cannot be loaded
e.Format(IDS_INVALID_FILE);
MessageBox(m_hWnd, e, App::GetAppName(), MB_OK|MB_ICONEXCLAMATION);
return;
}
// Is it already cached?
for(int i = 0; i<m_imageFiles.size(); i++) {
if(!e.CompareNoCase(m_imageFiles.at(i))) {
// It's already cached; find it
for (int j = 0; j<ComboBox_GetCount(m_tileset); j++)
if((int)ComboBox_GetItemData(m_tileset, j) == i) {
// Select it and activate
ComboBox_SetCurSel(m_tileset, j);
SetFocus(m_tileset);
OnChangeTileset();
return;
}
}
}
// Add it to the combo
m_imageFiles.push_back(e);
int iArrayPos = m_imageFiles.size()-1;
int iStart = e.ReverseFind('\\');
int iEnd = e.ReverseFind('.');
e = e.Mid(iStart<0?0:iStart+1,
(iEnd>0 && iEnd>iStart)?iEnd-iStart-1:e.GetLength());
e.SetAt(0, toupper(e.GetAt(0)));
int iComboPos = ComboBox_AddString(m_tileset, e);
ComboBox_SetItemData(m_tileset, iComboPos, iArrayPos);
ComboBox_SetCurSel(m_tileset, iComboPos);
SetFocus(m_tileset);
OnChangeTileset();
}
}
void SelectTileset::OnChangeBackground() {
CStdString szFileName;
int iSel;
if((iSel = ComboBox_GetCurSel(m_background)) != -1) {
int iIndex = ComboBox_GetItemData(m_background, iSel);
if(iIndex == -1) {
// Load default background
m_board.loadBackground("");
m_board.InvalidateRect(NULL, TRUE);
return;
} else {
szFileName = m_imageFiles.at(iIndex);
// Test whether image file is valid
if(!CBmpUtil::LoadBmpImage(szFileName)) {
// Error
return;
}
// Select tileset into board
m_board.loadBackground(szFileName);
m_board.InvalidateRect(NULL, TRUE);
}
}
}
void SelectTileset::OnBrowseBackground() {
CStdString e, szWindowsDir;
GetWindowsDirectory(szWindowsDir.GetBuffer(256), 256);
szWindowsDir.ReleaseBuffer(-1);
// Setup the Open dialog
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.hInstance = App::GetHInstance();
ofn.lpstrFilter = _T("Background Files (*.bmp)\0*.bmp\0\0");
ofn.lpstrInitialDir = szWindowsDir;
ofn.lpstrFile = e.GetBuffer(1024);
ofn.nMaxFile = 1024;
ofn.Flags = OFN_FILEMUSTEXIST;
int iSuccess = GetOpenFileName(&ofn);
e.ReleaseBuffer(-1);
if(iSuccess) {
// Is file valid?
if(!CBmpUtil::LoadBmpImage(e)) {
// Error
e.LoadString(IDS_INVALID_FILE);
MessageBox(m_hWnd, e, App::GetAppName(), MB_OK|MB_ICONEXCLAMATION);
return;
}
// Is it already cached?
for(int i = 0; i<m_imageFiles.size(); i++) {
if(!e.CompareNoCase(m_imageFiles.at(i))) {
// It's already cached; find it
for (int j = 0; j<ComboBox_GetCount(m_background); j++)
if((int)ComboBox_GetItemData(m_background, j) == i) {
// Select it and activate
ComboBox_SetCurSel(m_background, j);
SetFocus(m_background);
OnChangeBackground();
return;
}
}
}
// Add it to the combo
m_imageFiles.push_back(e);
int iArrayPos = m_imageFiles.size()-1;
int iStart = e.ReverseFind('\\');
int iEnd = e.ReverseFind('.');
e = e.Mid(iStart<0?0:iStart+1,
(iEnd>0 && iEnd>iStart)?iEnd-iStart-1:e.GetLength());
e.SetAt(0, toupper(e.GetAt(0)));
int iComboPos = ComboBox_AddString(m_background, e);
ComboBox_SetItemData(m_background, iComboPos, iArrayPos);
ComboBox_SetCurSel(m_background, iComboPos);
SetFocus(m_background);
OnChangeBackground();
}
}
void SelectTileset::OnOK() {
// See if tileset is cached
int iPos, iSel = ComboBox_GetCurSel(m_tileset);
if(iSel > 0 && ((iPos = ComboBox_GetItemData(m_tileset, iSel)) != -1) &&
iPos >= m_iNewFile) {
// Cache the tileset
CStdString s;
s.Format(_T("Tileset_%d"), m_iNextTileset);
App::GetProfile()->WriteProfileString(_T("Tilesets"), s, m_imageFiles.at(iPos));
}
// Set current tileset
App::GetProfile()->WriteProfileString(_T("Tilesets"), _T("Tileset"),
(m_szTileset = (iSel > 0)?m_imageFiles.at(iPos):""));
// See if background is cached
iSel = ComboBox_GetCurSel(m_background);
if(iSel > 0 && ((iPos = ComboBox_GetItemData(m_background, iSel)) != -1) &&
iPos >= m_iNewFile) {
// Cache the background
CStdString s;
s.Format(_T("Background_%d"), m_iNextBkgnd);
App::GetProfile()->WriteProfileString(_T("Tilesets"), s, m_imageFiles.at(iPos));
}
// Set current background
App::GetProfile()->WriteProfileString(_T("Tilesets"), _T("Background"),
(m_szBackground = (iSel > 0)?m_imageFiles.at(iPos):""));
}
/////////////////////////////////////////////////////////////////////////////
// About dialog
About::About(Window* pParent) :
Dialog(IDD, pParent) {
}
/////////////////////////////////////////////////////////////////////////////
// StaticText control
StaticText::StaticText() {
m_hFont = NULL; // default font
m_rgb = RGB(0, 0, 0); // black text
m_nFormat = DT_CENTER|DT_VCENTER; // centre text in control
m_bOwnFont = FALSE;
}
LRESULT StaticText::WndProc(UINT nMsg, WPARAM wParam, LPARAM lParam) {
switch(nMsg) {
case WM_PAINT:
OnPaint();
return 0L;
}
return Window::WndProc(nMsg, wParam, lParam);
}
void StaticText::OnDestroy() {
// If we own the font, we're responsible for deleting it
if(m_bOwnFont)
DeleteObject(m_hFont);
m_bOwnFont = FALSE;
Window::OnDestroy();
}
void StaticText::OnPaint() {
// Get the control text
CStdString szText;
GetWindowText(m_hWnd, szText.GetBuffer(1024), 1024);
szText.ReleaseBuffer(-1);
// Get the client rect
RECT rcText;
GetClientRect(&rcText);
// Prime the DC for drawing
HFONT oldFont;
PAINTSTRUCT ps;
BeginPaint(&ps);
COLORREF oldrgb = SetTextColor(ps.hdc, m_rgb);
int iOldMode = SetBkMode(ps.hdc, TRANSPARENT);
if(m_hFont)
oldFont = (HFONT)SelectObject(ps.hdc, m_hFont);
// Render the text
DrawText(ps.hdc, szText, -1, &rcText, m_nFormat);
// Cleanup the DC
if(m_hFont)
SelectObject(ps.hdc, oldFont);
SetTextColor(ps.hdc, oldrgb);
SetBkMode(ps.hdc, iOldMode);
EndPaint(&ps);
}
<< Back to Shisen-Sho
|
|