📄 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 "LaJournalPanel.h"
#include "LaLabel.h"
#include "LaLine.h"
#include "LaWaveCapture.h"
#include <assert.h>
#define SAFE_DELETE(x) if (x) { delete x; x = NULL; }
#define SAFE_DELETE_DC(h) if (h) { DeleteDC(h); h = NULL; }
#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_pBtCw = CreateButton(&m_pSetting->m_oCwKeyButton);
m_pBtSendPause = CreateButton(&m_pSetting->m_oSendPauseButton);
m_pBtSendFile = CreateButton(&m_pSetting->m_oSendFileButton);
m_pJpSend = CreateJournalPanel(&m_pSetting->m_oSendJournalRect, m_pSetting->m_nLongHit / m_pSetting->m_nSendJournalPeriod - 5);
m_pJpRecv = CreateJournalPanel(&m_pSetting->m_oRecvJournalRect, m_pSetting->m_nLongHit / m_pSetting->m_nRecvJournalPeriod - 5);
m_pRecvDctMonitor = CreateWaveCapture(&m_pSetting->m_oRecvMonitorRect);
m_pSendCharQueueLabel = CreateLabel(&m_pSetting->m_oSendCharQueueRect, NULL, DT_END_ELLIPSIS|DT_LEFT, "HHH");
RECT r = m_pSetting->m_oSendJournalRect;
OffsetRect(&r, 0, -56);
m_pSendLabel = CreateLabel(&r, "Send", DT_END_ELLIPSIS|DT_LEFT);
r = m_pSetting->m_oRecvJournalRect;
OffsetRect(&r, 0, -56);
m_pRecvLabel = CreateLabel(&r, "Receive", DT_END_ELLIPSIS|DT_LEFT);
m_pSendJpBorder = CreateLine(m_pSetting->m_oSendCharQueueRect.left, m_pSetting->m_oSendCharQueueRect.bottom + 1,
m_pSetting->m_oSendCharQueueRect.right, m_pSetting->m_oSendCharQueueRect.bottom + 1);
m_pRecvJpBorder = CreateLine(m_pSetting->m_oRecvJournalRect.left, m_pSetting->m_oRecvJournalRect.bottom + 1,
m_pSetting->m_oRecvJournalRect.right, m_pSetting->m_oRecvJournalRect.bottom + 1);
m_hMorseQueueThread = NULL;
m_nMorseQueueThreadID = 0;
m_hMorseJournalThread = NULL;
m_nMorseJournalThreadID = 0;
m_hRecvMonitorThread = NULL;
m_nRecvMonitorThreadID = 0;
BuildMorseButtons();
m_pSound = new CSinSound();
m_pSound->SetFrequency(m_pSetting->m_rBeepFreq);
m_pSound->SetScale(m_pSetting->m_rBeepVol);
m_bNeedExit = FALSE;
m_bCwFlag = FALSE;
m_nRecvIdleCount = 0;
m_bPause = FALSE;
m_bClear = FALSE;
AddCommandEventControl(this);
}
CLakeyMainWindow::~CLakeyMainWindow(void)
{
GetWindowRect(GetHWnd(), &m_pSetting->m_oWindowRect);
m_bNeedExit = TRUE;
ResumeThread(m_hMorseQueueThread);
JOIN_SAFELY(m_hMorseQueueThread);
JOIN_SAFELY(m_hMorseJournalThread);
JOIN_SAFELY(m_hRecvMonitorThread);
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_pSendLabel;
delete m_pRecvLabel;
delete m_pSound;
delete m_pFont;
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 nMaxY = r.bottom - r.top - 58;
int h = 12;
int w = 58;
char txt[] = { ' ', ' ', ' ', ' ', ' ', '#', '#', '#', '#', '#', '#', '\0' };
for (int i = 0; i < MORSECODECOUNT; ++i)
{
MORSECODE* p = &(m_pSetting->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);
}
}
}
MORSECODE* CLakeyMainWindow::GetMorseCode(char ch)
{
for (int i = 0; i < MORSECODECOUNT; ++i)
{
MORSECODE* p = &(m_pSetting->m_vMorseCode[i]);
if (ch == p->nAscCode || ch + ('A' - 'a') == p->nAscCode)
return p;
}
// '_' is default
return &(m_pSetting->m_vMorseCode[MORSECODECOUNT - 1]);
}
CLaButton* CLakeyMainWindow::CreateButton(const char* pText, int x, int y, int w, int h, int nWantKeyCode)
{
RECT r;
r.left = x; r.top = y; r.right = x + w; r.bottom = y + h;
CLaButton* pButton = new CLaButton(this, pText, &r, CLaButton::BT_NORMAL, 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)
{
return CreateButton(pMapping->vLabel, pMapping->x, pMapping->y, pMapping->w, pMapping->h, pMapping->nKeyCode);
}
CLaJournalPanel* CLakeyMainWindow::CreateJournalPanel(const RECT* pRect, int nMaxShortCount)
{
CLaJournalPanel* jp = new CLaJournalPanel(this, pRect, m_pSetting->m_vMorseCode, nMaxShortCount, m_pFont);
AddPaintEventControl(jp);
return jp;
}
CLaWaveCapture* CLakeyMainWindow::CreateWaveCapture(const RECT* pRect)
{
CLaWaveCapture* wc = new CLaWaveCapture(this, pRect, 44100, m_pSetting->m_nRecvAnalyzeSamples, this);
wc->SetFreqRange(m_pSetting->m_nRecvFreqStart, m_pSetting->m_nRecvFreqEnd);
wc->SetThresholdLevel(m_pSetting->m_rRecvThreshold);
AddPaintEventControl(wc);
return wc;
}
CLaLabel* CLakeyMainWindow::CreateLabel(const RECT* pRect, const char* pText, int nStyle, const char* pMutexName/* = NULL */)
{
CLaLabel* label = new CLaLabel(this, pRect, pText, nStyle, m_pFont, 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;
// */
return m_pSound->Initialize(GetHWnd());
}
void CLakeyMainWindow::GetRect(RECT* r)
{
GetClientRect(GetHWnd(), r);
}
void CLakeyMainWindow::OnPaint(void* owner, CGraphics* g, const RECT* pRect)
{
}
void CLakeyMainWindow::OnMouseMove(void* owner, int x, int y)
{
}
void CLakeyMainWindow::OnKeyDown(void* owner, int nKeyCode)
{
if (m_pBtCw == owner)
CwDown();
else if (' ' == nKeyCode)
{
m_pRecvDctMonitor->Refresh();
}
}
void CLakeyMainWindow::OnKeyUp(void* owner, int nKeyCode)
{
if (m_pBtCw == owner)
CwUp();
else if (m_pBtSendFile == owner)
{
ChooseSendFile();
}
}
void CLakeyMainWindow::OnMouseKeyDown(void* owner, MouseKeyType nMkt, int x, int y)
{
if (m_pBtCw == owner)
CwDown();
else if (this == owner)
{
}
}
void CLakeyMainWindow::OnMouseKeyUp(void* owner, MouseKeyType nMkt, int x, int y)
{
if (m_pBtCw == owner)
CwUp();
else if (m_pBtSendFile == owner)
{
ChooseSendFile();
}
else if (this == owner)
{
}
else
{
}
}
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(' '));
}
}
ResumeThread(m_hMorseQueueThread);
}
void CLakeyMainWindow::ClearQueue()
{
m_bClear = TRUE;
}
BOOL CLakeyMainWindow::OnClick(void* owner)
{
if (m_pBtCw == owner)
{
}
else if (m_pBtSendPause == owner)
{
if (m_bPause = !m_bPause)
m_pBtSendPause->SetText("Continue");
else
m_pBtSendPause->SetText("Pause");
return TRUE;
}
else if (m_pBtSendFile == owner)
{
}
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();
m_bCwFlag = TRUE;
}
void CLakeyMainWindow::CwUp()
{
m_pSound->Stop();
m_bCwFlag = FALSE;
}
void CLakeyMainWindow::OnCwEvent(BOOL bCwDown)
{
if (bCwDown)
m_nRecvIdleCount = 0;
if (m_nRecvIdleCount < m_pSetting->m_nRecvIdleLimit)
m_pJpRecv->Sample(bCwDown);
m_nRecvIdleCount += m_pSetting->m_nRecvJournalPeriod;
}
void CLakeyMainWindow::OnCommand(void* owner, int nCommId)
{
}
// 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());
while(!owner->m_bNeedExit && !owner->m_oSendMorseQueue.empty())
{
if (!owner->m_bPause)
{
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->m_nShortHit : owner->m_pSetting->m_nLongHit;
owner->CwDown();
NOTEVALIFNEEDEXIT(Sleep(nHitCount));
owner->CwUp();
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->m_nHitDelay));
}
}
else
{
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->m_nWordDelay));
}
}
owner->m_pSendCharQueueLabel->PopChar();
}
if (!owner->m_bClear)
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->m_nLetterDelay));
}
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->m_nSendIdleLimit)
owner->m_pJpSend->Sample(owner->m_bCwFlag);
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->m_nSendJournalPeriod));
nIdleCount += owner->m_pSetting->m_nSendJournalPeriod;
}
return 0;
}
DWORD WINAPI CLakeyMainWindow::RecvMonitorThreadProc(LPVOID pOwner)
{
CLakeyMainWindow* owner = (CLakeyMainWindow *)pOwner;
while(!owner->m_bNeedExit)
{
owner->m_pRecvDctMonitor->Refresh();
NOTEVALIFNEEDEXIT(Sleep(owner->m_pSetting->m_nRecvJournalPeriod));
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -