/********************************************************************
Windows interface for final project
(C)Adam Hatherly 2000
*********************************************************************/
#include <string.h>
#include <math.h>
#ifndef GLOBAL_DECL
#include "global.h" // Global data types and variables
#endif
// Global Variables
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK OptionsDlgProc (HWND, UINT, WPARAM, LPARAM);
FARPROC lpfnOptionsDlgProc;
BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
FARPROC lpfnAboutDlgProc;
char szAppName[] = "WebNewsSpeak"; // Window Name
char szCaption[] = "Web News Speak"; // Window Caption
HWND hButtons[10]; // Button handles
HWND hChecks[10]; // Check box handles
int ButtonFocus; // Index of the button with focus
buttons mbuttons; // Object maintaining button values
int WinMaWid; // Width of main window
int WinMaHei; // Height of main window
bool Timer_Set = false; // The timer for downloading is not set
pglist *pagelist; // Ptr to linked list of pages
config *settings; // Object to maintain user settings
statuswnd *status; // Pointer to status window object
// Subclassed window procedures - different types on different version of the compiler - why?
#if COMPILER_V6
WNDPROC OldButProc;
WNDPROC OldCheckProc;
#else
FARPROC OldButProc;
FARPROC OldCheckProc;
#endif
// Implementation
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
WNDCLASSEX wndclass;
hInst = hInstance;
// Define class features
wndclass.cbSize = sizeof (wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
// Register the class with Windows
RegisterClassEx (&wndclass);
hwndMain = CreateWindow
(szAppName, // window class name
szCaption, // window caption
WS_OVERLAPPEDWINDOW, // window style
10, // x position on screen
5, // y position on screen
608, // width
440, // height
NULL, // parent window handle
NULL, // window menu handle
hInst, // program instance handle
NULL); // creation parameters
ShowWindow (hwndMain, iCmdShow);
UpdateWindow (hwndMain);
settings = new config;
settings -> downloading = false;
settings -> cancel = false;
pagelist = ParseCategories (NULL, settings); // Get set of categories from file
settings -> load(pagelist); // Get options and page preferences from ini file
status = new statuswnd(settings); // Create the status window (hidden)
GetOS(settings); // Get the operating system
url_splitter_Test(); // Testing stub
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc
(HWND hwndMain, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int loop; // Loop variable
int butWid, butHei, butGap; // Button width, height, and gap
int butScaler, checkScaler; // Scaler to make buttons or checks invisible
struct tm *datetime;
time_t lTime;
char szTime[100];
char blank[10];
static int WinBorderLR, // Border between items and left/right edges
WinBorderTB; // Border between items and top/bottom edges
static RECT rectTitle, // Title rectangle
rectHeading; // Heading rectangle
switch (iMessage)
{
case WM_TIMER:
time (&lTime);
datetime = localtime (&lTime);
// if TIME REACHED
strcpy(szTime, itoa(HOUR, blank, 10)); strcat(szTime, ":");
strcat(szTime, itoa(MIN, blank, 10)); strcat(szTime, ":");
strcat(szTime, itoa(SEC, blank, 10));
if ( (HOUR == settings -> sleep_hrs) &&
(MIN == settings -> sleep_mins) )
{
KillTimer (hwndMain, 1);
settings -> save(pagelist); // Save options in case it crashes!
settings -> unsupervised = true; // The download is unsupervised
get_all_pages(pagelist, settings, status, hButtons[3]);
}
return 0;
case WM_CREATE:
#if !COMPILER_V6
lpfnAboutDlgProc = MakeProcInstance((FARPROC) AboutDlgProc, hInst);
lpfnOptionsDlgProc = MakeProcInstance((FARPROC) OptionsDlgProc, hInst);
#endif
// Create the buttons and check boxes
for (loop=0; loop<10; loop++)
{
// Create buttons - identifiers 0-9
hButtons[loop] = CreateWindow
("button", // window class name
NULL, // window caption
WS_CHILD | // window style
WS_VISIBLE |
WS_BORDER |
BS_PUSHBUTTON,
0, 0, 0, 0, // Pos and Size defined later
hwndMain, // parent window handle
(HMENU)loop, // Button identifier
hInst, // program instance handle
NULL); // creation parameters
// Create check boxes - identifiers 10-19
// NOTE - The last check box is never used -
// the back button is there instead
hChecks[loop] = CreateWindow
("button", // window class name
NULL, // window caption
WS_CHILD | // window style
WS_VISIBLE |
BS_AUTOCHECKBOX,
0, 0, 0, 0, // Pos and Size defined later
hwndMain, // parent window handle
(HMENU)(loop+10),// Check box identifier
hInst, // program instance handle
NULL); // creation parameters
// Re-direct to new function (subclass) and store old function
#if COMPILER_V6
OldButProc = (WNDPROC) SetWindowLong (hButtons[loop],
GWL_WNDPROC, (long) NewButtonProc);
OldCheckProc = (WNDPROC) SetWindowLong (hChecks[loop],
GWL_WNDPROC, (long) NewCheckProc);
#else
OldButProc = (FARPROC) SetWindowLong (hButtons[loop],
GWL_WNDPROC, (long) NewButtonProc);
OldCheckProc = (FARPROC) SetWindowLong (hChecks[loop],
GWL_WNDPROC, (long) NewCheckProc);
#endif
}
// Get the values to put onto the buttons
mbuttons.Set_Buttons (hButtons, hChecks, pagelist);
SetFocus (hButtons[0]); // set focus to first button
ButtonFocus = 0;
return 0;
case WM_SETFOCUS:
// Ensure one of the buttons or check boxes always has the focus
if (!mbuttons.AtLeaves())
SetFocus(hButtons[ButtonFocus]); // set focus to relevant button
else
SetFocus(hChecks[ButtonFocus]); // set focus to relevant check box
return 0;
case WM_SIZE:
WinMaWid = LOWORD(lParam);
WinMaHei = HIWORD(lParam);
// Set positions of objects in client area
WinBorderLR = (int)(WinMaWid * 0.03);
WinBorderTB = (int)(WinMaHei * 0.05);
// Alter positions to make either buttons or check boxes visible
if (!mbuttons.AtLeaves())
{
butScaler = 1;
checkScaler = -1;
}
else
{
butScaler = -1;
checkScaler = 1;
}
rectTitle.left = WinBorderLR;
rectTitle.right = WinMaWid - WinBorderLR;
rectTitle.top = WinBorderTB;
rectTitle.bottom = (int)(WinMaHei * 0.15 + WinBorderTB);
rectHeading.left = WinBorderLR;
rectHeading.right = WinMaWid - WinBorderLR;
rectHeading.top = (int)(rectTitle.bottom + 10);
rectHeading.bottom = (int)(WinMaHei * 0.1 + rectTitle.bottom + 10);
butWid = (int)(WinMaWid * 0.46);
butHei = (int)(WinMaHei * 0.1);
butGap = (int)(WinMaHei * 0.025);
// Put the buttons in the correct places
for (loop=0; loop<5; loop++)
{
MoveWindow( hButtons[loop*2], // handle
WinBorderLR * butScaler, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos
butWid * butScaler, // width
butHei, // height
TRUE);
MoveWindow( hButtons[loop*2+1], // handle
(WinMaWid - WinBorderLR - butWid) * butScaler, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos
butWid * butScaler, // width
butHei, // height
TRUE);
MoveWindow( hChecks[loop*2], // handle
WinBorderLR * checkScaler, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos
butWid * checkScaler, // width
butHei, // height
TRUE);
MoveWindow( hChecks[loop*2+1], // handle
(WinMaWid - WinBorderLR - butWid) * checkScaler, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*loop), // top y pos
butWid * checkScaler, // width
butHei, // height
TRUE);
}
// Make sure the back button is always in it's correct position
MoveWindow( hButtons[9], // handle
WinMaWid - WinBorderLR - butWid, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*4), // top y pos
butWid, // width
butHei, // height
TRUE);
// Make sure the last check box is never visible
MoveWindow( hChecks[9], // handle
(WinMaWid - WinBorderLR - butWid) * -1, // left x pos
(int)(rectHeading.bottom + 10 + (butHei + butGap)*9), // top y pos
butWid * -1, // width
butHei, // height
TRUE);
for (loop=0; loop<10; loop++)
{
if (strlen(mbuttons.szButtonValue[loop]) == 0)
{
ShowWindow(hButtons[loop], SW_HIDE);
ShowWindow(hChecks[loop], SW_HIDE);
}
else
{
ShowWindow(hButtons[loop], SW_SHOWNORMAL);
ShowWindow(hChecks[loop], SW_SHOWNORMAL);
}
}
// Hide the "Get news now" button while downloading
if (settings != NULL)
if ((settings -> downloading) && (mbuttons.MenuLevel() == 0))
ShowWindow(hButtons[3], SW_HIDE);
return 0;
case WM_KEYDOWN:
if (wParam-112 == 10) // F10 key pressed
return 0;
// Process function keys F1 to F9
if (!mbuttons.AtLeaves())
{
if ((wParam-112 >= 0) && (wParam-112 < 9))
SendMessage (hwndMain, WM_COMMAND, wParam-112, NULL);
}
else
{
if ((wParam-112 >= 0) && (wParam-112 < 9))
{
if (strlen(mbuttons.szButtonValue[wParam-112]) != 0)
{
SendMessage (hChecks[wParam-112], WM_LBUTTONDOWN, NULL, NULL);
SendMessage (hChecks[wParam-112], WM_LBUTTONUP, NULL, NULL);
}
}
}
if (wParam == VK_ESCAPE)
SendMessage (hwndMain, WM_COMMAND, 9, NULL);
return 0;
case WM_PAINT:
// Paint objects on the screen
hdc = BeginPaint (hwndMain, &ps);
// Draw rectangle around the title
RoundRect(hdc, rectTitle.left , rectTitle.top,
rectTitle.right, rectTitle.bottom, 12, 12);
// Set text to text color as set in control panel
SetTextColor(hdc, COLOR_WINDOWTEXT);
// Draw Title
SetBkMode(hdc, OPAQUE);
SelectObject(hdc, CreateTitleFont);
DrawText(hdc, szCaption, strlen(szCaption), &rectTitle,
DT_CENTER | DT_VCENTER | DT_SINGLELINE );
// Draw Heading
SetBkMode(hdc, TRANSPARENT);
SelectObject(hdc, GetStockObject(SYSTEM_FONT));
DrawText(hdc, mbuttons.szHeading, strlen(mbuttons.szHeading), &rectHeading,
DT_VCENTER | DT_SINGLELINE );
// End painting
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
EndPaint (hwndMain, &ps);
return 0;
case WM_COMMAND:
if (mbuttons.MenuLevel() == 0)
{
switch (LOWORD(wParam)) // Actions caused by buttons or function keys
{
case 0: Instructions(); break;
case 1: if (pagelist != NULL)
{
mbuttons.PickCategory(0, hChecks, pagelist); // change to new menu
mbuttons.Set_Buttons(hButtons, hChecks, pagelist); // set button values
SetFocus(hButtons[0]); // set focus to first button
ButtonFocus = 0;
SetFocus(hwndMain);
// Force windows to redraw the client area
SendMessage ( hwndMain, WM_SIZE, 0, MAKELONG(WinMaWid, WinMaHei) );
InvalidateRect( hwndMain, NULL, TRUE ); // Make sure window is re-painted
}
else
MessageBox(hwndMain, "You need to download the category file first (F6)", "WNS", MB_OK);
break;
case 2: ShowWindow(hwndMain, SW_MINIMIZE);
SetTimer(hwndMain, 1, 5000, NULL);
break;
case 3: if (MessageBox(hwndMain, "This may take a few minutes! Click OK to continue, or 'Cancel' to cancel.",
"Note", MB_OKCANCEL | MB_ICONWARNING ) == IDOK)
{
settings -> save(pagelist); // Save options in case it crashes!
status -> activate(); // Make the status window visible
settings -> unsupervised = false; // The download is not unsupervised
get_all_pages(pagelist, settings, status, hButtons[3]);
}
break;
case 4: OpenBrowser(); break;
case 5: // Get new page file from server
DialUp(settings);
if (!Download_Page_File(settings))
{
MessageBox(hwndMain, "Cannot get page file from server",
"Error!", MB_OK);
}
// Get new set of categories from file
else
{
settings -> save(pagelist);
pagelist = ParseCategories(pagelist, settings);
settings -> load(pagelist);
MessageBox(hwndMain, "Done! The new categories should now be available.", "WNS", MB_OK);
}
HangUp( settings );
break;
#if COMPILER_V6
case 6: DialogBox(hInst, "Options", hwndMain, OptionsDlgProc); break;
case 7: DialogBox(hInst, "About", hwndMain, AboutDlgProc); break;
#else
case 6: DialogBox(hInst, "Options", hwndMain, lpfnOptionsDlgProc); break;
case 7: DialogBox(hInst, "About", hwndMain, lpfnAboutDlgProc); break;
#endif
case 9:SendMessage (hwndMain, WM_DESTROY, NULL, NULL); break;
}
}
else if ((LOWORD(wParam)>=0) && (LOWORD(wParam)<10))
{
mbuttons.PickCategory(LOWORD(wParam), hChecks, pagelist); // move to new menu
mbuttons.Set_Buttons(hButtons, hChecks, pagelist); // set new button values
ButtonFocus = 0;
SetFocus(hwndMain);
if (!mbuttons.AtLeaves())
SetFocus(hButtons[0]); // set focus to first button
else
SetFocus(hChecks[0]); // set focus to first check box
// Force windows to redraw the client area
SendMessage ( hwndMain, WM_SIZE, 0, MAKELONG(WinMaWid, WinMaHei) );
InvalidateRect( hwndMain, NULL, TRUE ); // Make sure window is re-painted
}
return 0;
case WM_DESTROY :
// Application has been killed!!
if (MessageBox(hwndMain, "Quit - Are you sure?", "Confirm",
MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2 ) == IDYES)
{
settings -> save(pagelist); // Save options before exiting
KillTimer(hwndMain, 1); // Stop the timer
delete status; // Remove the status window object
delete settings; // Remove the settings object
delete pagelist; // Remove the page list object
PostQuitMessage (0);
return 0;
}
}
return DefWindowProc
(hwndMain, iMessage, wParam, lParam);
}
// The instructions
void Instructions()
{
ShellExecute(hwndMain, "open", "Instructions/index.htm", NULL, NULL, SW_SHOWNORMAL);
}
// Open the default windows web browser
void OpenBrowser()
{
ShellExecute(hwndMain, "open", "Converted Pages/index.htm", NULL, NULL, SW_SHOWNORMAL);
}
void OpenLog()
{
ShellExecute(hwndMain, "open", "log.txt", NULL, NULL, SW_SHOWNORMAL);
}
// Find previous visible button/check box
HWND Set_Prev(int index)
{
do {
index--;
if (index<0) index+=10;
ButtonFocus = index;
if (index == 9) return hButtons[9]; // Always allow back button to recieve focus
if (strlen(mbuttons.szButtonValue[index]) > 0)
if (!mbuttons.AtLeaves())
return hButtons[index];
else
return hChecks[index];
} while (index<20); // Endless loop - risky!
return NULL;
}
// Find next visible button/check box
HWND Set_Next(int index)
{
do {
index++;
if (index>9) index-=10;
ButtonFocus = index;
if (index == 9) return hButtons[9]; // Always allow back button to recieve focus
if (strlen(mbuttons.szButtonValue[index]) > 0)
if (!mbuttons.AtLeaves())
return hButtons[index];
else
return hChecks[index];
} while (index<20); // Endless loop - risky!
return NULL;
}
// Sub-Classed windows procedure for buttons
LRESULT CALLBACK NewButtonProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
if (iMsg == WM_KEYDOWN)
if ((wParam == VK_TAB) || (wParam == VK_DOWN) || (wParam == VK_RIGHT))
{
// Pass focus to new button
if (GetKeyState(VK_SHIFT) < 0) SetFocus( Set_Prev(ButtonFocus) );
else SetFocus( Set_Next(ButtonFocus) );
return 0;
}
else if ((wParam == VK_UP) || (wParam == VK_LEFT))
{
SetFocus( Set_Prev(ButtonFocus) ); // Pass focus to new button
return 0;
}
else if (((wParam-112 >= 0) && (wParam-112 < 9)) || (wParam == VK_ESCAPE))
SendMessage (hwndMain, WM_KEYDOWN, wParam, lParam); // Pass key to main window
return CallWindowProc (OldButProc, hwnd, iMsg, wParam, lParam); // Pass control back
}
// Sub-Classed windows procedure for check boxes
LRESULT CALLBACK NewCheckProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
if (iMsg == WM_KEYDOWN)
if ((wParam == VK_TAB) || (wParam == VK_DOWN) || (wParam == VK_RIGHT))
{
// Pass focus to new button
if (GetKeyState(VK_SHIFT) < 0) SetFocus( Set_Prev(ButtonFocus) );
else SetFocus( Set_Next(ButtonFocus) );
return 0;
}
else if ((wParam == VK_UP) || (wParam == VK_LEFT))
{
SetFocus( Set_Prev(ButtonFocus) ); // Pass focus to new button
return 0;
}
else if (((wParam-112 >= 0) && (wParam-112 < 9)) || (wParam == VK_ESCAPE))
SendMessage (hwndMain, WM_KEYDOWN, wParam, lParam); // Pass key to main window
return CallWindowProc (OldCheckProc, hwnd, iMsg, wParam, lParam); // Pass control back
}
BOOL CALLBACK AboutDlgProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
char os_str[100];
switch (iMsg)
{
case WM_INITDIALOG:
strcpy(os_str, "Detected Operating System: ");
strcat(os_str, settings -> OS);
SetDlgItemText(hDlg, OPT_OS, os_str);
return true;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case OPT_OK:
EndDialog( hDlg, 0 );
return true;
}
break;
}
return false;
}
BOOL CALLBACK OptionsDlgProc( HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
char port[10];
char timeout[10];
char retries[10];
static bool use_proxy;
static bool supervisor;
static bool show_extern;
static bool show_status;
static bool modem;
switch (iMsg)
{
case WM_INITDIALOG:
SetWindowText
(GetDlgItem(hDlg, OPT_PROXYADDR), settings -> proxy_addr);
SetWindowText
(GetDlgItem(hDlg, OPT_PROXYPORT), itoa(settings -> proxy_port, port, 10) );
SetWindowText
(GetDlgItem(hDlg, OPT_TIMEOUT), itoa(settings -> timeout, timeout, 10) );
SetWindowText
(GetDlgItem(hDlg, OPT_RETRIES), itoa(settings -> retries, retries, 10) );
SetWindowText
(GetDlgItem(hDlg, OPT_FONT), settings -> font_size);
SetWindowText
(GetDlgItem(hDlg, OPT_HOURS), settings -> hours);
SetWindowText
(GetDlgItem(hDlg, OPT_MINUTES), settings -> minutes);
use_proxy = settings -> use_proxy;
SendDlgItemMessage (hDlg, OPT_USEPROXY, BM_SETCHECK,
use_proxy, 0L);
supervisor = settings -> supervisor;
SendDlgItemMessage (hDlg, OPT_SUPERVISOR, BM_SETCHECK,
supervisor, 0L);
show_extern = settings -> show_extern;
SendDlgItemMessage (hDlg, OPT_SHOWEXTERN, BM_SETCHECK,
show_extern, 0L);
show_status = settings -> show_status;
SendDlgItemMessage (hDlg, OPT_SHOWSTATUS, BM_SETCHECK,
show_status, 0L);
modem = settings -> use_modem;
SendDlgItemMessage (hDlg, OPT_MODEM, BM_SETCHECK,
modem, 0L);
return true;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case OPT_OK:
GetWindowText
(GetDlgItem(hDlg, OPT_PROXYADDR), settings -> proxy_addr, 255);
GetWindowText
(GetDlgItem(hDlg, OPT_PROXYPORT), port, 10);
GetWindowText
(GetDlgItem(hDlg, OPT_TIMEOUT), timeout, 10);
GetWindowText
(GetDlgItem(hDlg, OPT_RETRIES), retries, 10);
GetWindowText
(GetDlgItem(hDlg, OPT_FONT), settings -> font_size, 3);
GetWindowText
(GetDlgItem(hDlg, OPT_HOURS), settings -> hours, 5);
GetWindowText
(GetDlgItem(hDlg, OPT_MINUTES), settings -> minutes, 5);
settings -> proxy_port = atoi( port );
settings -> use_proxy = use_proxy;
settings -> supervisor = supervisor;
settings -> show_extern = show_extern;
settings -> show_status = show_status;
settings -> use_modem = modem;
settings -> timeout = atoi( timeout );
settings -> retries = atoi( retries );
settings -> sleep_hrs = atoi( settings -> hours );
settings -> sleep_mins = atoi( settings -> minutes );
EndDialog( hDlg, 0 );
return true;
case OPT_CANCEL:
EndDialog( hDlg, 0 );
return true;
case OPT_LOG:
OpenLog();
return true;
case OPT_USEPROXY:
use_proxy = (!use_proxy);
SendDlgItemMessage (hDlg, OPT_USEPROXY, BM_SETCHECK,
use_proxy, 0L);
return true;
case OPT_SUPERVISOR:
supervisor = (!supervisor);
SendDlgItemMessage (hDlg, OPT_SUPERVISOR, BM_SETCHECK,
supervisor, 0L);
return true;
case OPT_SHOWEXTERN:
show_extern = (!show_extern);
SendDlgItemMessage (hDlg, OPT_SHOWEXTERN, BM_SETCHECK,
show_extern, 0L);
return true;
case OPT_SHOWSTATUS:
show_status = (!show_status);
SendDlgItemMessage (hDlg, OPT_SHOWSTATUS, BM_SETCHECK,
show_status, 0L);
return true;
case OPT_MODEM:
modem = (!modem);
SendDlgItemMessage (hDlg, OPT_MODEM, BM_SETCHECK,
modem, 0L);
return true;
}
break;
}
return false;
}
syntax highlighted by Code2HTML, v. 0.8.11