forked from chrisguo/beijing_fushengji
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TipDlg.cpp
executable file
·353 lines (275 loc) · 9.03 KB
/
TipDlg.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#include "stdafx.h"
#include "resource.h"
#include "TipDlg.h"
// CG: This file added by 'Tip of the Day' component.
#include <winreg.h>
#include <sys\stat.h>
#include <sys\types.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTipDlg dialog
#define MAX_BUFLEN 1000
static const TCHAR szSection[] = _T("Tip");
static const TCHAR szIntFilePos[] = _T("FilePos");
static const TCHAR szTimeStamp[] = _T("TimeStamp");
static const TCHAR szIntStartup[] = _T("StartUp");
CTipDlg::CTipDlg(CWnd* pParent /*=NULL*/)
: CDialog(IDD_TIP, pParent)
{
//{{AFX_DATA_INIT(CTipDlg)
m_bStartup = TRUE;
//}}AFX_DATA_INIT
// We need to find out what the startup and file position parameters are
// If startup does not exist, we assume that the Tips on startup is checked TRUE.
CWinApp* pApp = AfxGetApp();
m_bStartup = !pApp->GetProfileInt(szSection, szIntStartup, 0);
UINT iFilePos = pApp->GetProfileInt(szSection, szIntFilePos, 0);
m_nHelpID = 0;
// look in the application directory for the tip file
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
const char *path = _pgmptr ;
_splitpath(path, drive, dir, fname, ext );
CString sPath;
sPath.Format("%s%s%s", drive, dir, "Tips.txt");
TRACE("sPath is %s\n", sPath);
// Now try to open the tips file
m_pStream = fopen(sPath, "r");
if (m_pStream == NULL)
{
m_strHeader = "Oops!";
m_strTip.LoadString(CG_IDS_FILE_ABSENT);
return;
}
// If the timestamp in the INI file is different from the timestamp of
// the tips file, then we know that the tips file has been modified
// Reset the file position to 0 and write the latest timestamp to the
// ini file
struct _stat buf;
_fstat(_fileno(m_pStream), &buf);
CString strCurrentTime = ctime(&buf.st_ctime);
strCurrentTime.TrimRight();
CString strStoredTime =
pApp->GetProfileString(szSection, szTimeStamp, NULL);
if (strCurrentTime != strStoredTime)
{
iFilePos = 0;
pApp->WriteProfileString(szSection, szTimeStamp, strCurrentTime);
}
if (fseek(m_pStream, iFilePos, SEEK_SET) != 0)
{
AfxMessageBox(CG_IDP_FILE_CORRUPT);
}
else
{
GetNextTipString();
}
}
CTipDlg::~CTipDlg()
{
// This destructor is executed whether the user had pressed the escape key
// or clicked on the close button. If the user had pressed the escape key,
// it is still required to update the filepos in the ini file with the
// latest position so that we don't repeat the tips!
// But make sure the tips file existed in the first place....
if (m_pStream != NULL)
{
CWinApp* pApp = AfxGetApp();
pApp->WriteProfileInt(szSection, szIntFilePos, ftell(m_pStream));
fclose(m_pStream);
}
}
void CTipDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTipDlg)
DDX_Check(pDX, IDC_STARTUP, m_bStartup);
DDX_Text(pDX, ST_FOOTER, m_strFooter);
DDX_Text(pDX, ST_HEADER, m_strHeader);
DDX_Text(pDX, IDC_TIPSTRING, m_strTip);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTipDlg, CDialog)
//{{AFX_MSG_MAP(CTipDlg)
ON_BN_CLICKED(IDC_NEXTTIP, OnNextTip)
ON_BN_CLICKED(IDB_MORE, OnMore)
ON_WM_CTLCOLOR()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTipDlg message handlers
void CTipDlg::OnNextTip()
{
GetNextTipString();
// if the Help ID is 0, disable the Help button
GetDlgItem(IDB_MORE)->EnableWindow(m_nHelpID != 0);
UpdateData(FALSE);
}
// function to get a text string from the file
// the first half is mostly straight from the MFC component code
// it is followed by parsing of the string into its different
// components based on tab characters
// NOTE that I did remove the parameter that was passed to this
// function to recieve the string, and made the string a class member
void CTipDlg::GetNextTipString()
{
LPTSTR lpsz = m_strFileLine.GetBuffer(MAX_BUFLEN);
// This routine identifies the next string that needs to be
// read from the tips file
BOOL bStop = FALSE;
while (!bStop)
{
// reads up until the next newline character
if (_fgetts(lpsz, MAX_BUFLEN, m_pStream) == NULL)
{
// We have either reached EOF or enocuntered some problem
// In both cases reset the pointer to the beginning of the file
// This behavior is same as VC++ Tips file
if (fseek(m_pStream, 0, SEEK_SET) != 0)
AfxMessageBox(CG_IDP_FILE_CORRUPT);
}
else
{
if (*lpsz != ' ' && *lpsz != '\t' &&
*lpsz != '\n' && *lpsz != ';')
{
// There should be no space at the beginning of the tip
// This behavior is same as VC++ Tips file
// Comment lines are ignored and they start with a semicolon
bStop = TRUE;
}
}
}
m_strFileLine.ReleaseBuffer();
// here is where the standard tip component code ends
// and the enhanced code begins
TRACE("\nParsing help tip line\n");
// initialize the enhanced variables
// If there is no header, the default header of "Did You Know" is used
m_strHeader.LoadString(CG_IDS_DIDYOUKNOW);
m_strFooter.Empty();
m_nHelpID = 0;
int nIndex;
CString sTemp, sTemp2;
nIndex = m_strFileLine.Find('\t');
if (nIndex == -1)
{
m_strTip = m_strFileLine;
return;
}
m_strTip = m_strFileLine.Left(nIndex);
sTemp = m_strFileLine.Right(m_strFileLine.GetLength() - nIndex - 1);
TRACE("Tip is [%s]\n", m_strTip);
// parse the header line
nIndex = sTemp.Find('\t');
if (nIndex == -1)
{
m_strHeader = sTemp;
return;
}
if (nIndex != 0) m_strHeader = sTemp.Left(nIndex);
sTemp2 = sTemp.Right(sTemp.GetLength() - nIndex - 1);
TRACE("Header is [%s]\n", m_strHeader);
// parse the footer line
nIndex = sTemp2.Find('\t');
if (nIndex == -1)
{
m_strFooter = sTemp2;
return;
}
m_strFooter = sTemp2.Left(nIndex);
sTemp = sTemp.Right(sTemp2.GetLength() - nIndex - 1);
TRACE("Footer is [%s]\n", m_strFooter);
m_nHelpID = atoi(sTemp);
TRACE("Help ID is %d\n", m_nHelpID);
}
// draw text controls with a white background
HBRUSH CTipDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (pWnd->GetDlgCtrlID() == IDC_TIPSTRING)
return (HBRUSH)GetStockObject(WHITE_BRUSH);
if (pWnd->GetDlgCtrlID() == ST_FOOTER)
return (HBRUSH)GetStockObject(WHITE_BRUSH);
if (pWnd->GetDlgCtrlID() == ST_HEADER)
return (HBRUSH)GetStockObject(WHITE_BRUSH);
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
void CTipDlg::OnOK()
{
CDialog::OnOK();
// Update the startup information stored in the INI file
CWinApp* pApp = AfxGetApp();
pApp->WriteProfileInt(szSection, szIntStartup, !m_bStartup);
}
BOOL CTipDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// If Tips file does not exist then disable NextTip
if (m_pStream == NULL)
GetDlgItem(IDC_NEXTTIP)->EnableWindow(FALSE);
GetDlgItem(IDB_MORE)->EnableWindow(m_nHelpID != 0);
// set the font for the Header
CFont Font;
Font.CreatePointFont(12, "Arial");
GetDlgItem(ST_HEADER)->SetFont(&Font);
return TRUE; // return TRUE unless you set the focus to a control
}
void CTipDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// DoPaint (&dc, FALSE) ;
// return;
// Get paint area for the big static control
CWnd* pStatic = GetDlgItem(IDC_TIP_RECT);
CRect rcBig, rcBulb;
pStatic->GetWindowRect(&rcBig);
ScreenToClient(&rcBig);
// decrease the size slightly so there is a thin gray border between
// the white rectangle and the static control
rcBig.InflateRect(-6, -6, -6, -6);
// Paint the background white.
CBrush brush;
brush.CreateStockObject(WHITE_BRUSH);
dc.FillRect(rcBig, &brush);
brush.Detach();
// now change the brush to the button shadow color
brush.CreateSolidBrush( ::GetSysColor(COLOR_BTNSHADOW)) ;
// Get the position of the lightbulb
pStatic = GetDlgItem(IDB_LIGHTBULB);
pStatic->GetWindowRect(&rcBulb);
ScreenToClient(&rcBulb);
// Load bitmap and get dimensions of the bitmap
CBitmap bmp;
bmp.LoadBitmap(IDB_LIGHTBULB);
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
rcBulb.bottom = bmpInfo.bmHeight + rcBulb.top;
rcBulb.right = bmpInfo.bmWidth + rcBulb.left;
// change that right side of rcBig so it is even with the right side of the bitmap
rcBig.right = rcBulb.right;
// draw the left side shadow
dc.FillRect(rcBig, &brush);
// select the bitmap into the device context and draw
CDC dcTmp;
dcTmp.CreateCompatibleDC(&dc);
dcTmp.SelectObject(&bmp);
dcTmp.SelectObject(&brush) ;
dcTmp.ExtFloodFill(0,0, 0x00ffffff, FLOODFILLSURFACE) ;
dc.BitBlt(rcBulb.left, rcBulb.top, rcBulb.Width(), rcBulb.Height(),
&dcTmp, 0, 0, SRCCOPY);
// Do not call CDialog::OnPaint() for painting messages
}
// if the user clicks the More Info button, display the help topic
// associated with the tip
void CTipDlg::OnMore()
{
ASSERT(m_nHelpID != 0);
AfxGetApp()->WinHelp(m_nHelpID);
}