第七章 键盘-2

时间:2007-10-22 08:59:02   来源:chinaitzhe.com  作者:ChinaITzhe  编辑:gaopoadmin

键盘讯息和字元集
 

本章剩下的范例程式有缺陷。它们不能在所有版本的Windows下都正常执行。这些缺陷不是特意引过程式码中的;事实上,您也许永远不会遇到这些缺陷。只有在不同的键盘语言和键盘布局间切换,以及在多位元组字元集的远东版Windows下执行程式时,这些问题才会出现-所以我不愿将它们称为「错误」。

不过,如果程式使用Unicode编译并在Windows NT下执行,那么程式会执行得更好。我在第二章提到过这个问题,并且展示了Unicode对简化棘手的国际化问题的重要性。

KEYVIEW1程式
 

了解键盘国际化问题的第一步,就是检查Windows传递给视窗讯息处理程式的键盘内容和字元讯息。程式6-2所示的KEYVIEW1会对此有所帮助。该程式在显示区域显示Windows向视窗讯息处理程式发送的8种不同键盘讯息的全部资讯。

 

 程式6-2  KEYVIEW1
KEYVIEW1.C
/*---------------------------------------------------------------------
 KEYVIEW1.C -- Displays Keyboard and Character Messages
              (c) Charles Petzold, 1998
---------------------------------------------------------------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
     PSTR szCmdLine, int iCmdShow)
{
 static TCHAR szAppName[] = TEXT ("KeyView1") ;
 HWND    hwnd ;
 MSG    msg ;
 WNDCLASS   wndclass ;
    
 wndclass.style     = CS_HREDRAW | CS_VREDRAW ;
 wndclass.lpfnWndProc  = WndProc ;
 wndclass.cbClsExtra   = 0 ;
 wndclass.cbWndExtra   = 0 ;
 wndclass.hInstance    = hInstance ;
 wndclass.hIcon     = LoadIcon (NULL, IDI_APPLICATION) ;
 wndclass.hCursor   = LoadCursor (NULL, IDC_ARROW) ;
 wndclass.hbrBackground   = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
 wndclass.lpszMenuName  = NULL ;
 wndclass.lpszClassName  = szAppName ;

 if (!RegisterClass (&wndclass))
 {
  MessageBox (NULL, TEXT ("This program requires Windows NT!"),
      szAppName, MB_ICONERROR) ;
  return 0 ;
 }
    
 hwnd = CreateWindow (szAppName, TEXT ("Keyboard Message Viewer #1"),
       WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, CW_USEDEFAULT,
       CW_USEDEFAULT, CW_USEDEFAULT,
       NULL, NULL, hInstance, NULL) ;
    
 ShowWindow (hwnd, iCmdShow) ;
 UpdateWindow (hwnd) ;
    
 while (GetMessage (&msg, NULL, 0, 0))
 {
  TranslateMessage (&msg) ;
  DispatchMessage (&msg) ;
 }
  return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 static int   cxClientMax, cyClientMax, cxClient, cyClient, cxChar, cyChar ;
 static int   cLinesMax, cLines ;
 static PMSG  pmsg ;
 static RECT  rectScroll ;
 static TCHAR szTop[] = TEXT ("Message Key   Char ")
        TEXT ("Repeat Scan Ext ALT Prev Tran") ;
 static TCHAR szUnd[] = TEXT ("_______        ___       ____     ")
        TEXT ("______ ____ ___ ___ ____ ____") ;

 static TCHAR * szFormat[2] = {
    TEXT ("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),
    TEXT ("%-13s  0x%04X%1s%c %6u %4d %3s %3s %4s %4s") } ;
  static TCHAR * szYes  = TEXT ("Yes") ;
  static TCHAR * szNo   = TEXT ("No") ;
  static TCHAR * szDown = TEXT ("Down") ;
  static TCHAR * szUp   = TEXT ("Up") ;

  static TCHAR * szMessage [] = {
  TEXT ("WM_KEYDOWN"), TEXT ("WM_KEYUP"),
  TEXT ("WM_CHAR"),  TEXT ("WM_DEADCHAR"),
  TEXT ("WM_SYSKEYDOWN"),TEXT ("WM_SYSKEYUP"),
  TEXT ("WM_SYSCHAR"), TEXT ("WM_SYSDEADCHAR") } ;
  HDC   hdc ;
  int    i, iType ;
  PAINTSTRUCT  ps ;
  TCHAR    szBuffer[128], szKeyName [32] ;
  TEXTMETRIC   tm ;
    
 switch (message)
 {
 case WM_CREATE:
 case WM_DISPLAYCHANGE:
    // Get maximum size of client area
  cxClientMax = GetSystemMetrics (SM_CXMAXIMIZED) ;
  cyClientMax = GetSystemMetrics (SM_CYMAXIMIZED) ;

    // Get character size for fixed-pitch font
  hdc = GetDC (hwnd) ;
  SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  GetTextMetrics (hdc, &tm) ;
  cxChar = tm.tmAveCharWidth ;
  cyChar = tm.tmHeight ;

 ReleaseDC (hwnd, hdc) ;
    // Allocate memory for display lines
  if (pmsg)
   free (pmsg) ;
   cLinesMax = cyClientMax / cyChar ;
   pmsg = malloc (cLinesMax * sizeof (MSG)) ;
   cLines = 0 ;
   // fall through
 case WM_SIZE:
  if (message == WM_SIZE)
  {
   cxClient = LOWORD (lParam) ;
   cyClient = HIWORD (lParam) ;
  }
     // Calculate scrolling rectangle
  rectScroll.left  = 0 ;
  rectScroll.right = cxClient ;
  rectScroll.top   = cyChar ;
  rectScroll.bottom = cyChar * (cyClient / cyChar) ;

  InvalidateRect (hwnd, NULL, TRUE) ;
  return 0 ;
         
 case WM_KEYDOWN:
 case WM_KEYUP:
 case WM_CHAR:
 case WM_DEADCHAR:
 case WM_SYSKEYDOWN:
 case WM_SYSKEYUP:
 case WM_SYSCHAR:
 case WM_SYSDEADCHAR:
     // Rearrange storage array
  for (i = cLinesMax - 1 ; i > 0 ; i--)
  {
    pmsg[i] = pmsg[i - 1] ;
  }
     // Store new message
  pmsg[0].hwnd = hwnd ;
  pmsg[0].message = message ;
  pmsg[0].wParam = wParam ;
  pmsg[0].lParam = lParam ;

  cLines = min (cLines + 1, cLinesMax) ;
     // Scroll up the display
  ScrollWindow (hwnd, 0, -cyChar, &rectScroll, &rectScroll) ;
  break ;   // i.e., call DefWindowProc so Sys messages work
 case WM_PAINT:
  hdc = BeginPaint (hwnd, &ps) ;
  SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  SetBkMode (hdc, TRANSPARENT) ;
  TextOut (hdc, 0, 0, szTop, lstrlen (szTop)) ;
  TextOut (hdc, 0, 0, szUnd, lstrlen (szUnd)) ;

  for (i = 0 ; i < min (cLines, cyClient / cyChar - 1) ; i++)
  {
   iType =  pmsg[i].message == WM_CHAR ||
     pmsg[i].message == WM_SYSCHAR ||
     pmsg[i].message == WM_DEADCHAR ||
     pmsg[i].message == WM_SYSDEADCHAR ;

   GetKeyNameText (pmsg[i].lParam, szKeyName,
      sizeof (szKeyName) / sizeof (TCHAR)) ;

  TextOut (hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer,
  wsprintf (szBuffer, szFormat [iType],
  szMessage [pmsg[i].message - WM_KEYFIRST],
  pmsg[i].wParam,
  (PTSTR) (iType ? TEXT (" ") : szKeyName),
  (TCHAR) (iType ? pmsg[i].wParam : ' '),
  LOWORD (pmsg[i].lParam),
  HIWORD (pmsg[i].lParam) & 0xFF,
    0x01000000 & pmsg[i].lParam ? szYes  : szNo,
    0x20000000 & pmsg[i].lParam ? szYes  : szNo,
    0x40000000 & pmsg[i].lParam ? szDown : szUp,
    0x80000000 & pmsg[i].lParam ? szUp   : szDown)) ;
  }
  EndPaint (hwnd, &ps) ;
  return 0 ;

 case WM_DESTROY:
  PostQuitMessage (0) ;
  return 0 ;
 }
 return DefWindowProc (hwnd, message, wParam, lParam) ;
}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 下一页
关键字:Windows,程式,开发,入门,第七章 ,键盘
上一篇:第七章 键盘-1

相关文章

文章评论

共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面