一括表示

入力 投稿者:  

あけましておめでとうございます。
いつもお世話になっております。3度目の投稿になります。

現在 CW自動交信プログラムの 32BIT版を WINDOWS XPの パソコン
で コンパイル アッセンブルして作って そのパソコンで実行す
るようにしています。次の質問をします。

パソコンのキーボードから 1文字入力する関数で 入力が有った
場合はその文字のコードを返し 入力が無かった場合は例えば 00H
を返してその関数を抜け出る様な関数は有るでしょうか。今は WIN
DOWS APIの CreateFileでコンソール入力の設定をして ReadFile
関数でやってみたのですが キーボード入力待ちで 止まってしま
って 思った通りの動作をしません。

16BIT版の時は MSDOSのファンクションコール( INT 21H )を使って
アッセンブラのプログラムで この動作をしていました。

もし わかる方がおられましたら教えて下さい。よろしくお願いしま
す。では さようなら

2008/01/01(Tue) 16:18:15  [No.37]


Re: 入力 補足 投稿者:  

> あけましておめでとうございます。
> いつもお世話になっております。3度目の投稿になります。
>
> 現在 CW自動交信プログラムの 32BIT版を WINDOWS XPの パソコン
> で コンパイル アッセンブルして作って そのパソコンで実行す
> るようにしています。次の質問をします。
>
> パソコンのキーボードから 1文字入力する関数で 入力が有った
> 場合はその文字のコードを返し 入力が無かった場合は例えば 00H
> を返してその関数を抜け出る様な関数は有るでしょうか。今は WIN
> DOWS APIの CreateFileでコンソール入力の設定をして ReadFile
> 関数でやってみたのですが キーボード入力待ちで 止まってしま
> って 思った通りの動作をしません。
>
> 16BIT版の時は MSDOSのファンクションコール( INT 21H )を使って
> アッセンブラのプログラムで この動作をしていました。
>
> もし わかる方がおられましたら教えて下さい。よろしくお願いしま
> す。では さようなら

パソコン NEC MT850/2 CLOCK 2.8GHZ OS WINDOWS XP HDD 500GB

使える ソフト ビジュアルC++2003.NET MASM VERSION 7.2
アッセンブラ C C++ が使えます。

よろしくおねがいします。

2008/01/01(Tue) 16:40:01  [No.38]


Re: 入力 補足 投稿者:JG1MOU浜田 

そのソフトはGUIですか?
だとすれば、メッセージループの中で、フォーカスのあるコントロール
上でキーボードが押されたことをチェックすればよろしいのでは?
WM_KEYDOWN など。

GUIではなくて、Windows-APIが使えるのであれば、GetKeyboardState()、GetAsyncKeyState()、GetKeyState()などでしょうか。

2008/01/02(Wed) 12:15:14  [No.39]


Re: 入力 補足 投稿者:  

> そのソフトはGUIですか?
> だとすれば、メッセージループの中で、フォーカスのあるコントロール
> 上でキーボードが押された> そのソフトはGUIですか?
> だとすれば、メッセージループの中で、フォーカスのあるコントロール
> 上でキーボードが押されたことをチェックすればよろしいのでは?
> WM_KEYDOWN など。
>
> GUIではなくて、Windows-APIが使えるのであれば、GetKeyboardState()、GetAsyncKeyState()、GetKeyState()などでしょうか。

JG1MOU 浜田OM ご回答有難うございます。LOG管理ではお世話になって
おります。GetKeState()関数は 特定の文字キーが押されたかどうか
チェックする為の関数だと マイクロソフトのホームページで調べて
その使い方も分かったのですが 自分の作った CW自動交信プログラム
に組み込んでやって見たのですが 決められた文字のキーを押してから
プログラムが GetKeyState()関数の所を通ると思った通りの動作をする
のですが その後キー押さないで居て 2度目に GetKeyState()関数の
所を通ると 最初に押された状態を記憶していて 最初に通った時と
同じ動作をしてしまうので 不都合が有るのですが KeyStateの状態
を クリア 解除するにはどういうコマンドを書けばいいのでしょう
か。もし分かりましたら教えて下さい。宜しくお願いします。
ではさようなら

ことをチェックすればよろしいのでは?
> WM_KEYDOWN など。
>
> GUIではなくて、Windows-APIが使えるのであれば、GetKeyboardState()、GetAsyncKeyState()、GetKeyState()などでしょうか。

2008/01/03(Thu) 22:55:35  [No.40]


ReRe: 入力 補足 投稿者:  



