设为首页 加入收藏

TOP

四、Windows编程之插入符号(不是光标)
2012-11-05 12:26:13 】 浏览:549
Tags:Windows 编程 插入 符号 不是 光标

当您往程序中输入文字时,通常有一个底线、竖条或者方框来指示输入的下一个字符将出现在屏幕上的位置。这个标志通常称为「光标」,但是在Windows下写程序,您必须改变这个习惯。在Windows中,它称为「插入符号」。「光标」是指表示鼠标位置的那个位图图像。

插入符号函数

主要有五个插入符号函数:

  • CreateCaret 建立与窗口有关的插入符号
     
  • SetCaretPos 在窗口中设定插入符号的位置
     
  • ShowCaret 显示插入符号
     
  • HideCaret 隐藏插入符号
     
  • DestroyCaret 撤消插入符号
     

另外还有取得插入符号目前位置(GetCaretPos)和取得以及设定插入符号闪烁时间(GetCaretBlinkTime和SetCaretBlinkTime)的函数。

在Windows中,插入符号定义为水平线、与字符大小相同的方框,或者与字符同高的竖线。如果使用调和字体,例如Windows内定的系统字体,则推荐使用竖线插入符号。因为调和字体中的字符没有固定大小,水平线或方框不能设定为字符的大小。

如果程序中需要插入符号,那么您不应该简单地在窗口消息处理程序的WM_CREATE消息处理期间建立它,然后在WM_DESTROY消息处理期间撤消。其原因显而易见:一个消息队列只能支持一个插入符号。因此,如果您的程序有多个窗口,那么各个窗口必须有效地共享相同的插入符号。

其实,它并不像听起来那么多限制。您再想想就会发现,只有在窗口有输入焦点时,窗口内显示插入符号才有意义。事实上,闪烁的插入符号只是一种视觉提示:您可以在程序中输入文字。因为任何时候都只有一个窗口拥有输入焦点,所以多个窗口同时都有闪烁的插入符号是没有意义的。

通过处理WM_SETFOCUS和WM_KILLFOCUS消息,程序就可以确定它是否有输入焦点。正如名称所暗示的,窗口消息处理程序在有输入焦点的时候接收到WM_SETFOCUS消息,失去输入焦点的时候接收到WM_KILLFOCUS消息。这些消息成对出现:窗口消息处理程序在接收到WM_KILLFOCUS消息之前将一直接收到WM_SETFOCUS消息,并且在窗口打开期间,此窗口总是接收到相同数量的WM_SETFOCUS和WM_KILLFOCUS消息。

使用插入符号的主要规则很简单:窗口消息处理程序在WM_SETFOCUS消息处理期间呼叫CreateCaret,在WM_KILLFOCUS消息处理期间呼叫DestroyCaret。

这里还有几条其它规则:插入符号刚建立时是隐蔽的。如果想使插入符号可见,那么您在呼叫CreateCaret之后,窗口消息处理程序还必须呼叫ShowCaret。另外,当窗口消息处理程序处理一条非WM_PAINT消息而且希望在窗口内绘制某些东西时,它必须呼叫HideCaret隐藏插入符号。在绘制完毕后,再呼叫ShowCaret显示插入符号。HideCaret的影响具有累积效果,如果多次呼叫HideCaret而不呼叫ShowCaret,那么只有呼叫ShowCaret相同次数时,才能看到插入符号。

TYPER程序

程序6-5所示的TYPER程序使用了本章讨论的所有内容,您可以认为TYPER是一个相当简单的文字编辑器。在窗口中,您可以输入字符,用光标移动键(也可以称为插入符号移动键)来移动光标(I型标),按下Escape键清除窗口的内容等。缩放窗口、改变键盘输入语言时都会清除窗口的内容。本程序没有卷动,没有文字寻找和定位功能,不能储存文件,没有拼写检查,但它确实是写作一个文字编辑器的开始。

