在窗体上创建自己的光标并输入文字

    我们知道在文本框等可以接收输入的组件中,我们可以看到闪烁的光标,并可以输入文字,如果我们在,比如窗体上时,因为不支持输入,也无法显示闪烁的光标,那我们 有办法做自己的输入吗?当然可以,下面我们演示在Form上来输入文字。

    用到的API函数如下

 

GetTextMetrics:获取程序当前的字体信息,存放到TEXTMETRIC结构中

 

CreateCaret:为系统插入标记创建一个新的形状,并且将插入标记的属主关系指定给特定的窗口。插入标记的形状。可以是线、块或位图

 

ShowCaret:显示光标

 

SetCaretPos:设置光标的位置

Delphi代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure FormPaint(Sender: TObject);
  private
    { Private declarations }
    s:string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  //TTextMetric存放字体信息
  tm:TTextMetric;
begin
  s := '';
  GetTextMetrics(Self.Canvas.Handle,tm);
  {
  注意 CreateCaret 的第二个参数是HBITMAP类型,所以你可以使用自己的图形作为光标形状,这里采用默认
  后面两个参数是光标的宽度和高度,可以自定义
  }
  CreateCaret(Self.Handle,HBITMAP(nil),tm.tmAveCharWidth div 2,tm.tmHeight);
  ShowCaret(Self.Handle);
  //在(10,,10)这个点上显示
  SetCaretPos(10,10);
end;

//窗体按键事件,每次按一个键后,重写s的值,在OnPaint事件中会把s的值 画到窗体上
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  //如果是退格键,则删除前一个字符
  if Ord(Key) = VK_BACK then
  begin
    if (s <> '') then
      Delete(s,Length(s),1);
  end
  else
    s := s + Key;
  //重绘
  Self.Invalidate;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  Self.Canvas.TextOut(10,10,s);
  //重新设置光标位置
  SetCaretPos(Self.Canvas.TextWidth(s)+10,10);
end;

end.

 

VC代码:

//全局字符串变量
CString s;

//初始化时,设置光标
BOOL CTest_MFCDlg::OnInitDialog()
{
    CDialog::OnInitDialog();    
    ShowSelfCaret();
         ......
}

//为窗体添加函数,初始化光标
void CTest_MFCDlg::ShowSelfCaret(void)
{
    CClientDC dc(this);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    CreateSolidCaret(tm.tmAveCharWidth/2,tm.tmHeight);
    ShowCaret();
    POINT p;
    p.x = 0;
    p.y = 0;
    SetCaretPos(p);
}

//重载PreTranslateMessage
BOOL CTest_MFCDlg::PreTranslateMessage(MSG* pMsg)
{
    //如果是按键按下
    if (pMsg->message == WM_KEYDOWN)
    {
        //如果是退格键,删除末尾字符
        if (pMsg->wParam == VK_BACK)
        {
            if (s.GetLength() != 0)
            {
                s.Delete(s.GetLength() - 1,1);
            }
        }
        else
            //追加字符
            s.Insert(s.GetLength(),(TCHAR)pMsg->wParam);
        Invalidate(true);
    }
    return CDialog::PreTranslateMessage(pMsg);
}

//自画,将s的内容画到窗体上
void CTest_MFCDlg::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);    
    CSize size = dc.GetTextExtent(s);
    POINT p;
    p.x = size.cx;
    p.y = 0;
    SetCaretPos(p);
    dc.DrawText(s,s.GetLength(),rect,DT_LEFT);
}

 

 

posted @ 2014-05-12 12:01  青田  阅读(455)  评论(0编辑  收藏  举报