> > GUIではなくて、Windows-APIが使えるのであれば、GetKeyboardState()、GetAsyncKeyState()、GetKeyState()などでしょうか。
>
> JG1MOU 浜田OM ご回答有難うございます。LOG管理ではお世話になって
> おります。GetKeyState()関数は 特定の文字キーが押されたかどうか
> チェックする為の関数だと マイクロソフトのホームページで調べて
> その使い方も分かったのですが 自分の作った CW自動交信プログラム
> に組み込んでやって見たのですが 決められた文字のキーを押してから
> プログラムが GetKeyState()関数の所を通ると思った通りの動作をする
> のですが その後キー押さないで居て 2度目に GetKeyState()関数の
> 所を通ると 最初に押された状態を記憶していて 最初に通った時と
> 同じ動作をしてしまうので 不都合が有るのですが KeyStateの状態
> を クリア 解除するにはどういうコマンドを書けばいいのでしょう
> か。もし分かりましたら教えて下さい。宜しくお願いします。
> ではさようなら
>

JG1MOU 浜田OM いつも有難うございます。上記の件ですが 浜田OMが
教えてくれた GetAsyncKeyState()関数を 使ったら旨く動作しまし
た。もう1つ質問があります。上記の関数を使って キーを押すと
旨く動作はするのですが その情報が残っていて 他のキー入力画面
で その文字が表示されてしまうのですが キー入力した文字情報を
画面に表示しないで はきださせる 捨てる クリアーする方法はあ
るでしょうか。分かりましたら教えて下さい。宜しくおねがいします。では さようなら

2008/01/04(Fri) 11:33:15  [No.41]


ReRe: 入力 補足 投稿者:je6lao長野 

関数をもう一度呼び出せば、クリアされるようですけど。
よその掲示板では質問者が具体的なコードを示して、
それに対して回答者がアドバイスをするようです。
ここでもそれが望ましいと私は考えます。
回答者が無駄な推測をしなくてすみます。

以下、MSDNより

関数が成功すると、前回の GetAsyncKeyState 関数呼び出し以降にキーが押されたかどうか、およびキーが現在押されているかどうかを示す値が返ります。最上位ビットがセットされたときは現在そのキーが押されていることを示し、最下位ビットがセットされたときは前回の GetAsyncKeyState 関数呼び出し以降にそのキーが押されたことを示します。

2008/01/06(Sun) 20:47:07  [No.42]


ReRe: 入力 補足 投稿者:  

> 関数をもう一度呼び出せば、クリアされるようですけど。
> よその掲示板では質問者が具体的なコードを示して、
> それに対して回答者がアドバイスをするようです。
> ここでもそれが望ましいと私は考えます。
> 回答者が無駄な推測をしなくてすみます。
>
> 以下、MSDNより
>
> 関数が成功すると、前回の GetAsyncKeyState 関数呼び出し以降にキーが押されたかどうか、およ> 関数をもう一度呼び出せば、クリアされるようですけど。
> よその掲示板では質問者が具体的なコードを示して、
> それに対して回答者がアドバイスをするようです。
> ここでもそれが望ましいと私は考えます。
> 回答者が無駄な推測をしなくてすみます。
>
> 以下、MSDNより

ja6lao 長野OM アドバイス有難うございます。キー入力サブルーチン
のソースコードを送ります。なんの為にこのサブルーチンが必要かと
いうと CWのスピードを調整する為の変数の値を インクリメントや
デクリメント等の操作をするためです。交信中にキーを押すのでその時
画面には 送信や受信解読した文字が表示されているので押したキーの
文字が表示されないほうが良いのです。決められた特定の文字のキーが
押されたときの後プログラムがこのサブルーチンを実行するとその文字
のコードを返しそれ以外の文字のキーを押した時やキーを押さなかった
時は 00Hを返します。文字による機能は次の通りです。

A AUTO 自動調整    M MANUAL 手動調整
H スピード早く 変数のデクリメント
L スピード遅く 変数のインクリメント
E 送信又は受信の終わり

プログラム自体は WINDOWS XP の MSDOS 画面で動作します。

C++プログラムは次の通りです。


int CONINQ (void)


{
unsigned short b;

unsigned int c;

unsigned short mask = 0x8001;

c = (unsigned int)'A';

b = GetAsyncKeyState(c);

if ((b & mask)!= 0)

goto
endc;

else


{c = (unsigned int)'M';

b = GetAsyncKeyState(c);

if ((b & mask) != 0)

goto
endc;

else


{c = (unsigned int)'D';

b = GetAsyncKeyState(c);

if ((b & mask) != 0)

goto
endc;

else


{c = (unsigned int)'H';

b = GetAsyncKeyState(c);

if ((b & mask) != 0)

goto
endc;

else


{c = (unsigned int)'L';

b = GetAsyncKeyState(c);

if ((b & mask) != 0)

goto
endc;

else


{c = (unsigned int)'E';

b = GetAsyncKeyState(c);

if ((b & mask) != 0)

goto
endc;

else

c = 0; goto endc;
}
}}}}
endc:


return c;


}


上記の C++のプログラムをアッセンブルリストを出力するオプションで
コンパイルしたもの。

