.
================================================
FILE: README.md
================================================
# lakey
Lakey, a CW training tool.
Lakey是一款摩尔斯电码发报练习软件,具有摩尔斯电码解析、音频频谱分析、摩尔斯电码听抄练习、可进行多主机网络通联练习或试验等特点。

常见问题临时解决方案:
如果在Win7、Win8、Win10及以后版本的Windows上,包括32位和64位系统,遇到打开报错的问题,可以尝试检查是否打开了音频输入设备,一般插一个麦克风就好了。
制作思想:
- 简单至上,开箱即用,无需设置,简单直观。
- 最小依赖,仅依赖操作系统自带库。
- 短小精悍,体量仅200多KB。
- 共同进步,完全开源。
主要特性:
- 利用键盘或鼠标进行摩尔斯电码发报练习,支持键盘直接录入,支持手键和自动键方式;
- 摩尔斯电码听抄练习,可以将听抄音频转换为WAV文件,用于通过手机或其他移动设备进行听抄练习;
- 摩尔斯电码解析,可以用做发报练习参考;
- 音频频谱分析,可以对电脑音频模拟输入(Line in、Aux in或Mic in等)进行音频分析并显示;
- 发报键状态可以输出到计算机I/O接口,对外围设备进行简单控制;
- 可进行多主机网络通联练习或试验。
本软件的目标是设计成一个使用简便,能够尽量利用一般PC本身具有的硬件功能和性能(主要指CPU的运算和声卡的音频捕捉/播放能力), 实现不用另接特殊外围接口电路,不用改/加装电键等,即可让PC具有摩尔斯电码(Morse Code)的收发能力软件。未来可逐渐通过对PC硬件性能的挖掘, 实现对音频信号进行分析、过滤、处理。
从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号。 如2.0版本被赋予Zongzi(粽子)这个代号。但应该说明,Lakey项目本身将继续立足于实验目的,因此作者并不保证所有功能都是完美可用的, 即所有版本可能都带有BETA测试版本的意味,这点请大家使用时务必注意。 同时希望大家继续多提意见,帮助作者不断完善Lakey。这点在对以往版本的改进过程中已经被证实是最为重要的手段。在此感谢所有提出过意见或建议的朋友们!
================================================
FILE: bin/Lakey.v2.1.build.0019.Pencil/lakey.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=93,18,1013,454
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,Pause,Continue
sendfile=500,265,91,16,0075,File...
autokeyswitch=706,265,91,16,0009,Manual,Auto(L/R),Auto(R/L)
noiseswitch=809,265,91,16,0076,Disturb
sendvol=500,168,90,90,-80.000000,0.000000,0.000000,Volumn(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,Disturb(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,Speed(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,1.875000,Spectrogram(dB)
[KOCH]
charlist=
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0
================================================
FILE: bin/Lakey.v2.1.build.0019.Pencil/lakey_ZH.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=224,104,1144,540
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,ͣ,
sendfile=500,265,91,16,0075,ļ...
autokeyswitch=706,265,91,16,0009,ֶ,Զ(/),Զ(/)
noiseswitch=809,265,91,16,0076,
sendvol=500,168,90,90,-80.000000,0.000000,-15.312500,(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,ٶ(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,55.781250,Ƶ(dB)
[KOCH]
charlist=KMRSUAPTLOWI.NJEF0Y,VG5/Q9ZH38B?427C1D6X
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
)=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0
================================================
FILE: doc/index.html
================================================
Lakey 2.1 Pencil (Build 0019) - CW/摩尔斯码/发报/收报/练习/音频分析/联网(CW, Morse code, Sending, Receiving, Training, Analyzing, Networking)
Lakey 2.1 Pencil (Build 0019) - 使用手册
CW/摩尔斯码/发报/收报/练习/音频分析/联网
永久开源、免费!
最新下载(2012/6/30):
[运行程序 ]
[使用手册 ]
[源代码 ]
版本: 2.1.0019(Pencil)
作者: BG1VLZ
目录
Lakey这是一个多功能且完全免费的CW练习/收/发软件,供大家学习研究,有需要源码的朋友可以访问Lakey的主页www.lakey.cn 下载
(目前原域名: www.layala.org将继续使用),
由于该主机使用动态DNS访问一台非固定IP主机, 并不能保证100% 7x24小时运行, 如果不能下载, 请给我发邮件或加为MSN索取(idirect3d@hotmail.com)。
不便之处望朋友们谅解。在未来,我会不断改进其功能和修正错误。
最新的开发进展
v2.1(Pencil)
(1)实现了由BA3CE建议的发送练习功能,并能够将练习时发送的文本记录下来;
(2)新增加的频谱显示将频率坐标轴方向反向,即频率较低的数据显示在靠下的位置;
v2.0(Zongzi)
(1)响应众多HAM朋友的意见,同时也是对过去Lakey功能缺陷的弥补,修正了自动键功能(感谢BG8ST及其他提出了此问题但没有留下呼号的朋友);
(2)修正了“/”符号的Morse编码错误(感谢BD1GXH);
(3)引入FFT算法;
(4)增加了频率域与时间域相结合的频谱分析显示功能。应该说,此功能是本次Lakey的最大功能升级。
它可以将混杂在实际嘈杂电波中的CW信号明显的“标记”出来,从而帮助接受者通过眼睛来识别Morse编码。
该功能的灵感来源于Foobar2000这款音乐播放软件的频谱分析功能。
本软件的目标是设计成一个使用简便,能够尽量利用一般PC本身具有的硬件功能和性能(主要指CPU的运算和声卡的音频捕捉/播放能力),
实现不用另接特殊外围接口电路,不用改/加装电键等,即可让PC具有摩尔斯电码(Morse Code)的收发能力软件。未来可逐渐通过对PC硬件性能的挖掘,
实现对音频信号进行分析、过滤、处理。
从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号。
如2.0版本被赋予Zongzi(粽子)这个代号。但应该说明,Lakey项目本身将继续立足于实验目的,因此作者并不保证所有功能都是完美可用的,
即所有版本可能都带有BETA测试版本的意味,这点请大家使用时务必注意。
同时希望大家继续多提意见,帮助作者不断完善Lakey。这点在对以往版本的改进过程中已经被证实是最为重要的手段。在此感谢所有提出过意见或建议的朋友们!
支持虚拟自动键和手键发送方式。
支持多台计算机通过网络,实时进行CW通联和练习。
支持对音频信号的频率域、时间域的单独和组合分析显示。
利用PC声卡的音频捕捉播放功能,实现摩尔斯电码的收/发。收报时可自动实现摩尔斯电码到字母/数字的翻译转换;
发报时可以选择采用手工CW或者直接键入字母/数字两种方式。
手工方式可以使用键盘按键或者鼠标按键作为电键。也就是说,一台电脑通过普通音频连接线连接到普通发射/接收设备即可实现CW通信或练习。
通过并口、串口或其它以I/O地址寻址的计算机接口,实现了对外部发信机的简单发射控制。
生成任意抄报练习音频文件,可以放到手机等便携设备方便随时练习。
支持发送练习。
软件界面从上到下大体分为4部分,如下图所示:
英文模式(缺省)
中文模式(使用Lakey_zh.ini)
后面章节将对这些部分分别介绍。以上两种界面模式,可通过将不同.ini文件复制为Lakey.ini文件来实现。
首先要把收信机的音频输出接到PC的音频输入口,如:Line in, Aux in, CD audio in等等。由于软件使用单声道处理,而一般这些接口都为双声道,因此最好将两个声道并联后接收信机的单声道输出。
将操作系统的录音来源选择为接入的接口,如果来源选择不对将不能实现收报的摩尔斯码翻译。Windows的录音来源可进入[控制面板->声音和音频设备]中进行选择,如下图:
在上面的窗口中点击录音栏中的[音量…]按钮
在这里选择接入接收机音频输出信号的接口
完成上面的步骤,就可以收报了。收报信息中包括输入音频的波形、简单频谱分析、CW点记录和翻译后的的字符。
使用鼠标左键和右键点击频谱分析控件可以分别改变波形幅度和频谱分析坐标系(线性/对数)。
要注意的是,在录音控制界面中,应尽量调整输入接口的电平,使软件显示的波形振幅尽量大且没有削波失真。
从Lakey2.0版本(Zongzi)开始,新增加了结合频率、时间、分布能量显示的综合频谱图。
这个功能,可以帮助收报者,从嘈杂的无线电环境中发现和辨别有规律CW信号。
在Lakey界面右上方新增加的这个频谱图形中,横轴为时间域(不断滚动),纵轴为频率域(CW“音频”波长),
某一点的亮度为某一时刻某一频点的振幅(可以理解音量或者能量)。
这里需要注意的是,在靠下方显示的是收信机输出音频频率较低的信号。
同一个电台的CW信号通过收信机输出后的音频信号,一般为一个固定频率,
在频谱显示时一般会体现在一条直线上。因此使用者可以通过寻找同一水平线上有规律的间断线段来识别一个电台。
而通过不同水平线也可以用来区分不同电台的信号。
使用者可通过调节频谱增益旋钮(Spectrogram)来调节频率显示增益(亮度),以实现最佳的显示效果
这里需要提醒使用者的是,实际的显示和使用效果,
与收信机接收信号质量/输出电平、计算机的录音端口增益设置、Lakey的采样数量设置(设置页面)、
Lakey的频谱增益设置(主界面Spectrogram旋钮)等都有直接或关联的关系,
组合调整这些设置使信号与背景噪音能够获得一个比较好的显示对比度,让收报者能够比较容易的辨别CW信号,
这通常需要充分利用收信机、计算机声卡以及数字处理程序的动态范围。
而这也许需要一点点耐心。
在未来,Lakey会不断完善频谱分析功能,适时推出计算机自动识别CW信号功能,甚至有可能实现多电台的自动识别和自动应答。
如果您在这方面有好的想法,可以联系我,作者在此先表示感谢!
发报主要分以下四种方式:
首先需要点击发送模式按钮,调整到“Manual”模式(缺省),然后使用鼠标键点击“CW”按钮模拟手键发报,也可以使用键盘中的[Enter]键模拟手键发报。Lakey在按下按键时会发出声音,抬起时关闭声音,同时会在发送窗口显示键击记录,并试图用摩尔斯电码翻译为字符、数字或标点。不能翻译的部分显示为‘#’。
首先需要点击发送模式按钮,调整到“Auto”模式,然后使用鼠标左/右键点击“CW”按钮模拟自动键发报。自动键有L/R和R/L两种模式(di/da),可以按照使用者习惯进行调整。与手动键一样,Lakey会对发送的信号进行翻译。
直接敲击键盘上的字母或数字键,系统将自动把键入的信息转换成摩尔斯电码,并输出到发送队列;同时,在发报信息的最下部会显示这个发送队列。
点击[File…]按钮,打开一个要发送的文件。系统将把打开文件中符合摩尔斯电码的字符内容发送到4.2中介绍的发送队列。
其他关于发报的主题:
音频连接方式
这种方式适用于当使用非CW方式发射模式时,如使用FM方式搭载摩尔斯音频信号的方式。现在在U/V段已经有利用这种方式进行摩尔斯收发练习的HAM,如北京的144.650MHz。
如果需要将音频摩尔斯电码发送到发信机,只需将PC的音频输出接到发信机的音频输入端口即可。
并口连接方式
这种方式适用于当使用标准CW方式发射模式时。当使用鼠标、键盘进行击发,或者键盘字符输入、文本文件输入时,通过并口的某一个针脚的电平来控制CW发信机起停,从而代替传统电键进行CW发射。其中,并口输出针脚电平规则可以通过设置界面随意调整。祥见:端口控制
并口具体针脚定义如下:
针脚序号 说明
1 STROBE 选通
2-9 DATA0-DATA7 数据0-7
10 ACKNLG 确认
11 BUSY 忙
12 PE 缺纸
13 SLCT 选择
14 AUTO FEED 自动换行
15 ERROR 错误
16 INIT 初始化
17 SLCT IN 选择输入
18-25 GND 地线
点击[Pause]按钮可以暂停发送发送队列中的内容。再按[Continue]继续发送。这里需要说明的是,在暂停时仍可使用直接CW键击发报。
Lakey现在可以支持网络通联,如果您希望与另一个HAM通过网络进行通联,那么需要进行以下两步操作:1、启用网络通联功能(参见:网络 );2、了解对方的IP地址,并且在网络 参数中,将对方IP地址添加到主机列表中。设置好以上两步,您所发送的摩尔斯电码将通过网络传送到对方主机,并通过扬声器和显示器传达给对方。
从菜单 - 工具->设置 可以进入配置界面:
在这里可以对系统用到的大多数参数进行调整
下面是这些对这些参数的详细说明:
"滴"声长(ms): 摩尔斯电码中的短鸣声。
"哒"声长度(ms): 摩尔斯电码中的长鸣声。
键击间隔(ms): 在一个字符电码中按键的间隔。
字符间隔(ms): 字符与字符之间的延迟时间。
键速(wps): 按标准单词长度(1 word = “PARIS”),计算的发报速度。
上面的规则即适用于发送,也适用于接收分析。应适当调整,以适应自身习惯和接收信号的特点。
音调(Hz): CW发送的嘀嗒声基准频率;缺省值,1KHz
音量(0~1): CW发送的嘀嗒声音量。这里实际调整的是生成波形的振幅比例,1为最大,0为最小。具体输出音量也可以通过操作系统的“音量控制”来调节; 缺省值, 0.250000
采样间隔(ms): 对CW发送内容的采样间隔,适当提高采样间隔可以提高对发送内容分析精度。
空闲停止(ms): 当一定时间无输出时,停止记录,避免过多空白出现。
CW键: 这里是一个CW键的Win32键盘代码(Win32 Virtual key code),下面列出几个常用键代码:
空格延迟(ms): 空格延迟时间长度。
采样数量: 每次分析接收音频的采样点数量,数值约大,精度约高;可以参考下面的规则:
但要注意的是,过多的采样数量会过多的消耗CPU资源,有可能造成对其他功能的影响!经测试,使用Intel(R) Core(TM)2 Duo T6670@2.2GHz,采样数量设定为256时,CPU占用率小于20%,平均为15%左右。
采样间隔(ms): 对CW接收内容的采样间隔;从b0017版开始,此数值已经不对接收内容分析精度有任何影响,而只影响分析的实时性。
空闲停止(ms): 当一定时间无接收内容时,停止记录,避免过多空白出现。
阀值电平(0~1): 只有大于这个输入电平的音频信号才被当作是摩尔斯电码信号进行分析。
起始频率(Hz) 和 截止频率(Hz): 只有大于起始频率和小于截止频率的信号分量才参与摩尔斯电码信号分析。这样可以起到过滤杂波的作用。接收的CW音频信号频率应该包含在起始频率至截止频率这个范围内,但要注意的是,这个范围不应过小,应该保持在200Hz以上。这个可以从介绍“采样数量”时提到的公式得到,如果过小的范围,将有可能不被包含在最小分析区间!
字符集: 指定在练习模式或生成的练习音频文件中使用的字符。字符可以重复,出现次数多的字符在练习时出现的概率也相应增加。
字长度: 指定在练习模式或生成的练习音频文件中多少字符为一组,组与组之间使用相当于空格延迟时间长度的空白分开。
本地端口: 用于网络通讯的SOCKET端口,UDP类型。
启用网络: 是否允许Lakey通过网络进行发送和接收操作。
主机 - IP/端口/列表: 录入对方主机IP地址和端口,点击右边的“添加”按钮,可以将录入的主机加入静态主机列表,在列表中的主机将能接收到您发送的摩尔斯信号。
地址(HEX): 外部设备连接到计算机上端口的内部地址。如:打印端口通常为16进制的0378(默认)。为安全起见,此参数不能在此处修改。如有特别需要,可以调整Lakey.ini中的extportaddr属性值。
开启(HEX): 相当于电键按下时端口的输出状态。
关闭(HEX): 相当于电键抬起时端口的输出状态。
上面的开启和关闭两个参数,对应端口的输出数据;如:当设置为01时,相应设置状态下的输出为16进制的01,对于0378并口来讲,就是2针(D0)为高电平,3-9针(D1-D7)为低电平。
由于软件还处于测试期间,并未对参数进行合法性检查,如果不适当的调整参数,有可能造成软件不能启动。如果发生这种问题,可以把运行目录中的Lakey.ini文件删除,软件即可按照缺省参数启动。
Lakey可以在不使用外围电路的情况下,由键盘或鼠标键击发出di dah声,来练习发报,祥见:
发报
从菜单 - 工具->Koch训练法或者使用快捷键[Ctrl+K]都可以启动Koch模式练习功能。
启动时系统会提示如下图所示的对话框:
点击[确定]按钮或按[回车]键,系统弹出抄录栏,同时开始自动发报,正式开始Koch模式练习。抄录栏如下图所示:
训练过程中,错码会用红色标出,并在窗口下部的统计栏内显示统计实时信息,供练习者参考。如下图所示。
抄录中途可以通过点击[完成]按钮来结束训练模式。再点击[关闭]按钮退出Koch训练模式。也可以点击[ESC]键直接退出训练模式。
从菜单 - 工具->生成CW音频文件。
从这里可以生成任意字符的音频文件。
从菜单 - 工具->生成Koch音频文件。
从这里可以使用配置在参数调整 中练习里的字符集,生成随机序列的音频文件。
从菜单 - 工具->发报练习。
Lakey会提示你选择一个文本文件,这个文件应含有报底文本。选择好文件后,您就可以开始发报了。
发报时Lakey会实时解析你所发送的Morse码,但并不会提示是否与报底相同。因此,你在练习时应确保发送的内容与报底同步,否则事后Lakey的正确率统计将会不正确。
当然,如果不同步也没有关系,如果对Lakey统计的正确率有疑问,可以到报底文件所在文件夹下寻找一个以报底文件名为前缀,后缀为“.jrn”的记录文件。
该文件会完整记录Lakey的解析结果,对于错误或者不认识的字符会以“#”替代。
时下对CW感兴趣的HAM越来越多,这里搜集了几篇关于学习CW方法/技巧的文章,供朋友们参考。
古典练习法
Koch练习法
Farnsworth练习法
个人认为上面这几种方法在练习时选择其中一种即可,多种方法混用时可能会产生混乱。
文章全部从Internet上收集,其版权属于原作者所有,如被收集文章的作者认为文章出现在此处并不妥当,请联系我(联系方法在首页),我会立即从这里删除。
(摘自BG1TGP在ham.it168.com论坛上发表的《致HAM初学CW的建议》一文 )
致HAM初学CW的建议
给大家一点学习CW的建议,如果原先无基础还是先从记忆英文字母、数字、常用标点符号的电码符号开始,这是第一步也是基础,就象小学生学习一篇满是生字的课文一样,要想让别人听写你首先得能读下来,要想读下来首先得把生字认识了,那么所有字符对应的电码符号一共也就几十个这个应该不是什么问题吧.
另外还可以利用CW练习软件进行辅助练习,敲击键盘电脑就会发出字符对应的电码符号读音,电脑发完了你就跟它学着读速度不易过快,当你已经不能满足按照A----Z/0----9的有规律的报底的时候可以将顺序打乱编辑一段报底,还是由电脑领读你来学着读,将间隔时间设定的大一点留出你跟读的时间,这期间还可以穿插完全读报底的练习,对卡壳的字母重点练习,其实记忆的过程就是在不断的重复中实现的。
下一步我们就要跟电脑学习读报底的节奏了,将一些单词组成短句并用空格来隔出单词之间的间隙存在电脑里并抄写下来一份报底,还是由电脑来领读你来跟读,达到一定的熟练程度后可以试着和电脑同期读,重点是掌握正确的读音和节奏,期间可以随便找些英文的书或报纸等作为报底来读,你读的有多熟练就证明你记忆的有多熟练,和电脑同期练习时你读的和电脑发的有多同步就证明你将来发报时的节奏有多标准。这只是刚刚开始还没到练习收报的时候,这个阶段就是记忆---电脑领读你跟读---自己按报底读---和电脑同步读,总之就是一个字----读。
如果报文不长速度也不快不压码也可以,但是最好是养成压码收报的习惯,压码的好处是可以让你收报更轻松,比如当报文中出现E--I等电码符号特别短的字母连在一块的时候如果你不会压码收报就会觉得手忙脚乱,因为当你听到E的电码符号后需要大脑来辨别这个“嘀”是什么字母,然后手要把这个字母写下来或在键盘上撬出来,可是还没等你写完的时候第二I又来了,等你写第二个的时候第三个又来了,假如下一个是9你又会觉得时间太长还得等他一会,由于电码符号的长度不均匀就会出现上面的现象,这样的化你的书写势必会影响到你的听辨。收报的过程是耳朵听---大脑辨---手来写,节奏由各电码符号的时间长度决定,遇到符号少的时间就短要是几个连在一块就手忙脚乱,那么压码收报就可以把由于各字符电码符号时间长度不同带给你的处理时间不同的矛盾在一定程度上给化解了,当听辨出第一个电码后不下笔写先记在脑子里,集中精力听第二个,当听辨出来第二个电码后下笔写第一个,把第二个在记在脑子里集中精力听第三个依次类推,就是耳朵不停的听,脑袋不停的辨,手不停的写,压码的本领是通过训练获得的,刚开始可能不太习惯时间长了就好了,你会发现你的收报节奏不在受电码时间长度的影响完全在你的掌握之中,压一到两个码基本就够了就会轻松不少,试一试等你的好消息。
(摘自BG1WZ在www.hellocq.net论坛上名为《学习CW的捷径》的帖子及其回帖 )
Koch Method被证明是一种很少失败的训练方法。简单说来一开始只用标准速度(至少15 wpm)听2个字符,达到90%抄收的水平之后增加第三个字符,3个字符一起练习,再达到90%抄收的水平之后增加第四个字符,如此与时俱进,基本上使用高速度养成条件反射。训练选择的字符不从最简单的E或T开始,推荐的学习顺序是:
K M R S U A P T L O W I . N J E F 0 Y , V G 5 / Q 9 Z H 3 8 B ? 4 2 7 C 1 D 6 X <BT> <SK> <AR>
译一篇文章——如果你希望学习莫尔斯码
如果你希望学习莫尔斯码
忘记挫折:获得有价值的莫尔斯技巧并增加你的业余无线电乐趣
作者:Dave Finley, N1IRZ 译:BG1WZ(译者注:译文有删节)
关于莫尔斯码训练的完整信息、CW操作、历史和更多,请参见作者的书:《莫尔斯码:突破障碍》(原名:《Morse Code: Breaking the Barrier》),由MFJ Enterprises, Inc.出版。
业余执照做了一些调整,你不再需要通过13或20wpm的考试才能获得完全的操作许可,只要通过5-wpm的考试就得到一切。但是为什么你不做得更多些?具有熟练的莫尔斯码水平,也就是可以抄收12-13 wpm或更多,能够从业余无线电的空中得到无限的乐趣。许多有兴趣的短波活动如远程接收,比赛和QRP操作是依靠CW完成的。数千ham把CW当做他们自己有别于其他通讯手段的休闲方式,甚至在VHF和更高的频率你可以发现激动人心的月面反射和弱信号通联仍然有赖于熟练的莫尔斯技巧。
一般认为达到13或20wpm速度几乎是不可逾越的障碍,这种理解是不对的。只要花费比通过5-wpm考试不多的时间投入,你就能得到真正高速的抄收能力,增强你对这一业余爱好的兴趣。你听到的许多有关学习莫尔斯码的说法是错误的——绝对错误。业余无线电界传统使用极慢的、最使人灰心丧气的、最痛苦和最无效的方法学习莫尔斯码。你能够获得真正的熟练技巧,你能够在相当短的时间内以最少的挫折和痛苦得到这些。它要求实地操作,你需要每天拿出15-30分钟进行训练直到达到目标。你可能在一个月或七个月内成功,个人的差异是巨大的。
这里有什么新方法?训练方法是德国心理学家Ludwig Koch在大约60年前发明的,最少的挫折和充分的加强使你可以尽快的进步。
让我们丢弃一些ham-radio传统上出现过的废物,开始走上成功之路。它们是:
●慢速(5
wpm)电码——用这个速度教任何人都应该看为非法的,绝对是一种浪费。而且保证会在将来出现困难以至学不下去。5 wpm和15或20wpm的电码完全是两回事,你当然不希望在错误上浪费时间。
●对照表,记忆术,音乐的暗示和其他记忆帮助——这些事情让你在试图抄收电码的时候还要想别的,对于精确抄收是致命的。
●训练磁带——很短时间内,你不知不觉的记忆了磁带的内容,并对自己的能力建立起虚假的信心。这种虚假的信心在你听到未曾记忆的电码时很快就会被粉碎。
●抄收空中的QSOs——你不知道频率上发码的速度,而且许多电码发得很差,无助于训练的目的。正规的练习课程例如W1AW所发的当然不在此例。
技巧:训练什么,怎样练?
去电报操作员的工作房间或参观俱乐部野外电台的CW操作,看一看他们在30到35
wpm速度的收和发。你将注意到他们做这些很轻松,并不费脑子,电码已经成为他们的第二语言。关键是熟练程度。抄收必须是无需思考的处理,听到就知道了,不用想它是什么。这是一种条件反射,实际上抄收速度超过10 wpm就只能靠反射,靠脑子想就太慢了。这就是为什么说过慢的速度是致命的陷阱,为什么传统的业余莫尔斯码训练痛苦又困难。许多ham先记忆了全部字符,然后开始提高速度。他们不断在脑子里查表,把听到的码与头脑里的表相比较,找出相符的。这样的处理到10 wpm左右就行不通了,所以经常有人停留在10 wpm的水平,数周或数月没有任何进步。
他们最终越过“驼峰”,超过10 wpm是因为持续的练习使他们用反射代替了思考,他们是幸运的。10 wpm的障碍使许多人在挫折面前选择了放弃。于是莫尔斯码训练完全避免“查表”阶段而用建立条件反射实现熟练的抄收。最初是1930年代德国心理学家Ludwig Koch认识到这一点,设计出非常有效的莫尔斯码训练方法。
用Koch方法练习莫尔斯码
Koch方法简单、直接地建立起条件反射。然而它要求一台电脑加软件或一个教师的协助,这也是它在过去许多年受到冷落的原因。现在电脑很普及,也有望成为标准的莫尔斯码训练方法。它的工作过程是:
准备好纸和铅笔,设置你的电脑(或微处理器构成的电码练习器)以20 wpm的速度发送莫尔斯字符(最少也要15 wpm)——但是仅仅2个字符。是的,这是第一课,你只有两种选择。在纸上抄收5分钟,停下机器,把你抄收的结果与机器发送的字符做比较,计算字符数目和抄收正确的百分比。
如果你的正确率是90%或更高——恭喜你!你已经学完了最初的2个字符。并且非常重要的,你是用全速学会的,再也不需要重新学习它们。如果你的正确率不足90%,需要继续练习。
一旦你抄收前2个字符达到90%的正确率,就在练习中增加第三个字符。增加新字符后你的正确率会下降,但是很快会上升到超过90%,这时再加上第四个字符,如此类推。
这个方法不允许你在脑子里建立一个对照表,为了90%正确率的全速抄收,你必须建立起条件反射,我们花费时间练习就是这个目的,就像练习打网球或体操一样,练习到你掌握了它。逐字学习的Koch方法有点和训练打字的盲打相像,那是另一个必须建立条件反射的技巧。
这是一个非常独特的训练方法——以你自己最好的速度前进,只为增加每个新字符花费时间,在达到目标的途中不浪费时间。
多少时间是必须的?这取决于个人。以Koch来说,他挑选的一组学生掌握12
wpm的电码平均仅用13.5小时。你也许不完全是这样,但它确实比心理学文献记录的任何方法更快。在熟练掌握一些字符之后你就能估算出总的学习时间。跟踪你的训练课程(一些软件可以为你做)并计花费在每个字符上的时间,乘上43(业余莫尔斯码考试所用)就是总的时间。
虽然Koch方法是练习莫尔斯码最快的方法,速度并不是它最基本的好处,基本的好处和它有别于其他训练方法的是让你不断的得到肯定和加强。随着你的实践,刚掌握2个字符时已经达到15或20 wpm,随后每一个新字符的加入都更多的验证了你的进步。与慢慢的建立4或5 wpm速度,碰到10 wpm的平台长时间不能进步相比,Koch方法可能遇到的挫折是最小的。
不断的测试是保证你使用Koch方法得到最大效益所必需的。必须抄收在纸上,这样才能给自己定级。一定要记住,如果准确率达到或超过90%就加一个字符。如果少于90%,要继续练习。最少每5分钟测试一次,决定什么时候增加字符,可以使进度最快。
使用Koch方法学习,直到你掌握完整的字符集之前,自然抄收的是随机的字符组而不是单词。如果你的软件允许,让这些字符具有随机的长度,而不是固定的5个字符一组,这样更接近实际的单词。单词和随机的字符组之间在节奏和“感觉”上确实存在差异。当你能够熟练抄收单词,就可以抄收简单的QSO,这是业余无线电考试的格式。特别留意呼号、位置和数字的抄收,这些内容往往成为考试重点。
(摘自BG1WZ在www.hellocq.net论坛上名为《学习CW的捷径》的帖子及其回帖 )
学习CW的捷径
近日浏览了几个莫尔斯码学习软件,几乎都提到了Farnsworth
Method,于是又去搜索法恩斯沃斯方法的含义,中文内容竟然搜索不到(繁体的有一条)。只好费劲读英文,读过几段总算基本弄清了,现在把有关情况作一介绍,也许对新手学习CW有所帮助。
'Farnsworth'(法恩斯沃斯)方法的中心就是对于初学者不过分降低每个字符的发送速度(一般为每分钟15-18词wpm),只是加大字符之间的空隙(例如使用5wpm的空间)。一旦你确认能够分辩出每个字母、数字、符号,就开始减少字符间的空隙。
这时每个字符的声音没有改变——你已经熟悉了,不用再次学习,因此很快可以把速度提上去。更慢的字符速度会诱使你去数点和划,造成更难于按它有特性的节奏声音去识别的困难。
许多CW软件的作者(基本上都是ham)反对背记字符/莫尔斯码对照表。因为那样学习的结果会导致听到电码之后再到脑子里去“查表”,速度很难提高。他们也反对背记分离的di dah,提倡把一个字符的CW码作为一个声音来记忆。我理解这样记忆的结果不但反应速度快,点/划/空间的比率也不用考虑,一起记忆了。
支持DirectSound的全双工声卡
P3或同级别CPU
IP网络适配器(可选)
并行/串行接口(可选)
Version 2.1.0019 Pencil(铅笔) (2012-6-30)
实现了由BA3CE建议的发送练习功能,并能够将练习时发送的文本记录下来;
新增加的频谱显示将频率坐标轴方向反向,即频率较低的数据显示在靠下的位置;
Version 2.0.0018 Zongzi(粽子) (2012-6-22)
正式引入FFT算法,大幅降低精确音频分析的CPU占用率;
基于CPU占用率的降低,默认的FFT(原DFT)采样数量增加为512(实际使用可以更高);
增加了结合频率、时间、能量的频谱图;
修正了自动键的问题(感谢BG8ST及其他提出了此问题但没有留下呼号的朋友)
修正了“/”符号的Morse编码错误(感谢BD1GXH);
修正了底层图形API(复制图层)的一个缺陷(过去有些控件显示可能会有拖尾无法擦净);
从Lakey 2.0版本开始,Lakey版本中将去掉RELEASE/BETA标记,取而代之的将是为每一个新的版本赋予一个有趣的名字代号;
Version 1.1.0017 BETA (2010-8-15)
采样数默认值减至256每秒,以降低CPU使用率;
接收音频完整数据分析(过去为抽样分析);
改进摩尔斯解析算法,增加对抖动的过滤,提高准确性(包括接收和发送);
Version 1.1.0016 BETA (2010-8-14)
FFT计算精度由64位降低为32位,减少内存占用;
优化了代码, 修正一些变量的类型, 避免过多类型转换;
解决了按住空格画面显示错乱的问题;
手册错字修正;
Version 1.1.0015 BETA (2010-8-12)
增加音量\键速等控制旋钮及基础控件;
网络通联自动识别记录对方IP地址, 这样只要发送放设置对方IP即可;
取消精简模式(从初始版本一直以来的界面);
完善配置缺省值, 只要删除lakey.ini, 界面自动恢复为英文缺省界面;
Version 1.1.0014 BETA (2010-8-2)
增加模拟干扰信号;
界面文字完全可配置,并增加纯中文界面版本;
更正版本序列;
Version 1.1.0013 BETA (2010-5-2)
频谱分析增加对数和线性标尺;
频谱分析窗口样式改进;
改进了频谱分析状态提示;
Version 1.1.0012 BETA (2010-4-17)
修正了没有处理Win32消息返回值的错误,解决屏幕闪动的问题;
修正了当发送队列不为空时退出有时报错的问题;
增加了黑色;
Version 1.1.0011 BETA (2010-4-14)
增加了自动键模拟功能;
波形和频谱分析按比例完全显示(过去显示不全);
波形显示可放大幅度(鼠标左键切换);
频谱分析可按线性和对数两种方式显示(鼠标右键切换);
修正了DCT采样数量小于频谱分析控件宽度时报错的问题。
Version 1.1.0010 BETA (2010-4-5)
增加了对网络通联的支持;
标准控件改用系统主题风格(Windows XP版本以上);
加粗摩尔斯码记录条。
Version 1.0.0009 BETA (2009-11-22)
增加了设置wpm值的功能, 同时提供从复杂参数到wpm的反算功能;
增加了对硬件端口输出额外的控制,可使硬件端口只在需要的时候输出;
使用手册改为HTML格式。
Version 1.0.0008 BETA (2007-11-6)
增加了通过并行端口对外部设备进行控制的功能;
更新了用户手册。
Version 1.0.0007 RELEASE (2007-10-30)
修正了KOCH训练模式下,正常结束后不能再次启动训练模式的问题;
第一个稳定版本。
Version 1.0.0006 BETA (2007-7-10)
增加生成KOCH训练CW音频文件功能;
增加生成任意字符串CW音频文件功能;
改进分段、空格策略。
Version 1.0.0005 BETA (2007-3-29)
使用红色实时标记Koch模式训练时输入的错码;
增加Koch模式训练统计功能。
Version 1.0.0004 BETA (2007-3-28)
取得《中华人民共和国业余无线电台执照》及呼号特别纪念^_^;
增加Koch CW训练功能;
帮助文档中增加3篇有关CW学习方法的文章;
调整菜单布局。
Version 1.0.0003 BETA (2006-9-1)
增加了参数配置界面;
增加了可以调整的音频分析精度;
增加了CHM版本的用户手册。
Version 1.0.0002 BETA (2006-8-28)
增加了发送暂停功能;
增加了发送文本文件(只包含Morse code中的英文/数字/标点);
增加了发送队列的长度到8192;
修正了发送队列与显示不同步的问题。
Version 1.0.0001 BETA (2006-8-27)
初始版本。
================================================
FILE: src/CommFunc.cpp
================================================
#include "stdafx.h"
#include "Lakey.h"
#include "windows.h"
#include "Richedit.h"
#include "commctrl.h"
#include
#include
#include "LakeyMainWindow.h"
#include "CommFunc.h"
BOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen)
{
if (GetDlgItem(hDlg, nItemId))
{
GetDlgItemText(hDlg, nItemId, lpTxtBuf, nMaxLen);
return TRUE;
}
return FALSE;
}
BOOL SetDlgItemDec(HWND hDlg, UINT nItemId, double val)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
sprintf(vBuff, "%.4lf", val);
SetDlgItemText(hDlg, nItemId, vBuff);
return TRUE;
}
return FALSE;
}
BOOL GetDlgItemDec(HWND hDlg, UINT nItemId, double* pVal)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
sscanf(vBuff, "%lf", pVal);
return TRUE;
}
return FALSE;
}
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, BYTE val)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
sprintf(vBuff, "%2.2hX", val);
SetDlgItemText(hDlg, nItemId, vBuff);
return TRUE;
}
return FALSE;
}
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, BYTE* pVal)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
WORD w = 0;
sscanf(vBuff, "%hX", &w);
*pVal = (BYTE)w;
return TRUE;
}
return FALSE;
}
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, WORD val)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
sprintf(vBuff, "%4.4hX", val);
SetDlgItemText(hDlg, nItemId, vBuff);
return TRUE;
}
return FALSE;
}
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, WORD* pVal)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
sscanf(vBuff, "%hX", pVal);
return TRUE;
}
return FALSE;
}
BOOL GetDlgItemInt(HWND hDlg, UINT nItemId, int* pVal)
{
if (GetDlgItem(hDlg, nItemId))
{
char vBuff[32]; vBuff[sizeof(vBuff) - 1] = '\0';
GetDlgItemText(hDlg, nItemId, vBuff, sizeof(vBuff) - 1);
sscanf(vBuff, "%d", pVal);
return TRUE;
}
return FALSE;
}
================================================
FILE: src/CommFunc.h
================================================
#pragma once
#include "stdlib.h"
BOOL GetDlgItemTxt(HWND hDlg, int nItemId, LPSTR lpTxtBuf, int nMaxLen);
BOOL SetDlgItemDec(HWND hDlg, UINT nItemId, double val);
BOOL GetDlgItemDec(HWND hDlg, UINT nItemId, double* pVal);
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, BYTE val);
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, BYTE* pVal);
BOOL SetDlgItemHex(HWND hDlg, UINT nItemId, WORD val);
BOOL GetDlgItemHex(HWND hDlg, UINT nItemId, WORD* pVal);
BOOL GetDlgItemInt(HWND hDlg, UINT nItemId, int* pVal);
================================================
FILE: src/EventListener.cpp
================================================
#include "StdAfx.h"
#include "EventListener.h"
================================================
FILE: src/EventListener.h
================================================
#pragma once
#include "Graphics.h"
class IEventListener
{
};
class IClickEventListener
{
public:
virtual BOOL OnClick(void* owner) = 0;
};
class IPaintEventListener
{
public:
// virtual BOOL OnErase(void* owner, CGraphics* g, const RECT* pRect) = 0;
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect) = 0;
};
class IMouseMoveEventListener
{
public:
virtual BOOL OnMouseMove(void* owner, int x, int y) = 0;
};
class IKeyboardEventListener : public IClickEventListener
{
public:
virtual BOOL OnKeyDown(void* owner, int nKeyCode) = 0;
virtual BOOL OnKeyUp(void* owner, int nKeyCode) = 0;
};
class IMouseKeyEventListener : public IClickEventListener
{
public:
typedef enum { LBUTTON = 1, CBUTTON, RBUTTON } MouseKeyType;
public:
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y) = 0;
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y) = 0;
};
class ITimerEventListener
{
public:
virtual BOOL OnTimer(void* owner, int nTimerId) = 0;
};
class ICommandEventListener
{
public:
virtual BOOL OnCommand(void* owner, int nCommId) = 0;
};
================================================
FILE: src/EventManagerWin32.cpp
================================================
#include "StdAfx.h"
#include "eventmanagerwin32.h"
CEventDispatcherWin32::CEventDispatcherWin32(HWND hWnd)
{
m_hWnd = hWnd;
m_pGraphics = new CGraphics(hWnd);
}
CEventDispatcherWin32::~CEventDispatcherWin32(void)
{
delete m_pGraphics;
}
BOOL CEventDispatcherWin32::OnMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
BOOL r = FALSE;
switch (message)
{
case WM_ERASEBKGND:
r = EraseProc(); break;
case WM_PAINT:
r = PaintProc(); break;
case WM_MOUSEMOVE:
r = MouseMoveProc(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
case WM_KEYDOWN:
r = KeyDownProc((int)wParam); break;
case WM_KEYUP:
r = KeyUpProc((int)wParam); break;
case WM_LBUTTONDOWN:
r = MouseKeyDownProc(IMouseKeyEventListener::LBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
case WM_LBUTTONUP:
r = MouseKeyUpProc(IMouseKeyEventListener::LBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
case WM_RBUTTONDOWN:
r = MouseKeyDownProc(IMouseKeyEventListener::RBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
case WM_RBUTTONUP:
r = MouseKeyUpProc(IMouseKeyEventListener::RBUTTON, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break;
case WM_TIMER:
r = TimerProc((int)wParam); break;
case WM_COMMAND:
{
int nCtrlId = LOWORD(wParam);
if (nCtrlId)
r = CommandProc(nCtrlId);
break;
}
}
return r;
}
void CEventDispatcherWin32::AddPaintEventControl(IPaintEventControl* pCtrl)
{
m_oPaintEventControls.push_back(pCtrl);
}
void CEventDispatcherWin32::AddMouseMoveEventControl(IMouseMoveEventControl* pCtrl)
{
m_oMouseMoveEventControls.push_back(pCtrl);
}
void CEventDispatcherWin32::AddKeyboardEventControl(IKeyboardEventControl* pCtrl)
{
m_oKeyboardEventControls.push_back(pCtrl);
}
void CEventDispatcherWin32::AddMouseKeyEventControl(IMouseKeyEventControl* pCtrl)
{
m_oMouseKeyEventControls.push_back(pCtrl);
}
void CEventDispatcherWin32::AddTimerEventControl(ITimerEventControl* pCtrl, int nTimerId, int nInterval)
{
m_oTimerEventControls.push_back(pCtrl);
SetTimer(m_hWnd, nTimerId, nInterval, NULL);
}
void CEventDispatcherWin32::AddCommandEventControl(ICommandEventControl* pCtrl)
{
m_oCommandEventControls.push_back(pCtrl);
}
void CEventDispatcherWin32::RemovePaintEventControl(IPaintEventControl* pCtrl)
{
for (vector::iterator it = m_oPaintEventControls.begin();
it != m_oPaintEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oPaintEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::RemoveMouseMoveEventControl(IMouseMoveEventControl* pCtrl)
{
for (vector::iterator it = m_oMouseMoveEventControls.begin();
it != m_oMouseMoveEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oMouseMoveEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::RemoveKeyboardEventControl(IKeyboardEventControl* pCtrl)
{
for (vector::iterator it = m_oKeyboardEventControls.begin();
it != m_oKeyboardEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oKeyboardEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::RemoveMouseKeyEventControl(IMouseKeyEventControl* pCtrl)
{
for (vector::iterator it = m_oMouseKeyEventControls.begin();
it != m_oMouseKeyEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oMouseKeyEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::RemoveTimerEventControl(ITimerEventControl* pCtrl)
{
for (vector::iterator it = m_oTimerEventControls.begin();
it != m_oTimerEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oTimerEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::RemoveCommandEventControl(ICommandEventControl* pCtrl)
{
for (vector::iterator it = m_oCommandEventControls.begin();
it != m_oCommandEventControls.end();
++it)
{
if (pCtrl == (*it))
{
m_oCommandEventControls.erase(it);
break;
}
}
}
void CEventDispatcherWin32::Invalidate(const RECT* pRect)
{
::InvalidateRect(m_hWnd, pRect, TRUE);
}
CGraphics* CEventDispatcherWin32::NewGraphics(int w, int h)
{
HDC hDc = GetDC(m_hWnd);
CGraphics* g = new CGraphics(hDc, w, h);
ReleaseDC(m_hWnd, hDc);
return g;
}
BOOL CEventDispatcherWin32::EraseProc()
{
// m_pGraphics->SetErase();
return TRUE;
}
BOOL CEventDispatcherWin32::PaintProc()
{
BOOL r = FALSE;
m_pGraphics->BeginPaint();
for (vector::iterator it = m_oPaintEventControls.begin();
it != m_oPaintEventControls.end();
++it)
{
RECT cr, dr;
(*it)->GetRect(&cr);
const RECT* pRect = m_pGraphics->GetPaintRect();
if (NULL == pRect || IntersectRect(&dr, pRect, &cr))
{
OffsetRect(&dr, -cr.left, -cr.top);
m_pGraphics->SetOrigin(cr.left, cr.top);
r |= (*it)->OnPaint((*it), m_pGraphics, &dr);
}
}
m_pGraphics->EndPaint();
return r;
}
BOOL CEventDispatcherWin32::MouseMoveProc(int x, int y)
{
BOOL r = FALSE;
for (vector::iterator it = m_oMouseMoveEventControls.begin();
it != m_oMouseMoveEventControls.end();
++it)
{
if ((*it)->IsRelated(x, y))
{
RECT cr;
(*it)->GetRect(&cr);
r |= (*it)->OnMouseMove((*it), x - cr.left, y - cr.top);
}
}
return r;
}
BOOL CEventDispatcherWin32::KeyDownProc(int nKeyCode)
{
BOOL r = FALSE;
for (vector::iterator it = m_oKeyboardEventControls.begin();
it != m_oKeyboardEventControls.end();
++it)
{
r |= (*it)->OnKeyDown((*it), nKeyCode);
}
return r;
}
BOOL CEventDispatcherWin32::KeyUpProc(int nKeyCode)
{
BOOL r = FALSE;
for (vector::iterator it = m_oKeyboardEventControls.begin();
it != m_oKeyboardEventControls.end();
++it)
{
r |= (*it)->OnKeyUp((*it), nKeyCode);
}
return r;
}
BOOL CEventDispatcherWin32::MouseKeyDownProc(IMouseKeyEventControl::MouseKeyType nMkt, int x, int y)
{
BOOL r = FALSE;
for (vector::iterator it = m_oMouseKeyEventControls.begin();
it != m_oMouseKeyEventControls.end();
++it)
{
if ((*it)->IsRelated(x, y))
{
RECT cr;
(*it)->GetRect(&cr);
r |= (*it)->OnMouseKeyDown((*it), nMkt, x - cr.left, y - cr.top);
}
}
return r;
}
BOOL CEventDispatcherWin32::MouseKeyUpProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y)
{
BOOL r = FALSE;
for (vector::iterator it = m_oMouseKeyEventControls.begin();
it != m_oMouseKeyEventControls.end();
++it)
{
if ((*it)->IsRelated(x, y))
{
RECT cr;
(*it)->GetRect(&cr);
r |= (*it)->OnMouseKeyUp((*it), nMkt, x - cr.left, y - cr.top);
}
}
return r;
}
BOOL CEventDispatcherWin32::TimerProc(int nTimerId)
{
BOOL r = FALSE;
for (vector::iterator it = m_oTimerEventControls.begin();
it != m_oTimerEventControls.end();
++it)
{
r |= (*it)->OnTimer((*it), nTimerId);
}
return r;
}
BOOL CEventDispatcherWin32::CommandProc(int nCommId)
{
BOOL r = FALSE;
for (vector::iterator it = m_oCommandEventControls.begin();
it != m_oCommandEventControls.end();
++it)
{
r |= (*it)->OnCommand((*it), nCommId);
}
return r;
}
BOOL IControl::PointInRect(const RECT* pRect, int x, int y)
{
POINT pt;
pt.x = x;
pt.y = y;
return ::PtInRect(pRect, pt);
}
BOOL IControl::IntersectRect(RECT* pDest, const RECT* pSrc1, const RECT* pSrc2)
{
return ::IntersectRect(pDest, pSrc1, pSrc2);
}
================================================
FILE: src/EventManagerWin32.h
================================================
#pragma once
#include
#include "Graphics.h"
#include "EventListener.h"
using namespace std;
class IControl
{
public:
virtual BOOL IsRelated(int x, int y) = 0;
virtual void GetRect(RECT* r) = 0;
static BOOL PointInRect(const RECT* pRect, int x, int y);
static BOOL IntersectRect(RECT* pDest, const RECT* pSrc1, const RECT* pSrc2);
};
class IPaintEventControl : public IControl, public IPaintEventListener
{
};
class IMouseMoveEventControl : public IControl, public IMouseMoveEventListener
{
};
class IKeyboardEventControl : public IKeyboardEventListener
{
};
class IMouseKeyEventControl : public IControl, public IMouseKeyEventListener
{
};
class ITimerEventControl : public ITimerEventListener
{
};
class ICommandEventControl : public ICommandEventListener
{
};
class IUserData
{
public:
virtual void SetUserData(void* pUserData) = 0;
virtual void* GetUserData() = 0;
};
class IPaintableParent
{
public:
virtual void Invalidate(const RECT* pRect) = 0;
virtual CGraphics* NewGraphics(int w, int h) = 0;
};
class CEventDispatcherWin32
: public IPaintableParent
{
public:
CEventDispatcherWin32(HWND hWnd);
virtual ~CEventDispatcherWin32(void);
virtual BOOL OnMessage(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual void AddPaintEventControl(IPaintEventControl* pCtrl);
virtual void AddMouseMoveEventControl(IMouseMoveEventControl* pCtrl);
virtual void AddKeyboardEventControl(IKeyboardEventControl* pCtrl);
virtual void AddMouseKeyEventControl(IMouseKeyEventControl* pCtrl);
virtual void AddTimerEventControl(ITimerEventControl* pCtrl, int nTimerId, int nInterval);
virtual void AddCommandEventControl(ICommandEventControl* pCtrl);
virtual void Invalidate(const RECT* pRect);
virtual CGraphics* NewGraphics(int w, int h);
virtual BOOL EraseProc();
virtual BOOL PaintProc();
virtual BOOL MouseMoveProc(int x, int y);
virtual BOOL KeyDownProc(int nKeyCode);
virtual BOOL KeyUpProc(int nKeyCode);
virtual BOOL MouseKeyDownProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y);
virtual BOOL MouseKeyUpProc(IMouseKeyEventListener::MouseKeyType nMkt, int x, int y);
virtual BOOL TimerProc(int nTimerId);
virtual BOOL CommandProc(int nCommId);
virtual void RemovePaintEventControl(IPaintEventControl* pCtrl);
virtual void RemoveMouseMoveEventControl(IMouseMoveEventControl* pCtrl);
virtual void RemoveKeyboardEventControl(IKeyboardEventControl* pCtrl);
virtual void RemoveMouseKeyEventControl(IMouseKeyEventControl* pCtrl);
virtual void RemoveTimerEventControl(ITimerEventControl* pCtrl);
virtual void RemoveCommandEventControl(ICommandEventControl* pCtrl);
protected:
HWND GetHWnd() { return m_hWnd; };
CGraphics* GetGraphics() { return m_pGraphics; };
private:
vector m_oPaintEventControls;
vector m_oMouseMoveEventControls;
vector m_oKeyboardEventControls;
vector m_oMouseKeyEventControls;
vector m_oTimerEventControls;
vector m_oCommandEventControls;
CGraphics* m_pGraphics;
HWND m_hWnd;
};
================================================
FILE: src/FFT.cpp
================================================
#include "StdAfx.h"
#include "fft.h"
#include
================================================
FILE: src/FFT.h
================================================
#pragma once
#include
#ifdef PI
#undef PI
#endif
#define PI 3.1415926f
/**
* class T: unit of external stored
* class V: unit of internal handled
*/
template class IFilterDFT
{
public:
virtual T OnEncodeFilter(V val, int i) = 0;
virtual T OnDecodeFilter(V val, int i) = 0;
};
template class TCosDFT
{
public:
TCosDFT(int nAnalyzeSamples, IFilterDFT* pFilter = NULL);
~TCosDFT(void);
void Encode(T* pDest, const T* pSrc);
void Decode(T* pDest, const T* pSrc);
private:
int m_nAnalyzeSamples;
V** m_ppCosTab;
IFilterDFT* m_pFilter;
};
template class TSinDFT
{
public:
TSinDFT(int nAnalyzeSamples, IFilterDFT* pFilter = NULL);
~TSinDFT(void);
void Encode(T* pDest, const T* pSrc);
void Decode(T* pDest, const T* pSrc);
private:
int m_nAnalyzeSamples;
V** m_ppSinTab;
IFilterDFT* m_pFilter;
};
template class TFastFT
{
public:
TFastFT(int nAnalyzeSamples, IFilterDFT* pFilter = NULL);
~TFastFT(void);
void Encode(T* pDest, const T* pSrc);
void Decode(T* pDest, const T* pSrc);
private:
void fftCore();
int m_nAnalyzeSamples;
int m_nLog2;
V* m_vBuf[2];
IFilterDFT* m_pFilter;
};
template
TFastFT::TFastFT(int nAnalyzeSamples, IFilterDFT* pFilter/* = NULL*/)
{
m_nAnalyzeSamples = nAnalyzeSamples;
m_pFilter = pFilter;
m_vBuf[0] = new V[m_nAnalyzeSamples]; // real
m_vBuf[1] = new V[m_nAnalyzeSamples]; // imod
for (m_nLog2 = 0; nAnalyzeSamples > 1; ++m_nLog2)
{
nAnalyzeSamples >>= 1;
}
}
template
TFastFT::~TFastFT(void)
{
delete[] m_vBuf[0];
delete[] m_vBuf[1];
}
template
TCosDFT::TCosDFT(int nAnalyzeSamples, IFilterDFT* pFilter/* = NULL*/)
{
m_nAnalyzeSamples = nAnalyzeSamples;
m_ppCosTab = new V*[m_nAnalyzeSamples];
m_pFilter = pFilter;
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
m_ppCosTab[i] = new V[m_nAnalyzeSamples];
for (int x = 0; x < m_nAnalyzeSamples; ++x)
m_ppCosTab[i][x] = cos(((x * 2) + 1) * i * PI / (2 * m_nAnalyzeSamples));
}
}
template
TCosDFT::~TCosDFT(void)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
delete[] m_ppCosTab[i];
delete[] m_ppCosTab;
}
template
TSinDFT::TSinDFT(int nAnalyzeSamples, IFilterDFT* pFilter/* = NULL*/)
{
m_nAnalyzeSamples = nAnalyzeSamples;
m_ppSinTab = new V*[m_nAnalyzeSamples];
m_pFilter = pFilter;
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
m_ppSinTab[i] = new V[m_nAnalyzeSamples];
for (int x = 0; x < m_nAnalyzeSamples; ++x)
m_ppSinTab[i][x] = sin(((x * 2) + 1) * i * PI / (2 * m_nAnalyzeSamples));
}
}
template
TSinDFT::~TSinDFT(void)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
delete[] m_ppSinTab[i];
delete[] m_ppSinTab;
}
template
void TSinDFT::Encode(T* pDest, const T* pSrc)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
V c = 0;
for (int x = 0; x < m_nAnalyzeSamples; ++x)
{
c += pSrc[x] * m_ppSinTab[i][x];
}
pDest[i] = m_pFilter ? m_pFilter->OnEncodeFilter(2 * c / m_nAnalyzeSamples, i)
: (T)(2 * c / m_nAnalyzeSamples);
}
}
template
void TCosDFT::Encode(T* pDest, const T* pSrc)
{
V s = 0;
static int ddd = 100;
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
V c = 0;
for (int x = 0; x < m_nAnalyzeSamples; ++x)
{
c += pSrc[x] * m_ppCosTab[i][x];
}
pDest[i] = m_pFilter ? m_pFilter->OnEncodeFilter(2 * c / m_nAnalyzeSamples, i)
: (T)(2 * c / m_nAnalyzeSamples);
s += abs(pDest[i]);
}
if (!(0 != ddd || 1.0 < s))
{
ddd = 0;
}
if (0 < ddd)
--ddd;
}
template
void TSinDFT::Decode(T* pDest, const T* pSrc)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
V c = 0;
for (int x = 0; x < m_nAnalyzeSamples; ++x)
{
c += pSrc[x] * m_ppSinTab[i][x];
}
pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter(c, i)
: (T)c;
}
}
template
void TCosDFT::Decode(T* pDest, const T* pSrc)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
V c = 0;
for (int x = 0; x < m_nAnalyzeSamples; ++x)
{
c += pSrc[x] * m_ppCosTab[i][x];
}
pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter(c, i)
: (T)c;
}
}
template
void TFastFT::Encode(T* pDest, const T* pSrc)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
m_vBuf[0][i] = (V)pSrc[i];
m_vBuf[1][i] = (V)0;
}
fftCore();
int n = m_nAnalyzeSamples / 2;
V x, y;
// ֪ΪɶFFT任зֱʽһ룬ΪԳƣֲ
// ԭƵ(LaWaveCapture)ʾֻҪȡһ뼴
if (m_pFilter)
{
for (int i = 0; i < n; ++i)
{
x = m_vBuf[0][i];
y = m_vBuf[1][i];
//pDest[i] = (T)m_vBuf[0][i];
pDest[i * 2] = m_pFilter->OnEncodeFilter(sqrt(x * x + y * y), i * 2);
x = m_vBuf[0][m_nAnalyzeSamples - i - 1];
y = m_vBuf[1][m_nAnalyzeSamples - i - 1];
pDest[i * 2 + 1] = m_pFilter->OnEncodeFilter(sqrt(x * x + y * y), i * 2 + 1);
}
}
else
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
x = m_vBuf[0][i];
y = m_vBuf[1][i];
//pDest[i] = (T)m_vBuf[0][i];
pDest[i * 2] = sqrt(x * x + y * y);
x = m_vBuf[0][m_nAnalyzeSamples - i - 1];
y = m_vBuf[1][m_nAnalyzeSamples - i - 1];
pDest[i * 2 + 1] = sqrt(x * x + y * y);
}
}
}
template
void TFastFT::Decode(T* pDest, const T* pSrc)
{
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
m_vBuf[0][i] = (V)pSrc[i];
m_vBuf[1][i] = (V)0;
}
fftCore();
for (int i = 0; i < m_nAnalyzeSamples; ++i)
{
//pDest[i] = (T)(m_vBuf[0][i] / m_nAnalyzeSamples);
pDest[i] = m_pFilter ? m_pFilter->OnDecodeFilter((T)m_vBuf[0][i], i)
: (T)m_vBuf[0][i];
}
}
template
void TFastFT::fftCore()
{
int np, lmx, lix, nv2, npm1, lo, lm, li, j1, j2, i, j, k, l;
V scl, arg, s, c, t1, t2;
np = m_nAnalyzeSamples;
l = m_nLog2;
lmx = np;
scl = 2 * PI / np;
for (lo = 0; lo < l; ++lo)
{
lix = lmx;
lmx = lmx / 2;
arg = 0;
for (lm = 0; lm < lmx; ++lm)
{
c = cos(arg);
s = sin(arg);
arg = arg + scl;
for (li = lix; li <= np; li += lix)
{
j1 = li - lix + lm;
j2 = j1 + lmx;
t1 = m_vBuf[0][j1] - m_vBuf[0][j2];
t2 = m_vBuf[1][j1] - m_vBuf[1][j2];
m_vBuf[0][j1] += m_vBuf[0][j2];
m_vBuf[1][j1] += m_vBuf[1][j2];
m_vBuf[0][j2] = c * t1 + s * t2;
m_vBuf[1][j2] = c * t2 - s * t1;
} // for li
} // for lm
scl *= 2;
} // for lo
j = 0;
nv2 = np / 2;
npm1 = np - 1;
for (i = 0; i < npm1; ++i)
{
if (i < j)
{
t1 = m_vBuf[0][j];
t2 = m_vBuf[1][j];
m_vBuf[0][j] = m_vBuf[0][i];
m_vBuf[1][j] = m_vBuf[1][i];
m_vBuf[0][i] = t1;
m_vBuf[1][i] = t2;
}
k = nv2;
while(k - 1 < j)
{
j -= k;
k /= 2;
}
j += k;
}
}
================================================
FILE: src/Graphics.cpp
================================================
#include "StdAfx.h"
#include "graphics.h"
#include "stdio.h"
CGraphics::CGraphics(HWND hWnd)
{
m_hWnd = hWnd;
GetClientRect(m_hWnd, &m_oSize);
HDC hDc = GetDC(m_hWnd);
m_hDc = ::CreateCompatibleDC(hDc);
m_hBgBm = ::CreateCompatibleBitmap(hDc, m_oSize.right, m_oSize.bottom);
SelectObject(m_hDc, m_hBgBm);
ReleaseDC(m_hWnd, hDc);
SetOrigin(0, 0);
m_nColor = RGB(0, 0, 0);
//m_nBgColor = RGB(224, 224, 224);
m_nBgColor = RGB(255, 255, 255);
m_hPen = CreatePen(PS_SOLID, 1, m_nColor);
m_hPenDot = CreatePen(PS_DASH, 1, m_nColor);
m_hBrush = CreateSolidBrush(m_nBgColor);
DrawRect(&m_oSize);
// SetBkMode(m_hDc, TRANSPARENT);
}
CGraphics::CGraphics(HDC hParentDc, int w, int h)
{
m_oSize.left = m_oSize.top = 0;
m_oSize.right = w;
m_oSize.bottom = h;
m_hWnd = NULL;
m_hDc = ::CreateCompatibleDC(hParentDc);
m_hBgBm = ::CreateCompatibleBitmap(hParentDc, m_oSize.right, m_oSize.bottom);
SelectObject(m_hDc, m_hBgBm);
SetOrigin(0, 0);
m_nColor = RGB(0, 0, 0);
m_nBgColor = RGB(255, 255, 255);
m_hPen = ::CreatePen(PS_SOLID, 1, m_nColor);
m_hPenDot = CreatePen(PS_DASH, 1, m_nColor);
m_hBrush = ::CreateSolidBrush(m_nBgColor);
// SetBkMode(m_hDc, TRANSPARENT);
}
CGraphics::~CGraphics(void)
{
::DeleteObject(m_hBrush);
::DeleteObject(m_hPen);
::DeleteObject(m_hPenDot);
::DeleteObject(m_hBgBm);
if (m_hDc)
::DeleteDC(m_hDc);
}
void CGraphics::BeginPaint()
{
if (m_hWnd)
{
m_hWndDc = ::BeginPaint(m_hWnd, &m_ps);
::SetBkMode(m_hDc, TRANSPARENT);
}
}
void CGraphics::EndPaint()
{
if (m_hWnd)
{
//HDC hWndDc = ::BeginPaint(m_hWnd, &m_ps);
::BitBlt( m_hWndDc, m_ps.rcPaint.left, m_ps.rcPaint.top
, m_ps.rcPaint.right - m_ps.rcPaint.left, m_ps.rcPaint.bottom - m_ps.rcPaint.top
, m_hDc, m_ps.rcPaint.left, m_ps.rcPaint.top, SRCCOPY);
//printf("%d,%d,%d,%d", m_ps.rcPaint.left, m_ps.rcPaint.right, m_ps.rcPaint.top, m_ps.rcPaint.bottom);
/*
::BitBlt( m_hWndDc, m_oSize.left, m_oSize.top
, m_oSize.right - m_oSize.left, m_oSize.bottom - m_oSize.top
, m_hDc, 0, 0, SRCCOPY);
*/
::EndPaint(m_hWnd, &m_ps);
}
}
const RECT* CGraphics::GetPaintRect()
{
if (m_hDc)
return &m_ps.rcPaint;
return NULL;
}
void CGraphics::SetOrigin(int x, int y)
{
m_nOriginX = x;
m_nOriginY = y;
}
void CGraphics::SetColor(int rgb)
{
m_nColor = rgb;
::DeleteObject(m_hPen);
::DeleteObject(m_hPenDot);
m_hPen = ::CreatePen(PS_SOLID, 1, m_nColor);
m_hPenDot = ::CreatePen(PS_DOT, 1, m_nColor);
}
void CGraphics::SetBgColor(int rgb)
{
m_nBgColor = rgb;
DeleteObject(m_hBrush);
m_hBrush = CreateSolidBrush(m_nBgColor);
::SetBkColor(m_hDc, rgb);
}
void CGraphics::DrawRoundRect(const RECT* pRect, int nEllipseWidth, int nEllipseHeight)
{
::SelectObject(m_hDc, m_hPen);
::SelectObject(m_hDc, m_hBrush);
::RoundRect(m_hDc, pRect->left + m_nOriginX, pRect->top + m_nOriginY, pRect->right + m_nOriginX, pRect->bottom + m_nOriginY, nEllipseWidth, nEllipseHeight);
}
void CGraphics::DrawEllipse(const RECT* pRect)
{
::SelectObject(m_hDc, m_hPen);
::SelectObject(m_hDc, m_hBrush);
::Ellipse(m_hDc, pRect->left + m_nOriginX, pRect->top + m_nOriginY, pRect->right + m_nOriginX, pRect->bottom + m_nOriginY);
}
void CGraphics::DrawText(const RECT* pRect, char* pText, int nFormat, BOOL bTransparent /* = NULL */)
{
if (bTransparent)
{
if (TRANSPARENT != ::GetBkMode(m_hDc))
::SetBkMode(m_hDc, TRANSPARENT);
}
else
{
if (OPAQUE != ::GetBkMode(m_hDc))
::SetBkMode(m_hDc, OPAQUE);
}
::SetTextColor(m_hDc, m_nColor);
RECT r = *pRect;
::OffsetRect(&r, m_nOriginX, m_nOriginY);
::DrawText(m_hDc, pText, (int)strlen(pText), &r, nFormat);
}
void CGraphics::SetFont(CFont* pFont)
{
if (pFont)
::SelectObject(m_hDc, pFont->GetFont());
}
void CGraphics::Copy(const RECT* pDestRect, CGraphics* pSrc, int x, int y)
{
::BitBlt( m_hDc, pDestRect->left + m_nOriginX, pDestRect->top + m_nOriginY
, pDestRect->right - pDestRect->left, pDestRect->bottom - pDestRect->top
, pSrc->m_hDc, x, y, SRCCOPY);
}
void CGraphics::DrawRect(const RECT* pRect)
{
RECT r = *pRect;
::OffsetRect(&r, m_nOriginX, m_nOriginY);
::FillRect(m_hDc, &r, m_hBrush);
}
void CGraphics::DrawLine(int x1, int y1, int x2, int y2)
{
BOOL r;
HGDIOBJ old = ::SelectObject(m_hDc, m_hPen);
r = ::MoveToEx(m_hDc, x1 + m_nOriginX, y1 + m_nOriginY, NULL);
r = ::LineTo(m_hDc, x2 + m_nOriginX, y2 + m_nOriginY);
}
void CGraphics::DrawLineDot(int x1, int y1, int x2, int y2)
{
BOOL r;
HGDIOBJ old = ::SelectObject(m_hDc, m_hPenDot);
r = ::MoveToEx(m_hDc, x1 + m_nOriginX, y1 + m_nOriginY, NULL);
r = ::LineTo(m_hDc, x2 + m_nOriginX, y2 + m_nOriginY);
}
CFont::CFont(const char* pFaceName, int nHeight, FontWeight tWeight)
{
memset(&m_oLogFont, 0, sizeof(m_oLogFont));
strcpy(m_oLogFont.lfFaceName, pFaceName);
m_oLogFont.lfHeight = nHeight;
SetWeight(tWeight);
m_oLogFont.lfQuality = CLEARTYPE_QUALITY;
}
void CFont::SetFace(const char* pFaceName)
{
ReleaseHandle();
strcpy(m_oLogFont.lfFaceName, pFaceName);
}
void CFont::SetHeight(int h)
{
ReleaseHandle();
m_oLogFont.lfHeight = h;
}
void CFont::SetWeight(FontWeight tWeight)
{
ReleaseHandle();
switch(tWeight)
{
case THIN:
m_oLogFont.lfWeight = 100; break;
case NORMAL:
m_oLogFont.lfWeight = 400; break;
case BOLD:
m_oLogFont.lfWeight = 700; break;
}
}
void CFont::SetItalic(BOOL bFlag)
{
ReleaseHandle();
m_oLogFont.lfItalic = bFlag;
}
void CFont::SetUnderline(BOOL bFlag)
{
ReleaseHandle();
m_oLogFont.lfUnderline = bFlag;
}
void CFont::SetStrikeOut(BOOL bFlag)
{
ReleaseHandle();
m_oLogFont.lfStrikeOut = bFlag;
}
HFONT CFont::GetFont()
{
if (NULL == m_hFont)
m_hFont = CreateFontIndirect(&m_oLogFont);
return m_hFont;
}
void CFont::ReleaseHandle()
{
if (NULL != m_hFont)
{
DeleteObject(m_hFont);
m_hFont = NULL;
}
}
================================================
FILE: src/Graphics.h
================================================
#pragma once
#include
class CFont;
typedef struct tagSTYLE
{
int nColor;
int nBgColor;
int nTextFormat; // win32 DrawText macro: DT_...
CFont* pFont;
}STYLE;
class CGraphics
{
public:
CGraphics(HWND hWnd);
CGraphics(HDC hParentDc, int w, int h);
~CGraphics(void);
//void SetErase() { m_bNeedErase = TRUE; };
void BeginPaint();
void EndPaint();
const RECT* GetPaintRect();
void SetOrigin(int x, int y);
void DrawRoundRect(const RECT* pRect, int nEllipseWidth, int nEllipseHeight);
void DrawText(const RECT* pRect, char* pText, int nFormat, BOOL bTransparent = TRUE);
void SetColor(int rgb);
void SetBgColor(int rgb);
void SetFont(CFont* pFont);
void Copy(const RECT* pDestRect, CGraphics* pSrc, int x, int y);
void DrawRect(const RECT* pRect);
void DrawLine(int x1, int y1, int x2, int y2);
void DrawLineDot(int x1, int y1, int x2, int y2);
void DrawEllipse(const RECT* pRect);
private:
HWND m_hWnd;
HDC m_hWndDc;
HDC m_hDc;
PAINTSTRUCT m_ps;
HBITMAP m_hBgBm;
int m_nOriginX;
int m_nOriginY;
int m_nColor;
int m_nBgColor;
HBRUSH m_hBrush;
HPEN m_hPen;
HPEN m_hPenDot;
//BOOL m_bNeedErase;
RECT m_oSize;
};
class CFont
{
public:
typedef enum { THIN, NORMAL, BOLD } FontWeight;
CFont(const char* pFaceName, int nSize, FontWeight tWeight);
~CFont() { ReleaseHandle(); };
void SetFace(const char* pFaceName);
void SetHeight(int nSize);
void SetWeight(FontWeight tWeight);
void SetItalic(BOOL bFlag);
void SetUnderline(BOOL bFlag);
void SetStrikeOut(BOOL bFlag);
HFONT GetFont();
private:
void ReleaseHandle();
LOGFONT m_oLogFont;
HFONT m_hFont;
};
================================================
FILE: src/LaButton.cpp
================================================
#include "StdAfx.h"
#include "LaButton.h"
CLaButton::CLaButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle/* = BT_NORMAL */, CFont* pFont/* = NULL */)
{
InitButton(pParent, pText, pRect, nStyle, pFont);
}
void CLaButton::InitButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle, CFont* pFont)
{
m_nIdxTxt = 0;
m_pParent = pParent;
m_oRect = *pRect;
m_nStyle = nStyle;
m_pFont = pFont;
m_nState = BS_UP;
m_bIsDown = FALSE;
m_bMouseOver = FALSE;
m_bMouseHold = FALSE;
m_pKeyboardEventListener = NULL;
m_pMouseMoveEventListener = NULL;
m_pMouseKeyEventListener = NULL;
m_nWantKeyCode = 0;
ResolveTextList(pText);
}
CLaButton::~CLaButton(void)
{
while (0 < m_vText.size())
{
delete[] m_vText[m_vText.size() - 1];
m_vText.pop_back();
}
}
void CLaButton::AddKeyboardEventListener(IKeyboardEventListener* pListener)
{
m_pKeyboardEventListener = pListener;
}
void CLaButton::AddMouseMoveEventListener(IMouseMoveEventListener* pListener)
{
m_pMouseMoveEventListener = pListener;
}
void CLaButton::AddMouseKeyEventListener(IMouseKeyEventListener* pListener)
{
m_pMouseKeyEventListener = pListener;
}
BOOL CLaButton::IsRelated(int x, int y)
{
RECT rect = m_oRect;
BOOL r = IControl::PointInRect(&rect, x, y);
if (r != m_bMouseOver)
{
m_bMouseOver = r;
m_pParent->Invalidate(&rect);
}
return m_bMouseHold || r;
}
void CLaButton::GetRect(RECT* r)
{
*r = m_oRect;
}
void CLaButton::SetRect(const RECT* r)
{
m_oRect = *r;
m_pParent->Invalidate(r);
}
void CLaButton::SetText(const char* pNewText)
{
while (0 < m_vText.size())
{
delete[] m_vText[m_vText.size() - 1];
m_vText.pop_back();
}
ResolveTextList(pNewText);
m_pParent->Invalidate(&m_oRect);
}
BOOL CLaButton::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
RECT r = m_oRect;
OffsetRect(&r, -r.left, -r.top);
if (BS_UP == m_nState)
{
g->SetBgColor(RGB(255, 255, 255));
if (m_bMouseOver)
{
g->SetColor(RGB(0, 0, 0));
}
else
{
g->SetColor(RGB(127, 127, 127));
}
}
else
{
g->SetColor(RGB(0, 0, 0));
g->SetBgColor(RGB(240, 240, 240));
}
int rw = (r.right - r.left) / 2;
int rh = (r.bottom - r.top) / 2;
if (rw > 16) rw = 16;
if (rh > 16) rh = 16;
int rd = (rw > rh ? rh : rw);
g->DrawRoundRect(&r, rd, rd);
if (m_pFont)
g->SetFont(m_pFont);
g->DrawText(&r, m_vText[m_nIdxTxt], DT_VCENTER|DT_CENTER|DT_SINGLELINE);
return TRUE;
}
void CLaButton::ResolveTextList(const char* pText)
{
m_nCntTxt = 0;
for (int i = 0, j; '\0' != pText[i]; i = j, ++m_nCntTxt)
{
for (j = i; '\0' != pText[j] && ',' != pText[j]; ++j)
{
}
m_vText.push_back(new char[j - i + 1]);
strncpy(m_vText[m_nCntTxt], pText + i, j - i);
m_vText[m_nCntTxt][j - i] = '\0';
if (',' == pText[j])
++j;
}
m_nIdxTxt = 0;
}
BOOL CLaButton::OnKeyDown(void* owner, int nKeyCode)
{
if (m_nWantKeyCode == nKeyCode)
{
m_nState = BS_DOWN;
m_pParent->Invalidate(&m_oRect);
if (m_pKeyboardEventListener)
m_pKeyboardEventListener->OnKeyDown(this, nKeyCode);
return TRUE;
}
return FALSE;
}
BOOL CLaButton::OnKeyUp(void* owner, int nKeyCode)
{
if (m_nWantKeyCode == nKeyCode)
{
if (BT_LOCKABLE == m_nStyle)
{
m_bIsDown = !m_bIsDown;
m_nState = (m_bIsDown ? BS_DOWN : BS_UP);
}
else
m_nState = BS_UP;
m_pParent->Invalidate(&m_oRect);
if (m_pKeyboardEventListener)
m_pKeyboardEventListener->OnKeyUp(this, nKeyCode);
OnClick(this);
return TRUE;
}
return FALSE;
}
BOOL CLaButton::OnMouseMove(void* owner, int x, int y)
{
if (m_pMouseMoveEventListener)
{
return m_pMouseMoveEventListener->OnMouseMove(this, x, y);
}
return FALSE;
}
BOOL CLaButton::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
m_bMouseHold = TRUE;
m_nState = BS_DOWN;
m_pParent->Invalidate(&m_oRect);
if (m_pMouseKeyEventListener)
m_pMouseKeyEventListener->OnMouseKeyDown(this, nMkt, x, y);
return TRUE;
}
BOOL CLaButton::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
m_bMouseHold = FALSE;
if (BT_LOCKABLE == m_nStyle)
{
m_bIsDown = !m_bIsDown;
m_nState = (m_bIsDown ? BS_DOWN : BS_UP);
}
else
m_nState = BS_UP;
if (m_nCntTxt == ++m_nIdxTxt)
m_nIdxTxt = 0;
m_pParent->Invalidate(&m_oRect);
if (m_pMouseKeyEventListener)
m_pMouseKeyEventListener->OnMouseKeyUp(this, nMkt, x, y);
if (IControl::PointInRect(&m_oRect, x + m_oRect.left, y + m_oRect.top))
OnClick(this);
return TRUE;
}
BOOL CLaButton::OnClick(void* owner)
{
BOOL bProcess = FALSE;
if (m_pKeyboardEventListener)
bProcess = m_pKeyboardEventListener->OnClick(this);
if (m_pMouseKeyEventListener && !bProcess)
bProcess = m_pMouseKeyEventListener->OnClick(this);
return bProcess;
}
================================================
FILE: src/LaButton.h
================================================
#pragma once
#include "EventManagerWin32.h"
class CLaButton
: public IPaintEventControl
, public IMouseMoveEventControl
, public IMouseKeyEventControl
, public IKeyboardEventControl
, public IUserData
{
public:
typedef enum { BS_UP, BS_DOWN } ButtonState;
typedef enum { BT_NORMAL, BT_LOCKABLE } ButtonStyle;
public:
CLaButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle = BT_NORMAL, CFont* pFont = NULL);
virtual ~CLaButton(void);
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* pRect);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual BOOL OnKeyDown(void* owner, int nKeyCode);
virtual BOOL OnKeyUp(void* owner, int nKeyCode);
virtual BOOL OnMouseMove(void* owner, int x, int y);
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnClick(void* owner);
virtual void SetRect(const RECT* pRect);
virtual void SetText(const char* pNewText);
virtual void SetUserData(void* pUserData) { m_pUserData = pUserData; };
virtual void* GetUserData() { return m_pUserData; };
virtual BOOL IsPressed() { return m_bIsDown; };
void AddKeyboardEventListener(IKeyboardEventListener* pListener);
void AddMouseMoveEventListener(IMouseMoveEventListener* pListener);
void AddMouseKeyEventListener(IMouseKeyEventListener* pListener);
void SetWantKeyCode(int nKeyCode) { m_nWantKeyCode = nKeyCode; };
int GetWantKeyCode() { return m_nWantKeyCode; };
private:
IPaintableParent* m_pParent;
CFont* m_pFont;
vector m_vText;
RECT m_oRect;
ButtonStyle m_nStyle;
ButtonState m_nState;
BOOL m_bMouseOver;
int m_nWantKeyCode;
BOOL m_bIsDown;
BOOL m_bMouseHold;
int m_nIdxTxt;
int m_nCntTxt;
IKeyboardEventListener* m_pKeyboardEventListener;
IMouseMoveEventListener* m_pMouseMoveEventListener;
IMouseKeyEventListener* m_pMouseKeyEventListener;
void* m_pUserData;
void InitButton(IPaintableParent* pParent, const char* pText, const RECT* pRect, ButtonStyle nStyle, CFont* pFont);
void ResolveTextList(const char* pText);
};
================================================
FILE: src/LaHwControl.cpp
================================================
#include "StdAfx.h"
#include "LaHwControl.h"
//#include "WinIo.h"
CLaHwControl::CLaHwControl(WORD nInitAddr, BYTE bInit)
{
//m_bInitOk = InitializeWinIo();
if (m_bInitOk)
{
// m_bInitOk = SetPortVal(nInitAddr, bInit, 1);
}
}
CLaHwControl::~CLaHwControl()
{
//if (m_bInitOk)
// ShutdownWinIo();
}
BOOL CLaHwControl::OutByte(WORD nAddr, BYTE b)
{
if (m_bInitOk && m_bState)
{
// return SetPortVal(nAddr, b, 1);
}
return FALSE;
}
BOOL CLaHwControl::GetState()
{
return m_bState;
}
void CLaHwControl::SetState(BOOL bState)
{
m_bState = bState;
}
================================================
FILE: src/LaHwControl.h
================================================
#pragma once
class CLaHwControl
{
public:
CLaHwControl(WORD nInitAddr, BYTE bInit);
~CLaHwControl();
BOOL OutByte(WORD nAddr, BYTE b);
BOOL GetState();
void SetState(BOOL bState);
private:
BOOL m_bInitOk;
BOOL m_bState;
};
================================================
FILE: src/LaJournalPanel.cpp
================================================
#include "StdAfx.h"
#include "lajournalpanel.h"
CLaJournalPanel::CLaJournalPanel(IPaintableParent* pParent, const RECT* pRect, const MORSECODE* pMorseList
, int nMaxShortCount, STYLE* pStyle, IParseEventListener* pParseLsnr)
{
m_pParent = pParent;
m_pParseLsnr = pParseLsnr;
m_oRect = *pRect;
m_pStyle = pStyle;
m_pPaintBoard = pParent->NewGraphics(pRect->right - pRect->left, pRect->bottom - pRect->top);
RECT r;
SetRect(&r, 0, 0, pRect->right - pRect->left, pRect->bottom - pRect->top);
m_pPaintBoard->DrawRect(&r);
//m_pPaintBoard->DrawLine(0, pRect->bottom - pRect->top - 1, pRect->right - pRect->left, pRect->bottom - pRect->top - 1);
m_nCurrPos = 0;
m_pMorseParser = new CMorseParser(pMorseList, MORSECODECOUNT, nMaxShortCount, this);
SetMaxShortCount(nMaxShortCount);
m_nJitter = 0;
m_nStateCount = 0;
m_nStep = 1;
}
CLaJournalPanel::~CLaJournalPanel(void)
{
delete m_pMorseParser;
delete m_pPaintBoard;
}
BOOL CLaJournalPanel::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaJournalPanel::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaJournalPanel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
int w = m_oRect.right - m_oRect.left;
int h = m_oRect.bottom - m_oRect.top;
RECT r;
r.top = 0; r.bottom = h;
r.left = 0; r.right = w - m_nCurrPos;
g->Copy(&r, m_pPaintBoard, m_nCurrPos, 0);
if (0 < m_nCurrPos)
{
r.left = w - m_nCurrPos; r.right = w;
g->Copy(&r, m_pPaintBoard, 0, 0);
}
return TRUE;
}
void CLaJournalPanel::Sample(int nState)
{
// sample filter
switch(m_nStep)
{
case 1: // init
{
if (3 > m_nSampleDiv)
{
}
else if (nState) // key down
{
m_nStateCount = 1;
m_nStep = 2;
return;
}
if (m_nSampleDiv <= ++m_nStateCount)
{
SampleRender(nState);
m_pMorseParser->Sample(nState);
m_nStateCount = 0;
}
break;
}
case 2: // jitter(L) test
{
++m_nStateCount;
if (!nState)
{
m_nStep = 3;
}
else if (m_nSampleDiv <= m_nStateCount)
{
SampleRender(nState);
m_pMorseParser->Sample(nState);
m_nStep = 1;
break;
}
return;
}
case 3: // jitter(H) test
{
if (nState)
{
if (m_nSampleDiv <= ++m_nStateCount)
{
SampleRender(nState);
m_pMorseParser->Sample(nState);
m_nStateCount = 0;
m_nStep = 1;
break;
}
else
m_nStep = 2;
}
else
{
m_nStateCount = 2;
m_nStep = 1; // key up
}
return;
}
}
m_pParent->Invalidate(&m_oRect);
}
void CLaJournalPanel::SampleRender(int nState)
{
if (nState)
m_pPaintBoard->SetColor(m_pStyle->nColor);
else
m_pPaintBoard->SetColor(m_pStyle->nBgColor);
int y = 2;
m_pPaintBoard->DrawLine(m_nCurrPos, y, m_nCurrPos, y + 5);
m_pPaintBoard->SetColor(m_pStyle->nBgColor);
m_pPaintBoard->DrawLine(m_nCurrPos, m_oRect.bottom - m_oRect.top - 16, m_nCurrPos, m_oRect.bottom - m_oRect.top - 1);
if (++m_nCurrPos >= m_oRect.right - m_oRect.left)
m_nCurrPos = 0;
}
void CLaJournalPanel::OnWorkOut(void* owner, const MORSECODE* pResult)
{
char buff[] = { '#', '\0' };
if (pResult)
buff[0] = pResult->nAscCode;
m_pPaintBoard->SetColor(m_pStyle->nColor);
m_pPaintBoard->SetFont(m_pStyle->pFont);
RECT r;
r.right = m_nCurrPos;
r.left = r.right - 12;
r.bottom = m_oRect.bottom - m_oRect.top;
r.top = r.bottom - 16;
m_pPaintBoard->DrawText(&r, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
if (r.left < 0)
{
int w = m_oRect.right - m_oRect.left;
r.right += w;
r.left += w;
m_pPaintBoard->DrawText(&r, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
}
if (m_pParseLsnr)
m_pParseLsnr->OnWorkOut(this, pResult);
}
void CLaJournalPanel::SetMaxShortCount(int nCount)
{
m_nSampleDiv = nCount / 3;
if (0 == m_nSampleDiv)
m_nSampleDiv = 1;
m_pMorseParser->SetMaxShortCount(nCount / m_nSampleDiv);
}
================================================
FILE: src/LaJournalPanel.h
================================================
#pragma once
#include "EventManagerWin32.h"
#include "MorseParser.h"
class CLaJournalPanel
: public IPaintEventControl
, public IParseEventListener
{
public:
CLaJournalPanel(IPaintableParent* pParent, const RECT* pRect, const MORSECODE* pMorseList, int nMaxShortCount, STYLE* pStyle, IParseEventListener* pParseLsnr);
virtual ~CLaJournalPanel(void);
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual void OnWorkOut(void* owner, const MORSECODE* pResult);
virtual void Sample(int nState);
void SetMaxShortCount(int nCount);
private:
IPaintableParent* m_pParent;
IParseEventListener* m_pParseLsnr;
STYLE* m_pStyle;
RECT m_oRect;
CGraphics* m_pPaintBoard;
int m_nCurrPos;
int m_nSampleDiv;
int m_nJitter;
int m_nStateCount;
int m_nStep;
CMorseParser* m_pMorseParser;
void SampleRender(int nState);
};
================================================
FILE: src/LaLabel.cpp
================================================
#include "StdAfx.h"
#include "LaLabel.h"
#include
CLaLabel::CLaLabel(IPaintableParent* pParent, const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName/* = NULL */)
{
m_pParent = pParent;
m_oRect = *pRect;
m_pStyle = pStyle;
if (pText)
{
strncpy(m_vText, pText, MAX_LABEL_TEXT_LEN);
m_vText[MAX_LABEL_TEXT_LEN] = '\0';
}
else
m_vText[0] = '\0';
m_hMutex = (pMutexName ? CreateMutex(NULL, FALSE, pMutexName) : NULL);
}
CLaLabel::~CLaLabel(void)
{
}
BOOL CLaLabel::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaLabel::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaLabel::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
RECT r = m_oRect;
OffsetRect(&r, -r.left, -r.top);
g->SetBgColor(m_pStyle->nBgColor);
g->DrawRect(&r);
g->SetFont(m_pStyle->pFont);
g->SetColor(m_pStyle->nColor);
g->DrawText(&r, m_vText, m_pStyle->nTextFormat);
return TRUE;
}
void CLaLabel::SetText(const char* pText)
{
if (pText)
{
strncpy(m_vText, pText, MAX_LABEL_TEXT_LEN);
m_vText[MAX_LABEL_TEXT_LEN] = '\0';
}
else
m_vText[0] = '\0';
m_pParent->Invalidate(&m_oRect);
}
void CLaLabel::GetText(char* pText, int nSize)
{
strncpy(pText, m_vText, nSize);
}
const char* CLaLabel::GetText()
{
return (const char *)m_vText;
}
BOOL CLaLabel::PushChar(char ch)
{
assert(m_hMutex);
BOOL r = FALSE;
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, 1000L))
{
for (int i = 0; i < MAX_LABEL_TEXT_LEN; ++i)
{
if (!m_vText[i])
{
m_vText[i] = ch;
m_vText[i + 1] = '\0';
r = TRUE;
break;
}
}
ReleaseMutex(m_hMutex);
m_pParent->Invalidate(&m_oRect);
}
return r;
}
char CLaLabel::PopChar()
{
assert(m_hMutex);
char r = '\0';
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hMutex, 1000L))
{
r = m_vText[0];
for (int i = 0; i < MAX_LABEL_TEXT_LEN; ++i)
{
if (m_vText[i])
m_vText[i] = m_vText[i + 1];
else
break;
}
ReleaseMutex(m_hMutex);
m_pParent->Invalidate(&m_oRect);
}
return r;
}
================================================
FILE: src/LaLabel.h
================================================
#pragma once
#include "EventManagerWin32.h"
#define MAX_LABEL_TEXT_LEN 8193
class CLaLabel
: public IPaintEventControl
{
public:
CLaLabel(IPaintableParent* pParent, const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName = NULL);
virtual ~CLaLabel(void);
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual void SetText(const char* pText);
virtual void GetText(char* pText, int nSize);
virtual const char* GetText();
virtual BOOL PushChar(char ch);
virtual char PopChar();
private:
IPaintableParent* m_pParent;
STYLE* m_pStyle;
RECT m_oRect;
char m_vText[MAX_LABEL_TEXT_LEN + 1];
HANDLE m_hMutex;
};
================================================
FILE: src/LaLine.cpp
================================================
#include "StdAfx.h"
#include "LaLine.h"
CLaLine::CLaLine(IPaintableParent* pParent, int x1, int y1, int x2, int y2)
{
m_pParent = pParent;
m_x1 = x1;
m_x2 = x2;
m_y1 = y1;
m_y2 = y2;
if (x1 > x2) x1 ^= x2 ^= x1 ^= x2;
if (y1 > y2) y1 ^= y2 ^= y1 ^= y2;
m_oRect.left = x1;
m_oRect.top = y1;
m_oRect.right = x2 + 1;
m_oRect.bottom = y2 + 1;
m_x1 -= m_oRect.left;
m_x2 -= m_oRect.left;
m_y1 -= m_oRect.top;
m_y2 -= m_oRect.top;
}
CLaLine::~CLaLine()
{
}
BOOL CLaLine::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaLine::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaLine::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
g->SetColor(0);
g->DrawLine(m_x1, m_y1, m_x2, m_y2);
return TRUE;
}
================================================
FILE: src/LaLine.h
================================================
#pragma once
#include "EventManagerWin32.h"
class CLaLine
: public IPaintEventControl
{
public:
CLaLine(IPaintableParent* pParent, int x1, int y1, int x2, int y2);
virtual ~CLaLine();
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
private:
IPaintableParent* m_pParent;
RECT m_oRect;
int m_x1;
int m_x2;
int m_y1;
int m_y2;
};
================================================
FILE: src/LaNetwork.cpp
================================================
#include "StdAfx.h"
//#include "winsock2.h"
//#include "Ws2tcpip.h"
#include "LaNetwork.h"
#define JOIN_SAFELY(ht) \
{ \
if (NULL != ht) \
{ \
DWORD nExitCode_j = -1; \
if (GetExitCodeThread(ht, &nExitCode_j)) \
if (STILL_ACTIVE == nExitCode_j) \
WaitForSingleObject(ht, INFINITE); \
ht = NULL; \
} \
}
CLaNetwork::CLaNetwork(DWORD nFlgs)
{
m_nFlgs = nFlgs;
m_bWsaInit = FALSE;
m_pEventListener = NULL;
m_pFrameListener = NULL;
m_pStbTabHead = NULL;
m_pDynTabHead = NULL;
m_hNwRecvThread = m_hNwSendThread = NULL;
m_nSendInPos = m_nSendOutPos = 0;
m_socket = NULL;
}
CLaNetwork::~CLaNetwork()
{
if (m_hNwRecvThread)
{
Shutdown();
ResumeThread(m_hNwRecvThread);
JOIN_SAFELY(m_hNwRecvThread);
}
if (m_hNwSendThread)
{
Shutdown();
ResumeThread(m_hNwSendThread);
JOIN_SAFELY(m_hNwSendThread);
}
if (m_bWsaInit)
{
WSACleanup();
m_bWsaInit = FALSE;
}
while(m_pStbTabHead)
{
LANWSRCNODE* p = m_pStbTabHead->next;
delete m_pStbTabHead;
m_pStbTabHead = p;
}
}
BOOL CLaNetwork::AppendStbSrcNode(const LANWSRCNODE* pStbSrc)
{
LANWSRCNODE* p = m_pStbTabHead;
if (!m_pStbTabHead)
{
m_pStbTabHead = new LANWSRCNODE;
p = m_pStbTabHead;
}
else
{
while(p->next)
{
if (p->base.nAddr == pStbSrc->base.nAddr && p->base.nPort == pStbSrc->base.nPort)
return FALSE;
p = p->next;
}
p->next = new LANWSRCNODE;
p = p->next;
}
p->base = pStbSrc->base;
p->attr = pStbSrc->attr;
p->branch = NULL;
p->next = NULL;
return TRUE;
}
BOOL CLaNetwork::AppendNodeByAddr(const sockaddr* pAddr)
{
if (AF_INET == pAddr->sa_family)
{
LANWSRCNODE *pNode = new LANWSRCNODE;
pNode->base.nAddr = ((sockaddr_in*)pAddr)->sin_addr.S_un.S_addr;
pNode->base.nPort = ((sockaddr_in*)pAddr)->sin_port;
pNode->branch = pNode->next = NULL;
return AppendStbSrcNode(pNode);
}
return FALSE;
}
BOOL CLaNetwork::Startup(WORD nPort)
{
if (m_hNwRecvThread || m_hNwSendThread)
return TRUE; // only startup once, at the same time
if (!m_bWsaInit)
{
WSADATA wsaData;
// start up as need
if (NO_ERROR != WSAStartup(MAKEWORD(2,2), &wsaData))
return FALSE;
m_bWsaInit = TRUE;
}
m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/*IPPROTO_TCP*/);
if (INVALID_SOCKET == m_socket)
return FALSE;
if (!Bind(nPort))
return FALSE;
m_bNeedExit = FALSE;
m_hNwRecvThread = CreateThread(NULL, 0, NwRecvThreadProc, this, 0, &m_nNwRecvThreadID);
if (m_hNwRecvThread)
{
m_hNwSendThread = CreateThread(NULL, 0, NwSendThreadProc, this, 0, &m_nNwSendThreadID);
if (m_hNwSendThread)
return TRUE;
Shutdown();
JOIN_SAFELY(m_hNwRecvThread);
}
return FALSE;
}
BOOL CLaNetwork::AppendKeyFrame(const LANWPKGKEYFRAME* pFrame)
{
int nNextPos = m_nSendInPos + 1;
if (SEND_QUEUE_SIZE == nNextPos)
nNextPos = 0;
if (nNextPos == m_nSendOutPos)
return FALSE;
m_vSendQ[m_nSendInPos] = *pFrame;
m_nSendInPos = nNextPos;
ResumeThread(m_hNwSendThread);
return TRUE;
}
BOOL CLaNetwork::PickKeyFrame(LANWPKGKEYFRAME* pFrame)
{
if (IsSendKeyFrameQueueEmpty())
return FALSE; //empty Q
*pFrame = m_vSendQ[m_nSendOutPos];
if (++m_nSendOutPos == SEND_QUEUE_SIZE)
m_nSendOutPos = 0;
return TRUE;
}
void CLaNetwork::Shutdown()
{
m_bNeedExit = TRUE;
if (m_socket)
{
closesocket(m_socket);
m_socket = NULL;
}
}
BOOL CLaNetwork::Bind(WORD nPort)
{
m_nLocalPort = nPort;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");
service.sin_port = htons(m_nLocalPort);
if (bind(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
if (m_pEventListener)
m_pEventListener->OnEvent(NM_BIND_FAILED);
return FALSE;
}
return TRUE;
}
#define NOTEVALIFNEEDEXIT(expr) if (!owner->m_bNeedExit) expr
DWORD WINAPI CLaNetwork::NwRecvThreadProc(LPVOID pOwner)
{
CLaNetwork* owner = (CLaNetwork *)pOwner;
sockaddr saddr;
int nFromlen = sizeof(saddr);
char sPkgBuff[RECV_BUFF_BYTES];
int nFramePos;
int nReadLen;
LANWPKGHEAD* pLnph;
LANWPKGKEYFRAME* pLnpkf;
// LANWPKGSRCFRAME* pLnpsf;
// LANWPKGTXTFRAME* pLnptf;
while(!owner->m_bNeedExit)
{
nReadLen = recvfrom(owner->m_socket, sPkgBuff, sizeof(sPkgBuff), 0, &saddr, &nFromlen);
if (SOCKET_ERROR != nReadLen && !owner->m_bNeedExit)
{
if (sizeof(LANWPKGHEAD) > nReadLen)
continue; // invalid package size
nFramePos = 0;
pLnph = (LANWPKGHEAD *)(sPkgBuff + nFramePos);
if (LA_FLAG != pLnph->nLaFlg)
continue; // invalid package head flag
if (LNPF_KEEPALIVE == pLnph->nPkgFlgs)
{
if (sizeof(LANWPKGHEAD) != nReadLen)
continue; // invalid keep-alive package size
// TODO: handle keep alive package
owner->AppendNodeByAddr(&saddr);
continue;
}
if (LNPF_OFF_LINE == pLnph->nPkgFlgs)
{
if (sizeof(LANWPKGHEAD) != nReadLen)
continue; // invalid off-line package size
// TODO: handle off-line package
continue;
}
nFramePos += sizeof(LANWPKGHEAD);
if (LNPF_KEY_FRAME & pLnph->nPkgFlgs)
{
if (LNPF_SERVER_FRAME & pLnph->nPkgFlgs)
continue; // server must not send key-frame
if (nFramePos + sizeof(LANWPKGKEYFRAME) > (UINT)nReadLen)
continue; // package too small
pLnpkf = (LANWPKGKEYFRAME *)(sPkgBuff + nFramePos);
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnKeyFrame(pLnpkf);
nFramePos += sizeof(LANWPKGKEYFRAME);
}
/*
if (LNPF_OPERATOR_SOURCE_FRMAE & pLnph->nPkgFlgs)
{
if (nFramePos + sizeof(LANWPKGSRCFRAME) > nReadLen)
continue; // package too small
//TODO: handle operator source frame here
pLnpsf = (LANWPKGSRCFRAME *)(sPkgBuff + nFramePos);
nFramePos += sizeof(LANWPKGSRCFRAME);
if (LNPF_OTHER_SDN_FRAME & pLnph->nPkgFlgs)
{
if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
continue; // package too small
pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
nFramePos += sizeof(LANWPKGTXTFRAME);
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnSourceFrame(pLnpsf, pLnptf->vText);
}
else
{
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnSourceFrame(pLnpsf, NULL);
}
}
if (LNPF_OTHER_SOURCE_FRAME & pLnph->nPkgFlgs)
{
if (nFramePos + sizeof(LANWPKGSRCFRAME) < nReadLen)
continue; // package too small
//TODO: handle other source frame here
pLnpsf = (LANWPKGSRCFRAME *)(sPkgBuff + nFramePos);
nFramePos += sizeof(LANWPKGSRCFRAME);
if (LNPF_OTHER_SDN_FRAME & pLnph->nPkgFlgs)
{
if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
continue; // package too small
pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
nFramePos += sizeof(LANWPKGTXTFRAME);
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnSourceFrame(pLnpsf, pLnptf->vText);
}
else
{
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnSourceFrame(pLnpsf, NULL);
}
}
if (LNPF_TEXT_FRAME & pLnph->nPkgFlgs)
{
if (nFramePos + sizeof(LANWPKGTXTFRAME) < nReadLen)
continue; // package too small
//TODO: handle text frame here
pLnptf = (LANWPKGTXTFRAME *)(sPkgBuff + nFramePos);
if (owner->m_pFrameListener)
owner->m_pFrameListener->OnTextFrame(pLnptf);
nFramePos += sizeof(LANWPKGTXTFRAME);
}
*/
if (nFramePos != nReadLen)
{
//TODO: handle invalid package here
continue;
}
} // end of if (SOCKET_ERROR != nReadLen && !owner->m_bNeedExit)
else
{
int nErrCode = WSAGetLastError();
}
} // end of while(!owner->m_bNeedExit)
if (owner->m_pEventListener)
owner->m_pEventListener->OnEvent(NM_EXIT);
return 0;
}
DWORD WINAPI CLaNetwork::NwSendThreadProc(LPVOID pOwner)
{
CLaNetwork* owner = (CLaNetwork *)pOwner;
char sPkgBuff[SEND_BUFF_BYTES];
LANWPKGHEAD* pPkgHead = (LANWPKGHEAD *)sPkgBuff;
LANWPKGKEYFRAME* pFrame = (LANWPKGKEYFRAME *)(sPkgBuff + sizeof(LANWPKGHEAD));
sockaddr_in destAddr;
destAddr.sin_family = AF_INET;
while(!owner->m_bNeedExit)
{
if (owner->IsSendKeyFrameQueueEmpty())
{
SuspendThread(owner->m_hNwSendThread);
// now send frame immediatly, but may be sleep here for keep alive frame in future
}
else
{
pPkgHead->nLaFlg = LA_FLAG;
pPkgHead->nPkgFlgs = LNPF_KEY_FRAME;
owner->PickKeyFrame(pFrame);
if (owner->m_pStbTabHead)
owner->SendKeyFrame(sPkgBuff, sizeof(LANWPKGHEAD) + sizeof(LANWPKGKEYFRAME)
, &destAddr, owner->m_pStbTabHead);
/* not supported dynamic node now
if (owner->m_pDynTabHead)
owner->SendKeyFrame(sPkgBuff, sizeof(LANWPKGHEAD) + sizeof(LANWPKGKEYFRAME)
, &destAddr, owner->m_pDynTabHead);
*/
}
}
return 0;
}
BOOL CLaNetwork::SendKeyFrame(const char* pPkgBuff, int nLen, sockaddr_in* pAddr, const LANWSRCNODE* pHeadNode)
{
pAddr->sin_addr.s_addr = pHeadNode->base.nAddr;
pAddr->sin_port = htons(pHeadNode->base.nPort);
if (SOCKET_ERROR == sendto(m_socket, pPkgBuff, nLen, 0, (SOCKADDR *)pAddr, sizeof(sockaddr_in)))
return FALSE;
/* only sent to every branch head
if (NULL != pHeadNode->branch)
if (!SendKeyFrame(pPkgBuff, nLen, pAddr, pHeadNode->branch))
return FALSE;*/
if (NULL != pHeadNode->next)
return SendKeyFrame(pPkgBuff, nLen, pAddr, pHeadNode->next);
return TRUE;
}
================================================
FILE: src/LaNetwork.h
================================================
#pragma once
#define SEND_BUFF_BYTES 128
#define RECV_BUFF_BYTES 128
///ά֡/Ӧ֡
#define LNPF_KEEPALIVE 0x0000
//֡
#define LNPF_KEY_FRAME 0x0001
//ԴϢ֡
#define LNPF_OPERATOR_SOURCE_FRMAE 0x0002
//ԴϢ֡֡
#define LNPF_OPERATOR_SDN_FRMAE 0x0004
//ԴϢ֡
#define LNPF_OTHER_SOURCE_FRAME 0x0020
//ԴϢ֡֡
#define LNPF_OTHER_SDN_FRMAE 0x0040
//ɴֻϢ()
#define LNPF_TEXT_FRAME 0x0100
//֡/תKEY_FRAME
#define LNPF_SERVER_FRAME 0x8000
//
#define LNPF_OFF_LINE 0xffff
#define LNPSF_OFF_LINE 0x0000
#define LNPSF_ON_LINE 0x0001
#define LNPSF_REQUEST 0x0002
//ǿ־
#define LNPSF_SERVER 0x0004
//ǷתSERVER⣬Ҫתյİ
#define LNPSF_BROKER 0x0008
#define NM_BIND_OK 0x0010
#define NM_BIND_FAILED 0x8010
#define NM_EXIT 0x0030
#define LRC_WSASTARTUP_FAILED 0x8001
#define SEND_QUEUE_SIZE 100
#define LA_FLAG ((((WORD)'A') << 8) | ((WORD)'L'))
typedef struct
{
WORD nLaFlg; //'LA' LA_FLAG
WORD nPkgFlgs; //LNPF_...
} LANWPKGHEAD;
typedef struct
{
DWORD nToState : 1; // 0: off; 1: on
DWORD nActTick : 31; // action tickcount
DWORD nReserved; // 30,000,000
} LANWPKGKEYFRAME;
typedef struct
{
WORD nSrcFlgs; //LNPSF_
WORD nPort;
DWORD nAddr;
} LANWPKGSRCFRAME;
typedef struct
{
BYTE vText[32];
} LANWPKGTXTFRAME;
typedef struct
{
long nLastSendto; // ýڵʱ
long nLastRecvFrom; // Ըýڵʱ
long nSendPkgs; // ܰ
long nRecvPkgs; // ܰ
} LANWSRCNODEATTR;
typedef struct tagLANWSRCNODE
{
LANWPKGSRCFRAME base;
LANWSRCNODEATTR attr;
struct tagLANWSRCNODE* branch; // ͬһԴϵĽڵ⣬֧ڵֻbranch
struct tagLANWSRCNODE* next; // ͬԴ
} LANWSRCNODE;
class INetworkEventListener
{
public:
virtual void OnEvent(WORD nMsg) = 0;
};
class INetworkFrameListener
{
public:
virtual void OnKeyFrame(const LANWPKGKEYFRAME* pFrame) = 0;
virtual void OnSourceFrame(const LANWPKGSRCFRAME* pFrame, const char* szDomainName) = 0;
virtual void OnTextFrame(const LANWPKGTXTFRAME* pFrame) = 0;
};
/**
[STABLESOURCE]
node1=[www.layala.org:2009,x,x,x],[...],...
**/
class CLaNetwork
{
public:
CLaNetwork(DWORD nFlgs);
~CLaNetwork();
BOOL Startup(WORD nPort);
void Shutdown();
void BindEventListener(INetworkEventListener* pEventListener) { m_pEventListener = pEventListener; };
void BindFrameListener(INetworkFrameListener* pFrameListener) { m_pFrameListener = pFrameListener; };
BOOL AppendKeyFrame(const LANWPKGKEYFRAME* pFrame);
BOOL PickKeyFrame(LANWPKGKEYFRAME* pFrame);
BOOL IsSendKeyFrameQueueEmpty() { return m_nSendInPos == m_nSendOutPos; };
//void AppendTextFrameQ(const LANWPKGKEYFRAME* pFrame);
BOOL AppendStbSrcNode(const LANWSRCNODE* pStbSrc);
const LANWSRCNODE* GetStbSrcList() { return m_pStbTabHead; };
private:
//
DWORD m_nFlgs;
WORD m_nLocalPort;
BOOL m_bNeedExit;
// CWͶ
LANWPKGKEYFRAME m_vSendQ[SEND_QUEUE_SIZE];
int m_nSendInPos; // Ƚ, λ
int m_nSendOutPos; // ȳ, λ, InPosʱΪ
// ̬ڵ
LANWSRCNODE* m_pStbTabHead;
// ̬ڵ
LANWSRCNODE* m_pDynTabHead;
INetworkEventListener* m_pEventListener;
INetworkFrameListener* m_pFrameListener;
BOOL m_bWsaInit;
HANDLE m_hNwRecvThread;
HANDLE m_hNwSendThread;
DWORD m_nNwRecvThreadID;
DWORD m_nNwSendThreadID;
SOCKET m_socket;
BOOL Bind(WORD nPort);
static DWORD WINAPI NwRecvThreadProc(LPVOID pOwner);
static DWORD WINAPI NwSendThreadProc(LPVOID pOwner);
BOOL SendKeyFrame(const char* pPkgBuff, int nLen, sockaddr_in* pAddr, const LANWSRCNODE* pHeadNode);
BOOL AppendNodeByAddr(const sockaddr* pAddr);
};
================================================
FILE: src/LaSpectrogram.cpp
================================================
#include "StdAfx.h"
#include "LaSpectrogram.h"
CLaSpectrogram::CLaSpectrogram(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSamples)
{
m_nBorderWidth = 1;
m_pFont = new CFont("Arial", 8, CFont::THIN);
m_pParent = pParent;
m_oRect = *pRect;
int w = m_oRect.right - m_oRect.left;
int h = m_oRect.bottom - m_oRect.top;
SetRect(&m_oPaintRect, m_nBorderWidth, m_nBorderWidth, w - m_nBorderWidth, h - m_nBorderWidth);
m_nBgColor = 0x000000;
m_nFrColor = 0xffff00;
m_pPaintBoard = pParent->NewGraphics(m_oPaintRect.right - m_oPaintRect.left, m_oPaintRect.bottom - m_oPaintRect.top);
m_nAnalyzeSamples = nAnalyzeSamples;
m_bFraze = FALSE;
h = m_oPaintRect.bottom - m_oPaintRect.top;
m_rPaintScale = (float)(h) / (float)m_nAnalyzeSamples;
m_rPaintScaleNext = m_rPaintScale;
m_rPaintIdx = 0;
m_nCurrPos = 0;
m_vFilterBuf = new float[h];
m_nPhases = -1;
m_nPhasesDiv = 512 / m_nAnalyzeSamples;
m_bOrgSize = FALSE;
}
CLaSpectrogram::~CLaSpectrogram(void)
{
delete[] m_vFilterBuf;
delete m_pFont;
delete m_pPaintBoard;
}
BOOL CLaSpectrogram::Initialize()
{
return TRUE;
}
BOOL CLaSpectrogram::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaSpectrogram::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaSpectrogram::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
int w = m_oPaintRect.right - m_oPaintRect.left;
int h = m_oPaintRect.bottom - m_oPaintRect.top;
RECT r = m_oPaintRect;
r.right -= (m_nCurrPos + 1);
if (m_nCurrPos < w - 1)
{
g->Copy(&r, m_pPaintBoard, m_nCurrPos + 1, 0);
}
r.left = r.right; r.right = r.left + m_nCurrPos + 1;
g->Copy(&r, m_pPaintBoard, 0, 0);
w = m_oRect.right - m_oRect.left - 1;
h = m_oRect.bottom - m_oRect.top - 1;
g->SetColor(0x808080);
g->DrawLine(0, 0, 0, h + 1);
g->DrawLine(0, 0, w + 1, 0);
g->SetColor(0xffffff);
g->DrawLine(w, 0, w, h + 1);
g->DrawLine(0, h, w + 1, h);
return TRUE;
}
short int CLaSpectrogram::OnEncodeFilter(float val, int i)
{
if (0 == i)
{
if (++m_nPhases > m_nPhasesDiv)
{
Refresh();
if (++m_nCurrPos >= m_oPaintRect.right - m_oPaintRect.left)
m_nCurrPos = 0;
m_nPhases = 0;
m_rPaintScale = m_rPaintScaleNext;
}
m_rPaintIdx = 0.0f;
}
float currIdx = m_rPaintIdx;
m_rPaintIdx += m_rPaintScale;
float w = abs(val) * m_rPaintScale / 256.0f * m_rBrightnessScale;
int j = (int)currIdx + 1;
if (j < m_oPaintRect.bottom - m_oPaintRect.top)
{
for (; j <= (int)m_rPaintIdx; currIdx = j++)
{
m_vFilterBuf[j - 1] += w * (j - currIdx);
}
m_vFilterBuf[j - 1] += w * (m_rPaintIdx - currIdx);
}
return val;
}
void CLaSpectrogram::SetBrightness(float scale)
{
m_rBrightnessScale = pow(10.0f, scale / 20.0f);
}
short int CLaSpectrogram::OnDecodeFilter(float val, int i)
{
return val;
}
/***
* ˢ¿ؼػߣȡƵݣ
*
*/
BOOL CLaSpectrogram::Refresh()
{
int h = m_oPaintRect.bottom - m_oPaintRect.top;
int lval = min(abs(m_vFilterBuf[0]), 255);
int lpos = 0, i;
for (i = lpos + 1; i < h; ++i)
{
if (lval != m_vFilterBuf[i])
{
m_pPaintBoard->SetColor(RGB(lval, lval, lval));
m_pPaintBoard->DrawLine(m_nCurrPos, m_oPaintRect.bottom - (lpos + m_oPaintRect.top) - 1, m_nCurrPos, m_oPaintRect.bottom - (i + m_oPaintRect.top) - 1);
lval = min(abs(m_vFilterBuf[i]), 255);
lpos = i;
}
m_vFilterBuf[i] = 0;
}
if (i - 1 != lpos)
{
m_pPaintBoard->SetColor(RGB(0, 0, 0));
m_pPaintBoard->DrawLine(m_nCurrPos, lpos, m_nCurrPos, h);
}
m_vFilterBuf[0] = 0;
//RECT r = m_oPaintRect;
//OffsetRect(&r, m_oRect.left, m_oRect.top);
m_pParent->Invalidate(&m_oRect);
return TRUE;
}
BOOL CLaSpectrogram::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
switch(nMkt)
{
case MouseKeyType::RBUTTON:
{
if (m_bOrgSize = !m_bOrgSize)
{
m_rPaintScaleNext = 1.0f;
}
else
{
m_rPaintScaleNext = (m_oPaintRect.bottom - m_oPaintRect.top) / (float)m_nAnalyzeSamples;
}
return TRUE;
}
case MouseKeyType::LBUTTON:
{
return TRUE;
}
}
return FALSE;
}
BOOL CLaSpectrogram::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
return FALSE;
}
void CLaSpectrogram::SetBackgroundColor(int nColor)
{
m_nBgColor = nColor;
}
================================================
FILE: src/LaSpectrogram.h
================================================
#pragma once
#include "EventManagerWin32.h"
#include "FFT.h"
#include "dsound.h"
//log(32768)
//#define LOG_SAMPLE_RANGE 4.51545
#define LOG_SAMPLE_RANGE 4.51545f
class ICwEventListener;
class CLaSpectrogram
: public IPaintEventControl
, public IMouseKeyEventControl
, public IFilterDFT
{
public:
CLaSpectrogram(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSample);
~CLaSpectrogram(void);
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual BOOL Initialize();
virtual BOOL Refresh();
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnClick(void* owner) { return FALSE; };
virtual short int OnEncodeFilter(float val, int i);
virtual short int OnDecodeFilter(float val, int i);
void SetBackgroundColor(int nColor);
void SetFrontColor(int nColor);
void SetBrightness(float scale);
private:
int AnalyzeData();
DWORD GetSyncPos(short int* pBuff, DWORD nBuffSize);
void DrawRuler();
void DrawBorder();
void DrawGrid();
IPaintableParent* m_pParent;
CFont* m_pFont;
RECT m_oRect; // by parent
RECT m_oPaintRect; // by self
CGraphics* m_pPaintBoard;
int m_nAnalyzeSamples;
int m_nBorderWidth;
int m_nBgColor;
int m_nFrColor;
BOOL m_bFraze;
float* m_vFilterBuf;
float m_rPaintIdx;
int m_nCurrPos;
float m_rPaintScale; // m_nAnalyzeSamples / canvos height
float m_rPaintScaleNext;
int m_nPhases;
int m_nPhasesDiv;
float m_rBrightnessScale;
BOOL m_bOrgSize;
};
================================================
FILE: src/LaTuner.cpp
================================================
#include "StdAfx.h"
#include "latuner.h"
#include "FFT.h"
CLaTuner::CLaTuner(IPaintableParent* pParent, const char* pText, const RECT* pRect, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont)
{
InitButton(pParent, pRect, pText, nScaleL, nScaleR, nScale, pFont);
}
CLaTuner::~CLaTuner()
{
}
void CLaTuner::SetScale(LASCALE nScale)
{
m_nScaleCurr = nScale;
m_pParent->Invalidate(&m_oRect);
}
void CLaTuner::InitButton(IPaintableParent* pParent, const RECT* pRect, const char* pText, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont)
{
m_nIdxTxt = 0;
m_pParent = pParent;
m_oRect = *pRect;
m_pFont = pFont;
m_nScaleL = nScaleL;
m_nScaleR = nScaleR;
m_nScaleDiv = (nScaleR - nScaleL) / 256;
m_nScaleDivD = 0;
m_nScaleCurr = nScale;
m_bMouseOver = FALSE;
m_bRbuttonHold = FALSE;
m_bLbuttonHold = FALSE;
// m_pKeyboardEventListener = NULL;
m_pMouseMoveEventListener = NULL;
m_pMouseKeyEventListener = NULL;
m_pTunerEventListener = NULL;
ResolveTextList(pText);
((CEventDispatcherWin32 *)pParent)->AddTimerEventControl(this, LA_TUNER_HEARTBEAT_TIMER_ID, 60);
}
BOOL CLaTuner::IsRelated(int x, int y)
{
RECT rect = m_oRect;
BOOL r = IControl::PointInRect(&rect, x, y);
if (r != m_bMouseOver)
{
m_bMouseOver = r;
m_pParent->Invalidate(&rect);
}
return m_bRbuttonHold || m_bLbuttonHold || r;
}
void CLaTuner::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaTuner::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
char buff[16];
RECT a = m_oRect;
OffsetRect(&a, -a.left, -a.top);
g->SetBgColor(RGB(255, 255, 255));
if (m_bMouseOver)
{
g->SetColor(RGB(0, 0, 0));
}
else
{
g->SetColor(RGB(127, 127, 127));
}
if (m_pFont)
g->SetFont(m_pFont);
RECT t = a;
int r = (int)((a.bottom < a.right ? a.bottom : a.right) / 3.2f);
int ox = a.right / 2;
int oy = a.bottom / 2;
t.left = ox - r;
t.right = ox + r;
t.top = oy - r;
t.bottom = oy + r;
g->DrawEllipse(&t);
if (m_bMouseOver || m_bLbuttonHold || m_bRbuttonHold)
{
if (abs(m_nScaleR - m_nScaleL) > 20)
sprintf(buff, "%0.0f", m_nScaleCurr);
else if (abs(m_nScaleR - m_nScaleL) > 2)
sprintf(buff, "%0.1f", m_nScaleCurr);
else
sprintf(buff, "%0.2f", m_nScaleCurr);
g->DrawText(&t, buff, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
}
int nScaleLen = r / 5;
int nSplitWidth = nScaleLen / 2;
float rx, ry;
int nScaleCount = 10;
float srad = 0.75f / nScaleCount;
for (int i = 0; i <= nScaleCount; ++i)
{
rx = cosf(2 * PI * (i * srad + 0.375f));
ry = sinf(2 * PI * (i * srad + 0.375f));
if (0 == i || i == nScaleCount)
{
int tx = (int)(ox + (r + nScaleLen * 2 + nSplitWidth) * rx);
int ty = (int)(oy + (r + nScaleLen * 2 + nSplitWidth) * ry);
g->DrawLine((int)(ox + (r + nSplitWidth) * rx), (int)(oy + (r + nSplitWidth) * ry)
, tx, ty);
g->DrawLine(tx, ty, 0 == i ? 0 : a.right, ty);
}
else
{
g->DrawLine((int)(ox + (r + nSplitWidth) * rx), (int)(oy + (r + nSplitWidth) * ry)
, (int)(ox + (r + nScaleLen + nSplitWidth) * rx), (int)(oy + (r + nScaleLen + nSplitWidth) * ry));
}
}
t.left = 0;
t.right = ox - r;
t.top = 0;
t.bottom = oy + r + 0;
sprintf(buff, "%0.0f", m_nScaleL);
g->DrawText(&t, buff, DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);
t.left = ox + r + 2;
t.right = a.right;
sprintf(buff, "%0.0f", m_nScaleR);
g->DrawText(&t, buff, DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);
LASCALE rd = 2 * PI * 0.75f * (m_nScaleCurr - m_nScaleL) / (m_nScaleR - m_nScaleL) + PI * 0.75f;
int px = (int)((r - 8) * cosf(rd) + ox);
int py = (int)((r - 8) * sinf(rd) + oy);
t.left = px - 3;
t.right = px + 3;
t.top = py - 3;
t.bottom = py + 3;
g->DrawEllipse(&t);
g->DrawText(&a, m_vText[m_nIdxTxt], DT_BOTTOM|DT_CENTER|DT_SINGLELINE, FALSE);
return TRUE;
}
BOOL CLaTuner::OnMouseMove(void* owner, int x, int y)
{
return FALSE;
}
BOOL CLaTuner::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
switch(nMkt)
{
case LBUTTON:
m_bLbuttonHold = TRUE; break;
case RBUTTON:
m_bRbuttonHold = TRUE; break;
default:
return FALSE;
}
m_nScaleDivD = 0;
return TRUE;
}
BOOL CLaTuner::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
switch(nMkt)
{
case LBUTTON:
m_bLbuttonHold = FALSE; break;
case RBUTTON:
m_bRbuttonHold = FALSE; break;
default:
return FALSE;
}
m_nScaleDivD = 0;
m_pParent->Invalidate(&m_oRect);
return TRUE;
}
BOOL CLaTuner::OnTimer(void* owner, int nTimerId)
{
if (LA_TUNER_HEARTBEAT_TIMER_ID == nTimerId
&& m_bMouseOver)
{
if (m_bRbuttonHold)
m_nScaleCurr += (m_nScaleDiv + m_nScaleDivD);
else if (m_bLbuttonHold)
m_nScaleCurr -= (m_nScaleDiv + m_nScaleDivD);
else
return FALSE;
m_nScaleDivD += m_nScaleDiv;
if (m_nScaleDiv < 0)
{
if (m_nScaleCurr < this->m_nScaleR)
m_nScaleCurr = m_nScaleR;
else if (m_nScaleCurr > this->m_nScaleL)
m_nScaleCurr = m_nScaleL;
}
else
{
if (m_nScaleCurr < this->m_nScaleL)
m_nScaleCurr = m_nScaleL;
else if (m_nScaleCurr > this->m_nScaleR)
m_nScaleCurr = m_nScaleR;
}
m_pParent->Invalidate(&m_oRect);
if (m_pTunerEventListener)
m_pTunerEventListener->OnTune(this, m_nScaleCurr);
return TRUE;
}
return FALSE;
}
/*void CLaTuner::AddKeyboardEventListener(IKeyboardEventListener* pListener)
{
m_pKeyboardEventListener = pListener;
}*/
void CLaTuner::AddMouseMoveEventListener(IMouseMoveEventListener* pListener)
{
m_pMouseMoveEventListener = pListener;
}
void CLaTuner::AddMouseKeyEventListener(IMouseKeyEventListener* pListener)
{
m_pMouseKeyEventListener = pListener;
}
void CLaTuner::AddTunerEventListener(ITunerEventListener* pListener)
{
m_pTunerEventListener = pListener;
}
void CLaTuner::ResolveTextList(const char* pText)
{
m_nCntTxt = 0;
for (int i = 0, j; '\0' != pText[i]; i = j, ++m_nCntTxt)
{
for (j = i; '\0' != pText[j] && ',' != pText[j]; ++j)
{
}
m_vText.push_back(new char[j - i + 1]);
strncpy(m_vText[m_nCntTxt], pText + i, j - i);
m_vText[m_nCntTxt][j - i] = '\0';
if (',' == pText[j])
++j;
}
m_nIdxTxt = 0;
}
================================================
FILE: src/LaTuner.h
================================================
#pragma once
#include "EventManagerWin32.h"
#define LA_TUNER_HEARTBEAT_TIMER_ID 10060
typedef float LASCALE;
class ITunerEventListener
{
public:
virtual BOOL OnTune(void* owner, LASCALE nScale) = 0;
};
class CLaTuner
: public IPaintEventControl
, public IMouseMoveEventControl
, public IMouseKeyEventControl
, public ITimerEventControl
{
public:
CLaTuner(IPaintableParent* pParent, const char* pText, const RECT* pRect, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont);
virtual ~CLaTuner();
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual BOOL OnMouseMove(void* owner, int x, int y);
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnTimer(void* owner, int nTimerId);
virtual BOOL OnClick(void* owner) { return FALSE; };
// void AddKeyboardEventListener(IKeyboardEventListener* pListener);
void AddMouseMoveEventListener(IMouseMoveEventListener* pListener);
void AddMouseKeyEventListener(IMouseKeyEventListener* pListener);
void AddTunerEventListener(ITunerEventListener* pListener);
void SetScale(LASCALE nScale);
LASCALE GetScale() { return m_nScaleCurr; };
private:
IPaintableParent* m_pParent;
CFont* m_pFont;
vector m_vText;
RECT m_oRect;
LASCALE m_nScaleL;
LASCALE m_nScaleR;
LASCALE m_nScaleDiv;
LASCALE m_nScaleDivD;
LASCALE m_nScaleCurr;
BOOL m_bMouseOver;
BOOL m_bRbuttonHold;
BOOL m_bLbuttonHold;
int m_nIdxTxt;
int m_nCntTxt;
// IKeyboardEventListener* m_pKeyboardEventListener;
IMouseMoveEventListener* m_pMouseMoveEventListener;
IMouseKeyEventListener* m_pMouseKeyEventListener;
ITunerEventListener* m_pTunerEventListener;
void* m_pUserData;
void InitButton(IPaintableParent* pParent, const RECT* pRect, const char* pText, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale, CFont* pFont);
void ResolveTextList(const char* pText);
};
================================================
FILE: src/LaWaveCapture.cpp
================================================
#include "StdAfx.h"
#include "lawavecapture.h"
#include "sinsound.h"
CLaWaveCapture::CLaWaveCapture(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSamples, IFilterDFT* pNextFilter, ICwEventListener* pCwEventListener/* = NULL */)
{
m_bRulerInvalid = TRUE;
m_nBorderWidth = 1;
m_nRularH = 9;
m_nRularV = 16;
m_pFont = new CFont("Arial", 8, CFont::THIN);
m_nWaveState = WAVE_ORIGINAL;
m_nDctState = DCT_LOG10_FLOAT;
m_nWaveStateTip = 0;
m_nDctStateTip = 0;
m_pParent = pParent;
m_oRect = *pRect;
int w = m_oRect.right - m_oRect.left;
int h = m_oRect.bottom - m_oRect.top;
SetRect(&m_oPaintRect, m_nBorderWidth, m_nBorderWidth, w - m_nRularV - m_nBorderWidth, h - m_nRularH - m_nBorderWidth);
SetRect(&m_oRulerRectH, m_nBorderWidth, h - m_nRularH - m_nBorderWidth, w - m_nRularV - m_nBorderWidth, h - m_nBorderWidth);
SetRect(&m_oRulerRectV, m_oPaintRect.right, m_oPaintRect.top, w - m_nBorderWidth, h - m_nRularH - m_nBorderWidth);
m_nRulerWidthH = w - m_nRularV - m_nBorderWidth * 2;
m_nRulerWidthV = h - m_nRularH - m_nBorderWidth * 2;
m_nRulerGridsV = (100 < m_nRulerWidthV ? 8 : 4);
m_nRulerDbMax = 80;
m_nBgColor = 0x000000;
m_nWaveColor = 0x00f000;
m_nFreqAnaColor = 0x808080;
m_nFloatColor = 0xf0f0f0;
m_nRulerColorH = 0x008000;
m_nRulerColorV = 0x008080;
m_nGridColorH = 0x000080;
m_nGridColorV = 0x004040;
m_nEnabledColor = 0x00f000;
m_nDisabledColor = 0x808080;
m_pPaintBoard = pParent->NewGraphics(pRect->right - pRect->left, pRect->bottom - pRect->top);
m_pCwEventListener = pCwEventListener;
m_pDsCap = NULL;
m_pDsCapBuff = NULL;
memset(&m_oFormat, 0, sizeof(m_oFormat));
m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
m_oFormat.nChannels = 1;
m_oFormat.nSamplesPerSec = nSamplePerSec;
m_oFormat.wBitsPerSample = 16;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_oFormat.nBlockAlign = m_oFormat.wBitsPerSample / 8 * m_oFormat.nChannels;
m_oFormat.cbSize = 0;
memset(&m_oCaptureBufferDesc, 0, sizeof(m_oCaptureBufferDesc));
m_oCaptureBufferDesc.dwSize = sizeof(m_oCaptureBufferDesc);
m_oCaptureBufferDesc.dwFlags = 0;
m_oCaptureBufferDesc.dwBufferBytes = m_oFormat.nAvgBytesPerSec * 2; // 2 sec buffer
m_oCaptureBufferDesc.lpwfxFormat = &m_oFormat;
m_oCaptureBufferDesc.dwFXCount = 0;
m_oCaptureBufferDesc.lpDSCFXDesc = NULL;
m_nAnalyzeSamples = nAnalyzeSamples;
m_pWavBuff = new short int[m_nAnalyzeSamples * 2];
m_pDctBuff = new short int[m_nAnalyzeSamples];
m_pFreqRuler = new short int[m_nRulerWidthH];
m_pFloatLine = new short int[m_nAnalyzeSamples];
m_pFloatClear = new short int[m_nAnalyzeSamples];
memset(m_pFloatLine, 0, sizeof(short int) * m_nAnalyzeSamples);
memset(m_pFloatClear, 0, sizeof(short int) * m_nAnalyzeSamples);
//m_nFloatClear = 0;
//DrawRuler();
DrawBorder();
m_nRecvThreshold = (short int)(32768 * 0.5l);
m_nRecvFreqStart = 850;
m_nRecvFreqEnd = 1250;
// m_pFft = new TCosDFT(m_nAnalyzeSamples, this);
m_pFft = new TFastFT(m_nAnalyzeSamples, this);
m_pNextFilter = pNextFilter;
m_bFraze = FALSE;
InitTestBuffer();
m_nTestIndex = 0;
}
CLaWaveCapture::~CLaWaveCapture(void)
{
delete m_pFont;
delete m_pPaintBoard;
if (NULL != m_pDsCap)
{
if (NULL != m_pDsCapBuff)
{
m_pDsCapBuff->Release();
m_pDsCapBuff = NULL;
}
m_pDsCap->Release();
m_pDsCap = NULL;
}
delete[] m_pWavBuff;
delete[] m_pDctBuff;
delete[] m_pFreqRuler;
delete[] m_pFloatLine;
delete[] m_pFloatClear;
delete[] m_pTestBuff;
}
void CLaWaveCapture::SetThresholdLevel(double rThresholdLevel)
{
m_nRecvThreshold = (short int)(32768 * rThresholdLevel);
}
void CLaWaveCapture::SetFreqRange(int nLowFreq, int nHighFreq)
{
m_nRecvFreqStart = nLowFreq;
m_nRecvFreqEnd = nHighFreq;
}
void CLaWaveCapture::DrawRuler()
{
m_bRulerInvalid = FALSE;
double rTotalLogNum = log10(16000.0l) - 2;
for (int i = 0; i < m_nRulerWidthH; ++i)
{
m_pFreqRuler[i] = (short int)pow(10, 2 + (i * rTotalLogNum / m_nRulerWidthH));
}
m_pPaintBoard->SetBgColor(m_nBgColor);
m_pPaintBoard->DrawRect(&m_oRulerRectH);
m_pPaintBoard->SetColor(m_nRulerColorH);
m_pPaintBoard->DrawLine(m_oRulerRectH.left, m_oRulerRectH.top, m_oRulerRectH.right, m_oRulerRectH.top);
m_pPaintBoard->SetFont(m_pFont);
double d = m_nRulerWidthH / rTotalLogNum;
RECT r = m_oRulerRectH;
// RECT tr;
char grad[8];
r.top += 1;
for (int i = 0; i < rTotalLogNum; ++i)
{
r.left = (int)(d * i);
if (0 == i)
sprintf(grad, "%.0lfHz", pow(10.0, i + 2));
else if (3 > i + 2)
sprintf(grad, "%.0lf", pow(10.0, i + 2));
else
sprintf(grad, "%.0lfK", pow(10.0, i + 2) / 1000);
//m_pPaintBoard->SetColor(RGB(192, 192, 192));
r.left += 2;
m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
r.left -= 2;
//m_pPaintBoard->SetColor(RGB(224, 224, 224));
m_pPaintBoard->DrawLine(r.left, 0 == i ? 0 : m_oRulerRectH.top + 1, r.left, m_oRulerRectH.bottom - 1);
if (4 > i)
{
for (int j = 2; j < 6 && r.left < m_nRulerWidthH; ++j)
{
r.left = (int)(d * (i + log10((double)j)));
sprintf(grad, "%d", j);
// m_pPaintBoard->SetColor(m_nFreqAnaColor);
r.left += 2;
m_pPaintBoard->DrawText(&r, grad, DT_LEFT);
r.left -= 2;
// m_pPaintBoard->SetColor(m_nFreqAnaColor);
m_pPaintBoard->DrawLine(r.left, m_oRulerRectH.top + 1, r.left, m_oRulerRectH.bottom - 2);
}
}
}
// draw rular-V
m_pPaintBoard->SetBgColor(m_nBgColor);
m_pPaintBoard->DrawRect(&m_oRulerRectV);
m_pPaintBoard->DrawLine(m_oRulerRectV.left, m_oRulerRectV.top, m_oRulerRectV.left, m_oRulerRectV.bottom);
switch(m_nDctState)
{
case DCT_LOG10_FLOAT:
case DCT_LOG10:
m_pPaintBoard->SetColor(m_nRulerColorV);
r = m_oRulerRectV;
r.bottom = r.top + m_nRularV;
m_pPaintBoard->DrawText(&r, "dB", DT_CENTER);
//r.top -= 3;
for (int i = 1; i <= m_nRulerGridsV; ++i)
{
r.top = m_oRulerRectV.top + i * m_nRulerWidthV / m_nRulerGridsV - 3;
r.bottom = r.top + m_nRularV;
//OffsetRect(&r, 0, m_nRulerWidthV / m_nRulerGridsV);
sprintf(grad, "-%d", i * m_nRulerDbMax / m_nRulerGridsV);
m_pPaintBoard->DrawText(&r, grad, DT_CENTER);
}
break;
case DCT_LINEAR_FLOAT:
case DCT_LINEAR:
m_pPaintBoard->SetColor(m_nRulerColorV);
r = m_oRulerRectV;
r.bottom = m_nRularV;
m_pPaintBoard->DrawText(&r, "%", DT_CENTER);
r.top -= 3;
for (int i = 2; i <= m_nRulerGridsV; i+=2)
{
OffsetRect(&r, 0, m_nRulerWidthV * 2 / m_nRulerGridsV);
sprintf(grad, "%d", 100 - i * 100 / m_nRulerGridsV);
m_pPaintBoard->DrawText(&r, grad, DT_CENTER);
}
break;
}
}
void CLaWaveCapture::DrawBorder()
{
int w = m_oRect.right - m_oRect.left - 1;
int h = m_oRect.bottom - m_oRect.top - 1;
m_pPaintBoard->SetColor(0x808080);
m_pPaintBoard->DrawLine(0, 0, 0, h + 1);
m_pPaintBoard->DrawLine(0, 0, w + 1, 0);
m_pPaintBoard->SetColor(0xffffff);
m_pPaintBoard->DrawLine(w, 0, w, h + 1);
m_pPaintBoard->DrawLine(0, h, w + 1, h);
}
void CLaWaveCapture::DrawGrid()
{
m_pPaintBoard->SetColor(m_nGridColorV);
for (int i = 1; i < m_nRulerGridsV; ++i)
{
m_pPaintBoard->DrawLineDot(m_oPaintRect.left, m_nBorderWidth + i * m_nRulerWidthV / m_nRulerGridsV, m_oPaintRect.right, m_nBorderWidth + i * m_nRulerWidthV / m_nRulerGridsV);
}
}
BOOL CLaWaveCapture::Initialize()
{
m_nNextPeriodStartPos = -1;
if (FAILED(DirectSoundCaptureCreate8(NULL, &m_pDsCap, NULL)))
return FALSE;
if (FAILED(m_pDsCap->CreateCaptureBuffer(&m_oCaptureBufferDesc, &m_pDsCapBuff, NULL)))
return FALSE;
return FAILED(m_pDsCapBuff->Start(DSCBSTART_LOOPING));
}
BOOL CLaWaveCapture::IsRelated(int x, int y)
{
return IControl::PointInRect(&m_oRect, x, y);
}
void CLaWaveCapture::GetRect(RECT* r)
{
*r = m_oRect;
}
BOOL CLaWaveCapture::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
int w = m_oRect.right - m_oRect.left;
int h = m_oRect.bottom - m_oRect.top;
RECT r;
r.top = 0; r.bottom = h;
r.left = 0; r.right = w;
g->Copy(&r, m_pPaintBoard, 0, 0);
return TRUE;
}
#define TRANSFORM_SAMPLE(f, t) \
int x = f; \
x <<= (m_nWaveState - WAVE_ORIGINAL); \
if (x > 32767) \
x = 32767; \
else if (x < -32767) \
x = -32767; \
t = m_oPaintRect.top + (m_oPaintRect.bottom - m_oPaintRect.top) / 2 - x * (m_oPaintRect.bottom - m_oPaintRect.top) / 65536;
int CLaWaveCapture::AnalyzeData()
{
DWORD nStatus = 0;
if (!m_pDsCapBuff)
return -1;
m_pDsCapBuff->GetStatus(&nStatus);
if (!((DSCBSTATUS_CAPTURING & nStatus) && (DSCBSTATUS_LOOPING & nStatus)))
return -1;
DWORD nReadPosEnd;
DWORD nCapturePos;
int nFrameBytes = m_nAnalyzeSamples * sizeof(short int);
if (FAILED(m_pDsCapBuff->GetCurrentPosition(&nCapturePos, &nReadPosEnd)))
return -1;
// get read start pos
//int nReadPosStart = m_nNextPeriodStartPos;
if (0 > m_nNextPeriodStartPos)
{
// always read 1 frame data at first time since buffer be init
m_nNextPeriodStartPos = nReadPosEnd - nFrameBytes * 2;
if (0 > m_nNextPeriodStartPos)
m_nNextPeriodStartPos += m_oCaptureBufferDesc.dwBufferBytes;
}
// calc bytes should be read
int nReadBytes = nReadPosEnd - m_nNextPeriodStartPos;
if (nReadBytes < 0)
nReadBytes += m_oCaptureBufferDesc.dwBufferBytes;
int nReadTimes = nReadBytes / (nFrameBytes * 2);
if (0 == nReadTimes)
return -1;
// correct read bytes
nReadBytes = nReadTimes * nFrameBytes * 2;
short int *pHeadPortion, *pTailPortion;
DWORD nHpBytes, nTpBytes;
if (FAILED(m_pDsCapBuff->Lock(m_nNextPeriodStartPos, nReadBytes, (LPVOID *)&pHeadPortion, &nHpBytes, (LPVOID *)&pTailPortion, &nTpBytes, 0)))
return -1;
DWORD i, nBase = 0;
BOOL bTestFlg = FALSE; //(0 == (++m_nTestInt / 10) % 2);
int s = 0;
for (int nFrame = 0; nFrame < nReadTimes; ++nFrame)
{
for (i = 0; i < nFrameBytes && (nBase + i) < nHpBytes / sizeof(short int); ++i)
{
m_pWavBuff[i] = pHeadPortion[nBase + i];
s += abs(m_pWavBuff[i]);
if (bTestFlg)
{
if (++m_nTestIndex == m_nTestBuffLen)
m_nTestIndex = 0;
int t = (int)m_pWavBuff[i] + (int)m_pTestBuff[m_nTestIndex];
m_pWavBuff[i] = min(32767, t);
m_pWavBuff[i] = max(-32767, t);
}
}
// nFrameBytes same as (nFrameBytes * 2 / sizeof(short int))
for (; i < nFrameBytes; ++i)
{
m_pWavBuff[i] = pTailPortion[nBase + i];
s += abs(m_pWavBuff[i]);
if (bTestFlg)
{
if (++m_nTestIndex == m_nTestBuffLen)
m_nTestIndex = 0;
int t = (int)m_pWavBuff[i] + (int)m_pTestBuff[m_nTestIndex];
m_pWavBuff[i] = min(32767, t);
m_pWavBuff[i] = max(-32767, t);
}
}
//static int dddd = 100;
//_ASSERT(dddd != 0 || 0 != s);
//if (0 < dddd)
// --dddd;
m_nCwState = FALSE;
m_pFft->Encode(m_pDctBuff, m_pWavBuff);
//m_pFft->Decode(m_pWavBuff, m_pDctBuff);
if (NULL != m_pCwEventListener)
m_pCwEventListener->OnCwEvent(m_nCwState);
m_nCwState = FALSE;
m_pFft->Encode(m_pDctBuff, m_pWavBuff + m_nAnalyzeSamples);
//m_pFft->Decode(m_pWavBuff + m_nAnalyzeSamples, m_pDctBuff);
if (NULL != m_pCwEventListener)
m_pCwEventListener->OnCwEvent(m_nCwState);
nBase += nFrameBytes;
}
m_pDsCapBuff->Unlock(pHeadPortion, nHpBytes, pTailPortion, nTpBytes);
if ((m_nNextPeriodStartPos += nReadBytes) >= m_oCaptureBufferDesc.dwBufferBytes)
m_nNextPeriodStartPos -= m_oCaptureBufferDesc.dwBufferBytes;
return GetSyncPos(m_pWavBuff, m_nAnalyzeSamples);
}
short int CLaWaveCapture::OnEncodeFilter(float val, int i)
{
if (!m_nCwState && m_nRecvThreshold <= abs(val))
{
int nFreq = i * m_oFormat.nSamplesPerSec / 2 / m_nAnalyzeSamples;
if (m_nRecvFreqStart <= nFreq && nFreq <= m_nRecvFreqEnd)
m_nCwState = TRUE;
}
if (m_pNextFilter)
return m_pNextFilter->OnEncodeFilter(val, i);
return val;
}
short int CLaWaveCapture::OnDecodeFilter(float val, int i)
{
return val;
}
/***
* ˢ¿ؼػߣȡƵݣ
*
*/
BOOL CLaWaveCapture::Refresh()
{
if (m_bRulerInvalid)
DrawRuler();
int nSyncStart = AnalyzeData();
if (0 > nSyncStart)
return FALSE;
if (m_bFraze)
return TRUE;
// redraw data if need
m_pPaintBoard->SetColor(m_nBgColor);
//m_oPaintRect.left += 1;
m_pPaintBoard->DrawRect(&m_oPaintRect);
//m_oPaintRect.left -= 1;
DrawGrid();
m_pPaintBoard->SetColor(m_nWaveColor);
short int* pSyncWavBuff = m_pWavBuff + nSyncStart;
int last, curr;
TRANSFORM_SAMPLE(pSyncWavBuff[0], last);
int i, x1, x2 = m_nBorderWidth;
for (i = 1; m_nWaveState && i < m_nAnalyzeSamples; ++i)
{
int v = pSyncWavBuff[i];
TRANSFORM_SAMPLE(v, curr);
x1 = x2;
x2 = m_nBorderWidth + m_nRulerWidthH * i / m_nAnalyzeSamples;
m_pPaintBoard->DrawLine(x1, last, x2, curr);
last = curr;
}
m_pPaintBoard->SetColor(m_nFreqAnaColor);
//FFT
//m_pFft->Compute(m_pDctBuff, pSyncWavBuff);
//m_pPaintBoard->SetColor(RGB(0, 0, 0));
int fd, v, l = 1;
float db;
// BOOL bState = FALSE;
for (i = 0; i < m_nAnalyzeSamples; i += 2)
{
short int nFreq = (short int)(i * m_oFormat.nSamplesPerSec / 2 / m_nAnalyzeSamples);
for (; m_nDctState && l < m_nRulerWidthH; ++l)
{
if (m_pFreqRuler[l] >= nFreq)
{
v = 0;
switch (m_nDctState)
{
case DCT_LINEAR:
case DCT_LINEAR_FLOAT:
v = abs(m_pDctBuff[i]) * m_oPaintRect.bottom / 32768;
break;
case DCT_LOG10:
case DCT_LOG10_FLOAT:
db = log10f((float)abs(m_pDctBuff[i]));
if (db > LOG_SAMPLE_RANGE - 4)
v = (int)((log10f((float)(abs(m_pDctBuff[i]))) - (LOG_SAMPLE_RANGE - 4)) * m_oPaintRect.bottom / 4);
break;
}
if (v > m_oPaintRect.bottom)
v = m_oPaintRect.bottom;
m_pPaintBoard->DrawLine(l, m_oPaintRect.bottom - v, l, m_oPaintRect.bottom);
switch (m_nDctState)
{
case DCT_LINEAR_FLOAT:
case DCT_LOG10_FLOAT:
fd = (int)(0.005f * m_pFloatClear[i] * m_pFloatClear[i] * m_pFloatClear[i]);
if (m_pFloatLine[i] - fd < v)
{
m_pFloatLine[i] = v;
m_pFloatClear[i] = 0;
}
else if (1 < m_pFloatLine[i] - fd)
{
m_pPaintBoard->SetColor(m_nFloatColor);
fd = m_oPaintRect.bottom - (m_pFloatLine[i] - fd);
m_pPaintBoard->DrawLine(l, fd, l, fd + 2);
++m_pFloatClear[i];
m_pPaintBoard->SetColor(m_nFreqAnaColor);
}
}
break;
}
}
// if (!bState && m_nRecvThreshold <= abs(m_pDctBuff[i]))
// if (m_nRecvFreqStart <= nFreq && nFreq <= m_nRecvFreqEnd)
// bState = TRUE;
} // end of for (i = 0; i < m_nAnalyzeSamples; ++i)
RECT r = m_oPaintRect;
r.left += 2;
r.top += 2;
r.right = r.left + 32;
r.bottom = r.top + 12;
switch(m_nWaveState)
{
case WAVE_INVISIBLE:
m_pPaintBoard->SetColor(m_nDisabledColor);
m_pPaintBoard->DrawText(&r, "W", DT_LEFT); break;
case WAVE_ORIGINAL:
m_pPaintBoard->SetColor(m_nEnabledColor);
m_pPaintBoard->DrawText(&r, "W", DT_LEFT); break;
default:
char szBuff[16];
m_pPaintBoard->SetColor(m_nEnabledColor);
sprintf(szBuff, "W +%ddB", 6 * (m_nWaveState - WAVE_ORIGINAL));
m_pPaintBoard->DrawText(&r, szBuff, DT_LEFT); break;
}
OffsetRect(&r, 100, 0);
switch(m_nDctState)
{
case DCT_INVISIBLE:
case DCT_LOG10:
case DCT_LINEAR:
m_pPaintBoard->SetColor(m_nDisabledColor);
m_pPaintBoard->DrawText(&r, "~~~", DT_LEFT); break;
case DCT_LOG10_FLOAT:
case DCT_LINEAR_FLOAT:
m_pPaintBoard->SetColor(m_nEnabledColor);
m_pPaintBoard->DrawText(&r, "~~~", DT_LEFT); break;
}
OffsetRect(&r, 32, 0);
switch(m_nDctState)
{
case DCT_INVISIBLE:
m_pPaintBoard->SetColor(m_nDisabledColor);
m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
OffsetRect(&r, 32, 0);
m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
case DCT_LOG10_FLOAT:
case DCT_LOG10:
m_pPaintBoard->SetColor(m_nEnabledColor);
m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
OffsetRect(&r, 32, 0);
m_pPaintBoard->SetColor(m_nDisabledColor);
m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
case DCT_LINEAR_FLOAT:
case DCT_LINEAR:
m_pPaintBoard->SetColor(m_nDisabledColor);
m_pPaintBoard->DrawText(&r, "LOG", DT_LEFT);
OffsetRect(&r, 32, 0);
m_pPaintBoard->SetColor(m_nEnabledColor);
m_pPaintBoard->DrawText(&r, "LINEAR", DT_LEFT); break;
}
//r = m_oPaintRect;
//OffsetRect(&r, m_oRect.left, m_oRect.top);
//m_pParent->Invalidate(&r);
m_pParent->Invalidate(&m_oRect);
// if (NULL != m_pCwEventListener)
// m_pCwEventListener->OnCwEvent(bState);
return TRUE;
}
DWORD CLaWaveCapture::GetSyncPos(short int* pBuff, DWORD nBuffSize)
{
//synchronize the wave
int nStep = 1;
DWORD nSyncStart;
for (nSyncStart = 0; nSyncStart < nBuffSize - 1 && 0 < nStep; ++nSyncStart)
{
switch(nStep)
{
case 1:
if (pBuff[nSyncStart] < pBuff[nSyncStart + 1])
nStep = 2;
break;
case 2:
if (pBuff[nSyncStart] >= 0 && pBuff[nSyncStart] > pBuff[nSyncStart + 1])
nStep = 0;
/* for sin wave
case 1: // look for negative
if (m_vWavBuff[nSyncStart] < 0)
nStep = 2;
break;
case 2: // through the X axis
if (m_vWavBuff[nSyncStart] >= 0)
nStep = 0;
break;
*/
}
}
return nSyncStart;
}
BOOL CLaWaveCapture::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
return FALSE;
}
BOOL CLaWaveCapture::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
switch(nMkt)
{
case LBUTTON:
{
if (WAVE_GAIN_X32 < ++m_nWaveState)
m_nWaveState = 0;
m_nWaveStateTip = 50;
return TRUE;
}
case RBUTTON:
{
if (DCT_LINEAR < ++m_nDctState)
m_nDctState = 0;
m_nDctStateTip = 50;
m_bRulerInvalid = TRUE;
return TRUE;
}
}
return FALSE;
}
void CLaWaveCapture::SetBackgroundColor(int nColor)
{
m_nBgColor = nColor;
}
void CLaWaveCapture::SetWaveColor(int nColor)
{
m_nWaveColor = nColor;
}
void CLaWaveCapture::SetFloatColor(int nColor)
{
m_nFloatColor = nColor;
}
void CLaWaveCapture::SetFreqAnaColor(int nColor)
{
m_nFreqAnaColor = nColor;
}
void CLaWaveCapture::InitTestBuffer()
{
REAL f = 1000.0f;
REAL w = 1.0f / f;
REAL d = 1.0f / 44100.0f;
int nTimes;
for (nTimes = 100; nTimes <= 1000; ++nTimes)
{
REAL rRemScale = fmod(w * nTimes, d) / w;
if (rRemScale < 0.001l || rRemScale > 0.998l)
break;
}
REAL s = nTimes * w;
m_nTestBuffLen = s * 44100;
REAL DW = 2 * PI / m_oFormat.nSamplesPerSec;
m_pTestBuff = new short int[m_nTestBuffLen];
for (DWORD i = 0; i < m_nTestBuffLen; ++i)
{
REAL v = sin(DW * i * f * 3) * 0.3 + sin(DW * i * f * 2) * 0.4 + sin(DW * i * f) * 0.5; // -1.0 ~ +1.0
m_pTestBuff[i] = (short int)(v * 32767);
}
}
================================================
FILE: src/LaWaveCapture.h
================================================
#pragma once
#include "EventManagerWin32.h"
#include "FFT.h"
#include "dsound.h"
//log(32768)
//#define LOG_SAMPLE_RANGE 4.51545
#define LOG_SAMPLE_RANGE 4.51545f
// CLaWaveCapture.m_nWaveState values
#define WAVE_INVISIBLE 0
#define WAVE_ORIGINAL 1
#define WAVE_GAIN_X2 2
#define WAVE_GAIN_X4 3
#define WAVE_GAIN_X8 4
#define WAVE_GAIN_X16 5
#define WAVE_GAIN_X32 6
// CLaWaveCapture.m_nDctState values
#define DCT_INVISIBLE 0
#define DCT_LOG10_FLOAT 1
#define DCT_LOG10 2
#define DCT_LINEAR_FLOAT 3
#define DCT_LINEAR 4
class ICwEventListener
{
public:
virtual void OnCwEvent(BOOL bCwDown) = 0;
};
class CLaWaveCapture
: public IPaintEventControl
, public IMouseKeyEventControl
, public IFilterDFT
{
public:
CLaWaveCapture(IPaintableParent* pParent, const RECT* pRect, int nSamplePerSec, int nAnalyzeSample, IFilterDFT* pNextFilter, ICwEventListener* pCwEventListener = NULL);
~CLaWaveCapture(void);
virtual BOOL IsRelated(int x, int y);
virtual void GetRect(RECT* r);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual BOOL Initialize();
virtual BOOL Refresh();
virtual void SetThresholdLevel(double rThresholdLevel);
virtual void SetFreqRange(int nLowFreq, int nHighFreq);
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnClick(void* owner) { return FALSE; };
virtual short int OnEncodeFilter(float val, int i);
virtual short int OnDecodeFilter(float val, int i);
void SetBackgroundColor(int nColor);
void SetWaveColor(int nColor);
void SetFloatColor(int nColor);
void SetFreqAnaColor(int nColor);
BOOL GetFrazeState() { return m_bFraze; };
void SetFrazeState(BOOL bFraze) { m_bFraze = bFraze; }
private:
int AnalyzeData();
DWORD GetSyncPos(short int* pBuff, DWORD nBuffSize);
void DrawRuler();
void DrawBorder();
void DrawGrid();
IPaintableParent* m_pParent;
CFont* m_pFont;
RECT m_oRect; // by parent
RECT m_oPaintRect; // by self
RECT m_oRulerRectH; // by self
RECT m_oRulerRectV; // by self
int m_nRulerWidthH;
int m_nRulerWidthV;
int m_nRulerGridsV;
int m_nRulerDbMax;
CGraphics* m_pPaintBoard;
IDirectSoundCapture* m_pDsCap;
IDirectSoundCaptureBuffer* m_pDsCapBuff;
WAVEFORMATEX m_oFormat;
DSCBUFFERDESC m_oCaptureBufferDesc;
int m_nNextPeriodStartPos;
short int* m_pWavBuff; //[m_nAnalyzeSamples * 2];
short int* m_pDctBuff; //[m_nAnalyzeSamples];
short int* m_pFreqRuler; //[m_oRulerWidth];
short int* m_pFloatLine; //[m_nAnalyzeSamples];
short int* m_pFloatClear;
// TCosDFT* m_pFft;
TFastFT* m_pFft;
IFilterDFT* m_pNextFilter;
ICwEventListener* m_pCwEventListener;
DWORD m_nAnalyzeSamples;
int m_nRecvThreshold;
int m_nRecvFreqStart;
int m_nRecvFreqEnd;
BOOL m_nCwState;
short int m_nWaveState;
short int m_nDctState;
int m_nWaveStateTip;
int m_nDctStateTip;
int m_nBorderWidth;
int m_nRularH;
int m_nRularV;
int m_nBgColor;
int m_nWaveColor;
int m_nFloatColor;
int m_nFreqAnaColor;
int m_nRulerColorH;
int m_nRulerColorV;
int m_nGridColorH;
int m_nGridColorV;
int m_nEnabledColor;
int m_nDisabledColor;
BOOL m_bRulerInvalid;
BOOL m_bFraze;
/* for test only */
int m_nTestBuffLen;
int m_nTestIndex;
short int* m_pTestBuff;
void InitTestBuffer();
int m_nTestInt;
};
================================================
FILE: src/LaWaveFile.cpp
================================================
#include "StdAfx.h"
#include "stdio.h"
#include "math.h"
#include "assert.h"
#include "LaWaveFile.h"
#define RESOLVEDWORD(a, b, c, d) (((DWORD)(a)) | (((DWORD)(b)) << 8) | (((DWORD)(c)) << 16) | (((DWORD)(d)) << 24))
#define PI 3.1415926f
CWaveFile::CWaveFile(const char* pPathname, WORD nChannels, DWORD nSamplesPerSec, WORD wBitsPerSample, float rSampleBuffSec)
{
m_pDestFile = fopen(pPathname, "wb");
memset(&m_oWaveFileInfo, 0, sizeof(m_oWaveFileInfo));
m_oWaveFileInfo.nRiffFlag = RESOLVEDWORD('R', 'I', 'F', 'F');
m_oWaveFileInfo.nCbSize =
sizeof(m_oWaveFileInfo) - sizeof(m_oWaveFileInfo.nRiffFlag) - sizeof(m_oWaveFileInfo.nCbSize);
m_oWaveFileInfo.oWaveHeader.nWaveFlag = RESOLVEDWORD('W', 'A', 'V', 'E');
m_oWaveFileInfo.oWaveHeader.nFmtFlag = RESOLVEDWORD('f', 'm', 't', ' ');
m_oWaveFileInfo.oWaveHeader.nCbSize = sizeof(m_oWaveFileInfo.oWaveHeader.oWaveInfo);
m_oWaveFileInfo.oWaveHeader.oWaveInfo.nBlank = 1;
m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels = nChannels;
m_oWaveFileInfo.oWaveHeader.oWaveInfo.nSamplesPerSec = nSamplesPerSec;
m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec =
nSamplesPerSec * nChannels * wBitsPerSample / 8;
m_oWaveFileInfo.oWaveHeader.oWaveInfo.nBlockAlign = nChannels * wBitsPerSample / 8;
m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample = wBitsPerSample;
m_oWaveFileInfo.oWaveHeader.nDataFlag = RESOLVEDWORD('d', 'a', 't', 'a');
m_oWaveFileInfo.oWaveHeader.nDataLength = 0;
fwrite(&m_oWaveFileInfo, sizeof(m_oWaveFileInfo), 1, m_pDestFile);
m_rSampleBuffSec = rSampleBuffSec;
m_nWavBuffLen = (int)(rSampleBuffSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
m_pWavBuff = new char[m_nWavBuffLen];
m_bModified = TRUE;
}
CWaveFile::~CWaveFile()
{
delete[] m_pWavBuff;
fclose(m_pDestFile);
}
void CWaveFile::SetFreq(float rFreq)
{
m_rFreq = rFreq;
m_bModified = TRUE;
}
void CWaveFile::SetVolumn(float rVol)
{
m_rVol = rVol;
m_bModified = TRUE;
}
int CWaveFile::AppendRaw(const char* pBuff, DWORD nLen, int nCount)
{
assert(0 == (nLen * nCount) % 2);
DWORD nBlockSize = nLen * nCount;
m_oWaveFileInfo.nCbSize += nBlockSize;
m_oWaveFileInfo.oWaveHeader.nDataLength += nBlockSize;
fseek(m_pDestFile, 0, SEEK_END);
for (int i = 0; i < nCount; ++i)
fwrite(pBuff, 1, nLen, m_pDestFile);
fseek(m_pDestFile, 0, SEEK_SET);
fwrite(&m_oWaveFileInfo, sizeof(m_oWaveFileInfo), 1, m_pDestFile);
return nBlockSize;
}
int CWaveFile::AppendBlank(float rSec)
{
DWORD nBytes = (DWORD)(rSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
if (0 != nBytes % 2)
++nBytes;
char c = '\0';
return AppendRaw(&c, 1, nBytes);
}
int CWaveFile::Append(float rSec)
{
if (m_bModified)
{
InitWavBuff();
}
DWORD nBytes = (DWORD)(rSec * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nAvgBytesPerSec);
if (0 != nBytes % 2)
++nBytes;
assert(nBytes <= m_nWavBuffLen);
return AppendRaw(m_pWavBuff, nBytes, 1);
}
void CWaveFile::InitWavBuff()
{
float dt = 1.0f / m_oWaveFileInfo.oWaveHeader.oWaveInfo.nSamplesPerSec;
DWORD nBytesPerSample = m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample / 8;
for (DWORD i = 0; i < m_nWavBuffLen / nBytesPerSample; ++i)
{
float v = sin(2 * PI * dt * i * m_rFreq) * m_rVol; // -1.0 ~ +1.0
for (DWORD j = 0; j < m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels; ++j)
{
if (16 == m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample)
{
*(((short int *)m_pWavBuff) + i * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels + j) = (short int)(v * 32767);
}
else if (8 == m_oWaveFileInfo.oWaveHeader.oWaveInfo.wBitsPerSample)
{
*(((char *)m_pWavBuff) + i * m_oWaveFileInfo.oWaveHeader.oWaveInfo.nChannels + j) = (char)(v * 255);
}
else
{
assert(0);
}
}
}
m_bModified = FALSE;
}
================================================
FILE: src/LaWaveFile.h
================================================
typedef struct
{
DWORD nRiffFlag; //'RIFF'
DWORD nCbSize;
struct
{
DWORD nWaveFlag; //'WAVE'
DWORD nFmtFlag; //'fmt '
DWORD nCbSize;
struct
{
WORD nBlank;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
} oWaveInfo;
DWORD nDataFlag; //'data'
DWORD nDataLength;
} oWaveHeader;
} LAAUDIOFILEHEADER;
class CWaveFile
{
public:
CWaveFile(const char* pPathname, WORD nChannels, DWORD nSamplesPerSec, WORD wBitsPerSample, float rSampleBuffSec);
~CWaveFile();
int AppendRaw(const char* pBuff, DWORD nLen, int nCount);
void SetFreq(float rFreq);
void SetVolumn(float rVol);
int Append(float rSec);
int AppendBlank(float rSec);
private:
void InitWavBuff();
FILE* m_pDestFile;
LAAUDIOFILEHEADER m_oWaveFileInfo;
char* m_pWavBuff;
DWORD m_nWavBuffLen;
BOOL m_bModified;
float m_rSampleBuffSec;
float m_rFreq;
float m_rVol;
};
================================================
FILE: src/Lakey.h
================================================
#pragma once
#include "resource.h"
================================================
FILE: src/Lakey.rc
================================================
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// (壬й) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_LAKEY ICON "Lakey.ico"
IDI_SMALL ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_LAKEY MENU
BEGIN
POPUP "ļ(&F)"
BEGIN
MENUITEM "˳(&X)", IDM_EXIT
END
POPUP "(&T)"
BEGIN
MENUITEM "CWƵļ(&W)", IDM_PROMPTWAVE
MENUITEM SEPARATOR
MENUITEM "Kochѵ\tCtrl+K", IDM_KOCHSTART
MENUITEM "KochƵļ(&G)", IDM_KOCHWAVE
MENUITEM SEPARATOR
MENUITEM "ѵ(&T)", IDM_SENDTRAINING
MENUITEM SEPARATOR
MENUITEM "(&S)", IDM_SETTINGS
END
POPUP "(&H)"
BEGIN
MENUITEM "(&A)...", IDM_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_LAKEY ACCELERATORS
BEGIN
"/", IDM_ABOUT, ASCII, ALT, NOINVERT
"?", IDM_ABOUT, ASCII, ALT, NOINVERT
"K", IDM_KOCHSTART, VIRTKEY, CONTROL, NOINVERT
VK_ESCAPE, IDM_KOCHSTOP, VIRTKEY, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 22, 17, 215, 73
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Lakey"
FONT 9, "Arial", 400, 0, 0x0
BEGIN
CONTROL IDB_BITMAP1,IDC_MYICON,"Static",SS_BITMAP | SS_REALSIZEIMAGE | WS_BORDER,5,7,62,51
LTEXT "Lakey Version 2.2.0020 (Paper)",IDC_STATIC,76,6,129,8,SS_NOPREFIX
LTEXT "(C) 2006-2020",IDC_STATIC,76,16,129,8
LTEXT "DE BG1VLZ, idirect3d@hotmail.com, VY",IDC_STATIC,76,38,132,8
LTEXT "-.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.- -.-. --.-",IDC_STATIC,6,63,203,8
LTEXT "73 ^_^",IDC_STATIC,76,49,132,8
END
IDD_PROMPTBOX DIALOGEX 22, 17, 215, 73
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION ""
FONT 9, "Arial", 400, 0, 0x0
BEGIN
LTEXT ": ",IDC_PROMPTTEXT,7,10,200,8
EDITTEXT IDC_INPUTSTR,7,33,200,12,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
PUSHBUTTON "ύ",IDOK,155,56,47,10
PUSHBUTTON "ȡ",IDCANCEL,100,56,47,10
END
IDD_SETTINGS DIALOGEX 22, 17, 254, 194
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Settings"
FONT 9, "MS Shell Dlg", 400, 0, 0x0
BEGIN
CONTROL "",IDC_SETTINGSTAB,"SysTabControl32",0x0,2,3,249,170
PUSHBUTTON "ȷ",IDC_ACCEPT,190,178,47,12
PUSHBUTTON "ȡ",IDCANCEL,135,178,47,12
END
IDD_COPYPAD DIALOGEX 0, 0, 343, 199
STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW
CAPTION ""
FONT 8, "Courier New", 400, 0, 0x0
BEGIN
CONTROL "",IDC_COPYTEXT,"RichEdit20A",ES_MULTILINE | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,342,175
DEFPUSHBUTTON "",IDC_ACCEPT,277,181,55,12
LTEXT "00:00:00",IDC_ELAPSETIME,9,184,37,10
RTEXT "0",IDC_COPIED,59,184,37,10
RTEXT "0",IDC_INCORRECT,109,184,37,10
RTEXT "0%",IDC_CORRECTPERC,159,184,37,10
GROUPBOX "ʱ",IDC_STATIC,3,176,47,21
GROUPBOX "¼",IDC_STATIC,53,176,47,21
GROUPBOX "",IDC_STATIC,103,176,47,21
GROUPBOX "ȷ",IDC_STATIC,153,176,47,21
END
IDD_TEST DIALOGEX 0, 0, 348, 148
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "ȷ",IDOK,291,7,50,14
PUSHBUTTON "ȡ",IDCANCEL,291,24,50,14
CONTROL "",IDC_RICHEDIT21,"RichEdit20A",ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP,7,7,180,134
END
IDD_GENERAL DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_SHORTHIT,42,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_HITDELAY,137,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_SPEED,218,14,29,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_LONGHIT,42,32,29,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_LETTERDELAY,137,32,29,14,ES_AUTOHSCROLL | ES_NUMBER
PUSHBUTTON "",IDC_CALCSPEED,199,33,77,12
GROUPBOX "CW",IDC_STATIC,4,2,276,52
LTEXT """""",IDC_STATIC,8,17,35,9
LTEXT "(ms)",IDC_STATIC,76,17,19,9
LTEXT """""",IDC_STATIC,8,35,35,9
LTEXT "(ms)",IDC_STATIC,76,35,19,9
LTEXT "",IDC_STATIC,103,17,35,9
LTEXT "(ms)",IDC_STATIC,171,35,19,9
LTEXT "ַ",IDC_STATIC,103,35,35,9
LTEXT "(ms)",IDC_STATIC,171,17,19,9
LTEXT "",IDC_STATIC,199,17,18,9
LTEXT "(wpm)",IDC_STATIC,252,17,23,9
LTEXT "ͨڡ١¼Ҫļ٣WPMֵɣԶ㡣˳١IJͨ١ť㵱ǰֵ",IDC_STATIC,19,70,244,33
END
IDD_SEND DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_BEEPFREQ,49,14,53,14,ES_AUTOHSCROLL
EDITTEXT IDC_BEEPVOL,49,32,53,14,ES_AUTOHSCROLL
EDITTEXT IDC_SENDPERIOD,49,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_SENDILDELIMIT,184,14,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_CW,184,32,53,14,ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER
EDITTEXT IDC_WORDDELAY,184,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "趨ǺͷصIJ",IDC_STATIC,26,78,237,33
GROUPBOX "",IDC_STATIC,4,2,276,68
LTEXT "",IDC_STATIC,10,17,20,9
LTEXT "(Hz)",IDC_STATIC,107,17,17,9
LTEXT "",IDC_STATIC,10,35,20,9
LTEXT "0~1.0",IDC_STATIC,106,35,22,9
LTEXT "",IDC_STATIC,9,53,35,9
LTEXT "(ms)",IDC_STATIC,107,53,19,9
LTEXT "ֹͣ",IDC_STATIC,144,16,35,9
LTEXT "(ms)",IDC_STATIC,242,16,19,9
LTEXT "CW",IDC_STATIC,144,35,35,9
LTEXT "VK code",IDC_STATIC,242,35,31,9
LTEXT "ոӳ",IDC_STATIC,144,53,35,9
LTEXT "(ms)",IDC_STATIC,242,53,19,9
END
IDD_RECV DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_RECVANALYZESAMPLES,49,14,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_RECVPERIOD,49,32,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_RECVILDELIMIT,49,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_RECVTHRESHOLD,184,14,53,14,ES_AUTOHSCROLL
EDITTEXT IDC_RECVFREQSTART,184,32,53,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_RECVFREQEND,184,50,53,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "趨ǺձصIJ",IDC_STATIC,26,78,237,33
GROUPBOX "",IDC_STATIC,4,2,276,69
LTEXT "",IDC_STATIC,9,17,35,9
LTEXT "()",IDC_STATIC,107,17,14,9
LTEXT "",IDC_STATIC,9,35,35,9
LTEXT "(ms)",IDC_STATIC,107,35,19,9
LTEXT "ֹͣ",IDC_STATIC,9,53,35,9
LTEXT "(ms)",IDC_STATIC,107,53,19,9
LTEXT "ֵƽ",IDC_STATIC,144,17,35,9
LTEXT "0~1.0",IDC_STATIC,242,17,22,9
LTEXT "ʼƵ",IDC_STATIC,144,35,35,9
LTEXT "(Hz)",IDC_STATIC,242,35,17,9
LTEXT "ֹƵ",IDC_STATIC,144,53,35,9
LTEXT "(Hz)",IDC_STATIC,242,53,17,9
END
IDD_IO DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_EXTPORTENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,16,37,9
EDITTEXT IDC_EXTPORTADDR,99,14,37,14,ES_UPPERCASE | ES_READONLY
EDITTEXT IDC_OPENBYTE,188,14,15,14,ES_UPPERCASE
EDITTEXT IDC_CLOSEBYTE,251,14,15,14,ES_UPPERCASE
LTEXT "»̧CWʱLakeyָӲ˿ڵַضݣԱһЩΧ豸",IDC_STATIC,20,44,244,22
GROUPBOX "˿ڿ",IDC_STATIC,4,2,276,32
LTEXT "ַ(HEX)",IDC_STATIC,59,16,37,9
LTEXT "(HEX)",IDC_STATIC,146,16,37,9
LTEXT "ر(HEX)",IDC_STATIC,211,16,37,9
LTEXT "ע⣺ȷӲַ趨пܻżһЩӲ²ϵͳ쳣ģ",IDC_STATIC,19,90,244,25,WS_BORDER
LTEXT "(ö˿ڵַοֵ - 278H/378H - 3E8H/3F8H/2F8H)",IDC_STATIC,25,70,237,16
END
IDD_KOCH DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_KOCHCHARS,49,14,223,14,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
EDITTEXT IDC_KOCHWORDLEN,49,32,25,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "ڡַKOCHѵҪѵĸѵʱѡȡַеַѵÿšֳȡַһոһȣͣ١",IDC_STATIC,22,67,246,35
GROUPBOX "ϰ",IDC_STATIC,4,2,276,55
LTEXT "ַ",IDC_STATIC,9,17,31,9
LTEXT "ֳ",IDC_STATIC,9,35,32,9
LTEXT "Kochַ˳\n\nK M R S U A P T L O W I . N J E F 0 Y , V G 5 / Q 9 Z H 3 8 B ? 4 2 7 C 1 D 6 X ",IDC_STATIC,22,108,245,36
END
IDD_NETWORK DIALOGEX 0, 0, 284, 163
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
EXSTYLE WS_EX_TRANSPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_NWENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,227,15,48,10
EDITTEXT IDC_HOSTNAME,51,44,79,14,ES_AUTOHSCROLL
PUSHBUTTON "",IDC_HOSTADD,197,44,35,13,BS_FLAT
PUSHBUTTON "ɾ",IDC_HOSTDEL,238,44,35,13
CONTROL "",IDC_HOSTLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,62,263,62
EDITTEXT IDC_LOCALPORT,51,14,30,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
EDITTEXT IDC_HOSTPORT,158,44,29,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER
GROUPBOX "",IDC_STATIC,4,2,276,127
LTEXT "ض˿",IDC_STATIC,11,17,32,9
LTEXT "ڽڵпӾַ̬㲥ַȡ",IDC_STATIC,17,135,243,13
LTEXT "˿",IDC_STATIC,137,47,21,9
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,10,36,265,1
LTEXT " - IP",IDC_STATIC,11,47,31,9
END
IDD_SETTINGS2 DIALOGEX 22, 17, 243, 242
STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Settings"
FONT 9, "Arial", 400, 0, 0x0
BEGIN
GROUPBOX "",IDC_STATIC,3,3,117,105
LTEXT "",IDC_STATIC,7,17,17,8
EDITTEXT IDC_BEEPFREQ,41,15,45,12,ES_AUTOHSCROLL
LTEXT "(Hz)",IDC_STATIC,90,17,15,8
LTEXT "",IDC_STATIC,7,32,17,8
EDITTEXT IDC_BEEPVOL,41,30,45,12,ES_AUTOHSCROLL
LTEXT "0~1.0",IDC_STATIC,90,32,19,8
LTEXT "",IDC_STATIC,7,47,30,8
EDITTEXT IDC_SENDPERIOD,41,45,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,91,47,16,8
LTEXT "ֹͣ",IDC_STATIC,7,62,30,8
EDITTEXT IDC_SENDILDELIMIT,41,60,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,91,62,16,8
LTEXT "CW",IDC_STATIC,7,77,30,8
EDITTEXT IDC_CW,41,75,45,12,ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER
LTEXT "VK code",IDC_STATIC,91,77,27,8
LTEXT "ոӳ",IDC_STATIC,7,92,30,8
EDITTEXT IDC_WORDDELAY,41,90,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,91,92,16,8
GROUPBOX "",IDC_STATIC,125,3,115,105
LTEXT "",IDC_STATIC,132,17,30,8
EDITTEXT IDC_RECVANALYZESAMPLES,166,15,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "()",IDC_STATIC,216,17,12,8
LTEXT "",IDC_STATIC,132,32,30,8
EDITTEXT IDC_RECVPERIOD,166,30,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,216,32,16,8
LTEXT "ֹͣ",IDC_STATIC,132,47,30,8
EDITTEXT IDC_RECVILDELIMIT,166,45,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,216,47,16,8
LTEXT "ֵƽ",IDC_STATIC,132,62,30,8
EDITTEXT IDC_RECVTHRESHOLD,166,60,45,12,ES_AUTOHSCROLL
LTEXT "0~1.0",IDC_STATIC,216,62,19,8
LTEXT "ʼƵ",IDC_STATIC,132,77,30,8
EDITTEXT IDC_RECVFREQSTART,166,75,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(Hz)",IDC_STATIC,216,77,14,8
LTEXT "ֹƵ",IDC_STATIC,132,92,30,8
EDITTEXT IDC_RECVFREQEND,166,90,45,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(Hz)",IDC_STATIC,216,92,14,8
GROUPBOX "CW",IDC_STATIC,3,110,237,45
LTEXT """""",IDC_STATIC,7,122,30,8
EDITTEXT IDC_SHORTHIT,36,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,65,122,16,8
LTEXT """""",IDC_STATIC,7,136,30,8
EDITTEXT IDC_LONGHIT,36,135,25,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,65,136,16,8
LTEXT "",IDC_STATIC,88,121,30,8
EDITTEXT IDC_HITDELAY,117,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,147,136,16,8
LTEXT "ַ",IDC_STATIC,88,136,30,8
EDITTEXT IDC_LETTERDELAY,117,135,25,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(ms)",IDC_STATIC,147,121,16,8
LTEXT "",IDC_STATIC,170,121,30,8
EDITTEXT IDC_SPEED,187,120,25,12,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "(wpm)",IDC_STATIC,216,121,20,8
PUSHBUTTON "",IDC_CALCSPEED,170,136,66,10
GROUPBOX "˿ڿ",IDC_STATIC,3,156,237,28
CONTROL "",IDC_EXTPORTENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,168,32,8
LTEXT "ַ(HEX)",IDC_STATIC,51,168,32,8
EDITTEXT IDC_EXTPORTADDR,85,166,32,12,ES_UPPERCASE | ES_READONLY
LTEXT "(HEX)",IDC_STATIC,125,168,32,8
EDITTEXT IDC_OPENBYTE,161,166,13,12,ES_UPPERCASE
LTEXT "ر(HEX)",IDC_STATIC,181,168,32,8
EDITTEXT IDC_CLOSEBYTE,215,166,13,12,ES_UPPERCASE
GROUPBOX "ϰ",IDC_STATIC,3,190,237,28
LTEXT "ַ",IDC_STATIC,7,202,32,8
EDITTEXT IDC_KOCHCHARS,41,200,138,12,ES_UPPERCASE | ES_AUTOHSCROLL | ES_WANTRETURN
LTEXT "ֳ",IDC_STATIC,186,202,32,8
EDITTEXT IDC_KOCHWORDLEN,215,200,16,12,ES_AUTOHSCROLL | ES_NUMBER
PUSHBUTTON "ȷ",IDC_ACCEPT,190,224,47,10
PUSHBUTTON "ȡ",IDCANCEL,135,224,47,10
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
RIGHTMARGIN, 213
BOTTOMMARGIN, 72
END
IDD_SETTINGS, DIALOG
BEGIN
RIGHTMARGIN, 251
END
IDD_TEST, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 341
TOPMARGIN, 7
BOTTOMMARGIN, 141
END
IDD_GENERAL, DIALOG
BEGIN
BOTTOMMARGIN, 161
END
IDD_SEND, DIALOG
BEGIN
RIGHTMARGIN, 280
BOTTOMMARGIN, 160
END
IDD_RECV, DIALOG
BEGIN
BOTTOMMARGIN, 122
END
IDD_IO, DIALOG
BEGIN
BOTTOMMARGIN, 122
END
IDD_KOCH, DIALOG
BEGIN
BOTTOMMARGIN, 152
END
IDD_NETWORK, DIALOG
BEGIN
BOTTOMMARGIN, 152
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_LOGO BITMAP "logo.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_APP_TITLE "Lakey 2.2 (Paper)"
IDC_LAKEY "LAKEY"
END
#endif // (壬й) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
================================================
FILE: src/Lakey.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31313.79
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lakey", "Lakey.vcxproj", "{B20DFA3B-4DF4-464C-883D-940012A2178C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test4fft", "..\test4fft\test4fft.vcxproj", "{5A8D8698-A0EF-404A-B421-B49C0336EEB4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B20DFA3B-4DF4-464C-883D-940012A2178C}.Debug|Win32.ActiveCfg = Debug|Win32
{B20DFA3B-4DF4-464C-883D-940012A2178C}.Debug|Win32.Build.0 = Debug|Win32
{B20DFA3B-4DF4-464C-883D-940012A2178C}.Release|Win32.ActiveCfg = Release|Win32
{B20DFA3B-4DF4-464C-883D-940012A2178C}.Release|Win32.Build.0 = Release|Win32
{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Debug|Win32.ActiveCfg = Debug|Win32
{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Debug|Win32.Build.0 = Debug|Win32
{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Release|Win32.ActiveCfg = Release|Win32
{5A8D8698-A0EF-404A-B421-B49C0336EEB4}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {779ADF4C-AB52-4F67-9F6C-1407590493CD}
EndGlobalSection
EndGlobal
================================================
FILE: src/Lakey.vcproj
================================================
================================================
FILE: src/Lakey.vcxproj
================================================
Debug
Win32
Debug
x64
Release
Win32
Release
x64
{B20DFA3B-4DF4-464C-883D-940012A2178C}
Lakey
Win32Proj
Application
MultiByte
v142
Application
MultiByte
v142
Application
MultiByte
v142
Application
MultiByte
v142
<_ProjectFileVersion>10.0.30319.1
Debug\
Debug\
true
true
Release\
Release\
false
false
$(DXSDK_DIR)include;$(IncludePath)
$(DXSDK_DIR)include;$(IncludePath)
$(DXSDK_DIR)lib\x86;$(LibraryPath)
$(DXSDK_DIR)lib\x86;$(LibraryPath)
$(DXSDK_DIR)include;$(IncludePath)
$(DXSDK_DIR)include;$(IncludePath)
$(DXSDK_DIR)lib\x86;$(LibraryPath)
$(DXSDK_DIR)lib\x86;$(LibraryPath)
Disabled
%(AdditionalIncludeDirectories)
WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800;%(PreprocessorDefinitions)
true
EnableFastChecks
MultiThreadedDebug
Use
Level3
EditAndContinue
Cdecl
dxguid.lib;dsound.lib;WS2_32.lib;Comdlg32.lib;User32.lib;Gdi32.lib;%(AdditionalDependencies)
$(OutDir)Lakey.exe
%(AdditionalLibraryDirectories)
true
$(OutDir)Lakey.pdb
Windows
MachineX86
Disabled
%(AdditionalIncludeDirectories)
WIN32;_DEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
Use
Level3
ProgramDatabase
Cdecl
dxguid.lib;dsound.lib;WS2_32.lib;Comdlg32.lib;User32.lib;Gdi32.lib;%(AdditionalDependencies)
$(OutDir)Lakey.exe
%(AdditionalLibraryDirectories)
true
$(OutDir)Lakey.pdb
Windows
MaxSpeed
OnlyExplicitInline
true
_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800;%(PreprocessorDefinitions)
true
MultiThreaded
true
Use
Level3
ProgramDatabase
dxguid.lib;dsound.lib;WS2_32.lib;Comdlg32.lib;User32.lib;Gdi32.lib;%(AdditionalDependencies)
$(OutDir)Lakey.exe
true
Windows
true
true
MachineX86
MaxSpeed
OnlyExplicitInline
true
_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_WIN32_WINNT=0x0600;_WIN32_IE=0x0800;%(PreprocessorDefinitions)
true
MultiThreaded
true
Use
Level3
ProgramDatabase
dxguid.lib;dsound.lib;WS2_32.lib;Comdlg32.lib;User32.lib;Gdi32.lib;%(AdditionalDependencies)
$(OutDir)Lakey.exe
true
Windows
true
true
Create
Create
Create
Create
Designer
================================================
FILE: src/Lakey.vcxproj.filters
================================================
{4afbbfc2-bf6b-49a7-ac06-2381afa2f2cc}
cpp;c;cxx;def;odl;idl;hpj;bat;asm
{8e69d1d8-f0fa-4505-afa8-68c0163cbf89}
h;hpp;hxx;hm;inl;inc
{61be6223-e008-4882-b33e-1feda47e14f1}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
源文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
头文件
资源文件
资源文件
资源文件
资源文件
资源文件
资源文件
================================================
FILE: src/Lakey.vcxproj.user
================================================
================================================
FILE: src/LakeyMain.cpp
================================================
// LakeyMain.cpp : Ӧóڵ㡣
//
#include "stdafx.h"
#include "Lakey.h"
#include "windows.h"
#include "Richedit.h"
#include "commctrl.h"
#include
#include
#include "LakeyMainWindow.h"
#include "LakeySetting.h"
#include "LaWaveFile.h"
#include "CommFunc.h"
#include "mytest.h"
//#include "winio.h"
#define MAX_LOADSTRING 100
#define MAX_KOCH_SAMPLE 256
#define SAFE_DELETE(x) if (x) { delete x; x = NULL; }
#define PROMPT_BUFF_LEN 256
#define SETTING_PAGES 6
// ȫֱ
HINSTANCE hInst; // ǰʵ
TCHAR szTitle[MAX_LOADSTRING]; // ı
TCHAR szWindowClass[MAX_LOADSTRING]; //
CLakeyMainWindow* g_pMainWnd = NULL;
CLakeySetting* g_pGlobalSetting = NULL;
CUSTOMIZE g_oTmpCust;
HostList g_oTmpHosts;
HWND g_hWnd = NULL;
char g_vCopyText[MAX_KOCH_SAMPLE + 1];
char g_vKochSample[MAX_KOCH_SAMPLE];
char g_vPromptText[PROMPT_BUFF_LEN];
char g_vPromptBuff[PROMPT_BUFF_LEN] = {'\0'};
// ˴ģаĺǰ
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK SettingsPage(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
BOOL OnSettingsInit(HWND hDlg);
void DestroyCurrPage(HWND hDlg);
void SaveTemp(HWND hDlg);
void AddHost(HWND hCtrl, HOSTNODE* pNode);
LRESULT CALLBACK CopyPad(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK TestDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK PromptProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
const char* ConvertKochPathname(char* pDest, const char* pSrc, UINT nBuffLen);
void InitKochSample();
void PromptToWave(HWND hWnd);
void KochToWave(HWND hWnd);
void TextToWave(const char* pPathname, const char* pTxt, UINT nTxtLen, UINT nWordLen);
void TextToAskWave(char* pWavePathBuff, UINT nWavePathBuffSize, const char* pBuff, UINT nCount, HWND hWnd);
void CalcSpeed(HWND hDlg);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// Application::EnableVisualStyles();
// Application::SetCompatibleTextRenderingDefault(false);
InitCommonControls();
g_pGlobalSetting = new CLakeySetting();
// TODO: ڴ˷ô롣
MSG msg;
HACCEL hAccelTable;
// ʼȫַ
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_LAKEY, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// ִӦóʼ
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_LAKEY);
// Ϣѭ
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
delete g_pGlobalSetting;
return (int) msg.wParam;
}
//
// MyRegisterClass()
//
// Ŀģעᴰࡣ
//
// עͣ
//
// ϣӵ Windows 95
// RegisterClassEx֮ǰ˴ Win32 ϵͳʱ
// Ҫ˺÷ô˺
// ʮҪӦóͿԻù
// ʽȷġСͼꡣ
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_LAKEY);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = (LPCTSTR)IDC_LAKEY;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// InitInstance(HANDLE, int)
//
// Ŀģʵ
//
// עͣ
//
// ڴ˺Уȫֱбʵ
// ʾڡ
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // ʵ洢ȫֱ
g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
g_pGlobalSetting->cust.m_oWindowRect.left, g_pGlobalSetting->cust.m_oWindowRect.top
, g_pGlobalSetting->cust.m_oWindowRect.right - g_pGlobalSetting->cust.m_oWindowRect.left
, g_pGlobalSetting->cust.m_oWindowRect.bottom - g_pGlobalSetting->cust.m_oWindowRect.top
, NULL, NULL, hInstance, NULL);
if (!g_hWnd)
{
return FALSE;
}
g_pMainWnd = new CLakeyMainWindow(g_hWnd, g_pGlobalSetting);
::LoadLibrary("RICHED20.dll");
if (!g_pMainWnd->Initialize())
return FALSE;
g_pMainWnd->NetworkStartup();
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
return TRUE;
}
//
// WndProc(HWND, unsigned, WORD, LONG)
//
// ĿģڵϢ
//
// WM_COMMAND - Ӧó˵
// WM_PAINT -
// WM_DESTROY - ˳Ϣ
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
// PAINTSTRUCT ps;
// HDC hdc;
LRESULT r;
if (g_pMainWnd)
if (g_pMainWnd->OnMessage(message, wParam, lParam, &r))
return TRUE;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// ˵ѡ
switch (wmId)
{
case IDM_TEST:
{
//Test(hWnd, message, wParam, lParam);
break;
}
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_SETTINGS:
if (IDC_ACCEPT == DialogBox(hInst, (LPCTSTR)IDD_SETTINGS, hWnd, (DLGPROC)Settings))
{
if (g_pGlobalSetting->cust.m_bNetworkEnabled)
g_pMainWnd->NetworkStartup();
else
g_pMainWnd->NetworkShutdown();
}
break;
case IDM_KOCHSTART:
if (2 > strlen(g_pGlobalSetting->cust.m_vKochChar))
{
MessageBox(hWnd, "ûKochѵַ\nڲ˵[->]2ASCIIַ", "", MB_OK);
break;
}
DialogBox(hInst, (LPCTSTR)IDD_COPYPAD, hWnd, (DLGPROC)CopyPad);
break;
case IDM_KOCHWAVE:
{
if (2 > strlen(g_pGlobalSetting->cust.m_vKochChar))
{
MessageBox(hWnd, "ûKochѵַ\nڲ˵[->]2ASCIIַ", "", MB_OK);
break;
}
KochToWave(hWnd);
break;
}
case IDM_PROMPTWAVE:
{
strcpy(g_vPromptText, "벻200ַȵַ: ");
if (0 < DialogBox(hInst, (LPCTSTR)IDD_PROMPTBOX, hWnd, (DLGPROC)PromptProc))
{
if (0 < strlen(g_vPromptBuff))
{
PromptToWave(hWnd);
}
}
break;
}
case IDA_TEST:
DialogBox(hInst, (LPCTSTR)IDD_TEST, hWnd, (DLGPROC)TestDlg);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
SAFE_DELETE(g_pMainWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// ڡϢ
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
// 1 "PARIS" = 1 word
// .__. ._ ._. .. ...
//
void CalcSpeed(HWND hDlg)
{
if (!GetDlgItem(hDlg, IDC_SPEED))
return;
WPMS wpms;
wpms.wdelay = g_oTmpCust.m_nWordDelay;
GetDlgItemInt(hDlg, IDC_SHORTHIT, &wpms.di);
GetDlgItemInt(hDlg, IDC_LONGHIT, &wpms.dah);
GetDlgItemInt(hDlg, IDC_HITDELAY, &wpms.hdelay);
GetDlgItemInt(hDlg, IDC_LETTERDELAY, &wpms.ldelay);
paramsToWpm(&wpms);
SetDlgItemInt(hDlg, IDC_SPEED, (UINT)wpms.wpm, TRUE);
}
void UncalcSpeed(HWND hDlg)
{
WPMS wpms;
int wpm;
GetDlgItemInt(hDlg, IDC_SPEED, &wpm);
if (0 == wpm)
return;
wpms.wpm = (float)wpm;
wpmToParams(&wpms);
SetDlgItemInt(hDlg, IDC_SHORTHIT, wpms.di, TRUE);
SetDlgItemInt(hDlg, IDC_LONGHIT, wpms.dah, TRUE);
SetDlgItemInt(hDlg, IDC_HITDELAY, wpms.hdelay, TRUE);
SetDlgItemInt(hDlg, IDC_LETTERDELAY, wpms.ldelay, TRUE);
//SetDlgItemInt(hDlg, IDC_WORDDELAY, nHitLen * 3, TRUE);
g_oTmpCust.m_nWordDelay = wpms.wdelay;
}
DLGTEMPLATE * WINAPI DoLockDlgRes(LPCSTR lpszResName)
{
HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);
HGLOBAL hglb = LoadResource(hInst, hrsrc);
return (DLGTEMPLATE *) LockResource(hglb);
}
VOID WINAPI OnSelChanged(HWND hDlg)
{
HWND hTab = GetDlgItem(hDlg, IDC_SETTINGSTAB);
int iSel = TabCtrl_GetCurSel(hTab);
DestroyCurrPage(hTab);
DLGTEMPLATE* pDlgTemp = NULL;
switch(iSel)
{
case 0:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_GENERAL));
break;
case 1:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_SEND));
break;
case 2:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_RECV));
break;
case 3:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_KOCH));
break;
case 4:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_NETWORK));
break;
case 5:
pDlgTemp = DoLockDlgRes(MAKEINTRESOURCE(IDD_IO));
break;
}
if (pDlgTemp)
{
HWND hCurrPage = CreateDialogIndirect(hInst, pDlgTemp, hDlg, SettingsPage);
if (hCurrPage)
{
SetWindowLongPtr(hTab, GWL_USERDATA, (LONG)hCurrPage);
}
}
}
BOOL OnSettingsInit(HWND hDlg)
{
g_pGlobalSetting->GetCustomize(&g_oTmpCust);
g_oTmpHosts = g_pGlobalSetting->hosts;
//g_oTmpCust = g_pGlobalSetting->cust;
HWND hTabCtrl = GetDlgItem(hDlg, IDC_SETTINGSTAB);
TCITEM tie;
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "";
TabCtrl_InsertItem(hTabCtrl, 0, &tie);
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "";
TabCtrl_InsertItem(hTabCtrl, 1, &tie);
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "";
TabCtrl_InsertItem(hTabCtrl, 2, &tie);
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "Kochѵ";
TabCtrl_InsertItem(hTabCtrl, 3, &tie);
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "";
TabCtrl_InsertItem(hTabCtrl, 4, &tie);
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "I/O";
TabCtrl_InsertItem(hTabCtrl, 5, &tie);
OnSelChanged(hDlg);
return TRUE;
}
void HostListAdd(HWND hListCtrl, char* pHost, const char* pPort, int idx)
{
LVITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM; // | LVIF_IMAGE
lvi.state = 0;
lvi.stateMask = 0;
lvi.iSubItem = 0;
lvi.iItem = idx;
lvi.pszText = pHost;
lvi.lParam = (LPARAM)pPort;
ListView_InsertItem(hListCtrl, &lvi);
}
BOOL OnSettingPagesInit(HWND hDlg)
{
SetDlgItemDec(hDlg, IDC_BEEPFREQ, g_oTmpCust.m_rBeepFreq);
SetDlgItemDec(hDlg, IDC_BEEPVOL, g_oTmpCust.m_rBeepVol);
SetDlgItemInt(hDlg, IDC_SENDPERIOD, g_oTmpCust.m_nSendJournalPeriod, TRUE);
SetDlgItemInt(hDlg, IDC_SENDILDELIMIT, g_oTmpCust.m_nSendIdleLimit, TRUE);
SetDlgItemInt(hDlg, IDC_CW, g_oTmpCust.m_oCwKeyButton.nKeyCode, TRUE);
SetDlgItemInt(hDlg, IDC_WORDDELAY, g_oTmpCust.m_nWordDelay, TRUE);
SetDlgItemInt(hDlg, IDC_RECVANALYZESAMPLES, g_oTmpCust.m_nRecvAnalyzeSamples, TRUE);
SetDlgItemInt(hDlg, IDC_RECVPERIOD, g_oTmpCust.m_nRecvJournalPeriod, TRUE);
SetDlgItemInt(hDlg, IDC_RECVILDELIMIT, g_oTmpCust.m_nRecvIdleLimit, TRUE);
SetDlgItemDec(hDlg, IDC_RECVTHRESHOLD, g_oTmpCust.m_rRecvThreshold);
SetDlgItemInt(hDlg, IDC_RECVFREQSTART, g_oTmpCust.m_nRecvFreqStart, TRUE);
SetDlgItemInt(hDlg, IDC_RECVFREQEND, g_oTmpCust.m_nRecvFreqEnd, TRUE);
SetDlgItemInt(hDlg, IDC_SHORTHIT, g_oTmpCust.m_nShortHit, TRUE);
SetDlgItemInt(hDlg, IDC_LONGHIT, g_oTmpCust.m_nLongHit, TRUE);
SetDlgItemInt(hDlg, IDC_HITDELAY, g_oTmpCust.m_nHitDelay, TRUE);
SetDlgItemInt(hDlg, IDC_LETTERDELAY, g_oTmpCust.m_nLetterDelay, TRUE);
SetDlgItemText(hDlg, IDC_KOCHCHARS, g_oTmpCust.m_vKochChar);
SetDlgItemInt(hDlg, IDC_KOCHWORDLEN, g_oTmpCust.m_nKochWordLen, TRUE);
HWND hCtrl = GetDlgItem(hDlg, IDC_EXTPORTENABLE);
if (hCtrl)
SendMessage(hCtrl, BM_SETCHECK, g_oTmpCust.m_nExtPortEnable, 0);
SetDlgItemHex(hDlg, IDC_EXTPORTADDR, g_oTmpCust.m_nExtPortAddr);
SetDlgItemHex(hDlg, IDC_OPENBYTE, g_oTmpCust.m_nOpenByte);
SetDlgItemHex(hDlg, IDC_CLOSEBYTE, g_oTmpCust.m_nCloseByte);
CalcSpeed(hDlg);
SetDlgItemInt(hDlg, IDC_LOCALPORT, g_oTmpCust.m_nLocalPort, TRUE);
SetDlgItemInt(hDlg, IDC_HOSTPORT, g_oTmpCust.m_nLocalPort, TRUE);
if (NULL != (hCtrl = GetDlgItem(hDlg, IDC_HOSTLIST)))
{
LRESULT nStyle = SendMessage(hCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
SendMessage(hCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, nStyle | LVS_EX_FULLROWSELECT);
//DWORD nStyle = GetWindowLong(hCtrl, GWL_EXSTYLE) | LVS_EX_FULLROWSELECT;
//SetWindowLong(hCtrl, GWL_EXSTYLE, nStyle);
// char szText[256]; // temporary buffer
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT |
LVCF_SUBITEM;
lvc.iSubItem = 0;
lvc.pszText = "";
lvc.cx = 180;
lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(hCtrl, 0, &lvc);
lvc.iSubItem = 1;
lvc.pszText = "˿";
lvc.cx = 80;
lvc.fmt = LVCFMT_LEFT;
ListView_InsertColumn(hCtrl, 1, &lvc);
for (DWORD i = 0; i < g_oTmpHosts.size(); ++i)
{
AddHost(hCtrl, &(g_oTmpHosts[i]));
}
}
CheckDlgButton(hDlg, IDC_NWENABLED, g_oTmpCust.m_bNetworkEnabled ? BST_CHECKED : BST_UNCHECKED);
return TRUE;
}
void AddHost(HWND hCtrl, HOSTNODE* pNode)
{
LVITEM lvi;
lvi.mask = LVIF_TEXT; // | LVIF_STATE | LVIF_PARAM; // | LVIF_IMAGE
lvi.state = 0;
lvi.stateMask = 0;
lvi.iSubItem = 0;
lvi.iItem = ListView_GetItemCount(hCtrl);
lvi.pszText = pNode->szHostName;
lvi.lParam = 0; //(LPARAM)(pNode);
ListView_InsertItem(hCtrl, &lvi);
lvi.iSubItem = 1;
lvi.pszText = pNode->szPort;
ListView_SetItem(hCtrl, &lvi);
}
void DelHost(HWND hCtrl)
{
int nIdx = ListView_GetSelectionMark(hCtrl);
if (0 <= nIdx)
ListView_DeleteItem(hCtrl, nIdx);
}
void SaveTemp(HWND hDlg)
{
GetDlgItemDec(hDlg, IDC_BEEPFREQ, &g_oTmpCust.m_rBeepFreq);
GetDlgItemDec(hDlg, IDC_BEEPVOL, &g_oTmpCust.m_rBeepVol);
GetDlgItemInt(hDlg, IDC_SENDPERIOD, &g_oTmpCust.m_nSendJournalPeriod);
GetDlgItemInt(hDlg, IDC_SENDILDELIMIT, &g_oTmpCust.m_nSendIdleLimit);
GetDlgItemInt(hDlg, IDC_CW, &g_oTmpCust.m_oCwKeyButton.nKeyCode);
GetDlgItemInt(hDlg, IDC_WORDDELAY, &g_oTmpCust.m_nWordDelay);
GetDlgItemInt(hDlg, IDC_RECVANALYZESAMPLES, &g_oTmpCust.m_nRecvAnalyzeSamples);
GetDlgItemInt(hDlg, IDC_RECVPERIOD, &g_oTmpCust.m_nRecvJournalPeriod);
GetDlgItemInt(hDlg, IDC_RECVILDELIMIT, &g_oTmpCust.m_nRecvIdleLimit);
GetDlgItemDec(hDlg, IDC_RECVTHRESHOLD, &g_oTmpCust.m_rRecvThreshold);
GetDlgItemInt(hDlg, IDC_RECVFREQSTART, &g_oTmpCust.m_nRecvFreqStart);
GetDlgItemInt(hDlg, IDC_RECVFREQEND, &g_oTmpCust.m_nRecvFreqEnd);
GetDlgItemInt(hDlg, IDC_SHORTHIT, &g_oTmpCust.m_nShortHit);
GetDlgItemInt(hDlg, IDC_LONGHIT, &g_oTmpCust.m_nLongHit);
GetDlgItemInt(hDlg, IDC_HITDELAY, &g_oTmpCust.m_nHitDelay);
GetDlgItemInt(hDlg, IDC_LETTERDELAY, &g_oTmpCust.m_nLetterDelay);
GetDlgItemTxt(hDlg, IDC_KOCHCHARS, g_oTmpCust.m_vKochChar, sizeof(g_oTmpCust.m_vKochChar) / sizeof(char));
GetDlgItemInt(hDlg, IDC_KOCHWORDLEN, &g_oTmpCust.m_nKochWordLen);
HWND hCtrl = GetDlgItem(hDlg, IDC_EXTPORTENABLE);
g_oTmpCust.m_nExtPortEnable =
(int)SendMessage(hCtrl, BM_GETCHECK, 0, 0);
GetDlgItemHex(hDlg, IDC_EXTPORTADDR, &g_oTmpCust.m_nExtPortAddr);
GetDlgItemHex(hDlg, IDC_OPENBYTE, &g_oTmpCust.m_nOpenByte);
GetDlgItemHex(hDlg, IDC_CLOSEBYTE, &g_oTmpCust.m_nCloseByte);
hCtrl = GetDlgItem(hDlg, IDC_HOSTLIST);
if (NULL != hCtrl)
{
int nTmp = g_oTmpCust.m_nLocalPort;
GetDlgItemInt(hDlg, IDC_LOCALPORT, &nTmp);
if (0 < nTmp && 65535 > nTmp)
g_oTmpCust.m_nLocalPort = nTmp;
g_oTmpHosts.resize(ListView_GetItemCount(hCtrl));
for (UINT i = 0; i < g_oTmpHosts.size(); ++i)
{
ListView_GetItemText(hCtrl, i, 0, g_oTmpHosts[i].szHostName, sizeof(g_oTmpHosts[i].szHostName));
ListView_GetItemText(hCtrl, i, 1, g_oTmpHosts[i].szPort, sizeof(g_oTmpHosts[i].szPort));
}
g_oTmpCust.m_bNetworkEnabled = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_NWENABLED));
}
}
void DestroyCurrPage(HWND hTab)
{
HWND hCurrPage = (HWND)GetWindowLongPtr(hTab, GWL_USERDATA);
// Destroy the current child dialog box, if any.
if (hCurrPage)
{
SaveTemp(hCurrPage);
DestroyWindow(hCurrPage);
SetWindowLong(hTab, GWL_USERDATA, (LONG)NULL);
}
}
void OnSettingsAccept(HWND hDlg)
{
HWND hTab = GetDlgItem(hDlg, IDC_SETTINGSTAB);
DestroyCurrPage(hTab);
g_pGlobalSetting->SetCustomize(&g_oTmpCust);
g_pGlobalSetting->hosts = g_oTmpHosts;
SAFE_DELETE(g_pMainWnd);
g_pMainWnd = new CLakeyMainWindow(g_hWnd, g_pGlobalSetting);
g_pMainWnd->Initialize();
}
// áϢ
LRESULT CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
return OnSettingsInit(hDlg);
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_ACCEPT:
{
OnSettingsAccept(hDlg);
}
case IDCANCEL:
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
}
break;
}
case WM_NOTIFY:
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
switch(LOWORD(wParam))
{
case IDC_SETTINGSTAB:
{
if (TCN_SELCHANGE == lpnmhdr->code)
OnSelChanged(hDlg);
break;
}
}
break;
}
}
return FALSE;
}
INT_PTR CALLBACK SettingsPage(HWND hPage, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
SetWindowPos(hPage, HWND_TOP,
8, 32,
0, 0, SWP_NOSIZE);
return OnSettingPagesInit(hPage);
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_CALCSPEED:
{
CalcSpeed(hPage);
return TRUE;
}
case IDC_SPEED:
{
switch(HIWORD(wParam))
{
case EN_KILLFOCUS:
UncalcSpeed(hPage);
break;
}
break;
}
case IDC_HOSTADD:
{
HOSTNODE node;
node.szHostName[0] = '\0';
node.szPort[0] = '\0';
GetDlgItemTxt(hPage, IDC_HOSTNAME, node.szHostName, sizeof(node.szHostName));
if (0 < strlen(node.szHostName))
{
int nPort;
GetDlgItemInt(hPage, IDC_HOSTPORT, &nPort);
if (0 < nPort && 65535 > nPort)
{
sprintf(node.szPort, "%d", nPort);
AddHost(GetDlgItem(hPage, IDC_HOSTLIST), &node);
}
else
{
MessageBox(NULL, "ȱ˿", "", MB_OK);
}
}
else
{
MessageBox(NULL, "ȱIP", "", MB_OK);
}
break;
}
case IDC_HOSTDEL:
{
DelHost(GetDlgItem(hPage, IDC_HOSTLIST));
break;
}
}
break;
}
case WM_NOTIFY:
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
switch(LOWORD(wParam))
{
case IDC_HOSTLIST:
{
switch (lpnmhdr->code)
{
case LVN_ENDLABELEDIT:
{
NMLVDISPINFO* plvdi = (NMLVDISPINFO*)lParam;
plvdi->item.mask |= LVIF_TEXT;
return TRUE;
} // end of case LVN_ENDLABELEDIT
case LVN_BEGINLABELEDIT:
{
NMLVDISPINFO* plvdi = (NMLVDISPINFO*)lParam;
plvdi->item.mask |= LVIF_TEXT;
return FALSE;
} // end of case LVN_ENDLABELEDIT
} // end of switch
break;
} // end of case IDC_HOSTLIST
}
break;
} // end of case WM_NOTIFY
}
return FALSE;
}
void InitKochSample()
{
int nSampleRange = (int)strlen(g_pGlobalSetting->cust.m_vKochChar);
srand((unsigned)time(NULL ));
for (int i = 0; i < MAX_KOCH_SAMPLE; ++i)
{
if (0 < (i + 1) % (g_pGlobalSetting->cust.m_nKochWordLen + 1))
{
g_vKochSample[i] = g_pGlobalSetting->cust.m_vKochChar[rand() % nSampleRange];
}
else
{
g_vKochSample[i] = ' ';
}
}
}
#define TIMER_ELAPSETIME 101
// Ϣ
LRESULT CALLBACK CopyPad(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bFinished = FALSE;
static DWORD nTickCountStart = 0;
switch (message)
{
case WM_INITDIALOG:
{
bFinished = FALSE;
InitKochSample();
MessageBox(hDlg, "[ȷ][س]ʼ...", "", MB_OK);
g_pMainWnd->PushText(g_vKochSample, MAX_KOCH_SAMPLE, 0);
SetTimer(hDlg, TIMER_ELAPSETIME, 220, NULL);
nTickCountStart = GetTickCount();
SendMessage(GetDlgItem(hDlg, IDC_COPYTEXT), EM_SETEVENTMASK, 0, ENM_CHANGE);
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_ACCEPT:
{
if (!bFinished)
{
KillTimer(hDlg, TIMER_ELAPSETIME);
g_pMainWnd->ClearQueue();
/*
char vBuff[MAX_KOCH_SAMPLE * 2 + 256];
memset(vBuff, 0, sizeof(vBuff));
GetDlgItemText(hDlg, IDC_COPYTEXT, g_vCopyText, MAX_KOCH_SAMPLE);
g_vCopyText[MAX_KOCH_SAMPLE] = NULL;
strcpy(vBuff, g_vCopyText);
strcat(vBuff, "\r\n----------------------------------------------------------------------------------\r\n");
strncat(vBuff, g_vKochSample, strlen(g_vCopyText));
SetDlgItemText(hDlg, IDC_COPYTEXT, vBuff);
*/
SetDlgItemText(hDlg, IDC_ACCEPT, "ر");
bFinished = TRUE;
/*
CHARFORMAT fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.cbSize = sizeof(fmt);
fmt.dwMask = CFM_COLOR;
fmt.crTextColor = (toupper(g_vCopyText[nCopied - 1]) == g_vKochSample[nCopied - 1] ? RGB(0, 0, 0) : RGB(255, 0, 0));
SendMessage((HWND)lParam, EM_SETCHARFORMAT, SCF_SELECTION, ((LPARAM)&fmt));
*/
break;
}
}
case IDCANCEL:
{
KillTimer(hDlg, TIMER_ELAPSETIME);
g_pMainWnd->ClearQueue();
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
case IDC_COPYTEXT:
{
if (EN_CHANGE == HIWORD(wParam))
{
g_vCopyText[MAX_KOCH_SAMPLE] = NULL;
GetDlgItemTxt(hDlg, IDC_COPYTEXT, g_vCopyText, MAX_KOCH_SAMPLE);
char vBuff[20];
int nCopied = (int)strlen(g_vCopyText);
sprintf(vBuff, "%d", nCopied);
SetDlgItemText(hDlg, IDC_COPIED, vBuff);
int nCorrect = 0;
for (int i = 0; i < nCopied; ++i)
{
if (toupper(g_vCopyText[i]) == g_vKochSample[i])
++nCorrect;
}
sprintf(vBuff, "%d", nCopied - nCorrect);
SetDlgItemText(hDlg, IDC_INCORRECT, vBuff);
if (0 < nCopied)
sprintf(vBuff, "%2.1f%%", 100.0f * nCorrect / nCopied);
else
sprintf(vBuff, "%%");
SetDlgItemText(hDlg, IDC_CORRECTPERC, vBuff);
HWND hCopyText = (HWND)lParam;
CHARRANGE oRange;
oRange.cpMin = nCopied - 1;
oRange.cpMax = nCopied;
SendMessage(hCopyText, EM_EXSETSEL, 0, ((LPARAM)&oRange));
CHARFORMAT fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.cbSize = sizeof(fmt);
fmt.dwMask = CFM_COLOR;
fmt.crTextColor = (toupper(g_vCopyText[nCopied - 1]) == g_vKochSample[nCopied - 1] ? RGB(0, 0, 0) : RGB(255, 0, 0));
SendMessage(hCopyText, EM_SETCHARFORMAT, SCF_SELECTION, ((LPARAM)&fmt));
oRange.cpMin = oRange.cpMax;
SendMessage(hCopyText, EM_EXSETSEL, 0, ((LPARAM)&oRange));
return 0;
}
break;
}
}
break;
}
/* case WM_NOTIFY:
{
if (IDC_COPYTEXT == wParam)
{
LPNMHDR pNMHDR = (LPNMHDR)lParam;
switch(pNMHDR->code)
{
case EN_SELCHANGE:
{
g_vCopyText[MAX_KOCH_SAMPLE] = NULL;
GetDlgItemText(hDlg, IDC_COPYTEXT, g_vCopyText, MAX_KOCH_SAMPLE);
char vBuff[20];
int nCopied = (int)strlen(g_vCopyText);
sprintf(vBuff, "%d", nCopied);
SetDlgItemText(hDlg, IDC_COPIED, vBuff);
int nCorrect = 0;
for (int i = 0; i < nCopied; ++i)
{
if (toupper(g_vCopyText[i]) == g_vKochSample[i])
++nCorrect;
}
sprintf(vBuff, "%d", nCopied - nCorrect);
SetDlgItemText(hDlg, IDC_INCORRECT, vBuff);
if (0 < nCopied)
sprintf(vBuff, "%2.1f%%", 100.0f * nCorrect / nCopied);
else
sprintf(vBuff, "%%");
SetDlgItemText(hDlg, IDC_CORRECTPERC, vBuff);
CHARFORMAT fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.cbSize = sizeof(fmt);
fmt.dwMask = CFM_COLOR;
fmt.crTextColor = (toupper(g_vCopyText[nCopied - 1]) == g_vKochSample[nCopied - 1] ? RGB(0, 0, 0) : RGB(255, 0, 0));
SendMessage((HWND)lParam, EM_SETCHARFORMAT, SCF_SELECTION, ((LPARAM)&fmt));
break;
}
}
}
break;
}
*/
case WM_TIMER:
{
if (TIMER_ELAPSETIME == wParam)
{
DWORD nTickCount = (GetTickCount() - nTickCountStart) / 1000;
DWORD nSec = nTickCount % 60;
DWORD nMin = (nTickCount /= 60) % 60;
DWORD nHour = nTickCount / 60;
char vBuff[20];
sprintf(vBuff, "%2.2d:%2.2d:%2.2d", nHour, nMin, nSec);
SetDlgItemText(hDlg, IDC_ELAPSETIME, vBuff);
return TRUE;
}
break;
}
}
return FALSE;
}
LRESULT CALLBACK TestDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
const char* ConvertKochPathname(char* pDest, const char* pSrc, UINT nBuffLen)
{
UINT nLen = (UINT)strlen(pSrc);
UINT i;
for (i = 0; i < nBuffLen - 20 && i < nLen; ++i)
{
pDest[i] = (isalpha(pSrc[i]) ? pSrc[i] : '_');
}
strcpy(pDest + i, ".wav");
return pDest;
}
void PromptToWave(HWND hWnd)
{
char vDestPathname[260];
ConvertKochPathname(vDestPathname, g_vPromptBuff, 256);
TextToAskWave(vDestPathname, (UINT)sizeof(vDestPathname), g_vPromptBuff, (UINT)strlen(g_vPromptBuff), hWnd);
}
void KochToWave(HWND hWnd)
{
InitKochSample();
char vDestPathname[260];
ConvertKochPathname(vDestPathname, g_pGlobalSetting->cust.m_vKochChar, 256);
TextToAskWave(vDestPathname, sizeof(vDestPathname), g_vKochSample, MAX_KOCH_SAMPLE, hWnd);
}
void TextToAskWave(char* pWavePathBuff, UINT nWavePathBuffSize, const char* pBuff, UINT nCount, HWND hWnd)
{
OPENFILENAME ofn; // common dialog box structure
// HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = pWavePathBuff;
ofn.nMaxFile = nWavePathBuffSize;
ofn.lpstrFilter = "All\0*.*\0Wave\0*.wav\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn))
{
TextToWave(ofn.lpstrFile, pBuff, nCount, 0);
}
}
void TextToWave(const char* pPathname, const char* pTxt, UINT nTxtLen, UINT nWordLen)
{
CWaveFile oWaveFile(pPathname, 1, 8000, 16, g_pGlobalSetting->cust.m_nLongHit / 999.0f);
oWaveFile.SetFreq((float)g_pGlobalSetting->cust.m_rBeepFreq);
oWaveFile.SetVolumn((float)g_pGlobalSetting->cust.m_rBeepVol);
for (UINT i = 0; i < nTxtLen; ++i)
{
char ch = pTxt[i];
MORSECODE* pMorse = &(g_pGlobalSetting->cust.m_vMorseCode[MORSECODECOUNT - 1]);
for (int j = 0; j < MORSECODECOUNT; ++j)
{
MORSECODE* p = &(g_pGlobalSetting->cust.m_vMorseCode[j]);
if (ch == p->nAscCode || ch + ('A' - 'a') == p->nAscCode)
{
pMorse = p;
break;
}
}
if ('_' != pMorse->nAscCode)
{
int nWindow = pMorse->nMask + 1;
while(nWindow >>= 1)
{
int nHitCount =
nWindow & pMorse->nMorseCode ?
g_pGlobalSetting->cust.m_nShortHit : g_pGlobalSetting->cust.m_nLongHit;
oWaveFile.Append(nHitCount / 1000.0f);
oWaveFile.AppendBlank(g_pGlobalSetting->cust.m_nHitDelay / 1000.0f);
}
oWaveFile.AppendBlank(g_pGlobalSetting->cust.m_nLetterDelay / 1000.0f);
}
else
{
oWaveFile.AppendBlank(g_pGlobalSetting->cust.m_nWordDelay / 1000.0f);
}
if (0 < nWordLen && 0 == (i + 1) % nWordLen)
oWaveFile.AppendBlank(g_pGlobalSetting->cust.m_nWordDelay / 1000.0f);
}
}
LRESULT CALLBACK PromptProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
SetDlgItemText(hDlg, IDC_PROMPTTEXT, g_vPromptText);
SetDlgItemText(hDlg, IDC_INPUTSTR, g_vPromptBuff);
return TRUE;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDOK:
{
GetDlgItemTxt(hDlg, IDC_INPUTSTR, g_vPromptBuff, sizeof(g_vPromptBuff));
EndDialog(hDlg, 1);
return TRUE;
}
case IDCANCEL:
{
EndDialog(hDlg, 0);
return TRUE;
}
}
break;
}
}
return FALSE;
}
================================================
FILE: src/LakeyMainWindow.cpp
================================================
#include "StdAfx.h"
#include "lakeymainwindow.h"
#include "Mmreg.h"
#include "dsound.h"
#include "math.h"
#include "stdio.h"
#include "LakeySetting.h"
#include "SinSound.h"
#include "EventManagerWin32.h"
#include "LaButton.h"
#include "LaTuner.h"
#include "LaJournalPanel.h"
#include "LaLabel.h"
#include "LaLine.h"
#include "LaWaveCapture.h"
#include "LaHwControl.h"
#include "LaNetwork.h"
#include "LaSpectrogram.h"
#include "Resource.h"
#include
#define SAFE_DELETE(x) if (x) { delete x; x = NULL; }
#define SAFE_DELETE_DC(h) if (h) { DeleteDC(h); h = NULL; }
#define SEND_SHORT_COUNT_EXPR (m_pSetting->cust.m_nLongHit * 2 / (m_pSetting->cust.m_nSendJournalPeriod * 3))
#define RECV_SHORT_COUNT_EXPR (m_pSetting->cust.m_nShortHit * 1.5 * 44.100 / m_pSetting->cust.m_nRecvAnalyzeSamples)
#define JOIN_SAFELY(ht) \
{ \
if (NULL != ht) \
{ \
DWORD nExitCode_j = -1; \
if (GetExitCodeThread(ht, &nExitCode_j)) \
if (STILL_ACTIVE == nExitCode_j) \
WaitForSingleObject(ht, INFINITE); \
} \
}
CLakeyMainWindow::CLakeyMainWindow(HWND hWnd, CLakeySetting* pSetting)
: CEventDispatcherWin32(hWnd)
{
m_pSetting = pSetting;
m_pFont = new CFont("Arial", 12, CFont::THIN);
m_pLogoFont = new CFont("Courier New", 20, CFont::THIN);
m_pLogoFont->SetItalic(TRUE);
//m_pLogoFont->SetUnderline(TRUE);
m_oBtStyle.nTextFormat = DT_END_ELLIPSIS|DT_LEFT;
m_oBtStyle.pFont = m_pFont;
m_oLabelStyle.nTextFormat = DT_END_ELLIPSIS|DT_LEFT;
m_oLabelStyle.pFont = m_pFont;
m_oLabelStyle.nBgColor = RGB(255, 255, 255);
m_oLabelStyle.nColor = RGB(0, 0, 0);
m_oScqlStyle.nTextFormat = DT_END_ELLIPSIS|DT_LEFT;
m_oScqlStyle.pFont = m_pFont;
m_oScqlStyle.nBgColor = RGB(255, 255, 255);
m_oScqlStyle.nColor = RGB(0, 0, 0);
m_oLogoStyle.nTextFormat = DT_END_ELLIPSIS|DT_RIGHT|DT_BOTTOM|DT_SINGLELINE;
m_oLogoStyle.pFont = m_pLogoFont;
m_oLogoStyle.nBgColor = RGB(255, 255, 255);
m_oLogoStyle.nColor = RGB(32, 32, 32);
m_oVersionStyle.nTextFormat = DT_END_ELLIPSIS|DT_RIGHT|DT_BOTTOM|DT_SINGLELINE;
m_oVersionStyle.pFont = m_pFont;
m_oVersionStyle.nBgColor = RGB(255, 255, 255);
m_oVersionStyle.nColor = RGB(100, 100, 100);
AddPaintEventControl(this);
m_pBtCw = CreateButton(&m_pSetting->cust.m_oCwKeyButton);
m_pBtSendPause = CreateButton(&m_pSetting->cust.m_oSendPauseButton, CLaButton::BT_LOCKABLE);
m_pBtSendFile = CreateButton(&m_pSetting->cust.m_oSendFileButton);
m_pBtAutoKeySwitch = CreateButton(&m_pSetting->cust.m_oAutoKeySwitchButton);
m_pBtNoiseSwitch = CreateButton(&m_pSetting->cust.m_oNoiseSwitchButton, CLaButton::BT_LOCKABLE);
m_pJpSend = CreateJournalPanel(&m_pSetting->cust.m_oSendJournalRect, SEND_SHORT_COUNT_EXPR, &m_oLabelStyle, this);
m_pJpRecv = CreateJournalPanel(&m_pSetting->cust.m_oRecvJournalRect, (int)RECV_SHORT_COUNT_EXPR, &m_oLabelStyle, NULL);
m_pRecvSpectrogram = CreateSpectrogram(&m_pSetting->cust.m_oSpectrogramRect, NULL);
m_pRecvSpectrogram->SetBrightness(m_pSetting->cust.m_oSpecBrightnessTuner.v);
m_pRecvSpectrogram->Initialize();
m_pRecvDctMonitor = CreateWaveCapture(&m_pSetting->cust.m_oRecvMonitorRect, m_pRecvSpectrogram);
m_pSendCharQueueLabel = CreateLabel(&m_pSetting->cust.m_oSendCharQueueRect, NULL, &m_oScqlStyle, "HHH");
RECT r = m_pSetting->cust.m_oSendJournalRect;
OffsetRect(&r, m_pSetting->cust.m_oSendLabelOffset.cx, m_pSetting->cust.m_oSendLabelOffset.cy);
r.bottom = r.top + 12;
r.right = r.left + 40;
m_pSendLabel = CreateLabel(&r, m_pSetting->cust.m_vSendLabel, &m_oLabelStyle);
r = m_pSetting->cust.m_oRecvJournalRect;
OffsetRect(&r, m_pSetting->cust.m_oRecvLabelOffset.cx, m_pSetting->cust.m_oRecvLabelOffset.cy);
r.bottom = r.top + 12;
r.right = r.left + 40;
m_pRecvLabel = CreateLabel(&r, m_pSetting->cust.m_vRecvLabel, &m_oLabelStyle);
m_pSendJpBorder = CreateLine(m_pSetting->cust.m_oSendCharQueueRect.left, m_pSetting->cust.m_oSendCharQueueRect.bottom + 1,
m_pSetting->cust.m_oSendCharQueueRect.right, m_pSetting->cust.m_oSendCharQueueRect.bottom + 1);
m_pRecvJpBorder = CreateLine(m_pSetting->cust.m_oRecvJournalRect.left, m_pSetting->cust.m_oRecvJournalRect.bottom + 1,
m_pSetting->cust.m_oRecvJournalRect.right, m_pSetting->cust.m_oRecvJournalRect.bottom + 1);
m_hMorseQueueThread = NULL;
m_nMorseQueueThreadID = 0;
m_hMorseJournalThread = NULL;
m_nMorseJournalThreadID = 0;
m_hRecvMonitorThread = NULL;
m_nRecvMonitorThreadID = 0;
BuildMorseButtons();
m_pTnSendVol = CreateTuner(&m_pSetting->cust.m_oSendVolTuner);
m_pTnBgVol = CreateTuner(&m_pSetting->cust.m_oNoiseVolTuner);
m_pTnSendSpeed = CreateTuner(&m_pSetting->cust.m_oSendSpeedTuner);
m_pTnSpecBrightness = CreateTuner(&m_pSetting->cust.m_oSpecBrightnessTuner);
GetRect(&r);
r.right -= r.left;
r.bottom -= r.top + 20;
r.left = r.right - 80;
r.top = r.bottom - 20;
// m_pLogo = CreateLabel(&r, "Lakey ", &m_oLogoStyle);
r.top += 20;
r.bottom += 16;
r.right -= 10;
// m_pVersion = CreateLabel(&r, "b0019", &m_oVersionStyle);
m_pSound = new CSinSound();
m_pSound->SetFrequency((float)m_pSetting->cust.m_rBeepFreq);
m_pSound->SetScale((float)m_pSetting->cust.m_rBeepVol);
m_bNeedExit = FALSE;
m_bCwFlag = FALSE;
m_nRecvIdleCount = 0;
m_bPause = FALSE;
m_bClear = FALSE;
m_bNwSndState = FALSE;
m_nAutoKey = 0;
m_nEncryptTrngTotalChars = 0;
m_hSendJrnFile = NULL;
m_pExtPort = new CLaHwControl(m_pSetting->cust.m_nExtPortAddr, m_pSetting->cust.m_nCloseByte);
m_pNetwork = new CLaNetwork(0);
m_pNetwork->BindEventListener(this);
m_pNetwork->BindFrameListener(this);
AddCommandEventControl(this);
AddKeyboardEventControl(this);
}
CLakeyMainWindow::~CLakeyMainWindow(void)
{
// save current win rect
GetWindowRect(GetHWnd(), &m_pSetting->cust.m_oWindowRect);
m_bNeedExit = TRUE;
ResumeThread(m_hMorseQueueThread);
JOIN_SAFELY(m_hMorseQueueThread);
JOIN_SAFELY(m_hMorseJournalThread);
JOIN_SAFELY(m_hRecvMonitorThread);
m_pSetting->cust.m_oSendVolTuner.v = this->m_pTnSendVol->GetScale();
m_pSetting->cust.m_oNoiseVolTuner.v = this->m_pTnBgVol->GetScale();
m_pSetting->cust.m_oSendSpeedTuner.v = this->m_pTnSendSpeed->GetScale();
m_pSetting->cust.m_oSpecBrightnessTuner.v = this->m_pTnSpecBrightness->GetScale();
// delete m_pVersion;
// delete m_pLogo;
delete m_pTnSpecBrightness;
delete m_pTnSendSpeed;
delete m_pTnBgVol;
delete m_pTnSendVol;
delete m_pNetwork;
delete m_pExtPort;
delete m_pRecvDctMonitor;
delete m_pRecvJpBorder;
delete m_pJpRecv;
delete m_pSendJpBorder;
delete m_pSendCharQueueLabel;
delete m_pJpSend;
delete m_pBtCw;
delete m_pBtSendPause;
delete m_pBtSendFile;
delete m_pBtAutoKeySwitch;
delete m_pBtNoiseSwitch;
delete m_pSendLabel;
delete m_pRecvLabel;
delete m_pSound;
delete m_pLogoFont;
delete m_pFont;
delete m_pRecvSpectrogram;
for (int i = 0; i < MORSECODECOUNT; ++i)
delete m_vBtMorse[i];
}
void CLakeyMainWindow::BuildMorseButtons()
{
RECT r;
GetWindowRect(GetHWnd(), &r);
int x = 10;
int oy = 300;
int y = oy;
int h = 12;
int w = 58;
int nMaxY = r.bottom - r.top - 6 * h;
char txt[] = { ' ', ' ', ' ', ' ', ' ', '#', '#', '#', '#', '#', '#', '\0' };
for (int i = 0; i < MORSECODECOUNT; ++i)
{
MORSECODE* p = &(m_pSetting->cust.m_vMorseCode[i]);
txt[0] = p->nAscCode;
int nWin = 0x0020;
for (int j = 0; j < 6; ++j, nWin >>= 1)
{
if (nWin & p->nMask)
txt[j + 5] = (nWin & p->nMorseCode ? '.' : '-');
else
txt[j + 5] = ' ';
}
m_vBtMorse[i] = CreateButton(txt, x, y, w, h, p->nKeyCode);
m_vBtMorse[i]->SetUserData(p);
if ((y += (h + 2)) > nMaxY)
{
y = oy;
x += (6 * w / 5);
}
}
}
BOOL CLakeyMainWindow::OnTune(void* owner, LASCALE nScale)
{
if (m_pTnSendVol == owner)
m_pSound->SetVolume((LONG)(nScale * 100));
else if (m_pTnBgVol == owner)
m_pSound->SetNoiseVolume((LONG)(nScale * 100));
else if (m_pTnSendSpeed == owner)
{
WPMS wpms;
wpms.wpm = nScale;
wpmToParams(&wpms);
m_pSetting->cust.m_nShortHit = wpms.di;
m_pSetting->cust.m_nLongHit = wpms.dah;
m_pSetting->cust.m_nHitDelay = wpms.hdelay;
m_pSetting->cust.m_nLetterDelay = wpms.ldelay;
m_pSetting->cust.m_nWordDelay = wpms.wdelay;
m_pJpSend->SetMaxShortCount(SEND_SHORT_COUNT_EXPR);
m_pJpRecv->SetMaxShortCount((int)RECV_SHORT_COUNT_EXPR);
}
else if (m_pTnSpecBrightness == owner)
{
m_pRecvSpectrogram->SetBrightness(nScale);
}
else
return FALSE;
return TRUE;
}
MORSECODE* CLakeyMainWindow::GetMorseCode(char ch)
{
for (int i = 0; i < MORSECODECOUNT; ++i)
{
MORSECODE* p = &(m_pSetting->cust.m_vMorseCode[i]);
if (ch == p->nAscCode || ch + ('A' - 'a') == p->nAscCode)
return p;
}
// '_' is default
return &(m_pSetting->cust.m_vMorseCode[MORSECODECOUNT - 1]);
}
CLaTuner* CLakeyMainWindow::CreateTuner(const TUNERMAPPING* pMapping)
{
return CreateTuner(pMapping->vLabel, pMapping->x, pMapping->y, pMapping->w, pMapping->h, pMapping->vl, pMapping->vr, pMapping->v);
}
CLaTuner* CLakeyMainWindow::CreateTuner(const char* pText, int x, int y, int w, int h, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale)
{
RECT r;
r.left = x; r.top = y; r.right = x + w; r.bottom = y + h;
CLaTuner* pTuner = new CLaTuner(this, pText, &r, nScaleL, nScaleR, nScale, m_pFont);
AddPaintEventControl(pTuner);
AddMouseMoveEventControl(pTuner);
AddMouseKeyEventControl(pTuner);
// AddKeyboardEventControl(pButton);
pTuner->AddMouseKeyEventListener(this);
// pTuner->AddKeyboardEventListener(this);
pTuner->AddTunerEventListener(this);
return pTuner;
}
CLaButton* CLakeyMainWindow::CreateButton(const char* pText, int x, int y, int w, int h, int nWantKeyCode, CLaButton::ButtonStyle nStyle)
{
RECT r;
r.left = x; r.top = y; r.right = x + w; r.bottom = y + h;
CLaButton* pButton = new CLaButton(this, pText, &r, nStyle, m_pFont);
pButton->SetWantKeyCode(nWantKeyCode);
AddPaintEventControl(pButton);
AddMouseMoveEventControl(pButton);
AddMouseKeyEventControl(pButton);
AddKeyboardEventControl(pButton);
pButton->AddMouseKeyEventListener(this);
pButton->AddKeyboardEventListener(this);
return pButton;
}
CLaButton* CLakeyMainWindow::CreateButton(const BUTTONMAPPING* pMapping, CLaButton::ButtonStyle nStyle)
{
return CreateButton(pMapping->vLabel, pMapping->x, pMapping->y, pMapping->w, pMapping->h, pMapping->nKeyCode, nStyle);
}
CLaJournalPanel* CLakeyMainWindow::CreateJournalPanel(const RECT* pRect, int nMaxShortCount
, STYLE* pStyle, IParseEventListener* pParseListener)
{
CLaJournalPanel* jp = new CLaJournalPanel(this, pRect, m_pSetting->cust.m_vMorseCode, nMaxShortCount, pStyle, pParseListener);
AddPaintEventControl(jp);
return jp;
}
CLaWaveCapture* CLakeyMainWindow::CreateWaveCapture(const RECT* pRect, IFilterDFT* pNextFilter)
{
CLaWaveCapture* wc = new CLaWaveCapture(this, pRect, 44100, m_pSetting->cust.m_nRecvAnalyzeSamples, pNextFilter, this);
wc->SetFreqRange(m_pSetting->cust.m_nRecvFreqStart, m_pSetting->cust.m_nRecvFreqEnd);
wc->SetThresholdLevel(m_pSetting->cust.m_rRecvThreshold);
AddPaintEventControl(wc);
AddMouseKeyEventControl(wc);
return wc;
}
CLaSpectrogram* CLakeyMainWindow::CreateSpectrogram(const RECT* pRect, IFilterDFT* pNextFilter)
{
CLaSpectrogram* p_spectrogram = new CLaSpectrogram(this, pRect, 44100, m_pSetting->cust.m_nRecvAnalyzeSamples);
AddPaintEventControl(p_spectrogram);
AddMouseKeyEventControl(p_spectrogram);
return p_spectrogram;
}
CLaLabel* CLakeyMainWindow::CreateLabel(const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName/* = NULL */)
{
CLaLabel* label = new CLaLabel(this, pRect, pText, pStyle, pMutexName);
AddPaintEventControl(label);
return label;
}
CLaLine* CLakeyMainWindow::CreateLine(int x1, int y1, int x2, int y2)
{
CLaLine* line = new CLaLine(this, x1, y1, x2, y2);
AddPaintEventControl(line);
return line;
}
BOOL CLakeyMainWindow::Initialize()
{
m_hMorseQueueThread = CreateThread(NULL, 0, MorseQueueThreadProc, this, CREATE_SUSPENDED, &m_nMorseQueueThreadID);
if (!m_hMorseQueueThread)
return FALSE;
m_hMorseJournalThread = CreateThread(NULL, 0, MorseJournalThreadProc, this, 0, &m_nMorseJournalThreadID);
if (!m_hMorseJournalThread)
return FALSE;
///*
m_pRecvDctMonitor->Initialize();
m_hRecvMonitorThread = CreateThread(NULL, 0, RecvMonitorThreadProc, this, 0, &m_nRecvMonitorThreadID);
if (!m_hRecvMonitorThread)
return FALSE;
// */
if (!m_pSound->Initialize(GetHWnd()))
return FALSE;
m_pSound->SetVolume((LONG)(m_pTnSendVol->GetScale() * 100));
m_pSound->SetNoiseVolume((LONG)(m_pTnBgVol->GetScale() * 100));
AddTimerEventControl(m_pSound, 1, 500);
return TRUE;
}
void CLakeyMainWindow::GetRect(RECT* r)
{
GetClientRect(GetHWnd(), r);
}
BOOL CLakeyMainWindow::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
//g->SetBgColor(RGB(127,127,127));
//g->DrawRect(pRect);
return TRUE;
}
BOOL CLakeyMainWindow::OnMouseMove(void* owner, int x, int y)
{
return FALSE;
}
BOOL CLakeyMainWindow::OnKeyDown(void* owner, int nKeyCode)
{
if (m_pBtCw == owner)
{
CwDown();
return TRUE;
}
/*else if (' ' == nKeyCode)
{
m_pRecvDctMonitor->Refresh();
return TRUE;
}*/
return FALSE;
}
BOOL CLakeyMainWindow::OnKeyUp(void* owner, int nKeyCode)
{
if (m_pBtCw == owner)
{
CwUp();
return TRUE;
}
else if (m_pBtSendFile == owner)
{
ChooseSendFile();
return TRUE;
}
else if (VK_PAUSE == nKeyCode)
{
m_pRecvDctMonitor->SetFrazeState(!m_pRecvDctMonitor->GetFrazeState());
}
return FALSE;
}
BOOL CLakeyMainWindow::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
if (m_pBtCw == owner)
{
if (m_nAutoKey)
{
m_nAutoKeyState = (m_nAutoKey == nMkt);
m_oAutoKeyQueue.push(m_nAutoKeyState);
ResumeThread(m_hMorseQueueThread);
}
else
{
CwDown();
}
return FALSE;
}
else if (this == owner)
{
}
return FALSE;
}
BOOL CLakeyMainWindow::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
if (m_pBtCw == owner)
{
if (m_nAutoKey)
{
m_nAutoKeyState = -1;
}
else
{
CwUp();
return TRUE;
}
}
else if (m_pBtSendFile == owner)
{
ChooseSendFile();
return TRUE;
}
else if (this == owner)
{
}
else
{
}
return FALSE;
}
BOOL CLakeyMainWindow::ChooseSendFile()
{
OPENFILENAME ofn; // common dialog box structure
char szFile[260] = "*.txt"; // buffer for file name
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetHWnd();
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn))
{
hf = CreateFile(ofn.lpstrFile, GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
char vBuff[256];
int nRead = -1;
while(ReadFile(hf, vBuff, sizeof(vBuff), (LPDWORD)&nRead, NULL) && 0 < nRead)
{
PushText(vBuff, nRead, 0);
}
CloseHandle(hf);
return TRUE;
}
return FALSE;
}
void CLakeyMainWindow::PushText(const char* pBuff, int nSize, int nWordLen)
{
for (int i = 0; i < nSize; ++i)
{
if (m_pSendCharQueueLabel->PushChar(pBuff[i]))
m_oSendMorseQueue.push(GetMorseCode(pBuff[i]));
if (0 < nWordLen && 0 == (i + 1) % (nWordLen))
{
if (m_pSendCharQueueLabel->PushChar('_'))
m_oSendMorseQueue.push(GetMorseCode(' '));
}
}
m_nAutoKey = 0;
m_pBtAutoKeySwitch->SetText("Manual");
ResumeThread(m_hMorseQueueThread);
}
void CLakeyMainWindow::ClearQueue()
{
m_bClear = TRUE;
ResumeThread(m_hMorseQueueThread);
}
BOOL CLakeyMainWindow::OnClick(void* owner)
{
if (m_pBtCw == owner)
{
}
else if (m_pBtSendPause == owner)
{
if (!(m_bPause = m_pBtSendPause->IsPressed()))
ResumeThread(m_hMorseQueueThread);
return TRUE;
}
else if (m_pBtSendFile == owner)
{
}
else if (m_pBtAutoKeySwitch == owner)
{
switch(m_nAutoKey)
{
case LBUTTON:
//m_pBtAutoKeySwitch->SetText("Auto(R/L)");
m_nAutoKey = RBUTTON;
break;
case RBUTTON:
//m_pBtAutoKeySwitch->SetText("Manual");
m_nAutoKey = 0;
break;
default:
//m_pBtAutoKeySwitch->SetText("Auto(L/R)");
m_nAutoKey = LBUTTON;
break;
}
return TRUE;
}
else if (m_pBtNoiseSwitch == owner)
{
m_pSound->SetNoise(m_pBtNoiseSwitch->IsPressed());
return TRUE;
}
else if (this == owner)
{
}
else
{
CLaButton* pMorseBt = (CLaButton *)owner;
MORSECODE* pMorseCode = (MORSECODE *)pMorseBt->GetUserData();
if (pMorseCode && MAX_LABEL_TEXT_LEN > m_oSendMorseQueue.size())
{
if (m_pSendCharQueueLabel->PushChar(pMorseCode->nAscCode))
{
m_oSendMorseQueue.push(pMorseCode);
ResumeThread(m_hMorseQueueThread);
}
return TRUE;
}
}
return FALSE;
}
void CLakeyMainWindow::CwDown()
{
m_pSound->Play();
if (m_pSetting->cust.m_nExtPortEnable)
m_pExtPort->OutByte(m_pSetting->cust.m_nExtPortAddr, m_pSetting->cust.m_nOpenByte);
LANWPKGKEYFRAME frame;
frame.nToState = 1;
frame.nActTick = 0;
frame.nReserved = 0;
m_pNetwork->AppendKeyFrame(&frame);
m_bCwFlag = TRUE;
}
void CLakeyMainWindow::CwUp()
{
m_pSound->Stop();
if (m_pSetting->cust.m_nExtPortEnable)
m_pExtPort->OutByte(m_pSetting->cust.m_nExtPortAddr, m_pSetting->cust.m_nCloseByte);
LANWPKGKEYFRAME frame;
frame.nToState = 0;
frame.nActTick = 0;
frame.nReserved = 0;
m_pNetwork->AppendKeyFrame(&frame);
m_bCwFlag = FALSE;
}
void CLakeyMainWindow::OnCwEvent(BOOL bCwDown)
{
if (bCwDown)
m_nRecvIdleCount = 0;
if (m_nRecvIdleCount < m_pSetting->cust.m_nRecvIdleLimit)
m_pJpRecv->Sample(bCwDown);
m_nRecvIdleCount += (int)RECV_SHORT_COUNT_EXPR;
}
BOOL CLakeyMainWindow::OnCommand(void* owner, int nCommId)
{
switch(nCommId)
{
case IDM_SENDTRAINING:
StartEncryptTrng();
return TRUE;
}
return FALSE;
}
void CLakeyMainWindow::OnKeyFrame(const LANWPKGKEYFRAME* pFrame)
{
if (pFrame->nToState)
{
m_bNwSndState = TRUE;
m_pSound->Play();
}
else
{
m_bNwSndState = FALSE;
m_pSound->Stop();
}
}
void CLakeyMainWindow::OnSourceFrame(const LANWPKGSRCFRAME* pFrame, const char* szDomainName)
{
}
void CLakeyMainWindow::OnTextFrame(const LANWPKGTXTFRAME* pFrame)
{
}
void CLakeyMainWindow::OnEvent(WORD nMsg)
{
m_pSound->Stop();
}
BOOL CLakeyMainWindow::NetworkStartup()
{
if (m_pSetting->cust.m_bNetworkEnabled)
{
LANWSRCNODE node;
for (UINT i = 0; i < m_pSetting->hosts.size(); ++i)
{
node.base.nAddr = inet_addr(m_pSetting->hosts[i].szHostName);
if (INADDR_NONE != node.base.nAddr)
{
int nTmp;
sscanf(m_pSetting->hosts[i].szPort, "%d", &nTmp);
node.base.nPort = nTmp;
m_pNetwork->AppendStbSrcNode(&node);
}
}
if (!m_pNetwork->Startup(m_pSetting->cust.m_nLocalPort))
{
MessageBox(NULL, "繦", "", MB_OK);
return FALSE;
}
return TRUE;
}
return FALSE;
}
BOOL CLakeyMainWindow::StartEncryptTrng()
{
OPENFILENAME ofn; // common dialog box structure
char szFn[512] = "*.txt"; // buffer for file name
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = GetHWnd();
ofn.lpstrFile = szFn;
ofn.nMaxFile = sizeof(szFn) - 10; // reserved for postfix of journal file
ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn))
{
m_nEncryptTrngOkChars = 0;
m_rEncryptTrngOkStdWords = 0;
m_rEncryptTrngStdWords = 0;
hf = CreateFile(ofn.lpstrFile, GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
int nRead = -1;
char szBuf[256];
while(ReadFile(hf, szBuf, sizeof(szBuf), (LPDWORD)&nRead, NULL) && 0 < nRead)
{
PushEncryptTrngText(szBuf, nRead);
}
CloseHandle(hf);
if (0 == m_nEncryptTrngTotalChars)
return FALSE;
strcat(szFn, ".jrn");
m_hSendJrnFile = CreateFile(szFn, // file to create
GENERIC_WRITE | GENERIC_READ, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // overwrite existing
FILE_ATTRIBUTE_NORMAL,
NULL); // no attr. template
if (INVALID_HANDLE_VALUE == m_hSendJrnFile)
{
printf("Could not create journal file (error %d)\n", GetLastError());
}
m_nEncryptTrngStartTC = GetTickCount();
return TRUE;
}
return FALSE;
}
void CLakeyMainWindow::PushEncryptTrngText(const char* pText, int nSize)
{
for (int i = 0; i < nSize; ++i)
{
switch(pText[i])
{
case '\n':
case '\r':
case '\t':
case ' ':
break;
default:
m_oEncryptTrngQueue.push(pText[i]);
++m_nEncryptTrngTotalChars;
}
}
}
void CLakeyMainWindow::OnWorkOut(void* owner, const MORSECODE* pResult)
{
if (m_nEncryptTrngTotalChars)
{
if (!m_oEncryptTrngQueue.empty())
{
char ch = m_oEncryptTrngQueue.front();
m_oEncryptTrngQueue.pop();
if (pResult && (ch > 'Z' ? ch - 'a' + 'A' : ch) == pResult->nAscCode)
{
++m_nEncryptTrngOkChars;
m_rEncryptTrngOkStdWords += pResult->rStdWordLen;
}
m_rEncryptTrngStdWords += pResult->rStdWordLen;
}
DWORD t;
if (pResult)
{
if (!WriteFile(m_hSendJrnFile, &pResult->nAscCode, 1, &t, NULL))
{
printf("Could not write journal file (error %d)\n", GetLastError());
}
}
else
{
WriteFile(m_hSendJrnFile, "#", 1, &t, NULL);
}
if (m_oEncryptTrngQueue.empty())
{
char szBuf[128];
float t2 = (GetTickCount() - m_nEncryptTrngStartTC) / 1000.0f;
sprintf(szBuf
, "\nʱ:\t%2.1f\nӦķַ:\t%d\nȷ:\t%2.1f%%\nƽ:\t%2.1fwpm\nȷ:\t%2.1fwpm\n(ͳƲո)"
, t2
, m_nEncryptTrngTotalChars
, m_nEncryptTrngOkChars * 100.0f / m_nEncryptTrngTotalChars
, m_rEncryptTrngStdWords / (t2 / 60.0f)
, m_rEncryptTrngOkStdWords / (t2 / 60.0f)
);
WriteFile(m_hSendJrnFile, "\n====================", 16, &t, NULL);
WriteFile(m_hSendJrnFile, szBuf, strlen(szBuf), &t, NULL);
CloseHandle(m_hSendJrnFile);
MessageBox(GetHWnd(), szBuf, "ͳ", MB_OK);
m_nEncryptTrngTotalChars = 0;
}
}
}
void CLakeyMainWindow::StopEncryptTrng()
{
while(m_oEncryptTrngQueue.empty())
{
m_oEncryptTrngQueue.pop();
}
m_nEncryptTrngTotalChars = 0;
CloseHandle(m_hSendJrnFile);
}
// Threads definition
#define NOTEVALIFNEEDEXIT(expr) if (!owner->m_bNeedExit) expr
DWORD WINAPI CLakeyMainWindow::MorseQueueThreadProc(LPVOID pOwner)
{
CLakeyMainWindow* owner = (CLakeyMainWindow *)pOwner;
while(!owner->m_bNeedExit)
{
//assert(!owner->m_oSendMorseQueue.empty());
// need not exit and queue not empty and not pause and not in auto key mode
// send chars mode
while(!owner->m_bNeedExit && !owner->m_oSendMorseQueue.empty() && !owner->m_bPause && 0 == owner->m_nAutoKey)
{
MORSECODE* pMorse = owner->m_oSendMorseQueue.front();
owner->m_oSendMorseQueue.pop();
if (!owner->m_bClear)
{
if ('_' != pMorse->nAscCode)
{
int nWindow = pMorse->nMask + 1;
while((!owner->m_bNeedExit) && (nWindow >>= 1))
{
int nHitCount =
nWindow & pMorse->nMorseCode ?
owner->m_pSetting->cust.m_nShortHit : owner->m_pSetting->cust.m_nLongHit;
owner->CwDown();
NOTEVALIFNEEDEXIT(Sleep(nHitCount));
owner->CwUp();
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nHitDelay));
}
}
else
{
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nWordDelay));
}
}
owner->m_pSendCharQueueLabel->PopChar();
if (!owner->m_bClear)
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nLetterDelay));
}
// auto key mode
while(!owner->m_bNeedExit && !owner->m_oAutoKeyQueue.empty() && !owner->m_bPause && 0 != owner->m_nAutoKey)
{
BOOL bKey = owner->m_oAutoKeyQueue.front();
owner->m_oAutoKeyQueue.pop();
int nHitCount =
bKey ?
owner->m_pSetting->cust.m_nShortHit : owner->m_pSetting->cust.m_nLongHit;
owner->CwDown();
NOTEVALIFNEEDEXIT(Sleep(nHitCount));
owner->CwUp();
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nHitDelay));
if (0 <= owner->m_nAutoKeyState)
{
if (owner->m_oAutoKeyQueue.empty())
owner->m_oAutoKeyQueue.push(owner->m_nAutoKeyState);
}
}
owner->m_bClear = FALSE;
NOTEVALIFNEEDEXIT(SuspendThread(owner->m_hMorseQueueThread));
}
return 0;
}
DWORD WINAPI CLakeyMainWindow::MorseJournalThreadProc(LPVOID pOwner)
{
CLakeyMainWindow* owner = (CLakeyMainWindow *)pOwner;
int nIdleCount = 0;
while(!owner->m_bNeedExit)
{
if (owner->m_bCwFlag)
nIdleCount = 0;
if (nIdleCount < owner->m_pSetting->cust.m_nSendIdleLimit)
owner->m_pJpSend->Sample(owner->m_bCwFlag);
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nSendJournalPeriod));
nIdleCount += owner->m_pSetting->cust.m_nSendJournalPeriod;
}
return 0;
}
DWORD WINAPI CLakeyMainWindow::RecvMonitorThreadProc(LPVOID pOwner)
{
CLakeyMainWindow* owner = (CLakeyMainWindow *)pOwner;
int nIdleCount = 0;
while(!owner->m_bNeedExit)
{
owner->m_pRecvDctMonitor->Refresh();
if (owner->m_bNwSndState)
nIdleCount = 0;
if (nIdleCount < owner->m_pSetting->cust.m_nRecvIdleLimit)
owner->m_pJpRecv->Sample(owner->m_bNwSndState);
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->cust.m_nRecvJournalPeriod));
nIdleCount += owner->m_pSetting->cust.m_nRecvJournalPeriod;
}
return 0;
}
================================================
FILE: src/LakeyMainWindow.h
================================================
#pragma once
#include
#include "EventManagerWin32.h"
#include "LakeySetting.h"
#include "LaWaveCapture.h"
#include "LaNetwork.h"
#include "LaButton.h"
#include "LaTuner.h"
#include "MorseParser.h"
class CSinSound;
class CLaButton;
class CLaJournalPanel;
class CLaWaveCapture;
class CLaSpectrogram;
class CLaLabel;
class CLaLine;
class CLaHwControl;
class CLaNetwork;
class CLaTuner;
class CLakeyMainWindow
: public CEventDispatcherWin32
, public IMouseMoveEventListener
, public IKeyboardEventControl
, public IMouseKeyEventListener
, public IPaintEventControl
, public ICwEventListener
, public ICommandEventControl
, public INetworkFrameListener
, public INetworkEventListener
, public ITunerEventListener
, public IParseEventListener
{
public:
CLakeyMainWindow(HWND hWnd, CLakeySetting* pSetting);
virtual ~CLakeyMainWindow(void);
virtual BOOL Initialize();
virtual BOOL NetworkStartup();
virtual void NetworkShutdown() { return m_pNetwork->Shutdown(); };
virtual BOOL IsRelated(int x, int y) { return TRUE; };
virtual void GetRect(RECT* r);
virtual BOOL OnMouseMove(void* owner, int x, int y);
virtual BOOL OnKeyDown(void* owner, int nKeyCode);
virtual BOOL OnKeyUp(void* owner, int nKeyCode);
virtual BOOL OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y);
virtual BOOL OnClick(void* owner);
virtual BOOL OnPaint(void* owner, CGraphics* g, const RECT* pRect);
virtual BOOL OnTune(void* owner, LASCALE nScale);
virtual void OnCwEvent(BOOL bCwDown);
virtual BOOL OnCommand(void* owner, int nCommId);
virtual void OnKeyFrame(const LANWPKGKEYFRAME* pFrame);
virtual void OnSourceFrame(const LANWPKGSRCFRAME* pFrame, const char* szDomainName);
virtual void OnTextFrame(const LANWPKGTXTFRAME* pFrame);
virtual void OnEvent(WORD nMsg);
virtual void OnWorkOut(void* owner, const MORSECODE* pResult);
void PushText(const char* pText, int nSize, int nWordLen);
void ClearQueue();
BOOL StartEncryptTrng();
void PushEncryptTrngText(const char* pText, int nSize);
void StopEncryptTrng();
private:
CLaButton* CreateButton(const char* pText, int x, int y, int w, int h, int nWantKeyCode, CLaButton::ButtonStyle nStyle = CLaButton::BT_NORMAL);
CLaButton* CreateButton(const BUTTONMAPPING* pMapping, CLaButton::ButtonStyle nStyle = CLaButton::BT_NORMAL);
CLaJournalPanel* CreateJournalPanel(const RECT* pRect, int nMaxShortCount, STYLE* pStyle, IParseEventListener* pParseListener);
CLaWaveCapture* CreateWaveCapture(const RECT* pRect, IFilterDFT* pNextFilter);
CLaSpectrogram* CreateSpectrogram(const RECT* pRect, IFilterDFT* pNextFilter);
CLaLabel* CreateLabel(const RECT* pRect, const char* pText, STYLE* pStyle, const char* pMutexName = NULL);
CLaLine* CreateLine(int x1, int y1, int x2, int y2);
CLaTuner* CreateTuner(const char* pText, int x, int y, int w, int h, LASCALE nScaleL, LASCALE nScaleR, LASCALE nScale);
CLaTuner* CreateTuner(const TUNERMAPPING* pMapping);
MORSECODE* GetMorseCode(char ch);
BOOL ChooseSendFile();
void BuildMorseButtons();
void CwDown();
void CwUp();
private:
CLakeySetting* m_pSetting;
CSinSound* m_pSound;
// Resources
CFont* m_pFont;
CFont* m_pLogoFont;
STYLE m_oBtStyle;
STYLE m_oLabelStyle;
STYLE m_oScqlStyle;
STYLE m_oLogoStyle;
STYLE m_oVersionStyle;
// Controls
CLaButton* m_pBtCw;
CLaButton* m_pBtSendPause;
CLaButton* m_pBtSendFile;
CLaButton* m_pBtAutoKeySwitch;
CLaButton* m_pBtNoiseSwitch;
CLaTuner* m_pTnSendVol;
CLaTuner* m_pTnBgVol;
CLaTuner* m_pTnSendSpeed;
CLaTuner* m_pTnSpecBrightness;
BOOL m_bPause;
BOOL m_bClear;
BOOL m_bNwSndState;
int m_nAutoKey;
int m_nAutoKeyState;
// Morse buttons
CLaButton* m_vBtMorse[MORSECODECOUNT];
// CW journal panel
CLaJournalPanel* m_pJpSend;
CLaLabel* m_pSendCharQueueLabel;
CLaLine* m_pSendJpBorder;
CLaLine* m_pSendTunerBorder;
CLaWaveCapture* m_pRecvDctMonitor;
CLaSpectrogram* m_pRecvSpectrogram;
CLaJournalPanel* m_pJpRecv;
CLaLine* m_pRecvJpBorder;
CLaLine* m_pRecvTunerBorder;
CLaLabel* m_pSendLabel;
CLaLabel* m_pRecvLabel;
// CLaLabel* m_pLogo;
// CLaLabel* m_pVersion;
// CW Flag
BOOL m_bCwFlag;
// HW Control
CLaHwControl* m_pExtPort;
// Network
CLaNetwork* m_pNetwork;
// Send morse queue
queue m_oSendMorseQueue;
queue m_oAutoKeyQueue;
BOOL m_bNeedExit;
HANDLE m_hMorseQueueThread;
DWORD m_nMorseQueueThreadID;
HANDLE m_hMorseJournalThread;
DWORD m_nMorseJournalThreadID;
HANDLE m_hRecvMonitorThread;
DWORD m_nRecvMonitorThreadID;
int m_nRecvIdleCount;
// encrypt training
queue m_oEncryptTrngQueue;
DWORD m_nEncryptTrngTotalChars;
DWORD m_nEncryptTrngOkChars;
float m_rEncryptTrngStdWords;
float m_rEncryptTrngOkStdWords;
DWORD m_nEncryptTrngStartTC;
HANDLE m_hSendJrnFile;
static DWORD WINAPI MorseQueueThreadProc(LPVOID pOwner);
static DWORD WINAPI MorseJournalThreadProc(LPVOID pOwner);
static DWORD WINAPI RecvMonitorThreadProc(LPVOID pOwner);
};
================================================
FILE: src/LakeySetting.cpp
================================================
#include "StdAfx.h"
#include "lakeysetting.h"
#include "stdio.h"
#define SetMorseCode(s, asc, mc, mm, kc) \
s.nAscCode = (asc); s.nMorseCode = (mc); s.nMask = (mm); s.nKeyCode = (kc); s.rStdWordLen = calcStdWordLen(mc, mm);
#define SetButtonMapping(s, nx, ny, nw, nh, kc, txt) \
s.x = (nx); s.y = (ny); s.w = (nw); s.h = (nh); s.nKeyCode = (kc); strncpy(s.vLabel, (txt), sizeof(s.vLabel) - 1);
#define SetTunerMapping(s, nx, ny, nw, nh, nl, nr, nv, txt) \
s.x = (nx); s.y = (ny); s.w = (nw); s.h = (nh); s.vl = (nl); s.vr = (nr); s.v = (nv); strncpy(s.vLabel, (txt), sizeof(s.vLabel) - 1);
CLakeySetting::CLakeySetting(void)
{
cust.m_rBeepFreq = 1000.0;
cust.m_rBeepVol = 0.25;
cust.m_nShortHit = 80;
cust.m_nLongHit = 240;
cust.m_nHitDelay = 80;
cust.m_nLetterDelay = 240;
cust.m_nWordDelay = 240;
SetRect(&cust.m_oWindowRect, 0, 0, 936, 450);
cust.m_nSendJournalPeriod = 27;
SetRect(&cust.m_oSendJournalRect, 5,235,490,267);
cust.m_oSendLabelOffset.cx = 0;
cust.m_oSendLabelOffset.cy = -15;
cust.m_nSendIdleLimit = 750;
SetRect(&cust.m_oSendCharQueueRect, 5,270,490,281);
strcpy(cust.m_vSendLabel, "Send");
SetRect(&cust.m_oSpectrogramRect, 498,10,908,160);
cust.m_oSpecLabelOffset.cx = 0;
cust.m_oSpecLabelOffset.cy = -15;
strcpy(cust.m_vSpecLabel, "Spectrogram");
cust.m_nRecvJournalPeriod = 27;
SetRect(&cust.m_oRecvJournalRect, 5,180,490,212);
cust.m_oRecvLabelOffset.cx = 0;
cust.m_oRecvLabelOffset.cy = -15;
cust.m_nRecvIdleLimit = 750;
strcpy(cust.m_vRecvLabel, "Recieve");
SetRect(&cust.m_oRecvMonitorRect, 8,10,493,160);
cust.m_nRecvAnalyzeSamples = 512;
cust.m_rRecvThreshold = 0.3l;
cust.m_nRecvFreqStart = 850;
cust.m_nRecvFreqEnd = 1250;
SetButtonMapping(cust.m_oCwKeyButton, 500,290,400,92, VK_RETURN, "CW");
SetButtonMapping(cust.m_oSendFileButton, 500,265,91,16, VK_F6, "File...");
SetButtonMapping(cust.m_oSendPauseButton, 603,265,91,16, VK_F5, "Pause,Continue");
SetButtonMapping(cust.m_oAutoKeySwitchButton, 706,265,91,16, VK_TAB, "Manual,Auto(L/R),Auto(R/L)");
SetButtonMapping(cust.m_oNoiseSwitchButton, 809,265,91,16, VK_F7, "Disturb");
SetTunerMapping(cust.m_oSendVolTuner, 500,168,90,90,-80.000000,0.000000, 0, "Volumn(dB)");
SetTunerMapping(cust.m_oSendSpeedTuner, 603,168,90,90,5.000000,30.000000, 20, "Speed(wpm)");
SetTunerMapping(cust.m_oSpecBrightnessTuner, 706,168,90,90,-60.000000,60.000000, 0.0, "Spectrogram(dB)");
SetTunerMapping(cust.m_oNoiseVolTuner, 809,168,90,90,-80.000000,0.000000, 0, "Disturb(dB)");
SetMorseCode(cust.m_vMorseCode[0], 'A', 0x0002, 0x0003, 'A');
SetMorseCode(cust.m_vMorseCode[1], 'B', 0x0007, 0x000f, 'B');
SetMorseCode(cust.m_vMorseCode[2], 'C', 0x0005, 0x000f, 'C');
SetMorseCode(cust.m_vMorseCode[3], 'D', 0x0003, 0x0007, 'D');
SetMorseCode(cust.m_vMorseCode[4], 'E', 0x0001, 0x0001, 'E');
SetMorseCode(cust.m_vMorseCode[5], 'F', 0x000d, 0x000f, 'F');
SetMorseCode(cust.m_vMorseCode[6], 'G', 0x0001, 0x0007, 'G');
SetMorseCode(cust.m_vMorseCode[7], 'H', 0x000f, 0x000f, 'H');
SetMorseCode(cust.m_vMorseCode[8], 'I', 0x0003, 0x0003, 'I');
SetMorseCode(cust.m_vMorseCode[9], 'J', 0x0008, 0x000f, 'J');
SetMorseCode(cust.m_vMorseCode[10], 'K', 0x0002, 0x0007, 'K');
SetMorseCode(cust.m_vMorseCode[11], 'L', 0x000b, 0x000f, 'L');
SetMorseCode(cust.m_vMorseCode[12], 'M', 0x0000, 0x0003, 'M');
SetMorseCode(cust.m_vMorseCode[13], 'N', 0x0001, 0x0003, 'N');
SetMorseCode(cust.m_vMorseCode[14], 'O', 0x0000, 0x0007, 'O');
SetMorseCode(cust.m_vMorseCode[15], 'P', 0x0009, 0x000f, 'P');
SetMorseCode(cust.m_vMorseCode[16], 'Q', 0x0002, 0x000f, 'Q');
SetMorseCode(cust.m_vMorseCode[17], 'R', 0x0005, 0x0007, 'R');
SetMorseCode(cust.m_vMorseCode[18], 'S', 0x0007, 0x0007, 'S');
SetMorseCode(cust.m_vMorseCode[19], 'T', 0x0000, 0x0001, 'T');
SetMorseCode(cust.m_vMorseCode[20], 'U', 0x0006, 0x0007, 'U');
SetMorseCode(cust.m_vMorseCode[21], 'V', 0x000e, 0x000f, 'V');
SetMorseCode(cust.m_vMorseCode[22], 'W', 0x0004, 0x0007, 'W');
SetMorseCode(cust.m_vMorseCode[23], 'X', 0x0006, 0x000f, 'X');
SetMorseCode(cust.m_vMorseCode[24], 'Y', 0x0004, 0x000f, 'Y');
SetMorseCode(cust.m_vMorseCode[25], 'Z', 0x0003, 0x000f, 'Z');
SetMorseCode(cust.m_vMorseCode[26], '1', 0x0010, 0x001f, '1');
SetMorseCode(cust.m_vMorseCode[27], '2', 0x0018, 0x001f, '2');
SetMorseCode(cust.m_vMorseCode[28], '3', 0x001c, 0x001f, '3');
SetMorseCode(cust.m_vMorseCode[29], '4', 0x001e, 0x001f, '4');
SetMorseCode(cust.m_vMorseCode[30], '5', 0x001f, 0x001f, '5');
SetMorseCode(cust.m_vMorseCode[31], '6', 0x000f, 0x001f, '6');
SetMorseCode(cust.m_vMorseCode[32], '7', 0x0007, 0x001f, '7');
SetMorseCode(cust.m_vMorseCode[33], '8', 0x0003, 0x001f, '8');
SetMorseCode(cust.m_vMorseCode[34], '9', 0x0001, 0x001f, '9');
SetMorseCode(cust.m_vMorseCode[35], '0', 0x0000, 0x001f, '0');
SetMorseCode(cust.m_vMorseCode[36], '?', 0x0033, 0x003f, 0);
SetMorseCode(cust.m_vMorseCode[37], '/', 0x000d, 0x001f, VK_DIVIDE);
SetMorseCode(cust.m_vMorseCode[38], '(', 0x0012, 0x003f, 0);
SetMorseCode(cust.m_vMorseCode[39], '-', 0x000e, 0x003f, VK_SUBTRACT);
SetMorseCode(cust.m_vMorseCode[40], '.', 0x002a, 0x003f, VK_DECIMAL);
SetMorseCode(cust.m_vMorseCode[41], '_', 0x0000, 0x0000, ' ');
strcpy(cust.m_vKochChar, "KMRSUAPTLOWI.NJEF0Y,VG5/Q9ZH38B?427C1D6X");
cust.m_nKochWordLen = 5;
cust.m_nExtPortEnable = 0;
cust.m_nExtPortAddr = 0x378;
cust.m_nOpenByte = 0xff;
cust.m_nCloseByte = 0x00;
cust.m_bNetworkEnabled = TRUE;
cust.m_nLocalPort = 3010;
cust.m_nFaBgColor = 0x000000;
cust.m_nFaWaveColor = 0x00ff00;
cust.m_nFaFreqAnaColor = 0xd0d0d0;
cust.m_nFaFloatColor = 0xf0f0f0;
Load();
}
CLakeySetting::~CLakeySetting(void)
{
Save();
}
void CLakeySetting::StrToMorseCode(int nIdx, const char* pStr)
{
sscanf(pStr, "%8X,%8X,%4X"
, &(cust.m_vMorseCode[nIdx].nMorseCode)
, &(cust.m_vMorseCode[nIdx].nMask)
, &(cust.m_vMorseCode[nIdx].nKeyCode));
}
char* CLakeySetting::MorseCodeToStr(char* pStr, int nIdx)
{
sprintf(pStr, "%8.8X,%8.8X,%4.4X"
, cust.m_vMorseCode[nIdx].nMorseCode
, cust.m_vMorseCode[nIdx].nMask
, cust.m_vMorseCode[nIdx].nKeyCode);
return pStr;
}
void CLakeySetting::StrToButtonMapping(BUTTONMAPPING* pMapping, const char* pStr)
{
sscanf(pStr, "%d,%d,%d,%d,%4X,%s"
, &(pMapping->x)
, &(pMapping->y)
, &(pMapping->w)
, &(pMapping->h)
, &(pMapping->nKeyCode)
, pMapping->vLabel
);
}
char* CLakeySetting::ButtonMappingToStr(char* pStr, const BUTTONMAPPING* pMapping)
{
sprintf(pStr, "%d,%d,%d,%d,%4.4X,%s"
, pMapping->x
, pMapping->y
, pMapping->w
, pMapping->h
, pMapping->nKeyCode
, pMapping->vLabel
);
return pStr;
}
void CLakeySetting::StrToTunerMapping(TUNERMAPPING* pMapping, const char* pStr)
{
sscanf(pStr, "%d,%d,%d,%d,%f,%f,%f,%s"
, &(pMapping->x)
, &(pMapping->y)
, &(pMapping->w)
, &(pMapping->h)
, &(pMapping->vl)
, &(pMapping->vr)
, &(pMapping->v)
, pMapping->vLabel
);
}
char* CLakeySetting::TunerMappingToStr(char* pStr, const TUNERMAPPING* pMapping)
{
sprintf(pStr, "%d,%d,%d,%d,%f,%f,%f,%s"
, pMapping->x
, pMapping->y
, pMapping->w
, pMapping->h
, pMapping->vl
, pMapping->vr
, pMapping->v
, pMapping->vLabel
);
return pStr;
}
#define PROFILE_PATHNAME "./lakey.ini"
#define SECTION_CW "CW"
#define CW_BEEPFREQ "beepfreq"
#define CW_BEEPVOL "beepvol"
#define CW_SHORTHIT "shorthit"
#define CW_LONGHIT "longhit"
#define CW_HITDELAY "hitdelay"
#define CW_LETTERDELAY "letterdelay"
#define CW_WORDDELAY "worddelay"
#define SECTION_GLOBAL "GLOBAL"
#define GLOBAL_WINDOWRECT "windowrect"
#define SECTION_JOURNAL "JOURNAL"
#define JOURNAL_SENDPERIOD "sendperiod"
#define JOURNAL_SENDIDLELIMIT "sendidlelimit"
#define JOURNAL_SENDRECT "sendrect"
#define JOURNAL_SENDLABELOFFSET "sendlabeloffset"
#define JOURNAL_SENDLABEL "sendlabel"
#define JOURNAL_SENDQUEUERECT "sendqueuerect"
#define JOURNAL_SPECRECT "specrect"
#define JOURNAL_SPECLABELOFFSET "speclabeloffset"
#define JOURNAL_SPECLABEL "speclabel"
#define JOURNAL_RECVPERIOD "recvperiod"
#define JOURNAL_RECVIDLELIMIT "recvidlelimit"
#define JOURNAL_RECVRECT "recvrect"
#define JOURNAL_RECVLABELOFFSET "recvlabeloffset"
#define JOURNAL_RECVLABEL "recvlabel"
#define JOURNAL_RECVMRECT "recvmrect"
#define JOURNAL_RECVANALYZESAMPLE "recvanalyzesamples"
#define JOURNAL_RECVTHRESHOLD "recvthreshold"
#define JOURNAL_RECVFREQSTART "recvfreqstart"
#define JOURNAL_RECVFREQEND "recvfreqend"
#define SECTION_MORSE "MORSE"
#define SECTION_MAINPANEL "MAINPANEL"
#define MAINPANEL_CW "cw"
#define MAINPANEL_SENDPAUSE "sendpause"
#define MAINPANEL_SENDFILE "sendfile"
#define MAINPANEL_AUTOKEYSWITCH "autokeyswitch"
#define MAINPANEL_NOISESWITCH "noiseswitch"
#define MAINPANEL_SENDVOL "sendvol"
#define MAINPANEL_NOISEVOL "noisevol"
#define MAINPANEL_SENDSPEED "sendspeed"
#define MAINPANEL_SPECBRIGHTNESS "specbrightness"
#define SECTION_KOCH "KOCH"
#define KOCH_CHARS "charlist"
#define KOCH_WORDLEN "koch_wordlen"
#define SECTION_HWCTRL "HWCTRL"
#define HWCTRL_ENABLEEXTPORT "enableextport"
#define HWCTRL_EXTPORTADDR "extportaddr"
#define HWCTRL_OPENBYTE "openbyte"
#define HWCTRL_CLOSEBYTE "closebyte"
#define SECTION_NETWORK "NETWORK"
#define NETWORK_NWENABLED "nwenabled"
#define NETWORK_LOCALPORT "localport"
#define NETWORK_LOCALPORT_DEF 3010
//
#define NETWORK_HOSTS "hosts"
//Ϣǰ(host1, host2, host3, ...)
#define NETWORK_HOSTENTRYEXPR "host%d"
BOOL CLakeySetting::Load()
{
char vBuff[64];
cust.m_rBeepFreq = GetProfileDouble(SECTION_CW, CW_BEEPFREQ, cust.m_rBeepFreq);
cust.m_rBeepVol = GetProfileDouble(SECTION_CW, CW_BEEPVOL, cust.m_rBeepVol);
cust.m_nShortHit = GetProfileDec(SECTION_CW, CW_SHORTHIT, cust.m_nShortHit);
cust.m_nLongHit = GetProfileDec(SECTION_CW, CW_LONGHIT, cust.m_nLongHit);
cust.m_nHitDelay = GetProfileDec(SECTION_CW, CW_HITDELAY, cust.m_nHitDelay);
cust.m_nLetterDelay = GetProfileDec(SECTION_CW, CW_LETTERDELAY, cust.m_nLetterDelay);
cust.m_nWordDelay = GetProfileDec(SECTION_CW, CW_WORDDELAY, cust.m_nWordDelay);
GetProfileRect(SECTION_GLOBAL, GLOBAL_WINDOWRECT, &cust.m_oWindowRect);
cust.m_nSendJournalPeriod = GetProfileDec(SECTION_JOURNAL, JOURNAL_SENDPERIOD, cust.m_nSendJournalPeriod);
cust.m_nSendIdleLimit = GetProfileDec(SECTION_JOURNAL, JOURNAL_SENDIDLELIMIT, cust.m_nSendIdleLimit);
GetProfileRect(SECTION_JOURNAL, JOURNAL_SENDRECT, &cust.m_oSendJournalRect);
GetProfileRect(SECTION_JOURNAL, JOURNAL_SENDQUEUERECT, &cust.m_oSendCharQueueRect);
GetProfileSize(SECTION_JOURNAL, JOURNAL_SENDLABELOFFSET, &cust.m_oSendLabelOffset);
GetPrivateProfileString(SECTION_JOURNAL, JOURNAL_SENDLABEL, cust.m_vSendLabel, cust.m_vSendLabel, sizeof(cust.m_vSendLabel), PROFILE_PATHNAME);
GetProfileRect(SECTION_JOURNAL, JOURNAL_SPECRECT, &cust.m_oSpectrogramRect);
GetProfileSize(SECTION_JOURNAL, JOURNAL_SPECLABELOFFSET, &cust.m_oSpecLabelOffset);
GetPrivateProfileString(SECTION_JOURNAL, JOURNAL_SPECLABEL, cust.m_vSpecLabel, cust.m_vSpecLabel, sizeof(cust.m_vSpecLabel), PROFILE_PATHNAME);
cust.m_nRecvJournalPeriod = GetProfileDec(SECTION_JOURNAL, JOURNAL_RECVPERIOD, cust.m_nRecvJournalPeriod);
cust.m_nRecvIdleLimit = GetProfileDec(SECTION_JOURNAL, JOURNAL_RECVIDLELIMIT, cust.m_nRecvIdleLimit);
GetProfileRect(SECTION_JOURNAL, JOURNAL_RECVRECT, &cust.m_oRecvJournalRect);
GetProfileSize(SECTION_JOURNAL, JOURNAL_RECVLABELOFFSET, &cust.m_oRecvLabelOffset);
GetPrivateProfileString(SECTION_JOURNAL, JOURNAL_RECVLABEL, cust.m_vRecvLabel, cust.m_vRecvLabel, sizeof(cust.m_vRecvLabel), PROFILE_PATHNAME);
GetProfileRect(SECTION_JOURNAL, JOURNAL_RECVMRECT, &cust.m_oRecvMonitorRect);
cust.m_nRecvAnalyzeSamples = GetProfileDec(SECTION_JOURNAL, JOURNAL_RECVANALYZESAMPLE, cust.m_nRecvAnalyzeSamples);
cust.m_rRecvThreshold = GetProfileDouble(SECTION_JOURNAL, JOURNAL_RECVTHRESHOLD, cust.m_rRecvThreshold);
cust.m_nRecvFreqStart = GetProfileDec(SECTION_JOURNAL, JOURNAL_RECVFREQSTART, cust.m_nRecvFreqStart);
cust.m_nRecvFreqEnd = GetProfileDec(SECTION_JOURNAL, JOURNAL_RECVFREQEND, cust.m_nRecvFreqEnd);
GetButtonMapping(SECTION_MAINPANEL, MAINPANEL_CW, &cust.m_oCwKeyButton);
GetButtonMapping(SECTION_MAINPANEL, MAINPANEL_SENDPAUSE, &cust.m_oSendPauseButton);
GetButtonMapping(SECTION_MAINPANEL, MAINPANEL_SENDFILE, &cust.m_oSendFileButton);
GetButtonMapping(SECTION_MAINPANEL, MAINPANEL_AUTOKEYSWITCH, &cust.m_oAutoKeySwitchButton);
GetButtonMapping(SECTION_MAINPANEL, MAINPANEL_NOISESWITCH, &cust.m_oNoiseSwitchButton);
GetTunerMapping(SECTION_MAINPANEL, MAINPANEL_SENDVOL, &cust.m_oSendVolTuner);
GetTunerMapping(SECTION_MAINPANEL, MAINPANEL_NOISEVOL, &cust.m_oNoiseVolTuner);
GetTunerMapping(SECTION_MAINPANEL, MAINPANEL_SENDSPEED, &cust.m_oSendSpeedTuner);
GetTunerMapping(SECTION_MAINPANEL, MAINPANEL_SPECBRIGHTNESS, &cust.m_oSpecBrightnessTuner);
GetPrivateProfileString(SECTION_KOCH, KOCH_CHARS, "", cust.m_vKochChar, sizeof(cust.m_vKochChar), PROFILE_PATHNAME);
cust.m_nKochWordLen = GetProfileDec(SECTION_KOCH, KOCH_WORDLEN, cust.m_nKochWordLen);
for (int i = 0; i < MORSECODECOUNT; ++i)
{
char vMorseKey[2] = {' ', '\0'};
vMorseKey[0] = (char)cust.m_vMorseCode[i].nAscCode;
GetPrivateProfileString(SECTION_MORSE, vMorseKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
StrToMorseCode(i, vBuff);
}
cust.m_nExtPortEnable = GetProfileHex(SECTION_HWCTRL, HWCTRL_ENABLEEXTPORT, cust.m_nExtPortEnable);
cust.m_nExtPortAddr = GetProfileHex(SECTION_HWCTRL, HWCTRL_EXTPORTADDR, cust.m_nExtPortAddr);
cust.m_nOpenByte = GetProfileHex(SECTION_HWCTRL, HWCTRL_OPENBYTE, cust.m_nOpenByte);
cust.m_nCloseByte = GetProfileHex(SECTION_HWCTRL, HWCTRL_CLOSEBYTE, cust.m_nCloseByte);
cust.m_bNetworkEnabled = (0 == GetProfileDec(SECTION_NETWORK, NETWORK_NWENABLED, cust.m_bNetworkEnabled) ? FALSE : TRUE);
cust.m_nLocalPort = GetProfileDec(SECTION_NETWORK, NETWORK_LOCALPORT, cust.m_nLocalPort);
int nHosts = GetProfileDec(SECTION_NETWORK, NETWORK_HOSTS, 0);
// if (HOSTS_MAX < cust.m_nHosts)
// cust.m_nHosts = HOSTS_MAX;
hosts.resize(nHosts);
for (int i = 0; i < nHosts; ++i)
{
sprintf(vBuff, NETWORK_HOSTENTRYEXPR, i + 1);
GetPrivateProfileString(SECTION_NETWORK, vBuff, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
char* pSpliter = strstr(vBuff, ":");
*pSpliter = '\n';
sscanf(vBuff, "%s%s"
, hosts[i].szHostName
, hosts[i].szPort);
}
return TRUE;
}
BOOL CLakeySetting::Save()
{
WriteProfileDouble(SECTION_CW, CW_BEEPFREQ, cust.m_rBeepFreq);
WriteProfileDouble(SECTION_CW, CW_BEEPVOL, cust.m_rBeepVol);
WriteProfileDec(SECTION_CW, CW_SHORTHIT, cust.m_nShortHit);
WriteProfileDec(SECTION_CW, CW_LONGHIT, cust.m_nLongHit);
WriteProfileDec(SECTION_CW, CW_HITDELAY, cust.m_nHitDelay);
WriteProfileDec(SECTION_CW, CW_LETTERDELAY, cust.m_nLetterDelay);
WriteProfileDec(SECTION_CW, CW_WORDDELAY, cust.m_nWordDelay);
WriteProfileRect(SECTION_GLOBAL, GLOBAL_WINDOWRECT, &cust.m_oWindowRect);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_SENDPERIOD, cust.m_nSendJournalPeriod);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_SENDIDLELIMIT, cust.m_nSendIdleLimit);
WriteProfileRect(SECTION_JOURNAL, JOURNAL_SENDRECT, &cust.m_oSendJournalRect);
WriteProfileSize(SECTION_JOURNAL, JOURNAL_SENDLABELOFFSET, &cust.m_oSendLabelOffset);
WritePrivateProfileString(SECTION_JOURNAL, JOURNAL_SENDLABEL, cust.m_vSendLabel, PROFILE_PATHNAME);
WriteProfileRect(SECTION_JOURNAL, JOURNAL_SENDQUEUERECT, &cust.m_oSendCharQueueRect);
WriteProfileRect(SECTION_JOURNAL, JOURNAL_SPECRECT, &cust.m_oSpectrogramRect);
WriteProfileSize(SECTION_JOURNAL, JOURNAL_SPECLABELOFFSET, &cust.m_oSpecLabelOffset);
WritePrivateProfileString(SECTION_JOURNAL, JOURNAL_SPECLABEL, cust.m_vSpecLabel, PROFILE_PATHNAME);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_RECVPERIOD, cust.m_nRecvJournalPeriod);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_RECVIDLELIMIT, cust.m_nRecvIdleLimit);
WriteProfileRect(SECTION_JOURNAL, JOURNAL_RECVRECT, &cust.m_oRecvJournalRect);
WriteProfileSize(SECTION_JOURNAL, JOURNAL_RECVLABELOFFSET, &cust.m_oRecvLabelOffset);
WritePrivateProfileString(SECTION_JOURNAL, JOURNAL_RECVLABEL, cust.m_vRecvLabel, PROFILE_PATHNAME);
WriteProfileRect(SECTION_JOURNAL, JOURNAL_RECVMRECT, &cust.m_oRecvMonitorRect);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_RECVANALYZESAMPLE, cust.m_nRecvAnalyzeSamples);
WriteProfileDouble(SECTION_JOURNAL, JOURNAL_RECVTHRESHOLD, cust.m_rRecvThreshold);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_RECVFREQSTART, cust.m_nRecvFreqStart);
WriteProfileDec(SECTION_JOURNAL, JOURNAL_RECVFREQEND, cust.m_nRecvFreqEnd);
WriteButtonMapping(SECTION_MAINPANEL, MAINPANEL_CW, &cust.m_oCwKeyButton);
WriteButtonMapping(SECTION_MAINPANEL, MAINPANEL_SENDPAUSE, &cust.m_oSendPauseButton);
WriteButtonMapping(SECTION_MAINPANEL, MAINPANEL_SENDFILE, &cust.m_oSendFileButton);
WriteButtonMapping(SECTION_MAINPANEL, MAINPANEL_AUTOKEYSWITCH, &cust.m_oAutoKeySwitchButton);
WriteButtonMapping(SECTION_MAINPANEL, MAINPANEL_NOISESWITCH, &cust.m_oNoiseSwitchButton);
WriteTunerMapping(SECTION_MAINPANEL, MAINPANEL_SENDVOL, &cust.m_oSendVolTuner);
WriteTunerMapping(SECTION_MAINPANEL, MAINPANEL_NOISEVOL, &cust.m_oNoiseVolTuner);
WriteTunerMapping(SECTION_MAINPANEL, MAINPANEL_SENDSPEED, &cust.m_oSendSpeedTuner);
WriteTunerMapping(SECTION_MAINPANEL, MAINPANEL_SPECBRIGHTNESS, &cust.m_oSpecBrightnessTuner);
WritePrivateProfileString(SECTION_KOCH, KOCH_CHARS, cust.m_vKochChar, PROFILE_PATHNAME);
WriteProfileDec(SECTION_KOCH, KOCH_WORDLEN, cust.m_nKochWordLen);
for (int i = 0; i < MORSECODECOUNT; ++i)
{
char vMorseKey[2] = {' ', '\0'};
char vBuff[64];
vMorseKey[0] = (char)cust.m_vMorseCode[i].nAscCode;
WritePrivateProfileString(SECTION_MORSE, vMorseKey, MorseCodeToStr(vBuff, i), PROFILE_PATHNAME);
}
WriteProfileHex(SECTION_HWCTRL, HWCTRL_ENABLEEXTPORT, cust.m_nExtPortEnable);
WriteProfileHex(SECTION_HWCTRL, HWCTRL_EXTPORTADDR, cust.m_nExtPortAddr);
WriteProfileHex(SECTION_HWCTRL, HWCTRL_OPENBYTE, cust.m_nOpenByte);
WriteProfileHex(SECTION_HWCTRL, HWCTRL_CLOSEBYTE, cust.m_nCloseByte);
WriteProfileDec(SECTION_NETWORK, NETWORK_NWENABLED, cust.m_bNetworkEnabled);
WriteProfileDec(SECTION_NETWORK, NETWORK_LOCALPORT, cust.m_nLocalPort);
WriteProfileDec(SECTION_NETWORK, NETWORK_HOSTS, (int)hosts.size());
char vPropBuff[8];
char vHostBuff[64];
for (UINT i = 0; i < hosts.size(); ++i)
{
sprintf(vPropBuff, NETWORK_HOSTENTRYEXPR, i + 1);
sprintf(vHostBuff, "%s:%s", hosts[i].szHostName, hosts[i].szPort);
WritePrivateProfileString(SECTION_NETWORK, vPropBuff, vHostBuff, PROFILE_PATHNAME);
}
return TRUE;
}
int CLakeySetting::GetProfileHex(const char* pSec, const char* pKey, int nDefault)
{
char vBuff[32];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
sscanf(vBuff, "%8X", &nDefault);
return nDefault;
}
void CLakeySetting::WriteProfileHex(const char* pSec, const char* pKey, int n)
{
char vBuff[32];
sprintf(vBuff, "%8.8X", n);
WritePrivateProfileString(pSec, pKey, vBuff, PROFILE_PATHNAME);
}
int CLakeySetting::GetProfileDec(const char* pSec, const char* pKey, int nDefault)
{
char vBuff[32];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
sscanf(vBuff, "%d", &nDefault);
return nDefault;
}
void CLakeySetting::WriteProfileDec(const char* pSec, const char* pKey, int n)
{
char vBuff[32];
sprintf(vBuff, "%d", n);
WritePrivateProfileString(pSec, pKey, vBuff, PROFILE_PATHNAME);
}
double CLakeySetting::GetProfileDouble(const char* pSec, const char* pKey, double rDefault)
{
char vBuff[32];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
sscanf(vBuff, "%lf", &rDefault);
return rDefault;
}
void CLakeySetting::WriteProfileDouble(const char* pSec, const char* pKey, double r)
{
char vBuff[32];
sprintf(vBuff, "%lf", r);
WritePrivateProfileString(pSec, pKey, vBuff, PROFILE_PATHNAME);
}
void CLakeySetting::GetButtonMapping(const char* pSec, const char* pKey, BUTTONMAPPING* pBtMap)
{
char vBuff[64];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
StrToButtonMapping(pBtMap, vBuff);
}
void CLakeySetting::WriteButtonMapping(const char* pSec, const char* pKey, const BUTTONMAPPING* pBtMap)
{
char vBuff[64];
WritePrivateProfileString(pSec, pKey, ButtonMappingToStr(vBuff, pBtMap), PROFILE_PATHNAME);
}
void CLakeySetting::GetTunerMapping(const char* pSec, const char* pKey, TUNERMAPPING* pTnMap)
{
char vBuff[64];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
StrToTunerMapping(pTnMap, vBuff);
}
void CLakeySetting::WriteTunerMapping(const char* pSec, const char* pKey, const TUNERMAPPING* pTnMap)
{
char vBuff[64];
WritePrivateProfileString(pSec, pKey, TunerMappingToStr(vBuff, pTnMap), PROFILE_PATHNAME);
}
void CLakeySetting::GetProfileRect(const char* pSec, const char* pKey, RECT* pRect)
{
char vBuff[64];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
sscanf(vBuff, "%d,%d,%d,%d", &pRect->left, &pRect->top, &pRect->right, &pRect->bottom);
}
void CLakeySetting::WriteProfileRect(const char* pSec, const char* pKey, const RECT* pRect)
{
char vBuff[64];
sprintf(vBuff, "%d,%d,%d,%d", pRect->left, pRect->top, pRect->right, pRect->bottom);
WritePrivateProfileString(pSec, pKey, vBuff, PROFILE_PATHNAME);
}
void CLakeySetting::GetProfileSize(const char* pSec, const char* pKey, SIZE* pSize)
{
char vBuff[64];
GetPrivateProfileString(pSec, pKey, "", vBuff, sizeof(vBuff), PROFILE_PATHNAME);
if (strlen(vBuff))
sscanf(vBuff, "%d,%d", &pSize->cx, &pSize->cy);
}
void CLakeySetting::WriteProfileSize(const char* pSec, const char* pKey, const SIZE* pSize)
{
char vBuff[64];
sprintf(vBuff, "%d,%d", pSize->cx, pSize->cy);
WritePrivateProfileString(pSec, pKey, vBuff, PROFILE_PATHNAME);
}
void CLakeySetting::GetCustomize(CUSTOMIZE* pCust)
{
memcpy(pCust, &cust, sizeof(cust));
memcpy(pCust->m_vKochChar, cust.m_vKochChar, sizeof(cust.m_vKochChar));
}
void CLakeySetting::SetCustomize(const CUSTOMIZE* pCust)
{
memcpy(&cust, pCust, sizeof(cust));
memcpy(cust.m_vKochChar, pCust->m_vKochChar, sizeof(cust.m_vKochChar));
}
float calcStdWordLen(short int nMorseCode, short int nMask)
{
int s = 2; // word space - hit space
do
{
if (0x01 & nMorseCode)
{
// di
s += 2;
}
else
{
// dah
s += 4;
}
}
while(0x01 & (nMask >>= 1));
return (float)s / (float)STD_WORD_LEN;
}
void wpmToParams(WPMS* pWpms)
{
// .--. .- .-. .. ...
pWpms->di = (int)(60 * 1000 / (pWpms->wpm * STD_WORD_LEN));
pWpms->dah = pWpms->di * 3;
pWpms->hdelay = pWpms->di;
pWpms->ldelay = pWpms->di * 3;
pWpms->wdelay = pWpms->di * 3;
}
void paramsToWpm(WPMS* pWpms)
{
short nCalc = 10 * pWpms->di
+ 4 * pWpms->dah
+ 9 * pWpms->hdelay
+ 4 * pWpms->ldelay
+ 1 * pWpms->wdelay;
if (0 == nCalc)
nCalc = 1;
nCalc = (60 * 1000 + nCalc / 2) / nCalc;
if (99 < nCalc)
nCalc = 99;
pWpms->wpm = nCalc;
}
================================================
FILE: src/LakeySetting.h
================================================
#pragma once
#include
#include
#include "LaTuner.h"
using namespace std;
#define MORSECODECOUNT 42
#define PROFILE "lakey.ini"
#define HOSTS_MAX 8
#define HOSTS_NAME_LEN 64
// PARIS: .--. .- .-. .. ...
#define STD_WORD_LEN 46
typedef struct tagMorseCode
{
unsigned int nAscCode;
unsigned short int nMorseCode;
unsigned short int nMask;
unsigned int nKeyCode;
float rStdWordLen;
} MORSECODE;
typedef struct tagButtonMapping
{
int x;
int y;
int w;
int h;
int nKeyCode;
char vLabel[128];
} BUTTONMAPPING;
typedef struct tagTunerMapping
{
int x;
int y;
int w;
int h;
LASCALE vl;
LASCALE vr;
LASCALE v;
char vLabel[128];
} TUNERMAPPING;
typedef struct tagHostNode
{
char szHostName[60];
char szPort[8];
} HOSTNODE;
typedef vector HostList;
typedef struct tagCustomize
{
double m_rBeepFreq;
double m_rBeepVol;
int m_nShortHit;
int m_nLongHit;
int m_nHitDelay;
int m_nLetterDelay;
int m_nWordDelay;
RECT m_oWindowRect;
int m_nSendJournalPeriod;
int m_nSendIdleLimit;
RECT m_oSendJournalRect;
SIZE m_oSendLabelOffset;
char m_vSendLabel[16];
RECT m_oSendCharQueueRect;
int m_nRecvJournalPeriod;
int m_nRecvIdleLimit;
RECT m_oRecvJournalRect;
SIZE m_oRecvLabelOffset;
char m_vRecvLabel[16];
RECT m_oRecvMonitorRect;
int m_nRecvAnalyzeSamples;
double m_rRecvThreshold;
int m_nRecvFreqStart;
int m_nRecvFreqEnd;
RECT m_oSpectrogramRect;
SIZE m_oSpecLabelOffset;
char m_vSpecLabel[16];
BUTTONMAPPING m_oCwKeyButton;
BUTTONMAPPING m_oSendPauseButton;
BUTTONMAPPING m_oSendFileButton;
BUTTONMAPPING m_oAutoKeySwitchButton;
BUTTONMAPPING m_oNoiseSwitchButton;
TUNERMAPPING m_oSendVolTuner;
TUNERMAPPING m_oNoiseVolTuner;
TUNERMAPPING m_oSendSpeedTuner;
TUNERMAPPING m_oSpecBrightnessTuner;
char m_vKochChar[MORSECODECOUNT + 1];
int m_nKochWordLen;
MORSECODE m_vMorseCode[MORSECODECOUNT];
int m_nExtPortEnable;
WORD m_nExtPortAddr;
BYTE m_nOpenByte;
BYTE m_nCloseByte;
WORD m_nLocalPort;
BOOL m_bNetworkEnabled;
//char m_vHostList[HOSTS_MAX][HOSTS_NAME_LEN];
//Styles
//Frequency Analyzer
int m_nFaBgColor;
int m_nFaWaveColor;
int m_nFaFloatColor;
int m_nFaFreqAnaColor;
} CUSTOMIZE;
typedef struct tagWPMS
{
float wpm;
int di;
int dah;
int hdelay;
int ldelay;
int wdelay;
} WPMS;
void wpmToParams(WPMS* pWpms);
void paramsToWpm(WPMS* pWpms);
float calcStdWordLen(short int nMorseCode, short int nMask);
class CLakeySetting
{
public:
CLakeySetting(void);
virtual ~CLakeySetting(void);
virtual BOOL Load();
virtual BOOL Save();
CUSTOMIZE cust;
HostList hosts;
virtual void GetCustomize(CUSTOMIZE* pCust);
virtual void SetCustomize(const CUSTOMIZE* pCust);
private:
void StrToMorseCode(int nIdx, const char* pStr);
char* MorseCodeToStr(char* pStr, int nIdx);
char* ButtonMappingToStr(char* pStr, const BUTTONMAPPING* pMapping);
void StrToButtonMapping(BUTTONMAPPING* pMapping, const char* pStr);
char* TunerMappingToStr(char* pStr, const TUNERMAPPING* pMapping);
void StrToTunerMapping(TUNERMAPPING* pMapping, const char* pStr);
int GetProfileHex(const char* pSec, const char* pKey, int nDefault);
void WriteProfileHex(const char* pSec, const char* pKey, int n);
int GetProfileDec(const char* pSec, const char* pKey, int nDefault);
void WriteProfileDec(const char* pSec, const char* pKey, int n);
double GetProfileDouble(const char* pSec, const char* pKey, double rDefault);
void WriteProfileDouble(const char* pSec, const char* pKey, double r);
void GetButtonMapping(const char* pSec, const char* pKey, BUTTONMAPPING* pBtMap);
void WriteButtonMapping(const char* pSec, const char* pKey, const BUTTONMAPPING* pBtMap);
void GetTunerMapping(const char* pSec, const char* pKey, TUNERMAPPING* pTnMap);
void WriteTunerMapping(const char* pSec, const char* pKey, const TUNERMAPPING* pTnMap);
void GetProfileRect(const char* pSec, const char* pKey, RECT* pRect);
void WriteProfileRect(const char* pSec, const char* pKey, const RECT* pRect);
void GetProfileSize(const char* pSec, const char* pKey, SIZE* pSize);
void WriteProfileSize(const char* pSec, const char* pKey, const SIZE* pSize);
};
================================================
FILE: src/MorseParser.cpp
================================================
#include "StdAfx.h"
#include "morseparser.h"
CMorseParser::CMorseParser(const MORSECODE* pMorseList, int nCount, int nMaxShortCount, IParseEventListener* pListener)
{
m_pMorseCodeTree = new MORSECODETREENODE;
m_pMorseCodeTree->pMorseCode = NULL;
m_pMorseCodeTree->pDi = m_pMorseCodeTree->pDa = NULL;
for (int i = 0; i < nCount; ++i)
{
AddNode(m_pMorseCodeTree, pMorseList + i, ((pMorseList + i)->nMask + 1) >> 1);
}
m_pCurrNode = m_pMorseCodeTree;
m_nLastState = 0;
m_nStateCount = 0;
m_nMaxShortCount = nMaxShortCount;
m_pParseEventListener = pListener;
m_nStep = 1;
}
CMorseParser::~CMorseParser(void)
{
ReleaseAllNodes(m_pMorseCodeTree);
}
void CMorseParser::AddNode(MORSECODETREENODE* pCurrNode, const MORSECODE* pMorseCode, int nMcWin)
{
if (!nMcWin)
{
// position it!
pCurrNode->pMorseCode = pMorseCode;
}
else
{
if (pMorseCode->nMorseCode & nMcWin)
{
if (!pCurrNode->pDi)
{
pCurrNode->pDi = new MORSECODETREENODE;
pCurrNode->pDi->pMorseCode = NULL;
pCurrNode->pDi->pDi = pCurrNode->pDi->pDa = NULL;
}
AddNode(pCurrNode->pDi, pMorseCode, nMcWin >> 1);
}
else
{
if (!pCurrNode->pDa)
{
pCurrNode->pDa = new MORSECODETREENODE;
pCurrNode->pDa->pMorseCode = NULL;
pCurrNode->pDa->pDi = pCurrNode->pDa->pDa = NULL;
}
AddNode(pCurrNode->pDa, pMorseCode, nMcWin >> 1);
}
}
}
void CMorseParser::ReleaseAllNodes(MORSECODETREENODE* pRoot)
{
if (!pRoot)
{
ReleaseAllNodes(pRoot->pDi);
ReleaseAllNodes(pRoot->pDa);
delete pRoot;
}
}
void CMorseParser::Sample(int nState)
{
switch(m_nStep)
{
case 1: // test start new letter
if (1 == nState)
{
m_nStateCount = 1;
m_pCurrNode = m_pMorseCodeTree;
m_nStep = 2;
}
break;
case 2:
if (0 == nState)
{
m_nStep = 3;
if (m_nStateCount > m_nMaxShortCount)
{
if (m_pCurrNode->pDa)
m_pCurrNode = m_pCurrNode->pDa;
else
{
m_pParseEventListener->OnWorkOut(this, m_pCurrNode->pMorseCode);
m_nStep = 1;
}
}
else
{
if (m_pCurrNode->pDi)
m_pCurrNode = m_pCurrNode->pDi;
else
{
m_pParseEventListener->OnWorkOut(this, m_pCurrNode->pMorseCode);
m_nStep = 1;
}
}
m_nStateCount = 0;
}
else
++m_nStateCount;
break;
case 3:
if (1 == nState)
{
if (m_nStateCount > m_nMaxShortCount)
{
if (m_pCurrNode->pMorseCode)
{
m_pParseEventListener->OnWorkOut(this, m_pCurrNode->pMorseCode);
m_pCurrNode = m_pMorseCodeTree;
}
}
m_nStateCount = 1;
m_nStep = 2;
}
else
{
if (++m_nStateCount > m_nMaxShortCount)
{
if (m_pCurrNode->pMorseCode)
{
m_pParseEventListener->OnWorkOut(this, m_pCurrNode->pMorseCode);
m_nStep = 1;
}
else if (!m_pCurrNode->pDi && !m_pCurrNode->pDa || m_nStateCount > 1.5 * m_nMaxShortCount)
{
m_pParseEventListener->OnWorkOut(this, NULL);
m_nStep = 1;
}
}
}
break;
}
}
================================================
FILE: src/MorseParser.h
================================================
#pragma once
#include "LakeySetting.h"
class IParseEventListener
{
public:
virtual void OnWorkOut(void* owner, const MORSECODE* pResult) = 0;
};
typedef struct tagMorseCodeTreeNode
{
const MORSECODE* pMorseCode;
struct tagMorseCodeTreeNode* pDi;
struct tagMorseCodeTreeNode* pDa;
} MORSECODETREENODE;
class CMorseParser
{
public:
CMorseParser(const MORSECODE* pMorseList, int nCount, int nMaxShortCount, IParseEventListener* pListener);
virtual ~CMorseParser();
void SetMaxShortCount(int nCount) { m_nMaxShortCount = nCount; };
void Sample(int nState);
private:
void AddNode(MORSECODETREENODE* pCurrNode, const MORSECODE* pMorseCode, int nMcWin);
void ReleaseAllNodes(MORSECODETREENODE* pRoot);
MORSECODETREENODE* m_pMorseCodeTree;
int m_nMaxShortCount;
IParseEventListener* m_pParseEventListener;
// for parse work
MORSECODETREENODE* m_pCurrNode;
int m_nLastState;
int m_nStateCount;
int m_nStep;
};
================================================
FILE: src/ReadMe.txt
================================================
========================================================================
WIN32 Ӧó : Lakey Ŀſ
========================================================================
ӦóΪ Lakey Ӧó
ļ Lakey Ӧó
ÿļժҪ
Lakey.vcproj
Ӧóɵ VC++ ĿĿļ
йɴļ Visual C++ 汾ϢԼ
йӦóѡ
ƽ̨úĿܵϢ
Lakey.cpp
ӦóԴļ
/////////////////////////////////////////////////////////////////////////////
ӦóѴԴ
Lakey.rc
dzʹõ Microsoft Windows Դб
洢 RES Ŀ¼µͼꡢλͼꡣ
ļ Microsoft Visual C++ ֱӱ༭
Resource.h
DZͷļµԴ ID
Microsoft Visual C++ ȡ´ļ
Lakey.ico
һͼļӦóͼ (32x32)
ͼλԴļ Lakey.rc С
small.ico
һͼļС汾 (16x16)
ӦóͼꡣͼλԴ
ļ Lakey.rc С
/////////////////////////////////////////////////////////////////////////////
ļ
StdAfx.hStdAfx.cpp
ЩļΪ Lakey.pch
Ԥͷ (PCH) ļԼΪ StdAfx.obj Ԥļ
/////////////////////////////////////////////////////////////////////////////
עͣ
Ӧóʹ "TODO:" עָʾԴӦӵĻԶ
IJ֡
/////////////////////////////////////////////////////////////////////////////
================================================
FILE: src/Resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Lakey.rc
//
#define IDC_MYICON 2
#define IDD_LAKEY_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDD_SETTINGS 104
#define IDM_EXIT 105
#define IDI_LAKEY 107
#define IDI_SMALL 108
#define IDC_LAKEY 109
#define IDR_MAINFRAME 128
#define ID_129 129
#define IDB_BITMAP1 131
#define IDB_LOGO 131
#define ID_KOCH 132
#define ID__ 133
#define ID_KOCH_134 134
#define IDD_COPYPAD 135
#define IDD_TEST 136
#define IDD_GENERAL 137
#define IDM_TEST 199
#define IDC_EDIT1 1000
#define IDC_TONE 1001
#define IDC_BEEPFREQ 1002
#define IDC_COPYTEXT 1003
#define IDC_SETTINGSTAB 1004
#define IDC_BEEPVOL 1005
#define IDM_SETTINGS 1006
#define IDC_SENDPERIOD 1007
#define IDC_BUTTON1 1008
#define IDC_HOSTADD 1008
#define IDC_SENDILDELIMIT 1009
#define IDC_RECVPERIOD 1010
#define IDC_RECVILDELIMIT 1011
#define IDC_RECVANALYZESAMPLES 1012
#define IDC_RECVTHRESHOLD 1013
#define IDC_RECVFREQSTART 1014
#define IDC_RECVFREQEND 1015
#define IDC_HOTKEY1 1016
#define IDC_CALCSPEED 1017
#define IDC_SHORTHIT 1018
#define IDC_LONGHIT 1019
#define IDC_HITDELAY 1020
#define IDC_LETTERDELAY 1021
#define IDC_CW 1022
#define ID_ACCEPT 1023
#define IDC_ACCEPT 1024
#define IDC_SPEED 1025
#define IDC_KOCHCHARS 1026
#define IDC_ELAPSETIME 1027
#define IDC_COPIED 1028
#define IDC_INCORRECT 1029
#define IDC_CORRECTPERC 1030
#define IDC_RICHEDIT21 1031
#define IDC_LOCALPORT 1032
#define IDC_NWNODES 1033
#define IDC_HOSTPORT 1033
#define IDC_TAB1 1034
#define IDC_HOSTLIST 1034
#define IDC_HOSTADDR 1035
#define IDC_HOSTNAME 1035
#define IDC_HOSTDEL 1036
#define IDC_CHECK1 1038
#define IDC_NWENABLED 1038
#define IDM_KOCHSTART 1051
#define IDM_KOCHSTOP 1052
#define IDM_KOCHWAVE 1053
#define IDM_PROMPTWAVE 1054
#define IDM_SENDTRAINING 1055
#define IDC_KOCHWORDLEN 1061
#define IDC_WORDDELAY 1062
#define IDD_PROMPTBOX 1065
#define IDC_INPUTSTR 1066
#define IDD_SEND 1067
#define IDC_PROMPTTEXT 1068
#define IDD_RECV 1072
#define IDD_IO 1073
#define IDD_KOCH 1074
#define IDD_NETWORK 1075
#define IDD_SETTINGS2 1076
#define IDC_EXTPORTENABLE 1100
#define IDC_EXTPORTADDR 1101
#define IDC_OPENBYTE 1102
#define IDC_CLOSEBYTE 1103
#define IDA_TEST 32775
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 138
#define _APS_NEXT_COMMAND_VALUE 32777
#define _APS_NEXT_CONTROL_VALUE 1039
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
================================================
FILE: src/SinSound.cpp
================================================
#include "StdAfx.h"
#include "dsound.h"
#include "math.h"
#include "sinsound.h"
static float DW = 0;
CSinSound::CSinSound()
:m_pDs(NULL),
m_pDsb(NULL),
m_pBgDsb(NULL),
m_bFormatValid(FALSE),
m_bDsbValid(FALSE),
m_bDataValid(FALSE),
m_nLastEnd(0),
m_nTimeAxis(0),
m_bNoiseOn(FALSE)
{
memset(&m_oPlayedBufferDesc, 0, sizeof(m_oPlayedBufferDesc));
memset(&m_oBgBufferDesc, 0, sizeof(m_oBgBufferDesc));
memset(&m_oFormat, 0, sizeof(m_oFormat));
m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
m_oFormat.nChannels = 1;
m_oFormat.nSamplesPerSec = 44100;
m_oFormat.wBitsPerSample = 16;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_oFormat.nBlockAlign = 2;
m_oFormat.cbSize = 0;
DW = 2 * PI / m_oFormat.nSamplesPerSec;
SetFrequency(1000);
SetScale(1.0l);
}
CSinSound::~CSinSound(void)
{
if (NULL != m_pDsb)
{
m_pDsb->Release();
m_pDsb = NULL;
}
if (NULL != m_pBgDsb)
{
m_pBgDsb->Release();
m_pBgDsb = NULL;
}
if (NULL != m_pDs)
{
m_pDs->Release();
m_pDs = NULL;
}
}
BOOL CSinSound::Initialize(HWND hWnd)
{
HRESULT hr =
DirectSoundCreate(NULL, &m_pDs, NULL);
if (FAILED(hr))
return FALSE;
hr = m_pDs->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
if (FAILED(hr))
return FALSE;
return InitBufferFormat();
}
BOOL CSinSound::OnTimer(void* owner, int nTimerId)
{
FillBackground();
return TRUE;
}
void CSinSound::FillBackground()
{
if (m_bFormatValid)
{
DWORD dwOffset;
if (SUCCEEDED(m_pBgDsb->GetCurrentPosition(&dwOffset, NULL)))
{
DWORD nSafeLength = m_oFormat.nAvgBytesPerSec * 1;
DWORD nSoundBytes =
dwOffset <= m_nLastEnd
? nSafeLength - (m_nLastEnd - dwOffset + 2)
: nSafeLength - (m_oBgBufferDesc.dwBufferBytes - dwOffset + m_nLastEnd - 2);
if (nSoundBytes > nSafeLength)
nSoundBytes = nSafeLength;
LPVOID lpvPtr1, lpvPtr2;
DWORD dwBytes1, dwBytes2;
HRESULT hr = m_pBgDsb->Lock(m_nLastEnd, nSoundBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
m_pBgDsb->Restore();
hr = m_pBgDsb->Lock(m_nLastEnd, nSoundBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);
}
if (FAILED(hr))
return;
if (m_bNoiseOn)
{
FillNoises(lpvPtr1, dwBytes1);
if (lpvPtr2)
FillNoises(lpvPtr2, dwBytes2);
}
else
{
FillBlank(lpvPtr1, dwBytes1);
if (lpvPtr2)
FillBlank(lpvPtr2, dwBytes2);
}
m_pBgDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
m_nLastEnd += nSoundBytes;
if (m_nLastEnd >= m_oBgBufferDesc.dwBufferBytes)
m_nLastEnd -= m_oBgBufferDesc.dwBufferBytes;
}
}
}
inline void CSinSound::FillBlank(LPVOID lpvPtr, DWORD nBytes)
{
DWORD dw = nBytes / 2;
for (DWORD i = 0; i < dw; ++i)
{
*(((short int *)lpvPtr) + i) = 0;
}
}
#define NOISE_FREQ_STEP 0.001f
inline void CSinSound::FillNoises(LPVOID lpvPtr, DWORD nBytes)
{
DWORD dw = nBytes / 2;
static REAL f = 0;
static REAL df = NOISE_FREQ_STEP;
static REAL w = 0;
static int NC = 0;
static BOOL bNC = TRUE;
REAL wnl = m_rNoiseScale / 2;
REAL nl = m_rNoiseScale * 32767;
REAL v = 0;
REAL t;
int rnd;
static REAL ft = m_rFrequencyHz / 2;
for (DWORD i = 0; i < dw; ++i)
{
++m_nTimeAxis;
rnd = rand();
if ((f += df) >= ft && df > 0)
{
f = ft;
ft = (REAL)(abs(rnd) % (int)m_rFrequencyHz * 2);
if (ft < f)
df = -NOISE_FREQ_STEP;
}
else if (f <= ft && df < 0)
{
f = ft;
ft = (REAL)(abs(rnd) % (int)m_rFrequencyHz * 2);
if (ft > f)
df = NOISE_FREQ_STEP;
}
v = (0xffff & rnd) * wnl;
w += (DW * f);
if (w > PI2S)
w -= PI2S;
t = ((m_rFrequencyHz * 1.5f - abs(f - m_rFrequencyHz / 2.0f)) / (m_rFrequencyHz * 1.5f));
v += sin(w) * nl * t * t * t;
if (bNC)
{
if (0 >= --NC)
{
bNC = !bNC;
NC = rnd * 25;
}
t = sin(DW * 50 * m_nTimeAxis) * 10000;
v += (abs(t) > nl / 2 ? nl / 2 : t);
}
else
{
if (0 >= --NC)
{
bNC = !bNC;
NC = rnd * 20;
}
}
*(((short int *)lpvPtr) + i) = (short int)v; //(32767 < v ? 32767 : (-32767 > v ? -32767 : v));
}
}
BOOL CSinSound::InitBufferFormat()
{
m_oBgBufferDesc.dwSize = sizeof(DSBUFFERDESC);
m_oBgBufferDesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME
| DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS;
//DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS;
m_oBgBufferDesc.dwBufferBytes = 2 * m_oFormat.nAvgBytesPerSec;
m_oBgBufferDesc.lpwfxFormat = &m_oFormat;
HRESULT hr = m_pDs->CreateSoundBuffer(&m_oBgBufferDesc, &m_pBgDsb, NULL);
if (m_bFormatValid = SUCCEEDED(hr))
{
PlayBackground();
return InitPlayedBuffer();
}
return FALSE;
}
BOOL CSinSound::InitPlayedBuffer()
{
HRESULT hr;
m_oPlayedBufferDesc.dwSize = sizeof(DSBUFFERDESC);
m_oPlayedBufferDesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME;
m_oPlayedBufferDesc.dwBufferBytes = (DWORD)(m_rBufferLengthMs * m_oFormat.nAvgBytesPerSec / 1000);
m_oPlayedBufferDesc.lpwfxFormat = &m_oFormat;
hr = m_pDs->CreateSoundBuffer(&m_oPlayedBufferDesc, &m_pDsb, NULL);
if (m_bDsbValid = SUCCEEDED(hr))
return WriteBuffer();
return FALSE;
}
BOOL CSinSound::WriteBuffer()
{
LPVOID lpvPtr1;
DWORD dwBytes1;
HRESULT hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
m_pDsb->Restore();
hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, DSBLOCK_ENTIREBUFFER);
}
if (FAILED(hr))
return (m_bDataValid = FALSE);
DWORD nBytesPerSample = m_oFormat.wBitsPerSample / 8;
for (DWORD i = 0; i < dwBytes1 / nBytesPerSample; ++i)
{
REAL v = sin(DW * i * m_rFrequencyHz) * m_rScale; // -1.0 ~ +1.0
for (DWORD j = 0; j < m_oFormat.nChannels; ++j)
{
if (16 == m_oFormat.wBitsPerSample)
{
*(((short int *)lpvPtr1) + i * m_oFormat.nChannels + j) = (short int)(v * 32767);
}
else if (8 == m_oFormat.wBitsPerSample)
{
*(((char *)lpvPtr1) + i * m_oFormat.nChannels + j) = (char)(v * 255);
}
else
{
return (m_bDataValid = FALSE);
}
}
}
return (m_bDataValid = SUCCEEDED(m_pDsb->Unlock(lpvPtr1, dwBytes1, NULL, NULL)));
}
void CSinSound::Play()
{
m_pDsb->SetCurrentPosition(0);
HRESULT hr = m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
if (DSERR_BUFFERLOST == hr)
{
m_pDsb->Restore();
WriteBuffer();
m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
}
}
void CSinSound::Stop()
{
m_pDsb->Stop();
}
void CSinSound::PlayBackground()
{
HRESULT hr = m_pBgDsb->Play(0, 0, DSBPLAY_LOOPING);
if (DSERR_BUFFERLOST == hr)
{
m_pBgDsb->Restore();
m_pBgDsb->Play(0, 0, DSBPLAY_LOOPING);
}
}
void CSinSound::StopBackground()
{
m_pBgDsb->Stop();
}
void CSinSound::SetSampleRate(DWORD nSamplesPerSec)
{
if (m_oFormat.nSamplesPerSec != nSamplesPerSec)
{
m_oFormat.nSamplesPerSec = nSamplesPerSec;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
DW = 2 * PI / nSamplesPerSec;
m_bFormatValid = FALSE;
}
}
void CSinSound::SetBitsPerSample(WORD nBits)
{
if (m_oFormat.wBitsPerSample != nBits)
{
m_oFormat.wBitsPerSample = nBits;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_bFormatValid = FALSE;
}
}
void CSinSound::SetBufferLength(REAL rMSec)
{
if (m_rBufferLengthMs != rMSec)
{
m_rBufferLengthMs = rMSec;
m_bDsbValid = FALSE;
}
}
void CSinSound::SetFrequency(REAL rFrequency)
{
if (m_rFrequencyHz != rFrequency)
{
REAL w = 1.0f / (REAL)rFrequency;
REAL d = 1.0f / (REAL)m_oFormat.nSamplesPerSec;
int nTimes;
for (nTimes = 100; nTimes <= 1000; ++nTimes)
{
REAL rRemScale = fmod(w * nTimes, d) / w;
if (rRemScale < 0.001l || rRemScale > 0.998l)
break;
}
m_rFrequencyHz = rFrequency;
m_rBufferLengthMs = nTimes * w * 1000.0f;
m_bDsbValid = FALSE;
}
}
void CSinSound::SetScale(REAL rScale)
{
if (m_rScale != rScale)
{
m_rScale = rScale;
m_rNoiseScale = rScale * 0.25f;
m_bDataValid = FALSE;
}
}
BOOL CSinSound::Validate()
{
if (!m_bFormatValid)
{
m_pDsb->Release(); m_pDsb = NULL;
m_pBgDsb->Release(); m_pBgDsb = NULL;
return InitBufferFormat();
}
else if (!m_bDsbValid)
{
m_pDsb->Release(); m_pDsb = NULL;
return InitPlayedBuffer();
}
else if (!m_bDataValid)
{
return WriteBuffer();
}
return true;
}
void CSinSound::SetVolume(LONG nAtte)
{
HRESULT h = m_pDsb->SetVolume(nAtte);
//h = m_pBgDsb->SetVolume(nAtte);
}
LONG CSinSound::GetVolume()
{
LONG r = -1;
m_pDsb->GetVolume(&r);
return r;
}
void CSinSound::SetNoiseVolume(LONG nAtte)
{
m_pBgDsb->SetVolume(nAtte);
}
LONG CSinSound::GetNoiseVolume()
{
LONG r = -1;
m_pBgDsb->GetVolume(&r);
return r;
}
void CSinSound::SetNoise(BOOL bOn)
{
m_bNoiseOn = bOn;
}
================================================
FILE: src/SinSound.h
================================================
#pragma once
#include "EventManagerWin32.h"
#define PI 3.1415926f
#define PI2S 2 * PI
typedef float REAL;
class CSinSound : public ITimerEventControl
{
public:
CSinSound();
~CSinSound();
BOOL Initialize(HWND hWnd);
void SetSampleRate(DWORD nSamplesPerSec);
DWORD GetSampleRate() { return m_oFormat.nSamplesPerSec; };
void SetBitsPerSample(WORD nBits);
WORD GetBitsPerSample() { return m_oFormat.wBitsPerSample; };
void SetBufferLength(REAL rMSec);
REAL GetBufferLength() { return m_rBufferLengthMs; };
void SetFrequency(REAL rFrequency);
REAL GetFrequency() { return m_rFrequencyHz; };
void SetScale(REAL rScale);
REAL GetScale() { return m_rScale; };
void SetVolume(LONG rVol);
LONG GetVolume();
void SetNoiseVolume(LONG rVol);
LONG GetNoiseVolume();
BOOL Validate();
void Play();
void Stop();
void PlayBackground();
void StopBackground();
void SetNoise(BOOL bOn);
BOOL GetNoise() { return m_bNoiseOn; };
virtual BOOL OnTimer(void* owner, int nTimerId);
private:
BOOL InitBufferFormat();
BOOL InitPlayedBuffer();
BOOL WriteBuffer();
BOOL InitNoiseBuffer();
void FillBackground();
void FillNoises(LPVOID lpvPtr, DWORD nBytes);
void FillBlank(LPVOID lpvPtr, DWORD nBytes);
LPDIRECTSOUND m_pDs;
LPDIRECTSOUNDBUFFER m_pBgDsb;
LPDIRECTSOUNDBUFFER m_pDsb;
WAVEFORMATEX m_oFormat;
DSBUFFERDESC m_oPlayedBufferDesc;
DSBUFFERDESC m_oBgBufferDesc;
DWORD m_nLastEnd;
DWORD m_nTimeAxis;
REAL m_rBufferLengthMs;
REAL m_rFrequencyHz;
REAL m_rScale;
REAL m_rNoiseScale;
BOOL m_bFormatValid;
BOOL m_bDsbValid;
BOOL m_bDataValid;
BOOL m_bNoiseOn;
};
================================================
FILE: src/UpgradeLog.XML
================================================
================================================
FILE: src/UpgradeLog2.XML
================================================
================================================
FILE: src/UpgradeLog3.XML
================================================
================================================
FILE: src/html1.htm
================================================
================================================
FILE: src/lakey.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=53,64,989,514
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,400,92,000D,CW
sendpause=603,265,91,16,0074,Pause,Continue
sendfile=500,265,91,16,0075,File...
autokeyswitch=706,265,91,16,0009,Manual,Auto(L/R),Auto(R/L)
noiseswitch=809,265,91,16,0076,Disturb
sendvol=500,168,90,90,-80.000000,0.000000,0.000000,Volumn(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,Disturb(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,Speed(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,0.000000,Spectrogram(dB)
[KOCH]
charlist=
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0
================================================
FILE: src/lakey_EN.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=212,207,1132,643
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=256
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,Pause,Continue
sendfile=500,265,91,16,0075,File...
autokeyswitch=706,265,91,16,0009,Manual,Auto(L/R),Auto(R/L)
noiseswitch=809,265,91,16,0076,Disturb
sendvol=500,168,90,90,-80.000000,0.000000,0.000000,Send Vol(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,Disturb Vol(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,Speed(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,10.312500,Spec Gain(dB)
[KOCH]
charlist=KMRSUAPTLOWI.NJEF0Y,VG5/Q9ZH38B?427C1D6X
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
)=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0
================================================
FILE: src/lakey_ZH.ini
================================================
[CW]
beepfreq=1000.000000
beepvol=0.250000
shorthit=80
longhit=240
hitdelay=80
letterdelay=240
worddelay=240
[GLOBAL]
windowrect=224,104,1144,540
[JOURNAL]
sendperiod=27
sendidlelimit=750
sendrect=5,235,490,267
sendlabeloffset=0,-15
sendlabel=Send
sendqueuerect=5,270,490,281
specrect=498,10,908,160
speclabeloffset=0,-15
speclabel=Spectrogram
recvperiod=27
recvidlelimit=750
recvrect=5,180,490,212
recvlabeloffset=0,-15
recvlabel=Recieve
recvmrect=8,10,493,160
recvanalyzesamples=512
recvthreshold=0.300000
recvfreqstart=850
recvfreqend=1250
[MAINPANEL]
cw=500,290,297,92,000D,CW
sendpause=603,265,91,16,0074,ͣ,
sendfile=500,265,91,16,0075,ļ...
autokeyswitch=706,265,91,16,0009,ֶ,Զ(/),Զ(/)
noiseswitch=809,265,91,16,0076,
sendvol=500,168,90,90,-80.000000,0.000000,-15.312500,(dB)
noisevol=809,168,90,90,-80.000000,0.000000,0.000000,(dB)
sendspeed=603,168,90,90,5.000000,30.000000,20.000000,ٶ(wpm)
specbrightness=706,168,90,90,-60.000000,60.000000,55.781250,Ƶ(dB)
[KOCH]
charlist=KMRSUAPTLOWI.NJEF0Y,VG5/Q9ZH38B?427C1D6X
koch_wordlen=5
[MORSE]
A=00000002,00000003,0041
B=00000007,0000000F,0042
C=00000005,0000000F,0043
D=00000003,00000007,0044
E=00000001,00000001,0045
F=0000000D,0000000F,0046
G=00000001,00000007,0047
H=0000000F,0000000F,0048
I=00000003,00000003,0049
J=00000008,0000000F,004A
K=00000002,00000007,004B
L=0000000B,0000000F,004C
M=00000000,00000003,004D
N=00000001,00000003,004E
O=00000000,00000007,004F
P=00000009,0000000F,0050
Q=00000002,0000000F,0051
R=00000005,00000007,0052
S=00000007,00000007,0053
T=00000000,00000001,0054
U=00000006,00000007,0055
V=0000000E,0000000F,0056
W=00000004,00000007,0057
X=00000006,0000000F,0058
Y=00000004,0000000F,0059
Z=00000003,0000000F,005A
1=00000010,0000001F,0031
2=00000018,0000001F,0032
3=0000001C,0000001F,0033
4=0000001E,0000001F,0034
5=0000001F,0000001F,0035
6=0000000F,0000001F,0036
7=00000007,0000001F,0037
8=00000003,0000001F,0038
9=00000001,0000001F,0039
0=00000000,0000001F,0030
?=00000033,0000003F,0000
/=0000000D,0000001F,006F
(=00000012,0000003F,0000
)=00000012,0000003F,0000
-=0000000E,0000003F,006D
.=0000002A,0000003F,006E
_=00000000,00000000,0020
[HWCTRL]
enableextport=00000000
extportaddr=00000378
openbyte=000000FF
closebyte=00000000
[NETWORK]
nwenabled=1
localport=3010
hosts=0
================================================
FILE: src/mc.txt
================================================
A=10,VK_A
B=0111
C=0101
D=011
E=1
F=1101
G=001
H=1111
I=11
J=1000
K=010
L=1011
M=00
N=01
O=000
P=1001
Q=0010
R=101
S=111
T=0
U=110
V=1110
W=100
X=0110
Y=0100
Z=0011
?=110011
/=01101
(=010010
)=010010
-=01110
.=101010
1=10000
2=11000
3=11100
4=1111
5=11111
6=01111
7=00111
8=00011
9=00001
0=00000
================================================
FILE: src/mytest.cpp
================================================
#include "stdafx.h"
#include
#include
#include
#include "mytest.h"
BOOL GetDriveGeometry(DISK_GEOMETRY *pdg)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
hDevice = CreateFile("\\\\.\\PhysicalDrive0", // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
return (FALSE);
}
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
CloseHandle(hDevice);
return (bResult);
}
int mytest()
{
DISK_GEOMETRY pdg; // disk drive geometry structure
BOOL bResult; // generic results flag
ULONGLONG DiskSize; // size of the drive, in bytes
bResult = GetDriveGeometry (&pdg);
if (bResult)
{
printf("Cylinders = %I64d\n", pdg.Cylinders);
printf("Tracks/cylinder = %ld\n", (ULONG) pdg.TracksPerCylinder);
printf("Sectors/track = %ld\n", (ULONG) pdg.SectorsPerTrack);
printf("Bytes/sector = %ld\n", (ULONG) pdg.BytesPerSector);
DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
(ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
printf("Disk size = %I64d (Bytes) = %I64d (Gb)\n", DiskSize,
DiskSize / (1024 * 1024 * 1024));
}
else
{
printf ("GetDriveGeometry failed. Error %ld.\n", GetLastError ());
}
return ((int)bResult);
}
================================================
FILE: src/mytest.h
================================================
int mytest();
================================================
FILE: src/resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Lakey.rc
//
#define IDC_MYICON 2
#define IDD_LAKEY_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDD_SETTINGS 104
#define IDM_EXIT 105
#define IDI_LAKEY 107
#define IDI_SMALL 108
#define IDC_LAKEY 109
#define IDR_MAINFRAME 128
#define ID_129 129
#define IDB_BITMAP1 131
#define IDB_LOGO 131
#define ID_KOCH 132
#define ID__ 133
#define ID_KOCH_134 134
#define IDD_COPYPAD 135
#define IDD_TEST 136
#define IDD_GENERAL 137
#define IDM_TEST 199
#define IDC_EDIT1 1000
#define IDC_TONE 1001
#define IDC_BEEPFREQ 1002
#define IDC_COPYTEXT 1003
#define IDC_SETTINGSTAB 1004
#define IDC_BEEPVOL 1005
#define IDM_SETTINGS 1006
#define IDC_SENDPERIOD 1007
#define IDC_BUTTON1 1008
#define IDC_HOSTADD 1008
#define IDC_SENDILDELIMIT 1009
#define IDC_RECVPERIOD 1010
#define IDC_RECVILDELIMIT 1011
#define IDC_RECVANALYZESAMPLES 1012
#define IDC_RECVTHRESHOLD 1013
#define IDC_RECVFREQSTART 1014
#define IDC_RECVFREQEND 1015
#define IDC_HOTKEY1 1016
#define IDC_CALCSPEED 1017
#define IDC_SHORTHIT 1018
#define IDC_LONGHIT 1019
#define IDC_HITDELAY 1020
#define IDC_LETTERDELAY 1021
#define IDC_CW 1022
#define ID_ACCEPT 1023
#define IDC_ACCEPT 1024
#define IDC_SPEED 1025
#define IDC_KOCHCHARS 1026
#define IDC_ELAPSETIME 1027
#define IDC_COPIED 1028
#define IDC_INCORRECT 1029
#define IDC_CORRECTPERC 1030
#define IDC_RICHEDIT21 1031
#define IDC_LOCALPORT 1032
#define IDC_NWNODES 1033
#define IDC_HOSTPORT 1033
#define IDC_TAB1 1034
#define IDC_HOSTLIST 1034
#define IDC_HOSTADDR 1035
#define IDC_HOSTNAME 1035
#define IDC_HOSTDEL 1036
#define IDC_CHECK1 1038
#define IDC_NWENABLED 1038
#define IDM_KOCHSTART 1051
#define IDM_KOCHSTOP 1052
#define IDM_KOCHWAVE 1053
#define IDM_PROMPTWAVE 1054
#define IDM_SENDTRAINING 1055
#define IDC_KOCHWORDLEN 1061
#define IDC_WORDDELAY 1062
#define IDD_PROMPTBOX 1065
#define IDC_INPUTSTR 1066
#define IDD_SEND 1067
#define IDC_PROMPTTEXT 1068
#define IDD_RECV 1072
#define IDD_IO 1073
#define IDD_KOCH 1074
#define IDD_NETWORK 1075
#define IDD_SETTINGS2 1076
#define IDC_EXTPORTENABLE 1100
#define IDC_EXTPORTADDR 1101
#define IDC_OPENBYTE 1102
#define IDC_CLOSEBYTE 1103
#define IDA_TEST 32775
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 138
#define _APS_NEXT_COMMAND_VALUE 32777
#define _APS_NEXT_CONTROL_VALUE 1039
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
================================================
FILE: src/stdafx.cpp
================================================
// stdafx.cpp : ֻļԴļ
// Lakey.pch ΪԤͷ
// stdafx.obj ԤϢ
#include "stdafx.h"
// TODO: STDAFX.H
//κĸͷڴļ
================================================
FILE: src/stdafx.h
================================================
// stdafx.h : ϵͳļİļ
// dzõĵĿضİļ
//
#pragma once
//#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ
// Windows ͷļ
#include
#include
// C ʱͷļ
#include
#include
#include
#include
//#include
#include
#pragma comment(lib, "ComCtl32.Lib")
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
// TODO: ڴ˴óҪĸͷ