Win10 / Win11 系統自帶的微軟五筆潔方便流暢,兼容性好,干凈無廣告,無疑已成為最受歡迎的形碼輸入法之一。
使用免費開源軟件 WubiLex (僅 810 KB)可以替換微軟五筆的系統碼表、短語詞庫。WubiLex 已自帶五筆86、98、091、新世紀、小鶴音形、鄭碼、表形碼 …… 等碼表。
WubiLex 也支持一鍵智能造詞 —— 利用空碼自動補全流行詞,這通常可以添加十幾萬的流行詞。再也不用手動加詞了。
WubiLex 可以兼容很多的碼表格式,例如詞前碼后、碼前詞后,一碼一行,一行多碼等等。可以導入導出CSV、JSON、以及LZMA壓縮格式碼表。
WubiLex 也支持直接編輯五筆短語詞庫,并擴展了微軟五筆短語的功能,兼容各種短語詞庫格式,支持方便的自定義特殊字符數組。
WubiLex 提供了方便的反查拆字功能。按 Ctrl + F2 反查五筆編碼,再Ctrl + F2 回到原來窗口不影響繼續輸入。反查可顯示詳細的拆字圖解(五筆反查不僅支持單字,也可以支持詞組)。
反查時可通過虛擬鍵盤準確顯示按鍵方位,鼠標懸停在虛擬鍵上可顯示單鍵字根圖。
我們一般看到的五筆字根圖都是包含所有按鍵字根的全圖,但是這種字根圖會讓人眼花繚亂,如果我們的眼睛看到的內容越多,記憶效率就會越低。所以我制作了這種簡潔版的虛擬鍵盤。
WubiLex 還提供了強大的「超級熱鍵」功能( ImTip 也支持超級熱鍵 ),可以用于擴展輸入法功能,例如輸入數字后自動將句號轉換為小數點,輸入大寫中文數字的中文日期等等。
例如按超級熱鍵 Ctrl+$ 打開財務大寫、日期時間大寫、數學運算工具。
超級熱鍵可以做的事很多。
請參考教程:超級熱鍵:一學就會簡單編程,提升 Windows 效率
例如輸入法糾錯熱鍵 —— 已輸出英文自動轉為中文輸入:
["Ctrl+,"] = function(hFocus){
var openState,mode = key.ime.state();
if( openState && !key.ime.capital() ) return true; //當前已經是中文輸入模式,不改變默認行為
key.up("Ctrl");//先放開 Ctrl 鍵
//如果是大寫狀態,切換為小寫
if(key.ime.capital()) key.press("CAPSLK")
//英文直接切中文 + 中文標點
key.ime.setOpenStatus(true); //打開輸入法
key.ime.setConversionMode(1|0x400); //切換到中文狀態,這一步不能省略
//再次嘗試用鍵盤切換中文標點,這一步不能省略
key.combine("CTRL",".");
//現在再次檢測中文標點狀態
var openState,mode = key.ime.state();
if(mode!=3/*_IME_SYMBOLMODE_SYMBOL*/){
//說明切換到了英文標點,再切換回去
key.combine("CTRL",".")
}
//通過返回函數異步執行耗時操作(避免系統刪除熱鍵鉤子)
return function(){
key.combine("SHIFT","HOME");//選中當前行
key.combine("CTRL","C");//復制當前行
var line = win.clip.read(); //讀取剪貼板文本
var str = string.match(line,"[a-zA-Z]+$"); //查找尾部連續字母
key.press("RIGHT");//按右方向鍵,取消選區
//如果字符串非空
if(#str){
key.repeat("BACK",#str);//按退格鍵指定次數(取字符串長度)
key.send(str);//字符串轉換為發送按鍵
//key.press("SPACE");//發果需要按空格,請取消前面的注釋符號
}
};
};
WubiLex 還可以快捷開關、切換英文鍵盤、微軟五筆、微軟拼音,并可方便地切換微軟雙拼方案。如果小鶴雙拼方案未安裝仍然會出現在雙拼候選列表中 —— 勾選即可自動安裝。
一、背景
二、WinPcap中文技術文檔
http://www.ferrisxu.com/WinPcap/html/index.html
二、需要使用到的動態庫和外部頭文件
① 庫文件:Packet.dll、Packet.lib、wpcap.dll、wpcap.lib
② 頭文件
三、用vs創建工程(我這里使用的是vs2015)
工程創建完畢需要配置工程屬性
① 右鍵工程屬性-->VC++目錄-->找到包含目錄、庫目錄,把剛才的庫文件路徑和頭文件的路徑添加進去,如下圖所示
② 找到鏈接器--->附加依賴項,添加Packet.lib、wpcap.lib庫文件
四、示例代碼
① 頭文件
/***************************************************************************** * *
* @file RawEtherSniffer.h *
* @brief 通過原始以太網解析FPGA發送的數據 *
* Details. *
* *
* @author jiang shuang *
* @email *
* @version 1.0.0.0(版本號) *
* @date *
* @license *
* *
*----------------------------------------------------------------------------*
* Remark : Description *
*----------------------------------------------------------------------------*
* Change History : *
* <Date> | <Version> | <Author> | <Description> *
*----------------------------------------------------------------------------*
* 2019/09/10 | 1.0.0.0 | jiangshuang | Create file *
*----------------------------------------------------------------------------*
* *
*****************************************************************************/
#pragma once
#define WIN32
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
class RawEtherTools
{
public:
RawEtherTools();
~RawEtherTools();
/**
* @brief 以太網數據數據幀嗅探器
* @input 無
* @output 無
* @return 無
*/
void CaptureRawEtherFrame();
int ethernet_protocol_packet_handle(u_char *argument,
const struct pcap_pkthdr *packet_header,
const u_char *packet_content);
};
② cpp文件
#define _CRT_SECURE_NO_WARNINGS
#include "Tools.h"
using namespace std;
// 以太網協議格式的定義
typedef struct ether_header {
u_char ether_dhost[6]; // 目標MAC地址
u_char ether_shost[6]; // 源MAC地址
u_short ether_type; // 以太網類型
}ether_header;
// 用戶保存4字節的IP地址
typedef struct ip_address {
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}ip_address;
// 用于保存IPV4的首部
typedef struct ip_header {
#ifdef WORDS_BIGENDIAN
u_char ip_version : 4, header_length : 4;
#else
u_char header_length : 4, ip_version : 4;
#endif
u_char ver_ihl; // 版本以及首部長度,各4位
u_char tos; // 服務質量
u_short tlen; // 總長度
u_short identification; // 身份識別
u_short offset; // 分組偏移
u_char ttl; // 生命周期
u_char proto; // 協議類型
u_short checksum; // 包頭測驗碼
ip_address saddr; // 源IP地址
ip_address daddr; // 目的IP地址
u_int op_pad; // 可選 填充字段
}ip_header;
RawEtherTools::RawEtherTools()
{
}
RawEtherTools::~RawEtherTools()
{
}
/**
* @brief
* @input 無
* @output 無
* @return 無
*/
void RawEtherTools::CaptureRawEtherFrame()
{
struct pcap_pkthdr *header;
pcap_if_t * allDevs;
pcap_if_t * dev;
u_int netmask;
int inum;
int i = 0;
int res;
const u_char *pkt_data;
time_t local_tv_sec;
struct tm *ltime;
char timestr[16];
ip_header *ih;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &allDevs, errbuf) > 0)
{
printf("pcap_findallDevs_ex failed\n");
}
for (dev = allDevs; dev; dev = dev->next) {
printf("%d. %s", ++i, dev->name);
if (dev->description) {
printf("(%s)\n", dev->description);
}
else {
printf("No description available\n");
}
}
if (0 == i) {
printf("\nNo interface found!Make sure WinPcap is installed\n");
return;
}
printf("Enter the interface number(1-%d):", i);
scanf_s("%d", &inum);
if (inum < 1 || inum > i) {
printf("\nInterface number out of range.\n");
pcap_freealldevs(allDevs);
return;
}
for (dev = allDevs, i = 0; i < inum - 1; dev = dev->next, i++);
pcap_t * handler;
// 設備名,要捕捉的數據包的部分(65536保證能捕獲到不同數據鏈路層上的每個數據包的全部內容),混雜模式,讀取超時時間,錯誤緩沖池
if ((handler = pcap_open_live(dev->name, 65536, 1, 1000, errbuf)) == NULL) {
fprintf(stderr, "\nUnable to open the adapter.%s is not supported by WinPcap\n", errbuf);
pcap_freealldevs(allDevs);
return;
}
// 檢查數據鏈路層(只考慮了以太網)
if (pcap_datalink(handler) != DLT_EN10MB) {
fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
pcap_freealldevs(allDevs);
return;
}
if (dev->addresses != NULL) {
// 獲得接口的第一個地址的掩碼
netmask = ((struct sockaddr_in*)(dev->addresses->netmask))->sin_addr.S_un.S_addr;
}
else {
netmask = 0xffffff;
}
while ((res = pcap_next_ex(handler, &header, &pkt_data)) >= 0)
{
// 請求超時
if (0 == res) {
continue;
}
// 分析數據包
int ret = ethernet_protocol_packet_handle(NULL, header, pkt_data);
if (ret == -1)
continue;
// 將時間戳轉換成可識別的格式
local_tv_sec = header->ts.tv_sec;
ltime = localtime(&local_tv_sec);
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
ih = (ip_header *)(pkt_data + 14); //以太網頭部長度
// 輸出時間和IP信息
//printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len);
printf(" len:%d ", header->len);
printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
printf("%02x%02x%02x%02x -> %02x%02x%02x%02x\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
//輸出每個包的byte數據ws2_32.lib
for (int k = 0; k < header->len; k++)
{
if (k % 16 == 0 && k != 0)//輸出美觀
printf("\n");
printf("%02x ", *(pkt_data + k));
}
printf("\n");
}
if (-1 == res) {
printf("Error reading the packet:%s\n", pcap_geterr(handler));
return;
}
pcap_freealldevs(allDevs);
}
/**
* @brief 抓取以太網協議包
* @input 無
* @output 無
* @return 無
*/
int RawEtherTools::ethernet_protocol_packet_handle(u_char *argument,
const struct pcap_pkthdr *packet_header,
const u_char *packet_content)
{
u_short ethernet_type; // 以太網類型
struct ether_header *ethernet_protocol; // 以太網協議變量
u_char *mac_string; // 以太網地址
ethernet_protocol = (struct ether_header*)packet_content;// 獲取以太網數據內容
ethernet_type = ntohs(ethernet_protocol->ether_type); // 獲取以太網類型
if (ethernet_type != 0x00FF)
{
return -1;
}
printf("Ethernet type is : %04x\n", ethernet_type);
// 獲取以太網源地址
mac_string = ethernet_protocol->ether_shost;
printf(" MAC Source Address is === %02x:%02x:%02x:%02x:%02x:%02x",
*mac_string,
*(mac_string + 1),
*(mac_string + 2),
*(mac_string + 3),
*(mac_string + 4),
*(mac_string + 5)
);
// 獲取以太網目的地址
mac_string = ethernet_protocol->ether_dhost;
printf(" MAC Target Address === %02x:%02x:%02x:%02x:%02x:%02x\n",
*mac_string,
*(mac_string + 1),
*(mac_string + 2),
*(mac_string + 3),
*(mac_string + 4),
*(mac_string + 5)
);
printf("%d", sizeof(packet_content));
return 0;
}
③ Main.cpp
#include <iostream>
#include "Tools.h"
using namespace std;
int main()
{
RawEtherTools *raw = new RawEtherTools();
raw->CaptureRawEtherFrame();
system("pause");
return 0;
}
五、編譯程序
① 錯誤1 編譯程序報錯,如下圖所示
解決辦法:
ws2_32.lib文件,提供了對以下網絡相關API的支持,若使用其中的API,則應該將ws2_32.lib加入工程
在工程屬性--->鏈接器--->附加依賴項,添加ws2_32.lib庫文件
② 錯誤2 編譯程序報錯,如下圖所示
解決辦法:
1.error C3861: “pcap_findalldevs_ex”: 找不到標識符
2.error C2065: “PCAP_SRC_IF_STRING”: 未聲明的標識符
在WinPcap編程調試解決辦法 中,需要項目屬性-》配置屬性-》C/C++-》預處理器-》預處理器定義中添加HAVE_REMOTE,方可編譯成功。