PUBLIC
_CONINQ



;
CONINQ
EXTRN
__imp__GetAsyncKeyState@4:NEAR;
Function compile flags: /Odt
_TEXT
SEGMENT
_c$ = -12




;
size = 4
_b$ = -8




;
size = 2
_mask$ = -4




;
size = 2
_CONINQ
PROC NEAR


;
CONINQ;
Line 145

push
ebp

mov
ebp, esp

sub
esp, 12



;
0000000cH;
Line 148

mov
WORD PTR _mask$[ebp], 32769
;
00008001H;
Line 149

mov
DWORD PTR _c$[ebp], 65

;
00000041H;
Line 150

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 151

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63352;
Line 152

jmp
$endc$63353
$L63352:;
Line 154

mov
DWORD PTR _c$[ebp], 77

;
0000004dH;
Line 155

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 156

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63357;
Line 157

jmp
$endc$63353
$L63357:;
Line 159

mov
DWORD PTR _c$[ebp], 68

;
00000044H;
Line 160

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 161

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63361;
Line 162

jmp
SHORT $endc$63353
$L63361:;
Line 164

mov
DWORD PTR _c$[ebp], 72

;
00000048H;
Line 165

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 166

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63365;
Line 167

jmp
SHORT $endc$63353
$L63365:;
Line 169

mov
DWORD PTR _c$[ebp], 76

;
0000004cH;
Line 170

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 171

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63369;
Line 172

jmp
SHORT $endc$63353
$L63369:;
Line 174

mov
DWORD PTR _c$[ebp], 69

;
00000045H;
Line 175

mov
eax, DWORD PTR _c$[ebp]

push
eax

call
DWORD PTR __imp__GetAsyncKeyState@4

mov
WORD PTR _b$[ebp], ax;
Line 176

movzx
ecx, WORD PTR _b$[ebp]

movzx
edx, WORD PTR _mask$[ebp]

and
ecx, edx

je
SHORT $L63373;
Line 177

jmp
SHORT $endc$63353
$L63373:;
Line 179

mov
DWORD PTR _c$[ebp], 0
$endc$63353:;
Line 183

mov
eax, DWORD PTR _c$[ebp];
Line 185

mov
esp, ebp

pop
ebp

ret
0
_CONINQ
ENDP



;
CONINQ
_TEXT
ENDS

どうぞ宜しくお願いします。ではさようなら

2008/01/07(Mon) 22:49:49  [No.43]


ReRe: 入力 補足 投稿者:JG1MOU浜田 

ループで処理すれば、もう少し簡単に記述できると思います。

int CONINQ (void)

{ int i, c;
char key1[] = {'A','M','D','H','L','E'};
for (i=0; i<6; i++)
{ c = (int)key1[i];
if (GetAsyncKeyState(c) & 0x8000)
return c;
}
return 0;
}

2008/01/08(Tue) 20:30:29  [No.44]


ReRe: 入力 補足 投稿者:je6lao長野 

キー入力のサブルーチンはわかりました。
このサブルーチンをどのようなタイミングで呼び出しているかが鍵だと思います。
下記はDelphiでのWindowsプログラムの一例です。
メインフォームには、Memo1とMomo2という窓があります。
F5のキーが押されたときに、フォーカスがある方に
文字fを追加します。
このコードをタイマーで繰り返し呼び出しています。
Memo1からMemo2にフォーカスを移したとき、
文字が余分にプリントされることはありませんでした。

MS-DOSとは考え方が異なるかもしれませんが、
少しでも参考になれば幸いです。

procedure TForm1.Timer1Timer(Sender: TObject);
var
f: integer;
begin
f := GetAsyncKeyState(VK_F5);

if f<>0 then
if Memo1.Focused then Memo1.Text := Memo1.Text + 'f'
else if Memo2.Focused then Memo2.Text := Memo2.Text + 'f';
end;

2008/01/08(Tue) 23:59:13  [No.45]


ReRe: 入力 補足 投稿者:  



JG1MOU 浜田OM je6lao 長野OM アドバイス有難うございます。
早速浜田OMのプログラムを コンパイルやアッセンブルして 動作を
確認しました。私の考えた C++のコードと 全く同じ動作をしました。
さすが 浜田OM 私の書いた説明を的確に理解されて プログラムの
サンプルのコードを書けるのは すばらしいとおもいます。長野OMも
いつもアドバイスありがとうございます。私の作った CW自動交信プロ
グラムのことで まだ2.3質問したい 事が有るのですが 日を
改めて したいと思います。
以下 プログラムのコードを送ります。


int CONINQ (void)

{ unsigned int c = 0,a = 0;
unsigned short mask = 0x8001;
int i,
char key1[] = {'A','M','D','H','L','E'};
for (i=0; i<6; i++)
{ c = (unsigned int)key1[i];
if ((GetAsyncKeyState(c)) & mask)
a = c;
}
return a;

}

