使用Win API 创建自己的输入光标

来源:互联网 发布:大牌车载香薰 知乎 编辑:程序博客网 时间:2024/05/11 11:01

http://www.sudu.cn/info/html/edu/20071229/79088.html
http://ggvylf.blog.163.com/blog/static/34488831201002755628914/
http://www.blogms.com/StBlogPageMain/Efp_BlogLogSee.aspx?cBlogLog=1000332136

WIN32用户界面设计基础之Caret篇
当窗口拥有键盘焦点或处于激活状态时,能创建一个Caret,失去焦点之前必须销毁该Caret。CreateCaret()函数用来创建Caret,系统将该函数指定的位置Pixel取反得到Caret。Caret建立后用ShowCaret()显示Caret并使其闪烁。获得闪烁速度(Flash Time)用GetBlinkTime()*2,设置闪烁时间用SetBlinkTime()/2,Flash Time是Caret从复原到反色再到复原的周期,而Get/SetBlinkTime()得到和设置的是Caret从复原到反色或从反色到复原的时间,因此要乘/除2。获得Caret用GetCaretPos(),参数为一个POINT结构,存放Caret在当前窗口中的位置,SetCaretPos()在Caret不可见的情况下仍然起作用。暂时隐藏Caret使用HideCaret(),再显示用ShowCaret(),完全销毁Caret用DestroyCaret。

  一、 创建并显示Caret

  改动或显示一个窗口的Caret,应捕捉其WM_SETFOCUS消息

  1、 CreateCaret()函数
    CreateCaret(hWnd,(HBITMAP)NULL,30,60)

    hWnd:拥有Caret的窗口句柄

    NULL:如果使用位图Caret,此参数为一个HBITMAP,该HBITMAP能通过LoadBitmap、CreateBitmap和CreateDIBitmap获得,如果为NULL,将建立一个实心矩形光标。

    30,60:光标的大小单位为逻辑单位,如果非NULL的位图句柄,这两个参数被忽略。

   使用位图光标

HBITMAP hbm;
hbm=LoadBitmap((HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),MAKEINTRESOURCE(IDB_BITMAP1));
CreateCaret(hWnd,(HBITMAP)hbm,0,0);

  2、 为了精确确定Caret的大小,能传递SM_CXBORDER和SM_CYBORDER给GetSystemMetics()函数获得以Pixel为计量单位的窗口的边框的宽和高,据此计算Caret的大小。

  二、 使Caret随鼠标的移动而移动

  1、 捕捉WM_MOUSEMOVE消息:

    int x:
    int y;
    x=LOWORD(lParam);
    y=HIWORD(lParam);

  获得事件发生时鼠标的位置

  2、 将Caret移至光标处:

SetCaretPos(x,y)

  3、 在随鼠标移动的过程中Caret的闪烁效果不明显,鼠标停留片刻后,Caret恢复正常闪烁。


////////////////////////////////////////////////////////////////////////////////////////

近日一软件因为没有输入光标提示符,导致客户颇有微词,一些小人也趁机攻击偶的工作,于是静下心来花了一天的时间解决之。
    Caret---以前一直没注意这个东东,它就是你在记事本啊,word啊,或输入框上的那个一闪一闪的小坚线,DOS下叫光标,windows下学名叫“插入符”,呵呵,可能大家还是习惯叫它光标,但m$已把光标这个名字给了鼠标箭头等形状。
   言归正传,Caret如果你的应用程序中未创建他的话,他自己是不会出来的,偶的软件中以往一直一屏只有一个可输入文字处,所以也没人注意到需要一Caret来引导客户哪里是目前的输入焦点,因为大家的目光只有一个地方能注视,不巧的是ccb的代收费一定要在一屏中输入几项内容,原来做此块的哥们他也没考虑到输入时不方便性,于是就把问题留给了我。
   那么怎么解决此问题呢,先来看几个函数:
