Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

753 lines
19 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. status.cpp
  5. --*/
  6. #include "precomp.hxx"
  7. #pragma hdrstop
  8. // Adjust the size as necessary.
  9. // Obviously, if an assert that checks for mem overwrites goes off,
  10. // don't remove the assert, increase the char array size.
  11. // |
  12. // \|/
  13. #define MAX_TEMP_TXT 100
  14. //Status Bar : Structure definition
  15. typedef struct _STATUS
  16. {
  17. HWND hwndStatusBar;
  18. // The actual text to be displayed for each item
  19. PTSTR rgszItemText[nMAX_IDX_STATUSBAR];
  20. // The line column text is in the following format: Ln 000, Col 000
  21. // Where "Ln" & "Col" are loaded from the resource and since they could be
  22. // language dependent. This is why we have to clutter the structure with
  23. // these 2 additional references.
  24. PTSTR lpszLinePrefix;
  25. PTSTR lpszColumnPrefix;
  26. // Prefix help the user figure out which is the process & thread displays
  27. // Proc 000:000
  28. // Thrd 000:000
  29. PTSTR lpszProcessPrefix;
  30. PTSTR lpszThreadPrefix;
  31. // Indicates whether the text should be grayed out when displayed.
  32. // TRUE - grayed out
  33. // FALSE - normal color
  34. BOOL rgbGrayItemText[nMAX_IDX_STATUSBAR];
  35. // Indicates which ones are OWNER_DRAW. This is done
  36. // so we can gray things out.
  37. // TRUE - Owner draw
  38. // FALSE - Normal, status bar takes care of the drawing.
  39. int rgbOwnerDrawItem[nMAX_IDX_STATUSBAR];
  40. // TRUE - we are in src code mode
  41. // FALSE - we are in assembly mode
  42. BOOL bSrcMode;
  43. BOOL bOverType; // Overtype status
  44. BOOL bCapsLock; // CapsLock status
  45. BOOL bNumLock; // NumLock status
  46. } STATUS, * LPSTATUS;
  47. static STATUS status;
  48. ///////////////////////////////////////////////////////////
  49. // protos
  50. void RecalcItemWidths_StatusBar(void);
  51. void Internal_SetItemText_StatusBar(nIDX_STATUSBAR_ITEMS nId, PTSTR lpszNewText);
  52. ///////////////////////////////////////////////////////////
  53. // Init/term functions
  54. //
  55. BOOL
  56. CreateStatusBar(HWND hwndParent)
  57. /*++
  58. Routine Description:
  59. Creates and initializes the status bar.
  60. Arguments:
  61. hwndParent - Hwnd to the owner of the status bar
  62. --*/
  63. {
  64. TCHAR sz[MAX_MSG_TXT];
  65. status.hwndStatusBar = CreateStatusWindow(
  66. WS_CHILD | WS_BORDER
  67. | WS_VISIBLE | CCS_BOTTOM, // style
  68. _T(""), // initial text
  69. hwndParent, // parent
  70. IDC_STATUS_BAR); // id
  71. if (status.hwndStatusBar == NULL)
  72. {
  73. return FALSE;
  74. }
  75. //
  76. // We recalc the sizes even though we know they are 0, because,
  77. // the status bar needs to know how many parts there will be.
  78. //
  79. RecalcItemWidths_StatusBar();
  80. //
  81. // These are the owner draw items.
  82. //
  83. status.rgbOwnerDrawItem[nSRCASM_IDX_STATUSBAR] = TRUE;
  84. status.rgbOwnerDrawItem[nOVRTYPE_IDX_STATUSBAR] = TRUE;
  85. status.rgbOwnerDrawItem[nCAPSLCK_IDX_STATUSBAR] = TRUE;
  86. status.rgbOwnerDrawItem[nNUMLCK_IDX_STATUSBAR] = TRUE;
  87. //
  88. // Load the static stuff.
  89. //
  90. Dbg(LoadString(g_hInst, STS_MESSAGE_ASM, sz, _tsizeof(sz)));
  91. Internal_SetItemText_StatusBar(nSRCASM_IDX_STATUSBAR, sz);
  92. Dbg(LoadString(g_hInst, STS_MESSAGE_OVERTYPE, sz, _tsizeof(sz)));
  93. Internal_SetItemText_StatusBar(nOVRTYPE_IDX_STATUSBAR, sz);
  94. Dbg(LoadString(g_hInst, STS_MESSAGE_CAPSLOCK, sz, _tsizeof(sz)));
  95. Internal_SetItemText_StatusBar(nCAPSLCK_IDX_STATUSBAR, sz);
  96. Dbg(LoadString(g_hInst, STS_MESSAGE_NUMLOCK, sz, _tsizeof(sz)));
  97. Internal_SetItemText_StatusBar(nNUMLCK_IDX_STATUSBAR, sz);
  98. //
  99. // Preload prefixes
  100. //
  101. Dbg(LoadString(g_hInst, STS_MESSAGE_CURPROCID, sz, _tsizeof(sz)));
  102. status.lpszProcessPrefix = _tcsdup(sz);
  103. Dbg(status.lpszProcessPrefix);
  104. Dbg(LoadString(g_hInst, STS_MESSAGE_CURTHRDID, sz, _tsizeof(sz)));
  105. status.lpszThreadPrefix = _tcsdup(sz);
  106. Dbg(status.lpszThreadPrefix);
  107. Dbg(LoadString(g_hInst, STS_MESSAGE_LINE, sz, _tsizeof(sz)));
  108. status.lpszLinePrefix = _tcsdup(sz);
  109. Dbg(status.lpszLinePrefix);
  110. Dbg(LoadString(g_hInst, STS_MESSAGE_COLUMN, sz, _tsizeof(sz)));
  111. status.lpszColumnPrefix = _tcsdup(sz);
  112. Dbg(status.lpszColumnPrefix);
  113. SetLineColumn_StatusBar(0, 0);
  114. SetPidTid_StatusBar(0, 0, 0, 0);
  115. SetCapsLock_StatusBar(GetKeyState(VK_CAPITAL) & 0x0001);
  116. SetNumLock_StatusBar(GetKeyState(VK_NUMLOCK) & 0x0001);
  117. SetOverType_StatusBar(FALSE);
  118. return TRUE;
  119. }
  120. void
  121. TerminateStatusBar()
  122. /*++
  123. Routine Description:
  124. Just frees allocated resources.
  125. --*/
  126. {
  127. int i;
  128. for (i = 0; i < nMAX_IDX_STATUSBAR -1; i++)
  129. {
  130. if (status.rgszItemText[i])
  131. {
  132. free(status.rgszItemText[i]);
  133. status.rgszItemText[i] = NULL;
  134. }
  135. }
  136. if (status.lpszLinePrefix)
  137. {
  138. free(status.lpszLinePrefix);
  139. status.lpszLinePrefix = NULL;
  140. }
  141. if (status.lpszColumnPrefix)
  142. {
  143. free(status.lpszColumnPrefix);
  144. status.lpszColumnPrefix = NULL;
  145. }
  146. if (status.lpszProcessPrefix)
  147. {
  148. free(status.lpszProcessPrefix);
  149. status.lpszProcessPrefix = NULL;
  150. }
  151. if (status.lpszThreadPrefix)
  152. {
  153. free(status.lpszThreadPrefix);
  154. status.lpszThreadPrefix = NULL;
  155. }
  156. }
  157. ///////////////////////////////////////////////////////////
  158. // Operations that affect the entire status bar.
  159. //
  160. void
  161. Show_StatusBar(
  162. BOOL bShow
  163. )
  164. /*++
  165. Routine Description:
  166. Show/Hide the status bar. Automatically resizes/updates the MDI client.
  167. Arguments:
  168. bShow - TRUE - Show status bar
  169. FALSE - Hide status bar
  170. --*/
  171. {
  172. RECT rect;
  173. // Show/Hide the toolbar
  174. ShowWindow(status.hwndStatusBar, bShow ? SW_SHOW : SW_HIDE);
  175. //Ask the frame to resize, so that everything will be correctly positioned.
  176. GetWindowRect(g_hwndFrame, &rect);
  177. SendMessage(g_hwndFrame, WM_SIZE, SIZE_RESTORED,
  178. MAKELPARAM(rect.right - rect.left, rect.bottom - rect.top));
  179. // Ask the MDIClient to redraw itself and its children.
  180. // This is done in order to fix a redraw problem where some of the
  181. // MDIChild window are not correctly redrawn.
  182. Dbg(RedrawWindow(g_hwndMDIClient, NULL, NULL,
  183. RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME));
  184. } // UpdateToolbar()
  185. void
  186. WM_SIZE_StatusBar(
  187. WPARAM wParam,
  188. LPARAM lParam
  189. )
  190. /*++
  191. Routine Description:
  192. Causes the status bar to be resized. This function is meant to be
  193. called from the parent window, whenever a parent window receives a
  194. WM_SIZE message, ie:
  195. // parent window proc
  196. switch (uMsg) {
  197. case WM_SIZE:
  198. WM_SIZE_StatusBar(wParam, lParam);
  199. return TRUE;
  200. ...
  201. ...
  202. ...
  203. }
  204. Arguments:
  205. wParam & lParam - See docs for a desciption of the WM_SIZE message.
  206. --*/
  207. {
  208. // make the status bar resize.
  209. SendMessage(status.hwndStatusBar, WM_SIZE, wParam, lParam);
  210. // Since it was resized, the widths the text items need to be recalculated.
  211. // The is because of the way that status bar positions the elements on the
  212. // screen. See the docs for SB_SETPARTS, for more detail. The SB_SETPARTS
  213. // docs will enlighten you.
  214. RecalcItemWidths_StatusBar();
  215. }
  216. HWND
  217. GetHwnd_StatusBar()
  218. // I'm not documenting this function, everyone can figure this one out.
  219. {
  220. return status.hwndStatusBar;
  221. }
  222. ///////////////////////////////////////////////////////////
  223. // Main text display functions
  224. //
  225. void
  226. RecalcItemWidths_StatusBar(void)
  227. /*++
  228. Routine description:
  229. The function will recalculate the width of the text items.
  230. The calculations don't have to be exact. Status bar is very
  231. forgiving and pretty much needs a rough estimate.
  232. --*/
  233. {
  234. int rgnItemWidths[nMAX_IDX_STATUSBAR];
  235. int i, nWidth;
  236. HDC hdc;
  237. hdc = GetDC(status.hwndStatusBar);
  238. Dbg(hdc);
  239. // Get the width of the status bar's client area.
  240. {
  241. RECT rcClient;
  242. GetClientRect(status.hwndStatusBar, &rcClient);
  243. nWidth = rcClient.right;
  244. }
  245. // Calculate the right edge coordinate for each part, and
  246. // copy the coordinates to the array.
  247. for (i = nMAX_IDX_STATUSBAR -1; i >= 0; i--) {
  248. rgnItemWidths[i] = nWidth;
  249. if (NULL == status.rgszItemText[i]) {
  250. // We don't have any text, but we need a position anyways.
  251. nWidth -= 10; // Just any old number
  252. } else {
  253. PTSTR lpsz = status.rgszItemText[i];
  254. SIZE size;
  255. // Skip over tabs.
  256. // 1 tab is centered, 2 is right aligned.
  257. // See status bar docs for more info.
  258. if (_T('\t') == *lpsz) {
  259. lpsz++;
  260. if (_T('\t') == *lpsz) {
  261. lpsz++;
  262. }
  263. }
  264. Dbg(GetTextExtentPoint32(hdc, lpsz, _tcslen(lpsz), &size));
  265. nWidth -= size.cx;
  266. }
  267. }
  268. Dbg(ReleaseDC(status.hwndStatusBar, hdc));
  269. // Tell the status window to create the window parts.
  270. Dbg(SendMessage(status.hwndStatusBar, SB_SETPARTS,
  271. (WPARAM) nMAX_IDX_STATUSBAR, (LPARAM) rgnItemWidths));
  272. // The status bar invalidates the parts that changed. So it is
  273. // automatically updated.
  274. }
  275. void
  276. Internal_SetItemText_StatusBar(
  277. nIDX_STATUSBAR_ITEMS nId,
  278. PTSTR lpszNewText
  279. )
  280. /*++
  281. Routine Description:
  282. Set the text for a specified item.
  283. --*/
  284. {
  285. // Leave these sanity checks in here.
  286. // If they go off, someone did something wrong
  287. // or changed some important code
  288. Dbg((0 <= nId));
  289. Dbg((nId < nMAX_IDX_STATUSBAR));
  290. Dbg((lpszNewText));
  291. // Free any previous text
  292. if (status.rgszItemText[nId]) {
  293. free(status.rgszItemText[nId]);
  294. }
  295. // duplicate the text
  296. status.rgszItemText[nId] = _tcsdup(lpszNewText);
  297. // Make sure it was allocated
  298. Assert(status.rgszItemText[nId]);
  299. // Do we have any text to set?
  300. if (status.rgszItemText[nId]) {
  301. int nFormat = nId;
  302. // Make it owner draw???
  303. if (status.rgbOwnerDrawItem[nId]) {
  304. nFormat |= SBT_OWNERDRAW;
  305. }
  306. // Set the text
  307. Dbg(SendMessage(status.hwndStatusBar, SB_SETTEXT,
  308. (WPARAM) nFormat, (LPARAM) status.rgszItemText[nId]));
  309. }
  310. }
  311. void
  312. InvalidateItem_Statusbar(nIDX_STATUSBAR_ITEMS nIdx)
  313. /*++
  314. Routine description:
  315. Invalidates the item's rect on the status bar, so that an update
  316. to that region will take place.
  317. Arguments:
  318. nIdx - The status bar item that is to be updated.
  319. --*/
  320. {
  321. RECT rc;
  322. Dbg((0 <= nIdx));
  323. Dbg((nIdx < nMAX_IDX_STATUSBAR));
  324. SendMessage(status.hwndStatusBar, SB_GETRECT,
  325. (WPARAM) nIdx, (LPARAM) &rc);
  326. InvalidateRect(status.hwndStatusBar, &rc, FALSE);
  327. }
  328. void
  329. OwnerDrawItem_StatusBar(
  330. LPDRAWITEMSTRUCT lpDrawItem
  331. )
  332. /*++
  333. Routine Description:
  334. Called from the parent window for owner draw text items.
  335. Draws an actual status bar item onto the status bar.
  336. Depending the the flags set, it will draw the item grayed out.
  337. Arguments:
  338. See docs for WM_DRAWITEM, and Status bar -> owner draw items.
  339. --*/
  340. {
  341. PTSTR lpszItemText = (PTSTR) lpDrawItem->itemData;
  342. COLORREF crefOldTextColor = CLR_INVALID;
  343. COLORREF crefOldBkColor = CLR_INVALID;
  344. if (NULL == lpszItemText) {
  345. // nothing to do
  346. return;
  347. }
  348. // Set background color and save the old color.
  349. crefOldBkColor = SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_3DFACE));
  350. Assert(CLR_INVALID != crefOldBkColor);
  351. // should the item be grayed out?
  352. if (status.rgbGrayItemText[lpDrawItem->itemID]) {
  353. crefOldTextColor = SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_GRAYTEXT));
  354. Assert(CLR_INVALID != crefOldTextColor);
  355. }
  356. // draw the color coded text to the screen
  357. {
  358. UINT uFormat = DT_NOPREFIX | DT_VCENTER | DT_SINGLELINE;
  359. // "\t" is used to center
  360. // '\t\t" is used to right align.
  361. // No, I did not make this up, this is the way the status bar works.
  362. if (_T('\t') == *lpszItemText) {
  363. lpszItemText++;
  364. if (_T('\t') == *lpszItemText) {
  365. // 2 tabs found
  366. lpszItemText++;
  367. uFormat |= DT_RIGHT;
  368. } else {
  369. // 1 tab found
  370. uFormat |= DT_CENTER;
  371. }
  372. }
  373. DrawText(lpDrawItem->hDC, lpszItemText, _tcslen(lpszItemText),
  374. &lpDrawItem->rcItem, uFormat);
  375. }
  376. // Reset the the hDC back to its old state.
  377. if (CLR_INVALID != crefOldTextColor) {
  378. Dbg((CLR_INVALID != SetTextColor(lpDrawItem->hDC, crefOldTextColor)));
  379. }
  380. if (CLR_INVALID != crefOldBkColor) {
  381. Dbg((CLR_INVALID != SetBkColor(lpDrawItem->hDC, crefOldBkColor)));
  382. }
  383. }
  384. void
  385. SetItemText_StatusBar(
  386. nIDX_STATUSBAR_ITEMS nId,
  387. PTSTR lpszNewText
  388. )
  389. /*++
  390. Routine Description:
  391. Arguments:
  392. nId -
  393. lpszNewText
  394. --*/
  395. {
  396. Internal_SetItemText_StatusBar(nId, lpszNewText);
  397. // If nId is 0, the we don't have to recalc the widths, because this
  398. // is the only one that doesn't affect the rest.
  399. if (nId > 0) {
  400. RecalcItemWidths_StatusBar();
  401. }
  402. }
  403. ///////////////////////////////////////////////////////////
  404. // Set/get specialized items on the status bar.
  405. //
  406. // All of the Get????_StatusBar retrieve the current value.
  407. //
  408. // All of the Set????_StatusBar set the new value and return the
  409. // previous value.
  410. // TRUE - Item is enabled.
  411. // FALSE - Item is disabled.
  412. //
  413. // Src/Asm mode
  414. BOOL
  415. GetSrcMode_StatusBar()
  416. {
  417. return status.bSrcMode;
  418. }
  419. BOOL
  420. SetSrcMode_StatusBar(
  421. BOOL bNewValue
  422. )
  423. {
  424. BOOL b = status.bSrcMode;
  425. status.bSrcMode = bNewValue;
  426. status.rgbGrayItemText[nSRCASM_IDX_STATUSBAR] = bNewValue;
  427. InvalidateItem_Statusbar(nSRCASM_IDX_STATUSBAR);
  428. // Reflect the change to the menu
  429. InitializeMenu(GetMenu(g_hwndFrame));
  430. /*
  431. // Old code that was move in here.
  432. if ( (FALSE == bNewValue) && (NULL == GetDisasmHwnd()) ) {
  433. OpenDebugWindow(DISASM_WINDOW, TRUE); // User activated
  434. }
  435. */
  436. return b;
  437. }
  438. //
  439. // Insert/Overtype mode
  440. BOOL
  441. GetOverType_StatusBar()
  442. {
  443. return status.bOverType;
  444. }
  445. BOOL
  446. SetOverType_StatusBar(BOOL bNewValue)
  447. {
  448. BOOL b = status.bOverType;
  449. status.bOverType = bNewValue;
  450. status.rgbGrayItemText[nOVRTYPE_IDX_STATUSBAR] = !bNewValue;
  451. InvalidateItem_Statusbar(nOVRTYPE_IDX_STATUSBAR);
  452. return b;
  453. }
  454. //
  455. // Num lock mode
  456. BOOL
  457. GetNumLock_StatusBar()
  458. {
  459. return status.bNumLock;
  460. }
  461. BOOL
  462. SetNumLock_StatusBar(BOOL bNewValue)
  463. {
  464. BOOL b = status.bNumLock;
  465. status.bNumLock = bNewValue;
  466. status.rgbGrayItemText[nNUMLCK_IDX_STATUSBAR] = !bNewValue;
  467. InvalidateItem_Statusbar(nNUMLCK_IDX_STATUSBAR);
  468. return b;
  469. }
  470. //
  471. // Caps mode
  472. BOOL
  473. GetCapsLock_StatusBar()
  474. {
  475. return status.bCapsLock;
  476. }
  477. BOOL
  478. SetCapsLock_StatusBar(BOOL bNewValue)
  479. {
  480. BOOL b = status.bCapsLock;
  481. status.bCapsLock = bNewValue;
  482. status.rgbGrayItemText[nCAPSLCK_IDX_STATUSBAR] = !bNewValue;
  483. InvalidateItem_Statusbar(nCAPSLCK_IDX_STATUSBAR);
  484. return b;
  485. }
  486. ///////////////////////////////////////////////////////////
  487. // Specialized text display functions
  488. void
  489. SetMessageText_StatusBar(UINT StringId)
  490. {
  491. TCHAR Str[MAX_TEMP_TXT];
  492. // load format string from resource file
  493. if (LoadString(g_hInst, StringId, Str, sizeof(Str)) == 0)
  494. {
  495. Str[0] = 0;
  496. }
  497. SetItemText_StatusBar(nMESSAGE_IDX_STATUSBAR, Str);
  498. }
  499. void
  500. SetLineColumn_StatusBar(
  501. int nNewLine,
  502. int nNewColumn
  503. )
  504. /*++
  505. Routine Description:
  506. Used to display the line and column values in text edit controls.
  507. Loads the prefixs "Ln" & "Col" from the string resource section.
  508. Arguments:
  509. nNewLine - Line number in edit controls.
  510. nNewColumn - Column number in edit controls.
  511. --*/
  512. {
  513. TCHAR sz[MAX_TEMP_TXT];
  514. _stprintf(sz, _T("%s %d, %s %d"), status.lpszLinePrefix, nNewLine,
  515. status.lpszColumnPrefix, nNewColumn);
  516. Dbg((_tcslen(sz) < _tsizeof(sz)));
  517. SetItemText_StatusBar(nSRCLIN_IDX_STATUSBAR, sz);
  518. }
  519. void
  520. SetPidTid_StatusBar(
  521. ULONG ProcessId,
  522. ULONG ProcessSysId,
  523. ULONG ThreadId,
  524. ULONG ThreadSysId
  525. )
  526. /*++
  527. Routine Description:
  528. Display the Process ID and Task ID in the status bar.
  529. Display format:
  530. Internal Process number:OS Process ID Internal Task number:OS Task ID
  531. 000:000 000:000
  532. If the OS ID is greater than 3 digits, then it is displayed in hex
  533. 000:0xFFFFFFFF 000:0xFFFFFFFF
  534. --*/
  535. {
  536. TCHAR sz[MAX_TEMP_TXT];
  537. _stprintf(sz, _T("%s %03d:%x"), status.lpszProcessPrefix,
  538. ProcessId, ProcessSysId);
  539. // Sanity check, should never occur.
  540. // Mem overwrite?
  541. Assert(_tcslen(sz) < _tsizeof(sz));
  542. SetItemText_StatusBar(nPROCID_IDX_STATUSBAR, sz);
  543. _stprintf(sz, _T("%s %03d:%x"), status.lpszThreadPrefix,
  544. ThreadId, ThreadSysId);
  545. // Sanity check, should never occur.
  546. // Mem overwrite?
  547. Assert(_tcslen(sz) < _tsizeof(sz));
  548. SetItemText_StatusBar(nTHRDID_IDX_STATUSBAR, sz);
  549. }
  550. ///////////////////////////////////////////////////////////
  551. // Misc helper routines
  552. //
  553. /****************************************************************************
  554. FUNCTION: KeyboardHook
  555. PURPOSE: Check if keyboard hit is NUMLOCK, CAPSLOCK or INSERT
  556. ****************************************************************************/
  557. LRESULT
  558. KeyboardHook(
  559. int iCode,
  560. WPARAM wParam,
  561. LPARAM lParam
  562. )
  563. {
  564. if (iCode == HC_ACTION) {
  565. if (wParam == VK_NUMLOCK
  566. && HIWORD(lParam) & 0x8000 // Key up
  567. && GetKeyState(VK_CONTROL) >= 0) { //No Ctrl
  568. // CAPSLOCK has been hit, refresh status
  569. SetNumLock_StatusBar(GetKeyState(VK_NUMLOCK) & 0x0001);
  570. } else if (wParam == VK_CAPITAL
  571. && HIWORD(lParam) & 0x8000 //Key up
  572. && GetKeyState(VK_CONTROL) >= 0) { //No Ctrl
  573. // CAPSLOCK has been hit, refresh status
  574. SetCapsLock_StatusBar(GetKeyState(VK_CAPITAL) & 0x0001);
  575. } else if (wParam == VK_INSERT
  576. && ((HIWORD(lParam) & 0xE000) == 0x0000) //Key down was up before and No Alt
  577. && GetKeyState(VK_SHIFT) >= 0 //No Shift
  578. && GetKeyState(VK_CONTROL) >= 0) { //No Ctrl
  579. // INSERT has been hit and refresh status if so
  580. // We can't use the up down state, since there is no indicator light
  581. // as a referene to the user. We simple have to toggle it.
  582. SetOverType_StatusBar(!GetOverType_StatusBar());
  583. }
  584. }
  585. return CallNextHookEx( hKeyHook, iCode, wParam, lParam );
  586. } /* KeyboardHook() */