フット入力 > Winソフト(v0.3) > preset / enable / interval configuration

関連 http://qiita.com/7of9/items/c5e39a8c08ca7a6e5af6

## UDP通信の相手ソフト

http://qiita.com/7of9/items/faae2a627443ff137c84

Raspberry Piで走らせておく。
/etc/local登録が楽 (http://qiita.com/7of9/items/46ae6752db57205fd5e7)


## v0.3追加機能

以下を追加した

- preset
  - キー設定をプリセットで用意
  - ２種類から選択
- enable: UDP通信とキー転送の有効・無効化
- interval configuration
  - UDP通信のインターバル
  - 100msec/200/50
  - 100msecぐらいがちょうどいいかも

![qiita1.png](https://qiita-image-store.s3.amazonaws.com/0/32870/192a818a-811c-17a5-2957-5e319dfc64f5.png)

![qiita2.png](https://qiita-image-store.s3.amazonaws.com/0/32870/630c6cf6-69bc-4c15-5e53-11846aa3a1ad.png)

## 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;
    }
}
//---------------------------------------------------------------------------

```

## 備考

この記事はフット入力と左手だけで準備した

作業効率が格段に良くなった。

しかしキー入力時にブラインドタッチできないのは少し不便

３倍早くなる赤色モードをどうするか。。。

左手だけでの高速入力機構を田川欣哉さんのタグタイプをベースに作る、という妄想を抱く。
http://www.ipa.go.jp/files/000005781.pdf