1 // MainFrm.cpp : implementation of the CMainFrame class
\r
6 #include "xkeymacs.h"
\r
12 #define new DEBUG_NEW
\r
14 static char THIS_FILE[] = __FILE__;
\r
17 #define WM_USER_NTFYICON (WM_USER+100)
\r
19 /////////////////////////////////////////////////////////////////////////////
\r
22 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
\r
24 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
\r
25 //{{AFX_MSG_MAP(CMainFrame)
\r
27 ON_COMMAND(IDC_ABOUT, OnAbout)
\r
28 ON_COMMAND(IDC_QUIT, OnQuit)
\r
29 ON_COMMAND(IDC_DISABLE, OnDisable)
\r
30 ON_COMMAND(IDC_PROPERTIES, OnProperties)
\r
31 ON_COMMAND(IDC_OPTIONS, OnOptions)
\r
32 ON_COMMAND(IDC_KEYBOARD, OnKeyboard)
\r
33 ON_COMMAND(IDC_IMPORT, OnImport)
\r
34 ON_COMMAND(IDC_EXPORT, OnExport)
\r
35 ON_COMMAND(IDC_RESET, OnReset)
\r
36 ON_COMMAND(ID_HELP_FINDER, OnHelpFinder)
\r
37 ON_COMMAND(IDC_KEYBOARD_ANY_USER, OnKeyboardAnyUser)
\r
41 /////////////////////////////////////////////////////////////////////////////
\r
42 // CMainFrame construction/destruction
\r
44 CMainFrame::CMainFrame()
\r
46 m_pXkeymacsDll = new CXkeymacsDll;
\r
47 m_pPropertiesDlg = new CProperties;
\r
48 m_nResultPropertiesDlg = -1;
\r
49 m_bPropertiesDlgExist = FALSE;
\r
50 m_pAboutDlg = new CAboutDlg;
\r
51 m_nResultAboutDlg = -1;
\r
52 m_bAboutDlgExist = FALSE;
\r
53 m_pOptionsDlg = new COptionsDlg;
\r
54 m_nResultOptionsDlg = -1;
\r
55 m_bOptionsDlgExist = FALSE;
\r
56 memset(m_p104KeyboardDlg, 0, sizeof(m_p104KeyboardDlg));
\r
57 memset(m_p109KeyboardDlg, 0, sizeof(m_p109KeyboardDlg));
\r
58 for (int i = 0; i < MAX_HKEY_TYPE; ++i) {
\r
59 m_p104KeyboardDlg[i] = new C104Keyboard((HKEY_TYPE) i);
\r
60 m_p109KeyboardDlg[i] = new C109Keyboard((HKEY_TYPE) i);
\r
62 memset(m_nResultKeyboardDlg, -1, sizeof(m_nResultKeyboardDlg));
\r
63 memset(m_bKeyboardDlgExist, 0, sizeof(m_bKeyboardDlgExist));
\r
65 // register window class
\r
66 WNDCLASS stWndClass;
\r
67 CString szClassName(MAKEINTRESOURCE(AFX_IDS_APP_TITLE));
\r
69 stWndClass.style = CS_BYTEALIGNWINDOW;
\r
70 stWndClass.lpfnWndProc = &AfxWndProc;
\r
71 stWndClass.cbClsExtra = 0;
\r
72 stWndClass.cbWndExtra = 0;
\r
73 stWndClass.hInstance = AfxGetInstanceHandle();
\r
74 stWndClass.hIcon = NULL;
\r
75 stWndClass.hCursor = NULL;
\r
76 stWndClass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
\r
77 stWndClass.lpszMenuName = NULL;
\r
78 stWndClass.lpszClassName = szClassName;
\r
80 AfxRegisterClass(&stWndClass);
\r
83 CRect rect(0, 0, 100, 100);
\r
85 Create(szClassName, CString(MAKEINTRESOURCE(AFX_IDS_APP_TITLE)), WS_OVERLAPPEDWINDOW | WS_MINIMIZE, rect);
\r
88 CMainFrame::~CMainFrame()
\r
90 delete m_pXkeymacsDll;
\r
91 m_pXkeymacsDll = NULL;
\r
93 delete m_pPropertiesDlg;
\r
94 m_pPropertiesDlg = NULL;
\r
99 delete m_pOptionsDlg;
\r
100 m_pOptionsDlg = NULL;
\r
102 for (int i = 0; i < MAX_HKEY_TYPE; ++i) {
\r
103 delete m_p104KeyboardDlg[i];
\r
104 m_p104KeyboardDlg[i] = NULL;
\r
106 delete m_p109KeyboardDlg[i];
\r
107 m_p109KeyboardDlg[i] = NULL;
\r
111 int CMainFrame::OnCreate(const LPCREATESTRUCT lpCreateStruct)
\r
113 if (CFrameWnd::OnCreate(lpCreateStruct) == -1) {
\r
117 CXkeymacsData::Set106Keyboard(CProfile::Is106Keyboard());
\r
119 // init notify icon data
\r
120 NOTIFYICONDATA notifyIconData[MAX_ICON_TYPE] = {
\r
121 { sizeof(NOTIFYICONDATA), m_hWnd, MAIN_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
122 (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_SHARED) },
\r
123 { sizeof(NOTIFYICONDATA), m_hWnd, CX_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
124 AfxGetApp()->LoadIcon(IDI_CX_OFF) },
\r
125 { sizeof(NOTIFYICONDATA), m_hWnd, MX_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
126 AfxGetApp()->LoadIcon(IDI_MX_OFF) },
\r
127 { sizeof(NOTIFYICONDATA), m_hWnd, META_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
128 AfxGetApp()->LoadIcon(IDI_META_OFF) },
\r
129 { sizeof(NOTIFYICONDATA), m_hWnd, SHIFT_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
130 AfxGetApp()->LoadIcon(IDI_SHIFT_OFF) },
\r
131 { sizeof(NOTIFYICONDATA), m_hWnd, CTRL_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
132 AfxGetApp()->LoadIcon(IDI_CTRL_OFF) },
\r
133 { sizeof(NOTIFYICONDATA), m_hWnd, ALT_ICON, NIF_MESSAGE | NIF_ICON | NIF_TIP, WM_USER_NTFYICON,
\r
134 AfxGetApp()->LoadIcon(IDI_ALT_OFF) },
\r
136 LoadString(AfxGetInstanceHandle(), AFX_IDS_APP_TITLE, notifyIconData[MAIN_ICON].szTip,
\r
137 sizeof(notifyIconData[MAIN_ICON].szTip));
\r
138 LoadString(AfxGetInstanceHandle(), IDS_TIP_CX, notifyIconData[CX_ICON].szTip,
\r
139 sizeof(notifyIconData[CX_ICON].szTip));
\r
140 LoadString(AfxGetInstanceHandle(), IDS_TIP_MX, notifyIconData[MX_ICON].szTip,
\r
141 sizeof(notifyIconData[MX_ICON].szTip));
\r
142 LoadString(AfxGetInstanceHandle(), IDS_TIP_META, notifyIconData[META_ICON].szTip,
\r
143 sizeof(notifyIconData[META_ICON].szTip));
\r
144 LoadString(AfxGetInstanceHandle(), IDS_TIP_SHIFT, notifyIconData[SHIFT_ICON].szTip,
\r
145 sizeof(notifyIconData[SHIFT_ICON].szTip));
\r
146 LoadString(AfxGetInstanceHandle(), IDS_TIP_CTRL, notifyIconData[CTRL_ICON].szTip,
\r
147 sizeof(notifyIconData[CTRL_ICON].szTip));
\r
148 LoadString(AfxGetInstanceHandle(), IDS_TIP_ALT, notifyIconData[ALT_ICON].szTip,
\r
149 sizeof(notifyIconData[ALT_ICON].szTip));
\r
151 // set notify icon data
\r
152 m_pXkeymacsDll->SetNotifyIconData(MAIN_ICON, notifyIconData[MAIN_ICON],
\r
153 (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 16, 16, LR_SHARED),
\r
154 (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAIN_DISABLE_TMP), IMAGE_ICON, 16, 16, LR_SHARED),
\r
155 (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAIN_DISABLE_WOCQ), IMAGE_ICON, 16, 16, LR_SHARED), // disable without C-q
\r
156 (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAIN_DISABLE), IMAGE_ICON, 16, 16, LR_SHARED),
\r
157 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_MAIN)), 1));
\r
159 // set notify ^X icon data
\r
160 m_pXkeymacsDll->SetNotifyIconData(CX_ICON, notifyIconData[CX_ICON], AfxGetApp()->LoadIcon(IDI_CX_ON),
\r
161 AfxGetApp()->LoadIcon(IDI_CX_OFF),
\r
162 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_CX)), 0));
\r
164 // set notify M-x icon data
\r
165 m_pXkeymacsDll->SetNotifyIconData(MX_ICON, notifyIconData[MX_ICON], AfxGetApp()->LoadIcon(IDI_MX_ON),
\r
166 AfxGetApp()->LoadIcon(IDI_MX_OFF),
\r
167 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_MX)), 0));
\r
169 // set notify Meta icon data
\r
170 m_pXkeymacsDll->SetNotifyIconData(META_ICON, notifyIconData[META_ICON], AfxGetApp()->LoadIcon(IDI_META_ON),
\r
171 AfxGetApp()->LoadIcon(IDI_META_OFF),
\r
172 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_META)), 0));
\r
174 // set notify Shift icon data
\r
175 m_pXkeymacsDll->SetNotifyIconData(SHIFT_ICON, notifyIconData[SHIFT_ICON], AfxGetApp()->LoadIcon(IDI_SHIFT_ON),
\r
176 AfxGetApp()->LoadIcon(IDI_SHIFT_OFF),
\r
177 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_SHIFT)), 0));
\r
179 // set notify Ctrl icon data
\r
180 m_pXkeymacsDll->SetNotifyIconData(CTRL_ICON, notifyIconData[CTRL_ICON], AfxGetApp()->LoadIcon(IDI_CTRL_ON),
\r
181 AfxGetApp()->LoadIcon(IDI_CTRL_OFF),
\r
182 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_CTRL)), 0));
\r
184 // set notify Alt icon data
\r
185 m_pXkeymacsDll->SetNotifyIconData(ALT_ICON, notifyIconData[ALT_ICON], AfxGetApp()->LoadIcon(IDI_ALT_ON),
\r
186 AfxGetApp()->LoadIcon(IDI_ALT_OFF),
\r
187 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_ALT)), 0));
\r
189 m_pXkeymacsDll->SetKeyboardSpeed(CProfile::GetKeyboardSpeed());
\r
190 m_pXkeymacsDll->SetAccelerate(AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_ACCELERATE)), 1));
\r
192 m_pXkeymacsDll->SetCursorData((HCURSOR)::LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED),
\r
193 (HCURSOR)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_DISABLE_TMP_CURSOR), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED),
\r
194 (HCURSOR)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_DISABLE_WOCQ_CURSOR), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED),
\r
195 (HCURSOR)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_DISABLE_CURSOR), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED),
\r
196 AfxGetApp()->GetProfileInt(CString(), CString(MAKEINTRESOURCE(IDS_REG_ENTRY_CHANGE_CURSOR)), 0));
\r
198 m_pXkeymacsDll->SetHooks();
\r
203 /////////////////////////////////////////////////////////////////////////////
\r
204 // CMainFrame diagnostics
\r
207 void CMainFrame::AssertValid() const
\r
209 CFrameWnd::AssertValid();
\r
212 void CMainFrame::Dump(CDumpContext& dc) const
\r
214 CFrameWnd::Dump(dc);
\r
219 /////////////////////////////////////////////////////////////////////////////
\r
220 // CMainFrame message handlers
\r
222 void CMainFrame::SetForegroundTheDialog(CDialog *const pDialog)
\r
225 pDialog->SetForegroundWindow();
\r
229 void CMainFrame::SetForegroundSomeDialog()
\r
231 CDialog *pDialog = NULL;
\r
233 if (m_bPropertiesDlgExist) {
\r
234 pDialog = m_pPropertiesDlg;
\r
235 } else if (m_bOptionsDlgExist) {
\r
236 pDialog = m_pOptionsDlg;
\r
237 } else if (m_bKeyboardDlgExist[ENGLISH_KEYBOARD][CURRENT_USER]) {
\r
238 pDialog = m_p104KeyboardDlg[CURRENT_USER];
\r
239 } else if (m_bKeyboardDlgExist[ENGLISH_KEYBOARD][LOCAL_MACHINE]) {
\r
240 pDialog = m_p104KeyboardDlg[LOCAL_MACHINE];
\r
241 } else if (m_bKeyboardDlgExist[JAPANESE_KEYBOARD][CURRENT_USER]) {
\r
242 pDialog = m_p109KeyboardDlg[CURRENT_USER];
\r
243 } else if (m_bKeyboardDlgExist[JAPANESE_KEYBOARD][LOCAL_MACHINE]) {
\r
244 pDialog = m_p109KeyboardDlg[LOCAL_MACHINE];
\r
245 } else if (m_bAboutDlgExist) {
\r
246 pDialog = m_pAboutDlg;
\r
248 EnableWindow(FALSE);
\r
252 SetForegroundTheDialog(pDialog);
\r
256 void CMainFrame::PopUpDialog(CDialog *const pDialog, int *const pnResultDialog, BOOL *const pbDialogExist)
\r
258 if (pDialog == NULL
\r
259 || pnResultDialog == NULL
\r
260 || pbDialogExist == NULL) {
\r
264 if (!*pbDialogExist) {
\r
265 *pbDialogExist = TRUE;
\r
266 *pnResultDialog = pDialog->DoModal();
\r
267 *pbDialogExist = FALSE;
\r
268 *pnResultDialog = -1;
\r
270 SetForegroundSomeDialog();
\r
272 SetForegroundTheDialog(pDialog);
\r
276 void CMainFrame::PopUpPropertiesDialog()
\r
278 PopUpDialog(m_pPropertiesDlg, &m_nResultPropertiesDlg, &m_bPropertiesDlgExist);
\r
281 // show right menu on icon in system tray
\r
282 void CMainFrame::ShowRightMenu(const ICON_TYPE icon)
\r
285 rightMenu.LoadMenu(IDR_RIGHT_MENU);
\r
287 CMenu *popUp = rightMenu.GetSubMenu(0);
\r
289 if (icon == MAIN_ICON) {
\r
290 popUp->SetDefaultItem(IDC_PROPERTIES);
\r
292 CString szDisable(MAKEINTRESOURCE(IDS_ENABLE));
\r
293 if (m_pXkeymacsDll->IsKeyboardHook()) {
\r
294 szDisable.LoadString(IDS_DISABLE);
\r
296 szDisable += _T("\tCtrl+Q");
\r
297 popUp->ModifyMenu(IDC_DISABLE, MF_STRING, IDC_DISABLE, szDisable);
\r
299 TCHAR szUserName[UNLEN + 1] = {'0'};
\r
300 DWORD nSize = UNLEN + 1;
\r
301 if (GetUserName(szUserName, &nSize)) {
\r
303 szFor.Format(IDS_KEYBOARD, szUserName);
\r
304 popUp->ModifyMenu(IDC_KEYBOARD, MF_STRING, IDC_KEYBOARD, szFor);
\r
307 if (CProfile::IsVistaOrLater()) {
\r
308 popUp->DeleteMenu(IDC_KEYBOARD_ANY_USER, MF_BYCOMMAND);
\r
311 popUp->SetDefaultItem(IDC_OPTIONS);
\r
313 popUp->DeleteMenu(IDC_PROPERTIES, MF_BYCOMMAND);
\r
314 popUp->DeleteMenu(IDC_IMPORT, MF_BYCOMMAND);
\r
315 popUp->DeleteMenu(IDC_EXPORT, MF_BYCOMMAND);
\r
316 popUp->DeleteMenu(IDC_KEYBOARD, MF_BYCOMMAND);
\r
317 popUp->DeleteMenu(IDC_KEYBOARD_ANY_USER, MF_BYCOMMAND);
\r
318 popUp->DeleteMenu(IDC_DISABLE, MF_BYCOMMAND);
\r
319 popUp->DeleteMenu(IDC_RESET, MF_BYCOMMAND);
\r
320 popUp->DeleteMenu(IDC_QUIT, MF_BYCOMMAND);
\r
321 popUp->DeleteMenu(0, MF_BYPOSITION); // Delete separator
\r
322 popUp->DeleteMenu(1, MF_BYPOSITION); // Delete separator
\r
323 popUp->DeleteMenu(2, MF_BYPOSITION); // Delete popup menu of Keyboard Layout
\r
326 SetForegroundWindow();
\r
330 popUp->TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);
\r
333 // get message of icon on system tray
\r
334 LRESULT CMainFrame::WindowProc(const UINT message, const WPARAM wParam, const LPARAM lParam)
\r
336 static UINT s_uTaskbarRestart;
\r
340 s_uTaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated"));
\r
342 case WM_USER_NTFYICON:
\r
345 SetForegroundSomeDialog();
\r
347 case WM_LBUTTONDBLCLK:
\r
348 if (wParam == MAIN_ICON) {
\r
349 PopUpPropertiesDialog();
\r
351 PopUpOptionsDialog();
\r
355 ShowRightMenu((ICON_TYPE)wParam);
\r
361 if (message == s_uTaskbarRestart) {
\r
362 m_pXkeymacsDll->AddAllShell_NotifyIcon();
\r
367 return CFrameWnd::WindowProc(message, wParam, lParam);
\r
370 void CMainFrame::OnProperties()
\r
372 PopUpPropertiesDialog();
\r
375 void CMainFrame::PopUpOptionsDialog()
\r
377 PopUpDialog(m_pOptionsDlg, &m_nResultOptionsDlg, &m_bOptionsDlgExist);
\r
380 void CMainFrame::OnOptions()
\r
382 PopUpOptionsDialog();
\r
385 // stop/start keyboard hook
\r
386 void CMainFrame::OnDisable()
\r
388 if (m_pXkeymacsDll->IsKeyboardHook()) {
\r
389 m_pXkeymacsDll->SetKeyboardHookFlag(FALSE);
\r
391 m_pXkeymacsDll->SetKeyboardHookFlag(TRUE);
\r
395 // Close the Dialog if it is opened.
\r
396 void CMainFrame::CloseDialog(CDialog *const pDialog, int *const pnResult)
\r
398 if (*pnResult != -1) {
\r
399 pDialog->EndDialog(*pnResult);
\r
404 void CMainFrame::OnQuit()
\r
406 CloseDialog(m_pAboutDlg, &m_nResultAboutDlg);
\r
407 CloseDialog(m_pPropertiesDlg, &m_nResultPropertiesDlg);
\r
408 CloseDialog(m_pOptionsDlg, &m_nResultOptionsDlg);
\r
409 for (int i = 0; i < MAX_HKEY_TYPE; ++i) {
\r
410 CloseDialog(m_p104KeyboardDlg[i], &m_nResultKeyboardDlg[ENGLISH_KEYBOARD][i]);
\r
411 CloseDialog(m_p109KeyboardDlg[i], &m_nResultKeyboardDlg[JAPANESE_KEYBOARD][i]);
\r
414 m_pXkeymacsDll->ReleaseHooks();
\r
415 m_pXkeymacsDll->DeleteAllShell_NotifyIcon();
\r
417 PostQuitMessage(0);
\r
420 void CMainFrame::PopUpAboutDialog()
\r
422 PopUpDialog(m_pAboutDlg, &m_nResultAboutDlg, &m_bAboutDlgExist);
\r
425 void CMainFrame::OnAbout()
\r
427 PopUpAboutDialog();
\r
430 void CMainFrame::OnKeyboard()
\r
432 PopUpKeyboardDialog(CURRENT_USER);
\r
435 void CMainFrame::OnKeyboardAnyUser()
\r
437 PopUpKeyboardDialog(LOCAL_MACHINE);
\r
440 void CMainFrame::PopUpKeyboardDialog(const HKEY_TYPE hkeyType)
\r
442 if (CProfile::Is106Keyboard()) {
\r
443 PopUpDialog(m_p109KeyboardDlg[hkeyType], &m_nResultKeyboardDlg[JAPANESE_KEYBOARD][hkeyType], &m_bKeyboardDlgExist[JAPANESE_KEYBOARD][hkeyType]);
\r
445 PopUpDialog(m_p104KeyboardDlg[hkeyType], &m_nResultKeyboardDlg[ENGLISH_KEYBOARD][hkeyType], &m_bKeyboardDlgExist[ENGLISH_KEYBOARD][hkeyType]);
\r
449 void CMainFrame::OnImport()
\r
451 CProfile::ImportProperties();
\r
452 CProfile::InitDllData();
\r
455 void CMainFrame::OnExport()
\r
457 CProfile::ExportProperties();
\r
460 void CMainFrame::OnReset()
\r
462 m_pXkeymacsDll->ReleaseHooks();
\r
463 m_pXkeymacsDll->SetHooks();
\r
466 void CMainFrame::OnHelpFinder()
\r
468 TCHAR szPath[MAX_PATH] = {'\0'};
\r
469 const TCHAR szExt[] = _T("txt");
\r
470 _tmakepath(szPath, NULL, NULL, CString(MAKEINTRESOURCE(IDS_README)), szExt);
\r
472 TCHAR szModuleFileName[MAX_PATH] = {'\0'};
\r
473 if (GetModuleFileName(NULL, szModuleFileName, sizeof(szModuleFileName))) {
\r
474 TCHAR szDrive[_MAX_DRIVE] = {'\0'};
\r
475 TCHAR szDir[_MAX_DIR] = {'\0'};
\r
476 _tsplitpath(szModuleFileName, szDrive, szDir, NULL, NULL);
\r
477 _tmakepath(szPath, szDrive, szDir, CString(MAKEINTRESOURCE(IDS_README)), szExt);
\r
480 ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL);
\r