/
Tipdlg.cpp
232 lines (196 loc) · 6.23 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
// TipDlg.cpp : display tip of the day and allow toggle of display at startup
//
// Copyright (c) 2011 by Andrew W. Phillips.
//
// This file is distributed under the MIT license, which basically says
// you can do what you want with it but I take no responsibility for bugs.
// See http://www.opensource.org/licenses/mit-license.php for full details.
//
#include "stdafx.h"
#include "hexedit.h"
#include "misc.h"
#include "resource.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.
CHexEditApp *aa = dynamic_cast<CHexEditApp *>(AfxGetApp());
m_bStartup = aa->tipofday_;
UINT iFilePos = aa->GetProfileInt(szSection, szIntFilePos, 0);
const char *tip_name = "HexEdit.tip";
// Now try to open the tips file in the current directory
m_pStream = fopen(tip_name, "r");
if (m_pStream == NULL)
{
// AP: This bit added by me -----------------------------------------------------------
// Not found so try to open from the .exe dir
if ((m_pStream = fopen(GetExePath() + tip_name, "r")) == NULL)
// ------------------------------------------------------------------------------------
{
VERIFY(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 =
aa->GetProfileString(szSection, szTimeStamp, NULL);
if (strCurrentTime != strStoredTime)
{
iFilePos = 0;
aa->WriteProfileString(szSection, szTimeStamp, strCurrentTime);
}
if (fseek(m_pStream, iFilePos, SEEK_SET) != 0)
{
AfxMessageBox(CG_IDP_FILE_CORRUPT);
}
else
{
GetNextTipString(m_strTip);
}
}
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, IDC_TIPSTRING, m_strTip);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTipDlg, CDialog)
//{{AFX_MSG_MAP(CTipDlg)
ON_BN_CLICKED(IDC_NEXTTIP, OnNextTip)
ON_WM_CTLCOLOR()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTipDlg message handlers
void CTipDlg::OnNextTip()
{
GetNextTipString(m_strTip);
UpdateData(FALSE);
}
void CTipDlg::GetNextTipString(CString& strNext)
{
LPTSTR lpsz = strNext.GetBuffer(MAX_BUFLEN);
// This routine identifies the next string that needs to be
// read from the tips file
BOOL bStop = FALSE;
while (!bStop)
{
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;
}
}
}
strNext.ReleaseBuffer();
}
HBRUSH CTipDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (pWnd->GetDlgCtrlID() == IDC_TIPSTRING)
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
CHexEditApp *aa = dynamic_cast<CHexEditApp *>(AfxGetApp());
aa->tipofday_ = 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);
return TRUE; // return TRUE unless you set the focus to a control
}
void CTipDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Get paint area for the big static control
CWnd* pStatic = GetDlgItem(IDC_BULB);
CRect rect;
pStatic->GetWindowRect(&rect);
ScreenToClient(&rect);
// Paint the background white.
CBrush brush;
brush.CreateStockObject(WHITE_BRUSH);
dc.FillRect(rect, &brush);
dc.FillSolidRect(rect, RGB(255, 255, 255));
// Load bitmap and get dimensions of the bitmap
CBitmap bmp;
bmp.LoadBitmap(IDB_LIGHTBULB);
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
// Draw bitmap in top corner and validate only top portion of window
CDC dcTmp;
dcTmp.CreateCompatibleDC(&dc);
dcTmp.SelectObject(&bmp);
rect.bottom = bmpInfo.bmHeight + rect.top;
dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dcTmp, 0, 0, SRCCOPY);
// Draw out "Did you know..." message next to the bitmap
CString strMessage;
VERIFY(strMessage.LoadString(CG_IDS_DIDYOUKNOW));
rect.left += bmpInfo.bmWidth;
dc.DrawText(strMessage, rect, DT_VCENTER | DT_SINGLELINE);
// Do not call CDialog::OnPaint() for painting messages
}