上記の C++ のコードの MASM アッセンブリコード

PUBLIC _CONINQ ; CONINQ
EXTRN __imp__GetAsyncKeyState@4:NEAR;
Function compile flags: /Odt
_TEXT SEGMENT
_c$ = -40 ; size = 4
_mask$ = -36 ; size = 2
_key1$ = -32 ; size = 24
_i$ = -8 ; size = 4
_a$ = -4 ; size = 4
_CONINQ PROC NEAR ; CONINQ;
Line 145
push ebp
mov ebp, esp
sub esp, 40 ; 00000028H;
Line 146
mov DWORD PTR _c$[ebp], 0
mov DWORD PTR _a$[ebp], 0;
Line 147
mov WORD PTR _mask$[ebp], 32769 ; 00008001H;
Line 149
mov DWORD PTR _key1$[ebp], 65 ; 00000041H
mov DWORD PTR _key1$[ebp+4], 77 ; 0000004dH
mov DWORD PTR _key1$[ebp+8], 68 ; 00000044H
mov DWORD PTR _key1$[ebp+12], 72 ; 00000048H
mov DWORD PTR _key1$[ebp+16], 76 ; 0000004cH
mov DWORD PTR _key1$[ebp+20], 69 ;00000045H;
Line 150
mov DWORD PTR _i$[ebp], 0
jmp SHORT $L63353
$L63354:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$L63353:
cmp DWORD PTR _i$[ebp], 6
jge SHORT $L63355;
Line 151
mov ecx, DWORD PTR _i$[ebp]
mov edx, DWORD PTR _key1$[ebp+ecx*4]
mov DWORD PTR _c$[ebp], edx;
Line 152
mov eax, DWORD PTR _c$[ebp]
push eax
call DWORD PTR __imp__GetAsyncKeyState@4
movsx ecx, ax
movzx edx, WORD PTR _mask$[ebp]
and ecx, edx
je SHORT $L63357;
Line 153
mov eax, DWORD PTR _c$[ebp]
mov DWORD PTR _a$[ebp], eax
$L63357:;
Line 154
jmp SHORT $L63354
$L63355:;
Line 155
mov eax, DWORD PTR _a$[ebp];
Line 157
mov esp, ebp
pop ebp
ret 0
_CONINQ ENDP ; CONINQ
_TEXT ENDS

では さようなら

2008/01/10(Thu) 00:40:49  [No.46]


ReRe: 入力 補足 投稿者:JG1MOU浜田 

> さすが 浜田OM 私の書いた説明を的確に理解されて プログラムの

恐縮です。hi

> 以下 プログラムのコードを送ります。

私のプログラミング流儀、アマチュアなので、あくまでも我流ですが・・・

unsigned int c = 0
ですが、ループの中で必ず変数 c には代入されますので、宣言時にも
代入する必要は無いと思います。生成されるコードの効率化のため。

unsigned short mask = 0x8001;
一度しか代入しない変数は、定数にすべきと考えております。
#define MASK 0x8001;
その方が効率の良いコードが生成されるはずです。
吐き出されたアセンブリコードを見ても、変数の内容をいったんレジスタに
コピーしてからアンドをとってますので、定数にすれば直接いけるのではないでしょうか?

それから、GetAsyncKeyState() の引数は符号付き整数ですので、変数
c は int型で宣言しないとコンパイル時に警告が出るのではないでしょうか?

最近、あまりC言語やらないので、ちょっと自身がないところもありますけど。
では、がんばってください。

2008/01/10(Thu) 22:53:07  [No.47]


ReReRe: 入力 補足 投稿者:  

JG1MOU 浜田OM アドバイス有難うございます。浜田OMの言うとおりだと
思います。アッセンブラとの出会いは 東京 蒲田に有りました 日本
電子工学院と言う学校で コンピューターハードウェアコースという学
科で 習ったのが最初です。コンピューターの機械の勉強をしたのです
が 習った言語は アセンブラが主体で COBOL や FORTRANの簡単なプ
ログラムも勉強しました。私はそのコースの 一期生です。
学校を卒業してから 2年間通信関係の会社に就職して 回路の設計の様な仕事をしていたのですが退社してその後コンピューターとは関係の
ない仕事をしています。30年位前に NEC より TK-80 と言うマイコン
キットが出たときに買って 組み立てて プログラム入力して 遊んで
いるうちに 学校で習った アセンブラを思い出しました。現在は Z-
80 や PIC 等の CPU で遊んでいます。
私は 趣味でプログラムを組んで居ますので 冗長なコードを書くくせ
が有ります。直せる所は直していきたいと思いますので 宜しくお願い
します。いつもお世話になります。ではさようなら

2008/01/11(Fri) 23:24:08  [No.48]