1.先创建插入符光标

在WM_CREATE消息中

LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{ HDC hdc = GetDC(hWnd);
    //获取字体信息
TEXTMETRIC txtInfo; GetTextMetrics(hdc, &txtInfo);
//创建插入符
CreateCaret(hWnd, NULL, txtInfo.tmAveCharWidth/8, txtInfo.tmHeight);
    //显示插入符
ShowCaret(hWnd); ReleaseDC(hWnd, hdc);
return LRESULT();
}

2.定义两个全局变量

//全局变量
POINT g_point = { 0 };//保存鼠标点下的点的位置
CString g_string;        //保存输入的字符串

3.在鼠标按下消息中.WM_LBUTTONDOWN

LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
//获取鼠标点下时的点的坐标
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
//设置插入符的位置
SetCaretPos(pt.x,pt.y);
//把点的坐标保存到全局变量中
g_point = pt;
//清空字符串
g_string.Empty(); return LRESULT();
}

3.在键盘消息WM_CHAR中处理字符绘制和光标跟

LRESULT OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
//获得键入的字符
UINT nChar = (TCHAR)wParam; HDC hdc = GetDC(hWnd); if (nChar == VK_RETURN)//换行
{
g_string.Empty(); //清空字符串
TEXTMETRIC txtInfo;
GetTextMetrics(hdc, &txtInfo);//获取字符的高度
g_point.y = g_point.y + txtInfo.tmHeight;//设置插入符Y坐标的位置
}
else if (nChar == VK_BACK)//退格
{
//获取背景色
COLORREF color = GetBkColor(hdc);
//设置文本颜色
COLORREF oldColor = SetTextColor(hdc, color);
//用背景色擦除字符串
TextOut(hdc, g_point.x, g_point.y, g_string, g_string.GetLength());
//去掉最后一个字符
g_string = g_string.Left(g_string.GetLength() - 1);
//重新设置文本颜色为原来的颜色
SetTextColor(hdc, oldColor);
}
else
{
g_string += (TCHAR)nChar;//键入的字符累加到字符串中
} //获得字符串的像素宽度与高度
SIZE size = { 0 };
GetTextExtentPoint32(hdc, g_string, g_string.GetLength(), &size); int x = g_point.x + size.cx;
int y = g_point.y;
SetCaretPos(x, y);//重新设置光标位置 //绘制字符串到窗口上
TextOut(hdc,g_point.x, g_point.y, g_string,g_string.GetLength()); ReleaseDC(hWnd, hdc);
return LRESULT();
}

目前就先学到这里,以后有时间再进一步的去学习.

程序源码:

#include<windows.h>
#include <windowsx.h> //这是要用GET_X_LPARAM,GET_Y_LPARAM宏
#include <atlstr.h>  //字符串类CString //全局变量
POINT g_point = { 0 };
CString g_string; //函数的前置声明
LRESULT CALLBACK lpWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam); //WM_CREATE
LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);//WM_LBUTTONDOWN
LRESULT OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam); //WM_CHAR int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
//设计窗口类
TCHAR className[] = TEXT("myClass");//窗口类名称 //填充窗口类结构体
WNDCLASSEX wndClass = { 0 };
wndClass.cbSize = sizeof(WNDCLASSEX);
//判断是否是系统注册了的类
if (!GetClassInfoEx(hInstance, className, &wndClass))
{
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = lpWindowProc;
wndClass.lpszClassName = className;
wndClass.lpszMenuName = NULL;
wndClass.style = CS_VREDRAW | CS_HREDRAW; //注册窗口类
if (!RegisterClassEx(&wndClass))
{
return 1;
}
} //创建窗口
HWND hwnd = ::CreateWindowEx(0,className, TEXT("我的窗口"),
WS_OVERLAPPEDWINDOW, 100, 100, 600, 400, NULL, NULL, hInstance, 0);

if (!hwnd) {
return 1;
}

//显示并更新窗口
::ShowWindow(hwnd, nShowCmd); ::UpdateWindow(hwnd);

//消息循环 MSG msg;

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
    //销毁插入符
DestroyCaret(); return msg.lParam;
} LRESULT CALLBACK lpWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break; case WM_CREATE: return OnCreate( hWnd,wParam, lParam);
case WM_LBUTTONDOWN: return OnLButtonDown(hWnd, wParam, lParam);
case WM_CHAR: return OnChar(hWnd, wParam, lParam); } return DefWindowProc(hWnd, uMsg, wParam, lParam);
} LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
//获取字体信息
HDC hdc = GetDC(hWnd);
TEXTMETRIC txtInfo;
GetTextMetrics(hdc, &txtInfo); //创建插入符
CreateCaret(hWnd, NULL, txtInfo.tmAveCharWidth/8, txtInfo.tmHeight);
ShowCaret(hWnd); ReleaseDC(hWnd, hdc);
return LRESULT();
} LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
SetCaretPos(pt.x,pt.y);//设置插入符位置
g_point = pt;
g_string.Empty(); return LRESULT();
} LRESULT OnChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
//获得键入的字符
UINT nChar = (TCHAR)wParam; HDC hdc = GetDC(hWnd); if (nChar == VK_RETURN)//换行
{
g_string.Empty(); //清空字符串
TEXTMETRIC txtInfo;
GetTextMetrics(hdc, &txtInfo);//获取字符的高度
g_point.y = g_point.y + txtInfo.tmHeight;//设置插入符Y坐标的位置
}
else if (nChar == VK_BACK)//退格
{
//获取背景色
COLORREF color = GetBkColor(hdc);
//设置文本颜色
COLORREF oldColor = SetTextColor(hdc, color);
//用背景色擦除字符串
TextOut(hdc, g_point.x, g_point.y, g_string, g_string.GetLength());
//去掉最后一个字符
g_string = g_string.Left(g_string.GetLength() - 1);
//重新设置文本颜色为原来的颜色
SetTextColor(hdc, oldColor);
}
else
{
g_string += (TCHAR)nChar;//键入的字符累加到字符串中
} //获得字符串的像素宽度与高度
SIZE size = { 0 };
GetTextExtentPoint32(hdc, g_string, g_string.GetLength(), &size); int x = g_point.x + size.cx;
int y = g_point.y;
SetCaretPos(x, y);//重新设置光标位置 //绘制字符串到窗口上
TextOut(hdc,g_point.x, g_point.y, g_string,g_string.GetLength()); ReleaseDC(hWnd, hdc);
return LRESULT();
}

