関連 http://qiita.com/7of9/items/c5e39a8c08ca7a6e5af6
UDP通信の相手ソフト
Raspberry Piで走らせておく。
/etc/local登録が楽 (http://qiita.com/7of9/items/46ae6752db57205fd5e7)
v0.3追加機能
以下を追加した
- preset
- キー設定をプリセットで用意
- 2種類から選択
- enable: UDP通信とキー転送の有効・無効化
- interval configuration
- UDP通信のインターバル
- 100msec/200/50
- 100msecぐらいがちょうどいいかも
code v0.3
Main.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <memory>
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
/*
v0.3 2016 Mar. 1
- add intervalTbl[] to change Timer->Interval for UDP communication
- add preset feature
v0.2 2016 Mar. 1
- add assignKeyCode()
- add keyItemString
- add isAlternateKey()
- add keyTbl[]
v0.1 2016 Apr 24
- recognize rising edge (push)
- receive inputs through UDP
*/
/*
Timer1Timer: 200msec interval
*/
static const int kNumInput = 6;
static bool preInputs[kNumInput] = { 0 };
#define VK_F (0x46)
static const uint8_t vkKeyTbl[] = {
// 0..4
VK_CONTROL,
VK_SPACE,
VK_SHIFT,
VK_BACK,
VK_RETURN,
// 5..
VK_DIVIDE,
VK_PRIOR, // PgUp
VK_NEXT, // PgDn
VK_LEFT, // cursor
VK_UP, // cursor
// 10..
VK_RIGHT, // cursor
VK_DOWN, // cursor
};
static const String keyItemString =
// 0..
L"CONTROL"
L",SPACE"
L",SHIFT"
L",BACKSPACE"
L",RETURN"
// 5..
L",/"
L",PgUp"
L",PgDn"
L",<-"
L",UP"
// 10..
L",->"
L",DOWN"
;
static const int8_t presets[2][kNumInput] =
{
{ // preset 1
0, // CONTROL
6, // PgUp
7, // PgDn
2, // SHIFT
3, // Backspace
4, // RETURN
},
{ // preset 2
0, // CONTROL
8, // <-
9, // UP
10, // ->
11, // DOWN
3, // Backspace
},
};
static const int8_t intervalTbl[] = {
100, // msec
200, // msec
50, // msec
};
static const String intervalString =
L"100msec"
L",200msec"
L",50msec"
;
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;
IdUDPClient1->Host = E_ipadr->Text;
IdUDPClient1->Port = 7002;
IdUDPClient1->Active = true;
IdUDPClient1->Send("foot\r\n");
Sleep(10);
Application->ProcessMessages();
DWORD start = GetTickCount();
DWORD elapsed;
AnsiString res = IdUDPClient1->ReceiveString(300);
elapsed = GetTickCount() - start;
procInput(res);
IdUDPClient1->Active = false;
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
static bool isAlternateKey(int8_t vkkey)
{
if (vkkey == VK_SHIFT || vkkey == VK_CONTROL) {
return true;
}
return false;
}
bool __fastcall TForm1::assignKeyCode(int SWidx, int8_t *dstPtr)
{
int itmidx = -1;
if (dstPtr == NULL) {
return false;
}
switch(SWidx) {
case 0:
itmidx = CB_KeyAssign1->ItemIndex;
break;
case 1:
itmidx = CB_KeyAssign2->ItemIndex;
break;
case 2:
itmidx = CB_KeyAssign3->ItemIndex;
break;
case 3:
itmidx = CB_KeyAssign4->ItemIndex;
break;
case 4:
itmidx = CB_KeyAssign5->ItemIndex;
break;
case 5:
itmidx = CB_KeyAssign6->ItemIndex;
break;
}
if (itmidx < 0) {
return false;
}
*dstPtr = vkKeyTbl[itmidx];
return true;
}
void __fastcall TForm1::procInput(String res)
{
if(res.Length() == 0) {
return;
}
std::unique_ptr<TStringList> line(new TStringList);
line->CommaText = res;
bool ins[kNumInput];
try {
for(int idx=0; idx < kNumInput; idx++) {
ins[idx] = !( (bool)line->Strings[idx+1].ToInt() );
}
} catch (...) {
}
CheckBox1->Checked = ins[0];
CheckBox2->Checked = ins[1];
CheckBox3->Checked = ins[2];
CheckBox4->Checked = ins[3];
CheckBox5->Checked = ins[4];
CheckBox6->Checked = ins[5];
int8_t kycd;
bool resOK;
for(int idx=0; idx < kNumInput; idx++) {
if (preInputs[idx] == ins[idx]) {
continue;
}
preInputs[idx] = ins[idx];
resOK = assignKeyCode(idx, &kycd);
if (resOK == false) {
continue;
}
if (ins[idx]) {
keybd_event(kycd, 0, 0, 0);
} else {
if (isAlternateKey(kycd)) {
keybd_event(kycd, 0, KEYEVENTF_KEYUP, 0);
}
}
}
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
CB_KeyAssign1->Items->CommaText = keyItemString;
CB_KeyAssign2->Items->CommaText = keyItemString;
CB_KeyAssign3->Items->CommaText = keyItemString;
CB_KeyAssign4->Items->CommaText = keyItemString;
CB_KeyAssign5->Items->CommaText = keyItemString;
CB_KeyAssign6->Items->CommaText = keyItemString;
CB_speed->Items->CommaText = intervalString;
}
//---------------------------------------------------------------------------
// preset2
void __fastcall TForm1::B_preset1Click(TObject *Sender)
{
int pridx = 0;
CB_KeyAssign1->ItemIndex = presets[pridx][0];
CB_KeyAssign2->ItemIndex = presets[pridx][1];
CB_KeyAssign3->ItemIndex = presets[pridx][2];
CB_KeyAssign4->ItemIndex = presets[pridx][3];
CB_KeyAssign5->ItemIndex = presets[pridx][4];
CB_KeyAssign6->ItemIndex = presets[pridx][5];
}
void __fastcall TForm1::B_preset2Click(TObject *Sender)
{
int pridx = 1;
CB_KeyAssign1->ItemIndex = presets[pridx][0];
CB_KeyAssign2->ItemIndex = presets[pridx][1];
CB_KeyAssign3->ItemIndex = presets[pridx][2];
CB_KeyAssign4->ItemIndex = presets[pridx][3];
CB_KeyAssign5->ItemIndex = presets[pridx][4];
CB_KeyAssign6->ItemIndex = presets[pridx][5];
}
//---------------------------------------------------------------------------
int __fastcall TForm1::getInterval_msec(int idx)
{
int maxsz = sizeof(intervalTbl) / sizeof(intervalTbl[0]);
if (idx < 0 || idx >= maxsz) {
return 200; // デフォルト値
}
int ret = intervalTbl[idx];
return ret;
}
void __fastcall TForm1::CHK_enableClick(TObject *Sender)
{
if (CHK_enable->Enabled) {
Timer1->Interval = getInterval_msec(CB_speed->ItemIndex);
Timer1->Enabled = true;
} else {
Timer1->Enabled = false;
}
}
//---------------------------------------------------------------------------
備考
この記事はフット入力と左手だけで準備した
作業効率が格段に良くなった。
しかしキー入力時にブラインドタッチできないのは少し不便
3倍早くなる赤色モードをどうするか。。。
左手だけでの高速入力機構を田川欣哉さんのタグタイプをベースに作る、という妄想を抱く。
http://www.ipa.go.jp/files/000005781.pdf