{"id":112059,"date":"2026-02-12T07:00:00","date_gmt":"2026-02-12T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=112059"},"modified":"2026-02-12T10:50:40","modified_gmt":"2026-02-12T18:50:40","slug":"20260212-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260212-00\/?p=112059","title":{"rendered":"How can I distinguish between the numeric keypad 0 and the top-row 0 in the <CODE>WM_<WBR>KEY&shy;DOWN<\/CODE> message?"},"content":{"rendered":"<p>A customer wanted to know how to distinguish between the numeric keypad 0 and the top-row 0 in the <code>WM_<wbr \/>KEY\u00adDOWN<\/code> message. And while we&#8217;re at it, let&#8217;s also distinguish between the numeric keypad 0 and the <kbd>Ins<\/kbd> key.<\/p>\n<p>We start with this table of what you get in the <code>WM_<wbr \/>KEY\u00adDOWN<\/code> message when you press the numeric keypad 0.<\/p>\n<table style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Event<\/th>\n<th>wParam<\/th>\n<\/tr>\n<tr>\n<td>Numpad0 with NumLock on<\/td>\n<td><tt>VK_NUMPAD0<\/tt><\/td>\n<\/tr>\n<tr>\n<td>Numpad0 with NumLock off<\/td>\n<td><tt>VK_INSERT<\/tt><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Okay, so when the <code>wParam<\/code> is <code>VK_<wbr \/>NUMPAD0<\/code>, it seems pretty clear that we have the numeric keypad 0. But when it is <code>VK_<wbr \/>INSERT<\/code>, we aren&#8217;t sure whether it&#8217;s the numeric keypad 0 with NumLock off, or whether it&#8217;s the dedicated <kbd>Ins<\/kbd> key.<\/p>\n<p>For that, we can look at the <code>lParam<\/code>, specifically, bit 24, which is documented as the &#8220;extended key&#8221; bit.<\/p>\n<p>Rewind the clock to 1983. The IBM PC XT keyboard is introduced. To the left of the main keyboard is a set of numbered function keys, and to the right is a numeric keypad. But the keys on the numeric keypad do double-duty because arrows and other editing keys are overlaid onto them.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"width: 6ex;\" rowspan=\"2\" valign=\"center\">\u23ce<\/td>\n<td style=\"width: 6ex;\">\n<div>7<\/div>\n<div style=\"font-size: 80%;\">Home<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>8<\/div>\n<div style=\"font-size: 80%;\">\u2191<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>9<\/div>\n<div style=\"font-size: 80%;\">PgUp<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 6ex;\">\n<div>4<\/div>\n<div style=\"font-size: 80%;\">\u2190<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>5<\/div>\n<div style=\"font-size: 80%;\">\u00a0<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>6<\/div>\n<div style=\"font-size: 80%;\">\u2192<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 6ex;\">\n<div style=\"font-size: 80%;\">PrtSc<\/div>\n<div>*<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>1<\/div>\n<div style=\"font-size: 80%;\">End<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>2<\/div>\n<div style=\"font-size: 80%;\">\u2193<\/div>\n<\/td>\n<td style=\"width: 6ex;\">\n<div>3<\/div>\n<div style=\"font-size: 80%;\">PgDn<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 12ex; text-align: center;\" colspan=\"2\">\n<div>0<\/div>\n<div style=\"font-size: 80%;\">Ins<\/div>\n<\/td>\n<td style=\"width: 12ex; text-align: center;\" colspan=\"2\">\n<div>.<\/div>\n<div style=\"font-size: 80%;\">Del<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You select whether you want numbers or arrows\/editing keys by toggling <kbd>NumLock<\/kbd>.<\/p>\n<p>The IBM PS\/2 keyboard expanded the set of keys on the keyboard by inserting a block of keys between the main keyboard and the numeric keypad. This block contains the arrow keys and the editing keys. This keyboard layout closely resembles the keyboard layout used by most keyboards today, so I guess it held up okay.<\/p>\n<p>For compatibility, the bonus keys on the keyboard reported themselves to be the same as the numeric keypad keys they shadowed, but with an extra flag byte to say that they are &#8220;extended&#8221; keys. They&#8217;re &#8220;extended&#8221; because they weren&#8217;t in the original keyboard.<\/p>\n<p>This &#8220;extended&#8221; terminology has carried forward ever since. So we can distinguish between the dedicated <kbd>Ins<\/kbd> key and a numeric keypad 0 with NumLock off by seeing if we got an extended key. If so, then it came from the editing keys; if not, then it came from the numeric keypad.<\/p>\n<table style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Event<\/th>\n<th>wParam<\/th>\n<th>Extended?<\/th>\n<\/tr>\n<tr>\n<td>Numpad0 with NumLock on<\/td>\n<td><tt>VK_NUMPAD0<\/tt><\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>Numpad0 with NumLock off<\/td>\n<td><tt>VK_INSERT<\/tt><\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td><kbd>Ins<\/kbd> key<\/td>\n<td><tt>VK_INSERT<\/tt><\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Next time, we&#8217;ll look at distinguishing the numeric keypad 0 from the top-row 0 in the <code>WM_<wbr \/>CHAR<\/code> message. It&#8217;s a little messier.<\/p>\n<p><b>Bonus chatter<\/b>: That <kbd>PrtSc<\/kbd> key was <a href=\"https:\/\/forum.vcfed.org\/index.php?threads\/disabling-the-prtsc-key.63721\/\"> a major source of frustration because it sat right next to the shift key<\/a>. If your finger was slightly misaligned and hit both the shift key and the <kbd>PrtSc<\/kbd> key, you accidentally asked for the screen contents to be sent to the printer. Your computer just hung until you turned on your printer so you could get a printout that you didn&#8217;t want. (And if you didn&#8217;t have a printer, you were just dead.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Check whether it is an extended key.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-112059","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Check whether it is an extended key.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112059","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=112059"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112059\/revisions"}],"predecessor-version":[{"id":112060,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112059\/revisions\/112060"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=112059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=112059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=112059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}