Win32 插入符光标跟随的打字小程序的更多相关文章

  1. [转]wxParse-微信小程序富文本解析组件

    本文转自:https://github.com/icindy/wxParse 基本使用方法 Copy文件夹wxParse - wxParse/ -wxParse.js(必须存在) -html2json ...

  2. 【Windows编程】系列第十篇:文本插入符

    大家知道,在使用微软的编程环境创建工程时会让你选择是控制台模式还是Windows应用程序.如果选择控制台的console模式,就会在运行时出现一个黑洞洞的字符模式窗口,里面就有等待输入一闪一闪的插入符 ...

  3. 小程序实现sql插入语句转换成Laravel迁移语句

    sql的插入语句长这样: INSERT INTO `media` (`MediaID`, `type`, `filename`, `title`) VALUES (1, 'word', 'word1. ...

  4. 关于bootstrap--排版(标题、强调、背景、插入符等)

    1. 2.标题:<h1>这是主标题<small>这是副标题,为当前字号65%,灰色(#999)</small></h1>. 3.段落:<p> ...

  5. 微信小程序tab切换,可滑动切换,导航栏跟随滚动实现

    简介 看到今日头条小程序页面可以滑动切换,而且tab导航条也会跟着滚动,点击tab导航,页面滑动,切导航栏也会跟着滚动,就想着要怎么实现这个功能 像商城类商品类目如果做成左右滑动切换类目用户体验应该会 ...

  6. 微信小程序input组件抖动及textarea组件光标错位解决方案

    问题一: 使用微信小程序input组件时,在移动端唤起focus或blur事件时,因光标占位导致内容出现叠影及抖动现象. 解决方案: 用<textarea>组件代替了<input/& ...

  7. MFC中插入符的生成

    响应WM_CREATE消息的代码如下: int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct) { ) ; // 插入符在窗口重绘的过程中不会消失 ...

  8. 小程序插入html代码

    转自:https://blog.csdn.net/BetterGG/article/details/81027291 一.首先,html 分 2 种情况: 1.我在做详情页开发的时候发现获取到的数据是 ...

  9. 插入符的创建(MFC)

    int CDrawRectangleDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) { ) ; // TODO: 在此添加您专用的创建代码 CreateSol ...

  10. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:插入符

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

随机推荐

  1. Latex 公式 如何转为Word 公式,免费线上网站

    在实际中,我们常常需要讲将atex公式在word中书写.不采用手敲word公式,如何直接从Latex公式转word公式: 非常好的网站:https://www.latexlive.com/ 可以直接复 ...

  2. JSP四个作用域和九个对象

    一.四个作用域 (1)Requset 请求作用域,就是客户端的一次请求 (2)Session 会话作用域,当用户首次访问时,产生一个新的会话,以后服务器就可以记住这个会话状态.生命周期:会话超时,或者 ...

  3. 信奥一本通1164:digit函数

    1164:digit函数 时间限制: 1000 ms 内存限制: 65536 KB 提交数:41504 通过数: 26475 [题目描述] 在程序中定义一函数digit(n,k) ,它能分离出整数n ...

  4. 解析QAnything启动命令过程

    一.启动命令过程日志 启动命令bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat.输入日志如下所示: root@MM ...

  5. tcp_tw_reuse、tcp_tw_recycle、tcp_fin_timeout参数介绍

    参数介绍 net.ipv4.tcp_tw_reuse = 1 表示开启重用.允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭: net.ipv4.tcp_tw_rec ...

  6. 韦东山freeRTOS系列教程之【第三章】任务管理

    目录 系列教程总目录 概述 3.1 基本概念 3.2 任务创建与删除 3.2.1 什么是任务 3.2.2 创建任务 3.2.3 示例1: 创建任务 3.2.4 示例2: 使用任务参数 3.2.5 任务 ...

  7. Java 数据类型的包装数据类型

    什么是包装数据类型 Java是一个面向对象的编程语言,但基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型. 集合框架里面需要存储对象,不能存储基本数据类型,所以需要存储包装 ...

  8. Java-Cookie客户端会话技术

    会话技术 会话:一次对话中包含多次请求和响应 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求间,共享数据 方式: 客户端会话技术:Cook ...

  9. SQL Thinking

    s2下半年我在内部有一次部门级别的技术分享会,以本文内容分享为主. 其实有很多人问过我相同的问题,遇到需要改写的慢sql,不知道怎么改,改好了以后也不知道等不等价?不等价了也不知道错在哪?这个要怎么破 ...

  10. [oeasy]python0074_修改字体背景颜色_background_color_背景色

    修改背景色 回忆上次内容 上次将asciiart和颜色一起来玩 7 种基本色 变化多端 不过到目前为止 改的 都是前景色 背景色可以修改吗? 重温参数 具体动手试试 print("\033[ ...