程序6-5 TYPER
        TYPER.C        /*------------------------------------------------------------------------          TYPER.C --      Typing Program                                          (c) Charles Petzold, 1998        --------------------------------------------------------------------------*/        #include <windows.h>        #define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)        LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;        int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow)        {            static TCHAR  szAppName[] = TEXT ("Typer") ;            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 ("Typing Program"),                                                                  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 DWORD          dwCharSet = DEFAULT_CHARSET ;            static int            cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer,                                          xCaret, yCaret ;            static TCHAR *pBuffer = NULL ;            HDC                           hdc ;            int                           x, y, i ;            PAINTSTRUCT           ps ;            TEXTMETRIC            tm ;                       switch (message)            {            case   WM_INPUTLANGCHANGE:                    dwCharSet = wParam ;                       // fall through            case   WM_CREATE:                    hdc = GetDC (hwnd) ;                    SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,                                                                        dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;                                    GetTextMetrics (hdc, &tm) ;                    cxChar = tm.tmAveCharWidth ;                    cyChar = tm.tmHeight ;                                    DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;                    ReleaseDC (hwnd, hdc) ;                    // fall through                          case   WM_SIZE:                           // obtain window size in pixels                    if (message == WM_SIZE)                    {                                   cxClient = LOWORD (lParam) ;                                   cyClient = HIWORD (lParam) ;                    }                           // calculate window size in characters                                    cxBuffer = max (1, cxClient / cxChar) ;                    cyBuffer = max (1, cyClient / cyChar) ;                                           // allocate memory for buffer and clear it                                    if (pBuffer != NULL)                                   free (pBuffer) ;                    pBuffer = (TCHAR *) malloc (cxBuffer * cyBuffer * sizeof (TCHAR)) ;                                    for (y = 0 ; y < cyBuffer ; y++)                                   for (x = 0 ; x < cxBuffer ; x++)                                                  BUFFER(x,y) = ' ' ;                           // set caret to upper left corner                    xCaret = 0 ;                    yCaret = 0 ;                                              if (hwnd == GetFocus ())                                   SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;                    InvalidateRect (hwnd, NULL, TRUE) ;                    return 0 ;                                      case   WM_SETFOCUS:                                   // create and show the caret                    CreateCaret (hwnd, NULL, cxChar, cyChar) ;                    SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;                   ShowCaret (hwnd) ;                    return 0 ;                            case WM_KILLFOCUS:                                   // hide and destroy the caret                    HideCaret (hwnd) ;                    DestroyCaret () ;                    return 0 ;                            case   WM_KEYDOWN:                    switch (wParam)                    {                    case VK_HOME:                                   xCaret = 0 ;                                   break ;                                                        case   VK_END:                                                  xCaret = cxBuffer - 1 ;                                                  break ;                                                        case   VK_PRIOR:                                                  yCaret = 0 ;                                                  break ;                                                        case   VK_NEXT:                                                  yCaret = cyBuffer - 1 ;                                                  break ;                                                        case   VK_LEFT:                                                  xCaret = max (xCaret - 1, 0) ;                                                  break ;                                                case   VK_RIGHT:                                   xCaret = min (xCaret + 1, cxBuffer - 1) ;                                   break ;                                                case   VK_UP:                                  yCaret = max (yCaret - 1, 0) ;                                   break ;                                                case   VK_DOWN:                                   yCaret = min (yCaret + 1, cyBuffer - 1) ;                                   break ;                                                case   VK_DELETE:                                   for (x = xCaret ; x < cxBuffer - 1 ; x++)                                                  BUFFER (x, yCaret) = BUFFER (x + 1, yCaret) ;                                                        BUFFER (cxBuffer - 1, yCaret) = ' ' ;                                                        HideCaret (hwnd) ;                                   hdc = GetDC (hwnd) ;                                                   SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,                                                                         dwCharSet, 0, 0, 0,FIXED_PITCH, NULL)) ;                                  TextOut (hdc, xCaret * cxChar, yCaret * cyChar,                                                                  & BUFFER (xCaret, yCaret),                                                                  cxBuffer - xCaret) ;                                   DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;                                   ReleaseDC (hwnd, hdc) ;                                  ShowCaret (hwnd) ;                                  break ;                    }                    SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;                    return 0 ;                            case   WM_CHAR:                    for (i = 0 ; i < (int) LOWORD (lParam) ; i++)                    {                           switch (wParam)                                   {                           case '\b':                                           // backspace                                          if (xCaret > 0)                                                  {                                                          xCaret-- ;                                                        SendMessage (hwnd, WM_KEYDOWN, VK_DELETE, 1) ;                                                  }                                           break ;                                             case '\t':                                                  // tab                                   do                                           {                                                  SendMessage (hwnd, WM_CHAR, ' ', 1) ;                                           }                                   while (xCaret % 8 != 0) ;                                   break ;                    case '\n':                                                  // line feed                                   if (++yCaret == cyBuffer)                                                  yCaret = 0 ;                                   break ;                                              case '\r':                                                  // carriage return                                   xCaret = 0 ;                                                             if (++yCaret == cyBuffer)                                                  yCaret = 0 ;                                   break ;                                              case '\x1B':                                       // escape                                   for (y = 0 ; y < cyBuffer ; y++)                                   for (x = 0 ; x < cxBuffer ; x++)                                                  BUFFER (x, y) = ' ' ;                                                                  xCaret = 0 ;                                   yCaret = 0 ;                                                                  InvalidateRect (hwnd, NULL, FALSE) ;                                   break ;                                                   default:                                                    // character codes                           BUFFER (xCaret, yCaret) = (TCHAR) wParam ;                                                     HideCaret (hwnd) ;                           hdc = GetDC (hwnd) ;                                           SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,                                                                  dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;                           TextOut (hdc, xCaret * cxChar, yCaret * cyChar,                                                  & BUFFER (xCaret, yCaret), 1) ;                           DeleteObject (                                   SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;                           ReleaseDC (hwnd, hdc) ;                           ShowCaret (hwnd) ;                          if (++xCaret == cxBuffer)                                   {                                           xCaret = 0 ;                                           if (++yCaret == cyBuffer)                                                          yCaret = 0 ;                                   }                           break ;                    }            }                                    SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;                    return 0 ;                            case   WM_PAINT:                    hdc = BeginPaint (hwnd, &ps) ;                                    SelectObject (hdc, CreateFont (0, 0, 0, 0, 0, 0, 0, 0,                                                         dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)) ;                    for (y = 0 ; y < cyBuffer ; y++)                           TextOut (hdc, 0, y * cyChar, & BUFFER(0,y), cxBuffer) ;                    DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;                    EndPaint (hwnd, &ps) ;                    return 0 ;                            case   WM_DESTROY:                    PostQuitMessage (0) ;                    return 0 ;            }            return DefWindowProc (hwnd, message, wParam, lParam) ;        }        
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇一、Windows鼠标基础 下一篇三、Windows键盘消息和字符集—Tr..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目