The Caret Functions
There are five essential caret functions:
CreateCaret Creates a caret associated with a window.
SetCaretPos Sets the position of the caret within the window.
ShowCaret Shows the caret.
HideCaret Hides the caret.
DestroyCaret Destroys the caret.

   有这几个东东,基本就可以搞定了,可是也碰到一些烦心处----不然我花一天时间干嘛?听我一一道来:
  首先,就是在哪里创建Caret好,在“programming windows"中说到是在窗口获得焦点时CreateCaret,在失去焦点时DestroyCaret,说的是有道理的,不过偶的程序是基于对话框的,所有界面都是绘在其上,所以我理所当然的在"OnInitDialog"中CreateCaret了,这里也碰到了点问题,就是我如果在"OnInitDialog"中如果没有ShowCaret 的话,那么以后在别处也ShowCaret 不出来,这块还得再试试。
   然后,就碰到了让我花了大量时间在上头的,其实“programming windows"中写的很清楚了,可是自己懒得去看书(头痛),这就是" if you call HideCaret several times without calling ShowCaret, you must call ShowCaret the same number of times before the caret becomes visible again. "呵,没看的结果就是我花了半天的时间来思索和试验得出和他一样的结论,所以说啊,”书是阶梯“啊,别人的经验可以省下你很多的时间。以后还是多读读书嘻。
   好了,自己写的很零散,好象也没给人什么指导作用,下面还是copy一段书的例子吧.

     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 ;


就此over. Bye.


//////////////////////////////////////////////////////////////////////////////////////////////////////////

MFC文本编程:创建插入符 对软件有兴趣 2010-01-27 17:56:28 阅读9 评论0 字号:大中小
一、创建文本插入符

  Step01、创建插入符

  相关函数/结构体

  CWnd::CreateSolidCaret();

  定义:void CreateSolidCaret(int nWidth,int nHeight);

  在View类中加入WM_CREATE消息的响应函数OnCreate,加入CreateSolidCaret()

  效果:没有显示插入符呀!

  QUOTE FROM MSDN

  The CreateSolidCaret method automatically destroys the previous caret shape, if any, regardless of which window owns the caret. Once created, the caret is initially hidden. To show the caret, the ShowCaret method must be called.

  Step02、显示插入符

  加上ShowCaret();

  Step03、让插入符跟字体大小相关

  相关函数/结构体:

  获取字符信息CDC::GetTextMetrics

  字符属性结构体TEXTMETRIC Structure

  code

  /////////////////////////////////////////////////////////////////////////////

  // CTextView message handlers

  int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct)

  {

  if (CView::OnCreate(lpCreateStruct) == -1)

  return -1;

  //创建设备描述表

  CClientDC dc(this);

  //定义文本信息结构体变量

  TEXTMETRIC tm;

  //获得设备描述表中的文本信息

  dc.GetTextMetrics(&tm);

  //根据字体大小,创建合适的插入符

  CreateSolidCaret(tm.tmAveCharWidth/8, tm.tmHeight);

  //显示插入符

  ShowCaret();

  SetTimer(1,100,NULL);

  return 0;

  }

  二、创建图形插入符

  Step01、创建Bitmap

  定义:CBitmap bitmap;要放在View类的头文件中,并将其访问权限设置为private。为什么private?因为只在View类中调用。

  QUOTE

  若将CBitmap bitmap放在CTextView中,bitmap为局部变量,当OnCreate()执行完毕会发生析构,相关的资源也会被销毁。那么说那幅位图也被销毁?应该不会吧?

  Step02、创建图形插入符

  相关函数

  CWnd::CreateCaret();

  定义:void CreateCaret(CBitmap* pBitmap);

  Quote from MSDN

  The bitmap must have previously been created by the CBitmap::CreateBitmap member function, the CreateDIBitmap Windows function, or the CBitmap::LoadBitmap member function.

  所以需要Step01中把bitmap定义为全局变量。

  OnCreate消息响应函数源代码

  1

  2     /////////////////////////////////////////////////////////////////////////////

  3     // CTextView message handlers

  4     int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct)

  5     {

  6         if (CView::OnCreate(lpCreateStruct) == -1)

  7             return -1;

  8         bitmap.LoadBitmap(IDB_BITMAP1);

  9         CreateCaret(&bitmap);

  10         ShowCaret();

  11         SetTimer(1,100,NULL);

  12         return 0;

  13     }