Leaked source code of windows server 2003
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.

802 lines
20 KiB

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