ODFrame.c 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759
  1. /* OpenDoors Online Software Programming Toolkit
  2. * (C) Copyright 1991 - 1999 by Brian Pirie.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. *
  19. * File: ODFrame.c
  20. *
  21. * Description: Implements the OpenDoors frame window which provides the
  22. * menu, toolbar, and status bar. The frame window's client
  23. * area contains the display window which shows the door's
  24. * output as the remote user would see it. This file should
  25. * not be built into non-Windows versions of OpenDoors.
  26. *
  27. * Revisions: Date Ver Who Change
  28. * ---------------------------------------------------------------
  29. * Aug 20, 1995 6.00 BP Created.
  30. * Dec 20, 1995 6.00 BP Remember toolbar & statusbar settings.
  31. * Dec 22, 1995 6.00 BP Added od_connect_speed.
  32. * Jan 20, 1996 6.00 BP Made ODFrameCenter...() shared.
  33. * Jan 21, 1996 6.00 BP Added ODScrnShowMessage() and related.
  34. * Feb 17, 1996 6.00 BP Add ...Accelerator() return value.
  35. * Feb 17, 1996 6.00 BP Pass WM_MENUSELECT to DefWindowProc().
  36. * Feb 19, 1996 6.00 BP Changed version number to 6.00.
  37. * Feb 21, 1996 6.00 BP Fixed user keyboard off command.
  38. * Feb 22, 1996 6.00 BP Allow escape to close Help About box.
  39. * Feb 23, 1996 6.00 BP Properly update when toolbar turned on
  40. * Mar 03, 1996 6.10 BP Begin version 6.10.
  41. * Mar 14, 1996 6.10 BP Added configuration menu option.
  42. * Aug 10, 2003 6.23 SH *nix support
  43. */
  44. #define BUILDING_OPENDOORS
  45. #include <stdio.h>
  46. #include "windows.h"
  47. #include "commctrl.h"
  48. #include "OpenDoor.h"
  49. #include "ODRes.h"
  50. #include "ODFrame.h"
  51. #include "ODGen.h"
  52. #include "ODScrn.h"
  53. #include "ODKrnl.h"
  54. #ifdef ODPLAT_WIN32
  55. /* Frame window information structure. */
  56. typedef struct
  57. {
  58. HINSTANCE hInstance;
  59. BOOL bToolbarOn;
  60. HWND hwndToolbar;
  61. BOOL bStatusBarOn;
  62. HWND hwndStatusBar;
  63. HWND hwndTimeEdit;
  64. HWND hwndTimeUpDown;
  65. BOOL bWantsChatIndicator;
  66. HACCEL hacclFrameCommands;
  67. HWND hwndMessageWindow;
  68. char *pszCurrentMessage;
  69. int nCurrentMessageFlags;
  70. } tODFrameWindowInfo;
  71. /* Toolbar button information. */
  72. TBBUTTON atbButtons[] =
  73. {
  74. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  75. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  76. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  77. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  78. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  79. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  80. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  81. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  82. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  83. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  84. {0, ID_DOOR_CHATMODE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  85. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  86. {1, ID_DOOR_USERKEYBOARDOFF, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  87. {2, ID_DOOR_SYSOPNEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  88. {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0},
  89. {3, ID_DOOR_HANGUP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  90. {4, ID_DOOR_LOCKOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  91. {5, ID_DOOR_EXIT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
  92. };
  93. /* Other toolbar settings. */
  94. #define NUM_TOOLBAR_BITMAPS 6
  95. #define MIN_TIME 0
  96. #define MAX_TIME 1440
  97. /* Pointer to default edit box window procedure. */
  98. WNDPROC pfnDefEditProc = NULL;
  99. WNDPROC pfnDefToolbarProc = NULL;
  100. /* Global frame window handle. */
  101. static HWND hwndCurrentFrame;
  102. /* Status bar settings. */
  103. #define NUM_STATUS_PARTS 2
  104. #define NODE_PART_WIDTH 65
  105. /* Child window IDs. */
  106. #define ID_TOOLBAR 1000
  107. #define ID_TIME_EDIT 1001
  108. #define ID_TIME_UPDOWN 1002
  109. #define ID_STATUSBAR 1003
  110. /* Private function prototypes. */
  111. static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
  112. tODFrameWindowInfo *pWindowInfo);
  113. static void ODFrameDestroyToolbar(HWND hwndToolbar,
  114. tODFrameWindowInfo *pWindowInfo);
  115. static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance);
  116. static void ODFrameSetMainStatusText(HWND hwndStatusBar);
  117. static void ODFrameDestroyStatusBar(HWND hwndStatusBar);
  118. static void ODFrameSizeStatusBar(HWND hwndStatusBar);
  119. LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  120. LPARAM lParam);
  121. LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  122. LPARAM lParam);
  123. static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo);
  124. LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  125. LPARAM lParam);
  126. BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
  127. LPARAM lParam);
  128. static HWND ODFrameCreateWindow(HANDLE hInstance);
  129. static void ODFrameDestroyWindow(HWND hwndFrame);
  130. static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame);
  131. DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam);
  132. BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
  133. LPARAM lParam);
  134. /* ----------------------------------------------------------------------------
  135. * ODFrameCreateWindow() *** PRIVATE FUNCTION ***
  136. *
  137. * Creates the OpenDoors frame window and its children.
  138. *
  139. * Parameters: hInstance - Handle to application instance.
  140. *
  141. * Return: A handle to the newly created window, or NULL on failure.
  142. */
  143. static HWND ODFrameCreateWindow(HANDLE hInstance)
  144. {
  145. HWND hwndFrameWindow = NULL;
  146. WNDCLASS wcFrameWindow;
  147. tODFrameWindowInfo *pWindowInfo = NULL;
  148. tODThreadHandle hScreenThread;
  149. HKEY hOpenDoorsKey;
  150. DWORD cbData;
  151. /* Register the main frame window's window class. */
  152. memset(&wcFrameWindow, 0, sizeof(wcFrameWindow));
  153. wcFrameWindow.style = CS_HREDRAW | CS_VREDRAW;
  154. wcFrameWindow.lpfnWndProc = ODFrameWindowProc;
  155. wcFrameWindow.cbClsExtra = 0;
  156. wcFrameWindow.cbWndExtra = 0;
  157. wcFrameWindow.hInstance = hInstance;
  158. if(od_control.od_app_icon != NULL)
  159. {
  160. wcFrameWindow.hIcon = od_control.od_app_icon;
  161. }
  162. else
  163. {
  164. wcFrameWindow.hIcon
  165. = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_OPENDOORS));
  166. }
  167. wcFrameWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
  168. wcFrameWindow.hbrBackground = NULL;
  169. wcFrameWindow.lpszMenuName = MAKEINTRESOURCE(IDR_FRAME_MENU);
  170. wcFrameWindow.lpszClassName = "ODFrame";
  171. RegisterClass(&wcFrameWindow);
  172. /* Setup window information structure. */
  173. pWindowInfo = malloc(sizeof(tODFrameWindowInfo));
  174. if(!pWindowInfo)
  175. {
  176. return(NULL);
  177. }
  178. pWindowInfo->hInstance = hInstance;
  179. pWindowInfo->hwndTimeEdit = NULL;
  180. pWindowInfo->hwndTimeUpDown = NULL;
  181. pWindowInfo->bWantsChatIndicator = FALSE;
  182. pWindowInfo->hwndMessageWindow = NULL;
  183. /* Determine whether or not the toolbar and status bar are on. */
  184. RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
  185. &hOpenDoorsKey);
  186. cbData = sizeof(pWindowInfo->bToolbarOn);
  187. if(RegQueryValueEx(hOpenDoorsKey, "ToolBarOn", NULL, NULL,
  188. (LPBYTE)&pWindowInfo->bToolbarOn,
  189. &cbData) != ERROR_SUCCESS)
  190. {
  191. pWindowInfo->bToolbarOn = TRUE;
  192. RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
  193. (LPBYTE)&pWindowInfo->bToolbarOn,
  194. sizeof(pWindowInfo->bToolbarOn));
  195. }
  196. cbData = sizeof(pWindowInfo->bStatusBarOn);
  197. if(RegQueryValueEx(hOpenDoorsKey, "StatusBarOn", NULL, NULL,
  198. (LPBYTE)&pWindowInfo->bStatusBarOn,
  199. &cbData) != ERROR_SUCCESS)
  200. {
  201. pWindowInfo->bStatusBarOn = TRUE;
  202. RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
  203. (LPBYTE)&pWindowInfo->bStatusBarOn,
  204. sizeof(pWindowInfo->bStatusBarOn));
  205. }
  206. RegCloseKey(hOpenDoorsKey);
  207. /* Create the main frame window. */
  208. if((hwndFrameWindow = CreateWindowEx(
  209. 0L,
  210. wcFrameWindow.lpszClassName,
  211. od_control.od_prog_name,
  212. WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX,
  213. CW_USEDEFAULT,
  214. 0,
  215. 0,
  216. 0,
  217. NULL,
  218. NULL,
  219. hInstance,
  220. pWindowInfo)) == NULL)
  221. {
  222. /* On window creation failure, return NULL. */
  223. return(NULL);
  224. }
  225. /* Load accelerator table for the frame window. */
  226. pWindowInfo->hacclFrameCommands
  227. = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_FRAME));
  228. /* Create the OpenDoors toolbar. On failure, we will continue anyhow. */
  229. if(pWindowInfo->bToolbarOn)
  230. {
  231. pWindowInfo->hwndToolbar =
  232. ODFrameCreateToolbar(hwndFrameWindow, hInstance, pWindowInfo);
  233. }
  234. /* Create the status bar. On failure, we will continue anyhow. */
  235. if(pWindowInfo->bStatusBarOn)
  236. {
  237. pWindowInfo->hwndStatusBar =
  238. ODFrameCreateStatusBar(hwndFrameWindow, hInstance);
  239. }
  240. /* Updates state of the window from whether or not the user has */
  241. /* requested a chat with the sysop. */
  242. ODFrameUpdateWantChat();
  243. /* Create the local screen window, which occupies the remaining */
  244. /* client area of the frame window. */
  245. ODScrnStartWindow(hInstance, &hScreenThread, hwndFrameWindow);
  246. return(hwndFrameWindow);
  247. }
  248. /* ----------------------------------------------------------------------------
  249. * ODFrameCreateToolbar() *** PRIVATE FUNCTION ***
  250. *
  251. * Creates the OpenDoors toolbar.
  252. *
  253. * Parameters: hwndParent - Handle to the parent window.
  254. *
  255. * hInstance - Handle to the executable file's module instance.
  256. *
  257. * pWindowInfo - Pointer to frame window information structure.
  258. *
  259. * Return: A handle to the toolbar on success, or NULL on failure.
  260. */
  261. static HWND ODFrameCreateToolbar(HWND hwndParent, HANDLE hInstance,
  262. tODFrameWindowInfo *pWindowInfo)
  263. {
  264. HWND hwndToolbar = NULL;
  265. HWND hwndTimeEdit = NULL;
  266. HWND hwndTimeUpDown = NULL;
  267. HWND hwndToolTip;
  268. BOOL bSuccess = FALSE;
  269. ASSERT(hwndParent != NULL);
  270. ASSERT(hInstance != NULL);
  271. ASSERT(pWindowInfo != NULL);
  272. /* First, attempt to create the toolbar window. */
  273. hwndToolbar = CreateToolbarEx(hwndParent,
  274. WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS,
  275. ID_TOOLBAR, NUM_TOOLBAR_BITMAPS, hInstance, IDB_TOOLBAR,
  276. atbButtons, DIM(atbButtons), 0, 0, 0, 0, sizeof(TBBUTTON));
  277. if(hwndToolbar == NULL)
  278. {
  279. goto CleanUp;
  280. }
  281. /* Change the window proc for the toolbar window to our own, keeping a */
  282. /* pointer to the original window proc. */
  283. pfnDefToolbarProc = (WNDPROC)GetWindowLong(hwndToolbar, GWL_WNDPROC);
  284. SetWindowLong(hwndToolbar, GWL_WNDPROC, (LONG)ODFrameToolbarProc);
  285. /* Next, create an edit control on the toolbar, to allow the user's */
  286. /* time remaining online to be adjusted. */
  287. hwndTimeEdit = CreateWindowEx(WS_EX_STATICEDGE, "EDIT", "",
  288. WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT,
  289. 0, 0, 70, 22, hwndToolbar, (HMENU)ID_TIME_EDIT, hInstance, NULL);
  290. if(hwndTimeEdit == NULL)
  291. {
  292. goto CleanUp;
  293. }
  294. /* Now that the edit window has the appropriate parent, we set its */
  295. /* position accordingly. */
  296. SetWindowPos(hwndTimeEdit, NULL, 2, 2, 0, 0,
  297. SWP_NOZORDER | SWP_NOSIZE);
  298. /* Set font of the edit control to be the standard non-bold font. */
  299. SendMessage(hwndTimeEdit, WM_SETFONT,
  300. (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0));
  301. /* Change the window proc for the edit window to our own, keeping a */
  302. /* pointer to the original window proc. */
  303. pfnDefEditProc = (WNDPROC)GetWindowLong(hwndTimeEdit, GWL_WNDPROC);
  304. SetWindowLong(hwndTimeEdit, GWL_WNDPROC, (LONG)ODFrameTimeEditProc);
  305. /* Add the time edit control to the tooltip control. */
  306. /* Obtain a handle to the toolbar's tooltip control. */
  307. hwndToolTip = (HWND)SendMessage(hwndToolbar, TB_GETTOOLTIPS, 0, 0);
  308. if(hwndToolTip)
  309. {
  310. TOOLINFO ToolInfo;
  311. /* Fill TOOLINFO structure. */
  312. ToolInfo.cbSize = sizeof(ToolInfo);
  313. ToolInfo.uFlags = TTF_IDISHWND | TTF_CENTERTIP;
  314. ToolInfo.lpszText = "User's Time Remaining";
  315. ToolInfo.hwnd = hwndParent;
  316. ToolInfo.uId = (UINT)hwndTimeEdit;
  317. ToolInfo.hinst = hInstance;
  318. /* Setup tooltips for the time edit box. */
  319. SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ToolInfo);
  320. }
  321. /* Now, we create an up-down control to buddy with the edit control. */
  322. hwndTimeUpDown = CreateWindowEx(0L, UPDOWN_CLASS, "",
  323. WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ARROWKEYS |
  324. UDS_ALIGNRIGHT, 0, 0, 8, 8,
  325. hwndToolbar, (HMENU)ID_TIME_UPDOWN, hInstance, NULL);
  326. if(hwndTimeUpDown == NULL)
  327. {
  328. goto CleanUp;
  329. }
  330. /* Set the up-down control's buddy control to be the edit control that */
  331. /* we just created. */
  332. SendMessage(hwndTimeUpDown, UDM_SETBUDDY, (LONG)hwndTimeEdit, 0L);
  333. /* Set the valid range of values for the edit control. */
  334. SendMessage(hwndTimeUpDown, UDM_SETRANGE, 0L, MAKELONG(MAX_TIME, MIN_TIME));
  335. /* Store handles to time limit edit and up-down controls. */
  336. pWindowInfo->hwndTimeEdit = hwndTimeEdit;
  337. pWindowInfo->hwndTimeUpDown = hwndTimeUpDown;
  338. /* Next, we set the default text for the edit control. */
  339. ODFrameUpdateTimeLeft(pWindowInfo);
  340. /* Return with success. */
  341. bSuccess = TRUE;
  342. CleanUp:
  343. if(!bSuccess)
  344. {
  345. /* On failure, free any allocated resources. */
  346. if(hwndTimeUpDown != NULL)
  347. {
  348. DestroyWindow(hwndTimeUpDown);
  349. }
  350. if(hwndTimeEdit != NULL)
  351. {
  352. DestroyWindow(hwndTimeUpDown);
  353. }
  354. if(hwndToolbar != NULL)
  355. {
  356. DestroyWindow(hwndToolbar);
  357. hwndToolbar = NULL;
  358. }
  359. }
  360. /* Return handle to newly created toolbar, or NULL on failure. */
  361. return(hwndToolbar);
  362. }
  363. /* ----------------------------------------------------------------------------
  364. * ODFrameDestroyToolbar() *** PRIVATE FUNCTION ***
  365. *
  366. * Destroys the OpenDoors toolbar.
  367. *
  368. * Parameters: hwndToolbar - Handle to previously created toolbar.
  369. *
  370. * pWindowInfo - Pointer to frame window information structure.
  371. *
  372. * Return: void.
  373. */
  374. static void ODFrameDestroyToolbar(HWND hwndToolbar,
  375. tODFrameWindowInfo *pWindowInfo)
  376. {
  377. ASSERT(hwndToolbar != NULL);
  378. ASSERT(pWindowInfo != NULL);
  379. /* Destroy the time up-down control, and NULL its handle in the frame */
  380. /* window information structure. */
  381. DestroyWindow(pWindowInfo->hwndTimeUpDown);
  382. pWindowInfo->hwndTimeUpDown = NULL;
  383. /* Destroy the time edit control, and NULL its handle in the frame window */
  384. /* information structure. */
  385. DestroyWindow(pWindowInfo->hwndTimeEdit);
  386. pWindowInfo->hwndTimeEdit = NULL;
  387. /* Now, destroy the toolbar itself. */
  388. DestroyWindow(hwndToolbar);
  389. }
  390. /* ----------------------------------------------------------------------------
  391. * ODFrameCreateStatusBar() *** PRIVATE FUNCTION ***
  392. *
  393. * Creates the OpenDoors status bar.
  394. *
  395. * Parameters: hwndParent - Handle to the parent window.
  396. *
  397. * hInstance - Handle to the executable file's module instance.
  398. *
  399. * Return: A handle to the status bar on success, or NULL on failure.
  400. */
  401. static HWND ODFrameCreateStatusBar(HWND hwndParent, HANDLE hInstance)
  402. {
  403. HWND hwndStatusBar = NULL;
  404. char szStatusText[20];
  405. ASSERT(hwndParent != NULL);
  406. /* Create the status bar window. */
  407. hwndStatusBar = CreateWindowEx(0L, STATUSCLASSNAME, "",
  408. WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
  409. hwndParent, (HMENU)ID_STATUSBAR, hInstance, NULL);
  410. if(hwndStatusBar == NULL)
  411. {
  412. return(NULL);
  413. }
  414. /* Set the size of the status bar parts from the size of the frame */
  415. /* window. */
  416. ODFrameSizeStatusBar(hwndStatusBar);
  417. /* Add the user's name, location and connection info string. */
  418. ODFrameSetMainStatusText(hwndStatusBar);
  419. /* Add the node number string. */
  420. sprintf(szStatusText, "Node %d", od_control.od_node);
  421. SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)1, (LPARAM)szStatusText);
  422. return(hwndStatusBar);
  423. }
  424. /* ----------------------------------------------------------------------------
  425. * ODFrameSetMainStatusText() *** PRIVATE FUNCTION ***
  426. *
  427. * Updates the text that is displayed in the main pane of the status bar.
  428. *
  429. * Parameters: hwndStatusBar - Handle to the status bar.
  430. *
  431. * Return: void.
  432. */
  433. static void ODFrameSetMainStatusText(HWND hwndStatusBar)
  434. {
  435. char szStatusText[160];
  436. ASSERT(hwndStatusBar != NULL);
  437. /* Generate base status bar text, with the user's name, location and */
  438. /* connection information. */
  439. if(od_control.baud == 0)
  440. {
  441. sprintf(szStatusText, "%s of %s in local mode",
  442. od_control.user_name,
  443. od_control.user_location);
  444. }
  445. else
  446. {
  447. sprintf(szStatusText, "%s of %s at %ldbps",
  448. od_control.user_name,
  449. od_control.user_location,
  450. od_control.od_connect_speed);
  451. }
  452. /* If the user has paged the sysop, then include reason for chat if */
  453. /* it is available. */
  454. if(od_control.user_wantchat && strlen(od_control.user_reasonforchat) > 0)
  455. {
  456. strcat(szStatusText, " (Reason for chat: \"");
  457. strcat(szStatusText, od_control.user_reasonforchat);
  458. strcat(szStatusText, "\")");
  459. }
  460. /* Update status bar text in the main status bar pane with the newly */
  461. /* generated string. */
  462. SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
  463. }
  464. /* ----------------------------------------------------------------------------
  465. * ODFrameDestroyStatusBar() *** PRIVATE FUNCTION ***
  466. *
  467. * Destroys the OpenDoors status bar.
  468. *
  469. * Parameters: hwndStatusBar - Handle to previously created status bar.
  470. *
  471. * Return: void.
  472. */
  473. static void ODFrameDestroyStatusBar(HWND hwndStatusBar)
  474. {
  475. DestroyWindow(hwndStatusBar);
  476. }
  477. /* ----------------------------------------------------------------------------
  478. * ODFrameSizeStatusBar() *** PRIVATE FUNCTION ***
  479. *
  480. * Creates the OpenDoors status bar.
  481. *
  482. * Parameters: hwndStatusBar - Handle to existing status bar window.
  483. *
  484. * Return: void.
  485. */
  486. static void ODFrameSizeStatusBar(HWND hwndStatusBar)
  487. {
  488. int anWidths[NUM_STATUS_PARTS];
  489. int nStatusWidth;
  490. RECT rcStatusBar;
  491. /* Determine the total width of the status bar. */
  492. GetWindowRect(hwndStatusBar, &rcStatusBar);
  493. nStatusWidth = rcStatusBar.right - rcStatusBar.left;
  494. /* Calculate the width of the parts from the total width. */
  495. anWidths[0] = nStatusWidth - NODE_PART_WIDTH;
  496. anWidths[1] = -1;
  497. /* Update the status bar part settings. */
  498. SendMessage(hwndStatusBar, SB_SETPARTS, NUM_STATUS_PARTS,
  499. (LPARAM)anWidths);
  500. }
  501. /* ----------------------------------------------------------------------------
  502. * ODFrameGetUsedClientAtTop()
  503. *
  504. * Determines height in pixels of the space used at the top of the
  505. * frame window's client area, by the toolbar, etc.
  506. *
  507. * Parameters: hwndFrame - Handle to the OpenDoors frame window.
  508. *
  509. * Return: The height of the used space, in pixels.
  510. */
  511. INT ODFrameGetUsedClientAtTop(HWND hwndFrame)
  512. {
  513. tODFrameWindowInfo *pWindowInfo;
  514. RECT rcWindow;
  515. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
  516. if(!pWindowInfo->bToolbarOn) return(0);
  517. GetWindowRect(pWindowInfo->hwndToolbar, &rcWindow);
  518. return(rcWindow.bottom - rcWindow.top - 2);
  519. }
  520. /* ----------------------------------------------------------------------------
  521. * ODFrameGetUsedClientAtBottom()
  522. *
  523. * Determines height in pixels of the space used at the bottom of the
  524. * frame window's client area, by the status bar, etc.
  525. *
  526. * Parameters: hwndFrame - Handle to the OpenDoors frame window.
  527. *
  528. * Return: The height of the used space, in pixels.
  529. */
  530. INT ODFrameGetUsedClientAtBottom(HWND hwndFrame)
  531. {
  532. tODFrameWindowInfo *pWindowInfo;
  533. RECT rcWindow;
  534. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
  535. if(!pWindowInfo->bStatusBarOn) return(0);
  536. GetWindowRect(pWindowInfo->hwndStatusBar, &rcWindow);
  537. return(rcWindow.bottom - rcWindow.top - 1);
  538. }
  539. /* ----------------------------------------------------------------------------
  540. * ODFrameWindowProc() *** PRIVATE FUNCTION ***
  541. *
  542. * The OpenDoors frame window proceedure.
  543. *
  544. * Parameters: hwnd - Handle to the OpenDoors frame window.
  545. *
  546. * uMsg - Specifies the message.
  547. *
  548. * wParam - Specifies additional message information. The content
  549. * of this parameter depends on the value of the uMsg
  550. * parameter.
  551. *
  552. * lParam - Specifies additional message information. The content
  553. * of this parameter depends on the value of the uMsg
  554. * parameter.
  555. *
  556. * Return: The return value is the result of the message processing and
  557. * depends on the message.
  558. */
  559. LRESULT CALLBACK ODFrameWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  560. LPARAM lParam)
  561. {
  562. tODFrameWindowInfo *pWindowInfo;
  563. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwnd, GWL_USERDATA);
  564. switch(uMsg)
  565. {
  566. case WM_CREATE:
  567. {
  568. /* At window creation time, store a pointer to the window */
  569. /* information structure in window's user data. */
  570. CREATESTRUCT *pCreateStruct = (CREATESTRUCT *)lParam;
  571. pWindowInfo = (tODFrameWindowInfo *)pCreateStruct->lpCreateParams;
  572. SetWindowLong(hwnd, GWL_USERDATA, (LONG)pWindowInfo);
  573. /* Update the enabled and checked states of frame window commands. */
  574. ODFrameUpdateCmdUI();
  575. /* If the client has not provided a help callback function, then */
  576. /* remove the Contents item from the help menu. */
  577. if(od_control.od_help_callback == NULL)
  578. {
  579. RemoveMenu(GetMenu(hwnd), ID_HELP_CONTENTS, MF_BYCOMMAND);
  580. }
  581. if(od_control.od_config_callback == NULL)
  582. {
  583. RemoveMenu(GetMenu(hwnd), ID_DOOR_CONFIG, MF_BYCOMMAND);
  584. }
  585. break;
  586. }
  587. case WM_CLOSE:
  588. /* If door exit has been chosen, confirm with local user. */
  589. if(MessageBox(hwnd,
  590. "You are about to terminate this session and return the user to the BBS.\nDo you wish to proceed?",
  591. od_control.od_prog_name,
  592. MB_ICONQUESTION | MB_YESNO) == IDYES)
  593. {
  594. /* Normal door exit (drop to BBS) is implemented by the */
  595. /* WM_DESTROY handler. */
  596. ODFrameDestroyWindow(hwnd);
  597. }
  598. break;
  599. case WM_DESTROY:
  600. /* If toolbar is on, then it must be destroyed when the frame */
  601. /* window is destroyed. */
  602. if(pWindowInfo->bToolbarOn)
  603. {
  604. ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR), pWindowInfo);
  605. }
  606. /* If status bar is on, then it must be destroyed when the frame */
  607. /* window is destroyed. */
  608. if(pWindowInfo->bStatusBarOn)
  609. {
  610. ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
  611. }
  612. /* Now, force OpenDoors to shutdown. */
  613. ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_DROPTOBBS);
  614. /* When the frame window is destroyed, it is the window proc's */
  615. /* responsiblity to deallocate the window information structure. */
  616. free(pWindowInfo);
  617. SetWindowLong(hwnd, GWL_USERDATA, (LONG)NULL);
  618. /* Reset current frame window handle. */
  619. hwndCurrentFrame = NULL;
  620. break;
  621. case WM_SETFOCUS:
  622. /* Whenver input focus is set to the frame window, pass the input */
  623. /* focus on to the screen window, which fills most of our client */
  624. /* area. */
  625. ODScrnSetFocusToWindow();
  626. break;
  627. case WM_TIMER:
  628. /* If the window flash timer has elapsed, then flash the window. */
  629. FlashWindow(hwnd, TRUE);
  630. break;
  631. case WM_COMMAND:
  632. /* An OpenDoors-defined command has been selected, so switch on */
  633. /* the command ID. */
  634. switch(LOWORD(wParam))
  635. {
  636. case ID_HELP_ABOUT:
  637. /* Display the OpenDoors default about box. */
  638. DialogBox(pWindowInfo->hInstance, MAKEINTRESOURCE(IDD_ABOUT),
  639. hwnd, ODFrameAboutDlgProc);
  640. break;
  641. case ID_HELP_CONTENTS:
  642. /* Call the client's help callback function, if one was */
  643. /* provided. */
  644. if(od_control.od_help_callback != NULL)
  645. {
  646. (*od_control.od_help_callback)();
  647. }
  648. break;
  649. case ID_DOOR_CONFIG:
  650. if(od_control.od_config_callback != NULL)
  651. {
  652. (*od_control.od_config_callback)();
  653. }
  654. break;
  655. case ID_DOOR_EXIT:
  656. /* On request for normal door exit (drop to BBS), just send */
  657. /* a close message to this window. This will prompt to */
  658. /* confirm exit, and then shutdown OpenDoors if appropriate. */
  659. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  660. break;
  661. case ID_DOOR_CHATMODE:
  662. /* If chat mode is currently active, then end it. */
  663. if(od_control.od_chat_active)
  664. {
  665. ODKrnlEndChatMode();
  666. }
  667. /* If chat mode is not currently active, then start it. */
  668. else
  669. {
  670. ODKrnlStartChatThread(TRUE);
  671. }
  672. break;
  673. case ID_DOOR_USERKEYBOARDOFF:
  674. /* If user keyboard off command has been chosen, then toggle */
  675. /* keyboard off mode on or off. */
  676. od_control.od_user_keyboard_on
  677. = !od_control.od_user_keyboard_on;
  678. /* Update the keyboard off menu item and toolbar button. */
  679. CheckMenuItem(GetMenu(hwnd), ID_DOOR_USERKEYBOARDOFF,
  680. MF_BYCOMMAND | (od_control.od_user_keyboard_on
  681. ? MF_UNCHECKED : MF_CHECKED));
  682. SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
  683. ID_DOOR_USERKEYBOARDOFF,
  684. MAKELONG(!od_control.od_user_keyboard_on, 0));
  685. break;
  686. case ID_DOOR_SYSOPNEXT:
  687. /* If sysop next command has been chosen, then toggle the */
  688. /* sysop next flag on or off. */
  689. od_control.sysop_next = !od_control.sysop_next;
  690. /* Update the sysop next menu item and toolbar button. */
  691. CheckMenuItem(GetMenu(hwnd), ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
  692. (od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
  693. SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), TB_CHECKBUTTON,
  694. ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
  695. break;
  696. case ID_DOOR_HANGUP:
  697. /* If hangup command has been chosen, then confirm with the */
  698. /* local user. */
  699. if(MessageBox(hwnd,
  700. "You are about to disconnect this user. Do you wish to proceed?",
  701. od_control.od_prog_name,
  702. MB_ICONQUESTION | MB_YESNO) == IDYES)
  703. {
  704. ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
  705. }
  706. break;
  707. case ID_DOOR_LOCKOUT:
  708. /* If lockout command has been chosen, the confirm with the */
  709. /* local user. */
  710. if(MessageBox(hwnd,
  711. "You are about to lock out this user. Do you wish to proceed?",
  712. od_control.od_prog_name,
  713. MB_ICONQUESTION | MB_YESNO) == IDYES)
  714. {
  715. /* Set the user's access security level to 0. */
  716. od_control.user_security = 0;
  717. ODKrnlForceOpenDoorsShutdown(ERRORLEVEL_HANGUP);
  718. }
  719. break;
  720. case ID_VIEW_TOOL_BAR:
  721. {
  722. HKEY hOpenDoorsKey;
  723. /* If toolbar on/off command has been chosen ... */
  724. if(pWindowInfo->bToolbarOn)
  725. {
  726. /* If the toolbar is on, then turn it off. */
  727. ODFrameDestroyToolbar(GetDlgItem(hwnd, ID_TOOLBAR),
  728. pWindowInfo);
  729. pWindowInfo->bToolbarOn = FALSE;
  730. CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
  731. MF_BYCOMMAND | MF_UNCHECKED);
  732. }
  733. else
  734. {
  735. /* If the toolbar is off, then turn it on. */
  736. pWindowInfo->hwndToolbar = ODFrameCreateToolbar(hwnd,
  737. pWindowInfo->hInstance, pWindowInfo);
  738. pWindowInfo->bToolbarOn = TRUE;
  739. CheckMenuItem(GetMenu(hwnd), ID_VIEW_TOOL_BAR,
  740. MF_BYCOMMAND | MF_CHECKED);
  741. ODFrameUpdateCmdUI();
  742. }
  743. /* Adjust window sizes accordingly. */
  744. ODScrnAdjustWindows();
  745. /* Update the toolbar setting in the registry. */
  746. RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
  747. &hOpenDoorsKey);
  748. RegSetValueEx(hOpenDoorsKey, "ToolBarOn", 0, REG_DWORD,
  749. (LPBYTE)&pWindowInfo->bToolbarOn,
  750. sizeof(pWindowInfo->bToolbarOn));
  751. RegCloseKey(hOpenDoorsKey);
  752. break;
  753. }
  754. case ID_VIEW_STAT_BAR:
  755. {
  756. HKEY hOpenDoorsKey;
  757. /* If the status bar on/off command has been chosen ... */
  758. if(pWindowInfo->bStatusBarOn)
  759. {
  760. /* If the status bar is on, then turn it off. */
  761. pWindowInfo->bStatusBarOn = FALSE;
  762. CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
  763. MF_BYCOMMAND | MF_UNCHECKED);
  764. ODFrameDestroyStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
  765. }
  766. else
  767. {
  768. /* If the status bar is off, then turn it on. */
  769. pWindowInfo->bStatusBarOn = TRUE;
  770. CheckMenuItem(GetMenu(hwnd), ID_VIEW_STAT_BAR,
  771. MF_BYCOMMAND | MF_CHECKED);
  772. pWindowInfo->hwndStatusBar =
  773. ODFrameCreateStatusBar(hwnd, pWindowInfo->hInstance);
  774. }
  775. /* Adjust window sizes accordingly. */
  776. ODScrnAdjustWindows();
  777. /* Update the status bar setting in the registry. */
  778. RegCreateKey(HKEY_CURRENT_USER, "Software\\Pirie\\OpenDoors",
  779. &hOpenDoorsKey);
  780. RegSetValueEx(hOpenDoorsKey, "StatusBarOn", 0, REG_DWORD,
  781. (LPBYTE)&pWindowInfo->bStatusBarOn,
  782. sizeof(pWindowInfo->bStatusBarOn));
  783. RegCloseKey(hOpenDoorsKey);
  784. break;
  785. }
  786. case ID_USER_ADDONEMINUTE:
  787. /* If add one minute command has been chosen, then */
  788. /* increment the user's time, up to the maximum allowable */
  789. /* time. */
  790. if(od_control.user_timelimit < MAX_TIME)
  791. {
  792. od_control.user_timelimit++;
  793. ODFrameUpdateTimeLeft(pWindowInfo);
  794. }
  795. break;
  796. case ID_USER_ADDFIVEMINUTES:
  797. /* If add five minutes command has been chosen, then */
  798. /* adjust the user's time accordingly. */
  799. od_control.user_timelimit =
  800. MIN(od_control.user_timelimit + 5, MAX_TIME);
  801. ODFrameUpdateTimeLeft(pWindowInfo);
  802. break;
  803. case ID_USER_SUBTRACTONEMINUTE:
  804. /* If subtract one minute command has been chosen, then */
  805. /* adjust the user's time accordingly. */
  806. if(od_control.user_timelimit > MIN_TIME)
  807. {
  808. od_control.user_timelimit--;
  809. ODFrameUpdateTimeLeft(pWindowInfo);
  810. }
  811. break;
  812. case ID_USER_SUBTRACTFIVEMINUTES:
  813. /* If the subtract five mintues command has been chosen, */
  814. /* then adjust the user's time accordingly. */
  815. od_control.user_timelimit =
  816. MAX(od_control.user_timelimit - 5, MIN_TIME);
  817. ODFrameUpdateTimeLeft(pWindowInfo);
  818. break;
  819. case ID_USER_INACTIVITYTIMER:
  820. /* If the user inactivity timer command has been chosen, */
  821. /* then toggle the timer on or off. */
  822. od_control.od_disable_inactivity =
  823. !od_control.od_disable_inactivity;
  824. CheckMenuItem(GetMenu(hwnd), ID_USER_INACTIVITYTIMER,
  825. MF_BYCOMMAND | (od_control.od_disable_inactivity ?
  826. MF_UNCHECKED : MF_CHECKED));
  827. break;
  828. case ID_TIME_EDIT:
  829. {
  830. /* If the user's time remaining has been directly edited, */
  831. /* then adjust the time limit accordingly. */
  832. if(HIWORD(wParam) == EN_CHANGE)
  833. {
  834. char szTimeText[40];
  835. GetWindowText((HWND)lParam, szTimeText, sizeof(szTimeText));
  836. od_control.user_timelimit = atoi(szTimeText);
  837. /* Do not allow the time limit to fall outside of the */
  838. /* valid range. */
  839. od_control.user_timelimit =
  840. MAX(MIN_TIME, od_control.user_timelimit);
  841. od_control.user_timelimit =
  842. MIN(MAX_TIME, od_control.user_timelimit);
  843. /* Update the position of the up-down control. */
  844. SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
  845. (LPARAM)MAKELONG(od_control.user_timelimit, 0));
  846. }
  847. }
  848. default:
  849. return(TRUE);
  850. }
  851. return(FALSE);
  852. case WM_NOTIFY:
  853. /* A control parent notification message has been sent. */
  854. switch(((LPNMHDR)lParam)->code)
  855. {
  856. case TTN_NEEDTEXT:
  857. {
  858. /* This is the message from the tool tip control, requesting */
  859. /* the appropriate string to display for the current toolbar */
  860. /* item. */
  861. LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT)lParam;
  862. switch(lpToolTipText->hdr.idFrom)
  863. {
  864. case ID_DOOR_EXIT:
  865. lpToolTipText->lpszText = "Exit To BBS";
  866. break;
  867. case ID_DOOR_CHATMODE:
  868. lpToolTipText->lpszText = "Chat Mode";
  869. break;
  870. case ID_DOOR_USERKEYBOARDOFF:
  871. lpToolTipText->lpszText = "User Keyboard Off";
  872. break;
  873. case ID_DOOR_SYSOPNEXT:
  874. lpToolTipText->lpszText = "Sysop Next";
  875. break;
  876. case ID_DOOR_HANGUP:
  877. lpToolTipText->lpszText = "Hangup";
  878. break;
  879. case ID_DOOR_LOCKOUT:
  880. lpToolTipText->lpszText = "Lockout";
  881. break;
  882. }
  883. break;
  884. }
  885. }
  886. break;
  887. case WM_VSCROLL:
  888. /* A scrolling action has taken place. */
  889. /* If it is the time limit up-down control that has scrolled. */
  890. if((HWND)lParam == pWindowInfo->hwndTimeUpDown)
  891. {
  892. int nPos = HIWORD(wParam);
  893. /* Adjust the user's time limit. */
  894. od_control.user_timelimit = MAX(MIN(nPos, MAX_TIME), MIN_TIME);
  895. /* Update the time left displayed in the edit box. */
  896. ODFrameUpdateTimeLeft(pWindowInfo);
  897. }
  898. break;
  899. case WM_SIZE:
  900. /* The OpenDoors frame window has been resized, so its contents */
  901. /* must now be resized accordingly. */
  902. /* Pass the message on to the status bar window, so that it will */
  903. /* automatically adjust its own position and overall size. */
  904. SendMessage(GetDlgItem(hwnd, ID_STATUSBAR), WM_SIZE, wParam, lParam);
  905. /* Now, adjust the size of each part of the status bar. */
  906. ODFrameSizeStatusBar(GetDlgItem(hwnd, ID_STATUSBAR));
  907. /* Pass the message on to the toolbar, so that it will resize */
  908. /* iteself. */
  909. SendMessage(GetDlgItem(hwnd, ID_TOOLBAR), WM_SIZE, wParam, lParam);
  910. break;
  911. case WM_MENUSELECT:
  912. /* If the user has selected an item on the menu, then we should */
  913. /* update the status bar accordingly. */
  914. if(HIWORD(wParam) == 0xFFFF)
  915. {
  916. /* If menu is being exited, then turn off the status bar simple */
  917. /* mode. */
  918. HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
  919. SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)FALSE, 0L);
  920. }
  921. else
  922. {
  923. char szCommandString[160] = "";
  924. HWND hwndStatusBar = GetDlgItem(hwnd, ID_STATUSBAR);
  925. /* A new menu item is being selected. */
  926. /* If this item is on the system menu, then provide the strings */
  927. /* for any of those menu items. */
  928. if(HIWORD(wParam) & MF_SYSMENU)
  929. {
  930. switch(LOWORD(wParam))
  931. {
  932. case SC_SIZE:
  933. strcpy(szCommandString,
  934. "Resizes this window.");
  935. break;
  936. case SC_MOVE:
  937. strcpy(szCommandString,
  938. "Moves this window.");
  939. break;
  940. case SC_MINIMIZE:
  941. strcpy(szCommandString,
  942. "Collapses this window to an icon.");
  943. break;
  944. case SC_MAXIMIZE:
  945. strcpy(szCommandString,
  946. "Expands this window to fill the screen.");
  947. break;
  948. case SC_CLOSE:
  949. strcpy(szCommandString,
  950. "Closes this window, and returns the user to the BBS.");
  951. break;
  952. case SC_RESTORE:
  953. strcpy(szCommandString,
  954. "Restores this window to normal size.");
  955. break;
  956. case SC_TASKLIST:
  957. strcpy(szCommandString,
  958. "");
  959. break;
  960. }
  961. }
  962. else
  963. {
  964. /* If this item is on the window menu provided by OpenDoors, */
  965. /* then load the status bar string for this command ID. */
  966. LoadString(pWindowInfo->hInstance, LOWORD(wParam),
  967. szCommandString, sizeof(szCommandString));
  968. }
  969. /* Switch the status bar into simple (single-paned) mode. */
  970. SendMessage(hwndStatusBar, SB_SIMPLE, (WPARAM)TRUE, 0L);
  971. /* Set the text for the status bar. */
  972. SendMessage(hwndStatusBar, SB_SETTEXT, (WPARAM)255 | SBT_NOBORDERS,
  973. (LPARAM)szCommandString);
  974. }
  975. return(DefWindowProc(hwnd, uMsg, wParam, lParam));
  976. case WM_SHOW_MESSAGE:
  977. if(pWindowInfo->hwndMessageWindow == NULL)
  978. {
  979. pWindowInfo->pszCurrentMessage = (char *)lParam;
  980. pWindowInfo->nCurrentMessageFlags = (int)wParam;
  981. /* Create the message window. */
  982. DialogBoxParam(pWindowInfo->hInstance,
  983. MAKEINTRESOURCE(IDD_MESSAGE), hwnd, ODFrameMessageDlgProc,
  984. (LPARAM)pWindowInfo);
  985. }
  986. break;
  987. case WM_REMOVE_MESSAGE:
  988. if(pWindowInfo->hwndMessageWindow != NULL)
  989. {
  990. PostMessage(pWindowInfo->hwndMessageWindow, WM_COMMAND,
  991. MAKELONG(IDOK, 0), 0L);
  992. pWindowInfo->hwndMessageWindow = NULL;
  993. }
  994. break;
  995. default:
  996. /* Pass messages that we don't explicitly handle on to the */
  997. /* default window proc. */
  998. return(DefWindowProc(hwnd, uMsg, wParam, lParam));
  999. }
  1000. return(0);
  1001. }
  1002. /* ----------------------------------------------------------------------------
  1003. * ODFrameUpdateCmdUI()
  1004. *
  1005. * Updates the enabled and checked state of OpenDoors commands that may change.
  1006. *
  1007. * Parameters: None.
  1008. *
  1009. * Return: void.
  1010. */
  1011. void ODFrameUpdateCmdUI(void)
  1012. {
  1013. HWND hwndFrame = hwndCurrentFrame;
  1014. HMENU hMenu = GetMenu(hwndFrame);
  1015. HWND hwndToolbar = GetDlgItem(hwndFrame, ID_TOOLBAR);
  1016. tODFrameWindowInfo *pWindowInfo;
  1017. if(hwndFrame == NULL) return;
  1018. /* Obtain window information structure. */
  1019. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
  1020. if(pWindowInfo == NULL) return;
  1021. /* Check or uncheck the toolbar and status bar menu items. */
  1022. CheckMenuItem(hMenu, ID_VIEW_TOOL_BAR, MF_BYCOMMAND |
  1023. (pWindowInfo->bToolbarOn ? MF_CHECKED : MF_UNCHECKED));
  1024. CheckMenuItem(hMenu, ID_VIEW_STAT_BAR, MF_BYCOMMAND |
  1025. (pWindowInfo->bStatusBarOn ? MF_CHECKED : MF_UNCHECKED));
  1026. /* Check or uncheck the inactivity timer menu item. */
  1027. CheckMenuItem(hMenu, ID_USER_INACTIVITYTIMER, MF_BYCOMMAND |
  1028. (od_control.od_disable_inactivity ? MF_UNCHECKED : MF_CHECKED));
  1029. /* Check or uncheck the sysop next menu item and toolbar button. */
  1030. CheckMenuItem(hMenu, ID_DOOR_SYSOPNEXT, MF_BYCOMMAND |
  1031. (od_control.sysop_next ? MF_CHECKED : MF_UNCHECKED));
  1032. SendMessage(hwndToolbar, TB_CHECKBUTTON,
  1033. ID_DOOR_SYSOPNEXT, MAKELONG(od_control.sysop_next, 0));
  1034. /* Check or uncheck the keyboard off menu item and toolbar button. */
  1035. CheckMenuItem(hMenu, ID_DOOR_USERKEYBOARDOFF, MF_BYCOMMAND |
  1036. (od_control.od_user_keyboard_on ? MF_UNCHECKED : MF_CHECKED));
  1037. SendMessage(hwndToolbar, TB_CHECKBUTTON,
  1038. ID_DOOR_USERKEYBOARDOFF,
  1039. MAKELONG(!od_control.od_user_keyboard_on, 0));
  1040. /* Update the chat mode menu item and toolbar button. */
  1041. CheckMenuItem(hMenu, ID_DOOR_CHATMODE, MF_BYCOMMAND |
  1042. (od_control.od_chat_active ? MF_CHECKED : MF_UNCHECKED));
  1043. SendMessage(hwndToolbar, TB_CHECKBUTTON, ID_DOOR_CHATMODE,
  1044. MAKELONG(od_control.od_chat_active, 0));
  1045. }
  1046. /* ----------------------------------------------------------------------------
  1047. * ODFrameUpdateTimeDisplay()
  1048. *
  1049. * Updates the remaining time online that is displayed anywhere by the frame
  1050. * window. Uses ODFrameUpdateTimeLeft().
  1051. *
  1052. * Parameters: None.
  1053. *
  1054. * Return: void.
  1055. */
  1056. void ODFrameUpdateTimeDisplay(void)
  1057. {
  1058. tODFrameWindowInfo *pWindowInfo;
  1059. /* If there is no current frame window, then return without doing */
  1060. /* anything. */
  1061. if(hwndCurrentFrame == NULL) return;
  1062. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
  1063. GWL_USERDATA);
  1064. ASSERT(pWindowInfo != NULL);
  1065. ODFrameUpdateTimeLeft(pWindowInfo);
  1066. }
  1067. /* ----------------------------------------------------------------------------
  1068. * ODFrameUpdateWantChat()
  1069. *
  1070. * Updates the state of the flashing wants-chat indicator on the frame window.
  1071. *
  1072. * Parameters: None.
  1073. *
  1074. * Return: void.
  1075. */
  1076. void ODFrameUpdateWantChat(void)
  1077. {
  1078. tODFrameWindowInfo *pWindowInfo;
  1079. /* If there is no current frame window, then return without doing */
  1080. /* anything. */
  1081. if(hwndCurrentFrame == NULL) return;
  1082. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndCurrentFrame,
  1083. GWL_USERDATA);
  1084. ASSERT(pWindowInfo != NULL);
  1085. /* If the status bar is on, then update the text displayed in the */
  1086. /* status bar's main pane. */
  1087. if(pWindowInfo->bStatusBarOn)
  1088. {
  1089. ODFrameSetMainStatusText(pWindowInfo->hwndStatusBar);
  1090. }
  1091. /* Toggle the state of the wants-chat indicator, of needed. */
  1092. if(pWindowInfo->bWantsChatIndicator && !od_control.user_wantchat)
  1093. {
  1094. /* Restore original window text. */
  1095. SetWindowText(hwndCurrentFrame, od_control.od_prog_name);
  1096. /* Restore the window flash to its original state. */
  1097. FlashWindow(hwndCurrentFrame, FALSE);
  1098. /* Destroy the Windows timer. */
  1099. KillTimer(hwndCurrentFrame, 1);
  1100. /* Record that wants chat indicator is now off. */
  1101. pWindowInfo->bWantsChatIndicator = FALSE;
  1102. }
  1103. else if (!pWindowInfo->bWantsChatIndicator && od_control.user_wantchat)
  1104. {
  1105. /* Set window title to include the wants chat indicator. */
  1106. char szNewWindowTitle[sizeof(od_control.od_prog_name) + 20];
  1107. sprintf(szNewWindowTitle, "%s - User Wants Chat",
  1108. od_control.od_prog_name);
  1109. SetWindowText(hwndCurrentFrame, szNewWindowTitle);
  1110. /* Start the flashing the window. */
  1111. SetTimer(hwndCurrentFrame, 1,
  1112. GetCaretBlinkTime(), NULL);
  1113. /* Record that wants chat indicator is now on. */
  1114. pWindowInfo->bWantsChatIndicator = TRUE;
  1115. }
  1116. }
  1117. /* ----------------------------------------------------------------------------
  1118. * ODFrameDestroyWindow() *** PRIVATE FUNCTION ***
  1119. *
  1120. * Destroys the OpenDoors frame window and its children.
  1121. *
  1122. * Parameters: hwndFrame - Handle to the window previously created by
  1123. * ODFrameCreateWindow().
  1124. *
  1125. * Return: void.
  1126. */
  1127. static void ODFrameDestroyWindow(HWND hwndFrame)
  1128. {
  1129. tODFrameWindowInfo *pWindowInfo;
  1130. ASSERT(hwndFrame != NULL);
  1131. /* Obtain a pointer to the frame window information structure. */
  1132. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
  1133. /* At this point, deallocate the accelerator table. */
  1134. if(pWindowInfo->hacclFrameCommands != NULL)
  1135. {
  1136. DestroyAcceleratorTable(pWindowInfo->hacclFrameCommands);
  1137. }
  1138. /* Destroying the main frame window will automatically cause its */
  1139. /* children to be destroyed. */
  1140. DestroyWindow(hwndFrame);
  1141. }
  1142. /* ----------------------------------------------------------------------------
  1143. * ODFrameToolbarProc() *** PRIVATE FUNCTION ***
  1144. *
  1145. * The toolbar window proceedure.
  1146. *
  1147. * Parameters: hwnd - Handle to the toolbar window.
  1148. *
  1149. * uMsg - Specifies the message.
  1150. *
  1151. * wParam - Specifies additional message information. The content
  1152. * of this parameter depends on the value of the uMsg
  1153. * parameter.
  1154. *
  1155. * lParam - Specifies additional message information. The content
  1156. * of this parameter depends on the value of the uMsg
  1157. * parameter.
  1158. *
  1159. * Return: The return value is the result of the message processing and
  1160. * depends on the message.
  1161. */
  1162. LRESULT CALLBACK ODFrameToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  1163. LPARAM lParam)
  1164. {
  1165. switch(uMsg)
  1166. {
  1167. /* Forward needed message to the main frame window proceedure. */
  1168. case WM_VSCROLL:
  1169. case WM_COMMAND:
  1170. SendMessage(GetParent(hwnd), uMsg, wParam, lParam);
  1171. break;
  1172. }
  1173. /* Pass all messages on to the default toolbar window proceedure. */
  1174. return(CallWindowProc(pfnDefToolbarProc, hwnd, uMsg, wParam, lParam));
  1175. }
  1176. /* ----------------------------------------------------------------------------
  1177. * ODFrameUpdateTimeLeft() *** PRIVATE FUNCTION ***
  1178. *
  1179. * Updates the displayed time remaining from od_control.user_timelimit.
  1180. *
  1181. * Parameters: pWindowInfo - Pointer to frame window information structure.
  1182. *
  1183. * Return: void.
  1184. */
  1185. static void ODFrameUpdateTimeLeft(tODFrameWindowInfo *pWindowInfo)
  1186. {
  1187. char szTimeLeft[12];
  1188. RECT rcWindow;
  1189. if(pWindowInfo->hwndTimeEdit == NULL)
  1190. {
  1191. /* If the time limit edit control does not exist (i.e., if the */
  1192. /* toolbar is not currently on), then there is nothing for us to do. */
  1193. return;
  1194. }
  1195. /* Generate the string to be displayed in the edit control. */
  1196. sprintf(szTimeLeft, "%d min.", od_control.user_timelimit);
  1197. /* Set the edit control's text to the new string. */
  1198. SetWindowText(pWindowInfo->hwndTimeEdit, szTimeLeft);
  1199. /* Force edit control to be redrawn. (Except for rightmost pixel */
  1200. /* column.) */
  1201. GetWindowRect(pWindowInfo->hwndTimeEdit, &rcWindow);
  1202. rcWindow.right--;
  1203. InvalidateRect(pWindowInfo->hwndTimeEdit, &rcWindow, TRUE);
  1204. /* Set the position of the up-down control to match. */
  1205. SendMessage(pWindowInfo->hwndTimeUpDown, UDM_SETPOS, 0,
  1206. (LPARAM)MAKELONG(od_control.user_timelimit, 0));
  1207. }
  1208. /* ----------------------------------------------------------------------------
  1209. * ODFrameTimeEditProc() *** PRIVATE FUNCTION ***
  1210. *
  1211. * The time edit window proceedure. Relays mouse messages from the edit box
  1212. * to the tooltip control, and then passes all messages on to the standard
  1213. * edit box window proceedure.
  1214. *
  1215. * Parameters: hwnd - Handle to the time edit window.
  1216. *
  1217. * uMsg - Specifies the message.
  1218. *
  1219. * wParam - Specifies additional message information. The content
  1220. * of this parameter depends on the value of the uMsg
  1221. * parameter.
  1222. *
  1223. * lParam - Specifies additional message information. The content
  1224. * of this parameter depends on the value of the uMsg
  1225. * parameter.
  1226. *
  1227. * Return: The return value is the result of the message processing and
  1228. * depends on the message.
  1229. */
  1230. LRESULT CALLBACK ODFrameTimeEditProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  1231. LPARAM lParam)
  1232. {
  1233. switch(uMsg)
  1234. {
  1235. case WM_MOUSEMOVE:
  1236. case WM_LBUTTONDOWN:
  1237. case WM_LBUTTONUP:
  1238. {
  1239. MSG msg;
  1240. HWND hwndToolTip;
  1241. /* Setup message structure. */
  1242. msg.lParam = lParam;
  1243. msg.wParam = wParam;
  1244. msg.message = uMsg;
  1245. msg.hwnd = hwnd;
  1246. /* Obtain handle to the tooltip window. */
  1247. hwndToolTip = (HWND)SendMessage(GetParent(hwnd), TB_GETTOOLTIPS,
  1248. 0, 0);
  1249. /* Relay the message to the tooltip window. */
  1250. SendMessage(hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
  1251. break;
  1252. }
  1253. }
  1254. /* Pass all messages on to the default edit box window proceedure. */
  1255. return(CallWindowProc(pfnDefEditProc, hwnd, uMsg, wParam, lParam));
  1256. }
  1257. /* ----------------------------------------------------------------------------
  1258. * ODFrameAboutDlgProc()
  1259. *
  1260. * DialogProc for the OpenDoors default Help About dialog box.
  1261. *
  1262. * Parameters: hwndDlg - Window handle to the dialog box.
  1263. *
  1264. * uMsg - Message ID.
  1265. *
  1266. * wParam - First message parameter.
  1267. *
  1268. * lParam - Second message parameter.
  1269. *
  1270. * Return: TRUE if message is processed, FALSE otherwise.
  1271. */
  1272. BOOL CALLBACK ODFrameAboutDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
  1273. LPARAM lParam)
  1274. {
  1275. switch(uMsg)
  1276. {
  1277. case WM_INITDIALOG:
  1278. /* At dialog box creation time, update the text in the about */
  1279. /* box with any information provided by the OpenDoors programmer. */
  1280. /* If a program name has been provided, then display it. */
  1281. if(strcmp(od_control.od_prog_name, OD_VER_SHORTNAME) != 0)
  1282. {
  1283. SetWindowText(GetDlgItem(hwndDlg, IDC_DOORNAME),
  1284. od_control.od_prog_name);
  1285. }
  1286. /* If copyright information has been provided, then display it. */
  1287. if(strlen(od_control.od_prog_copyright) > 0)
  1288. {
  1289. SetWindowText(GetDlgItem(hwndDlg, IDC_COPYRIGHT),
  1290. od_control.od_prog_copyright);
  1291. }
  1292. /* If program version information has been provided, then display */
  1293. /* it. */
  1294. if(strlen(od_control.od_prog_version) > 0)
  1295. {
  1296. SetWindowText(GetDlgItem(hwndDlg, IDC_VERSION),
  1297. od_control.od_prog_version);
  1298. }
  1299. /* Center the about dialog box in the area occupied by the */
  1300. /* main frame window. */
  1301. ODFrameCenterWindowInParent(hwndDlg);
  1302. return(TRUE);
  1303. case WM_COMMAND:
  1304. /* If a command has been chosen. */
  1305. switch(LOWORD(wParam))
  1306. {
  1307. case IDCANCEL:
  1308. case IDOK:
  1309. /* If the OK button has been pressed, then close the dialog. */
  1310. EndDialog(hwndDlg, IDOK);
  1311. break;
  1312. }
  1313. return(TRUE);
  1314. default:
  1315. /* Otherwise, indicate that this message has not been processed. */
  1316. return(FALSE);
  1317. }
  1318. }
  1319. /* ----------------------------------------------------------------------------
  1320. * ODFrameCenterWindowInParent() *** PRIVATE FUNCTION ***
  1321. *
  1322. * Repositions the specified window so that it is centered in its parent.
  1323. *
  1324. * Parameters: hwndChild - The window to reposition.
  1325. *
  1326. * Return: void.
  1327. */
  1328. void ODFrameCenterWindowInParent(HWND hwndChild)
  1329. {
  1330. HWND hwndParent;
  1331. RECT rcParent;
  1332. RECT rcChild;
  1333. INT nChildWidth;
  1334. INT nChildHeight;
  1335. INT nParentWidth;
  1336. INT nParentHeight;
  1337. ASSERT(hwndChild != NULL);
  1338. /* Obtain a handle to the parent window. */
  1339. hwndParent = GetParent(hwndChild);
  1340. ASSERT(hwndParent != NULL);
  1341. /* Obtain the bounding boxes of both windows. */
  1342. GetWindowRect(hwndChild, &rcChild);
  1343. GetWindowRect(hwndParent, &rcParent);
  1344. /* Determine the height and width of both windows. */
  1345. nChildWidth = rcChild.right - rcChild.left;
  1346. nChildHeight = rcChild.bottom - rcChild.top;
  1347. nParentWidth = rcParent.right - rcParent.left;
  1348. nParentHeight = rcParent.bottom - rcParent.top;
  1349. /* Move the child to the center of the parent. */
  1350. SetWindowPos(hwndChild, NULL,
  1351. rcParent.left + (nParentWidth - nChildWidth) / 2,
  1352. rcParent.top + (nParentHeight - nChildHeight) / 2,
  1353. 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  1354. }
  1355. /* ----------------------------------------------------------------------------
  1356. * ODFrameMessageLoop() *** PRIVATE FUNCTION ***
  1357. *
  1358. * Message loop for OpenDoors local UI thread (frame window handling).
  1359. *
  1360. * Parameters: hInstance - Handle to current instance.
  1361. *
  1362. * hwndFrame - Handle to the frame window.
  1363. *
  1364. * Return: void.
  1365. */
  1366. static void ODFrameMessageLoop(HANDLE hInstance, HWND hwndFrame)
  1367. {
  1368. MSG msg;
  1369. ASSERT(hInstance != NULL);
  1370. ASSERT(hwndFrame != NULL);
  1371. /* Loop, fetching, translating and dispatching messages for any windows */
  1372. /* created by this thread. (GetMessage() blocks when no messages are */
  1373. /* available.) */
  1374. while(GetMessage(&msg, NULL, 0, 0))
  1375. {
  1376. if(!ODFrameTranslateAccelerator(hwndFrame, &msg))
  1377. {
  1378. TranslateMessage(&msg);
  1379. DispatchMessage(&msg);
  1380. }
  1381. }
  1382. }
  1383. /* ----------------------------------------------------------------------------
  1384. * ODFrameTranslateAccelerator()
  1385. *
  1386. * Translates WM_KEYDOWN or WM_SYSKEYDOWN messages to frame window commands,
  1387. * if needed, based on the frame window's accelerator table.
  1388. *
  1389. * Parameters: hwndFrame - Handle to the OpenDoors main frame window.
  1390. *
  1391. * pMsg - Pointer to the message that may require
  1392. * translation.
  1393. *
  1394. * Return: TRUE if message was translated, FALSE if not.
  1395. */
  1396. BOOL ODFrameTranslateAccelerator(HWND hwndFrame, LPMSG pMsg)
  1397. {
  1398. tODFrameWindowInfo *pWindowInfo;
  1399. ASSERT(hwndFrame != NULL);
  1400. ASSERT(pMsg != NULL);
  1401. /* Obtain a pointer to the frame window information structure. */
  1402. pWindowInfo = (tODFrameWindowInfo *)GetWindowLong(hwndFrame, GWL_USERDATA);
  1403. ASSERT(pWindowInfo != NULL);
  1404. /* Perform accelerator translation, based on the frame window's */
  1405. /* accelerator table, sending any resulting WM_COMMAND messages */
  1406. /* to the frame window. */
  1407. return(TranslateAccelerator(hwndFrame, pWindowInfo->hacclFrameCommands,
  1408. pMsg) != 0);
  1409. }
  1410. /* ----------------------------------------------------------------------------
  1411. * ODFrameThreadProc() *** PRIVATE FUNCTION ***
  1412. *
  1413. * Function that execute the OpenDoors frame window thread.
  1414. *
  1415. * Parameters: pParam - The thread parameter, which must be the handle to the
  1416. * current application instance.
  1417. *
  1418. * Return: TRUE on success, or FALSE on failure.
  1419. */
  1420. DWORD OD_THREAD_FUNC ODFrameThreadProc(void *pParam)
  1421. {
  1422. HWND hwndFrame;
  1423. HANDLE hInstance = (HANDLE)pParam;
  1424. /* Create the frame window. */
  1425. hwndFrame = ODFrameCreateWindow(hInstance);
  1426. if(hwndFrame == NULL)
  1427. {
  1428. return(FALSE);
  1429. }
  1430. /* Store a pointer to the frame window. */
  1431. hwndCurrentFrame = hwndFrame;
  1432. /* Loop, processing messages for the frame window. */
  1433. ODFrameMessageLoop(hInstance, hwndFrame);
  1434. /* Destroy the frame window. */
  1435. ODFrameDestroyWindow(hwndFrame);
  1436. return(TRUE);
  1437. }
  1438. /* ----------------------------------------------------------------------------
  1439. * ODFrameStart()
  1440. *
  1441. * Function that starts up the frame window.
  1442. *
  1443. * Parameters: hInstance - Handle to the current application instance.
  1444. *
  1445. * phFrameThread - Pointer to the frame thread handle.
  1446. *
  1447. * Return: kODRCSuccess on success, or an error code on failure.
  1448. */
  1449. tODResult ODFrameStart(HANDLE hInstance, tODThreadHandle *phFrameThread)
  1450. {
  1451. return(ODThreadCreate(phFrameThread, ODFrameThreadProc,
  1452. (void *)hInstance));
  1453. }
  1454. /* ----------------------------------------------------------------------------
  1455. * ODFrameMessageDlgProc()
  1456. *
  1457. * Dialog proceedure for the OpenDoors message window.
  1458. *
  1459. * Parameters: hwndDlg - Window handle to the dialog box.
  1460. *
  1461. * uMsg - Message ID.
  1462. *
  1463. * wParam - First message parameter.
  1464. *
  1465. * lParam - Second message parameter.
  1466. *
  1467. * Return: TRUE if message is processed, FALSE otherwise.
  1468. */
  1469. BOOL CALLBACK ODFrameMessageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
  1470. LPARAM lParam)
  1471. {
  1472. switch(uMsg)
  1473. {
  1474. case WM_INITDIALOG:
  1475. {
  1476. tODFrameWindowInfo *pWindowInfo;
  1477. pWindowInfo = (tODFrameWindowInfo *)lParam;
  1478. ASSERT(pWindowInfo != NULL);
  1479. pWindowInfo->hwndMessageWindow = hwndDlg;
  1480. /* Set the message window title. */
  1481. SetWindowText(hwndDlg, od_control.od_prog_name);
  1482. /* Change the text displayed in the message window. */
  1483. SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE_TEXT1),
  1484. (char *)pWindowInfo->pszCurrentMessage);
  1485. /* Center window in parent window. */
  1486. ODFrameCenterWindowInParent(hwndDlg);
  1487. return(FALSE);
  1488. }
  1489. case WM_COMMAND:
  1490. /* If a command has been chosen. */
  1491. switch(LOWORD(wParam))
  1492. {
  1493. case IDOK:
  1494. /* If the OK button has been pressed, then close the dialog. */
  1495. EndDialog(hwndDlg, IDOK);
  1496. break;
  1497. }
  1498. return(TRUE);
  1499. default:
  1500. /* Indicate that this message has not been processed. */
  1501. return(FALSE);
  1502. }
  1503. return(TRUE);
  1504. }
  1505. #endif /* ODPLAT_WIN32 */