G:\stock\TskingVS2019\src\Client\StkUI\StkUI.rc
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//热键、快捷键定义 by freeman
IDR_MAINFRAME ACCELERATORS
BEGIN
"A", ID_EDIT_SELECT_ALL, VIRTKEY, CONTROL, NOINVERT
"B", ID_VIEW_RESUMEDRUP, VIRTKEY, CONTROL, NOINVERT
"C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
"F", ID_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT
"P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
"V", ID_VIEW_RESUMEDRDOWN, VIRTKEY, CONTROL, NOINVERT
VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
VK_F1, ID_REALTIME_REPORTDETAIL, VIRTKEY, NOINVERT
VK_F10, ID_VIEW_F10, VIRTKEY, NOINVERT
VK_F11, ID_VIEW_SIMU, VIRTKEY, NOINVERT
VK_F12, ID_TOOL_TRADER, VIRTKEY, NOINVERT
VK_F2, ID_VIEW_SLIST, VIRTKEY, NOINVERT
VK_F3, ID_REALTIME_VIEWSZZS, VIRTKEY, NOINVERT
VK_F4, ID_REALTIME_VIEWSZNCZ, VIRTKEY, NOINVERT
VK_F5, ID_VIEW_GRAPH, VIRTKEY, NOINVERT
VK_F6, ID_SLIST_GROUPSELF, VIRTKEY, NOINVERT
VK_F7, ID_VIEW_MULTISORT, VIRTKEY, NOINVERT
VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
"X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
"Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
END
第一部分 主程序对按键的处理
主程序对按键的消息处理由PreTranslateMessage(MSG* pMsg)来实现。如果检测到按下的键是0-9,a-z,则判断是否要弹出键盘精灵窗口。具体根据哪些视图需要弹出键盘精灵窗口.
1.1 定义键盘精灵窗口变量m_SearchBox
G:\stock\TskingVS2019\src\Client\StkUI\MainFrm.h
class CMainFrame : public CTskMainFrame
{
....
public:
CSearchBox m_SearchBox;
//CDateComboBox m_DateBox;
....
}
1.2 初始化键盘精灵窗口变量m_SearchBox
G:\stock\TskingVS2019\src\Client\StkUI\MainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
....
// Name Search ComboBox
if (!m_SearchBox.Create(WS_CHILD | CBS_DROPDOWN | CBS_SORT | CBS_AUTOHSCROLL | WS_VSCROLL | CBS_HASSTRINGS,
CRect(-FRM_SEARCH_WIDTH, -FRM_SEARCH_HEIGHT, 0, 200), this, ID_SLISTBAR_NAME))
{
TRACE0("Failed to create m_SearchBox\n");
return FALSE;
}
m_SearchBox.SetItemHeight(-1, 16);
m_SearchBox.SetAutoHide(TRUE);
.....
}
1.3 主程序对按键进行检测,判断是否键盘精灵
G:\stock\TskingVS2019\src\Client\StkUI\MainFrm.cpp
//主程序对按键的消息处理 by freeman
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
/* ProfUIS Using Code
if (m_wndMenuBar.TranslateMainFrameMessage(pMsg))
return TRUE;
*/
if (WM_KEYDOWN == pMsg->message)
{
int nVirtKey = (int)pMsg->wParam;
if (VK_ESCAPE == nVirtKey && m_fullScreen.bFullScreen)
OnViewFullscreen();
if (m_SearchBox.IsWantChar(pMsg->wParam))//键盘精灵有效字符检测:0-9 a-z
{
CView* pView = AfxGetStaticDoc()->GetActiveView();
if (!pView ||
(pView->IsKindOf(RUNTIME_CLASS(CWizardView))
|| pView->IsKindOf(RUNTIME_CLASS(CGraphView))
|| pView->IsKindOf(RUNTIME_CLASS(CRealTimeView))
|| pView->IsKindOf(RUNTIME_CLASS(CMultiSortView))
|| pView->IsKindOf(RUNTIME_CLASS(CSListView))
|| pView->IsKindOf(RUNTIME_CLASS(CBaseView))
|| pView->IsKindOf(RUNTIME_CLASS(CSelectorView))))
{
CRect rect;
GetClientRect(&rect);
m_SearchBox.SetWindowPos(NULL, rect.right - FRM_SEARCH_WIDTH - 18, rect.bottom - FRM_SEARCH_HEIGHT - 22,
0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
m_SearchBox.OnChangeStatus(pMsg->wParam, pMsg->lParam, FALSE);
}
}
else if (/*::IsWindow(m_wndWorkspBar.GetSafeHwnd())
&& */!m_SearchBox.GetDroppedState()/* && !m_wndWorkspBar.IsWindowVisible()*/)
{
CView* pView = AfxGetStaticDoc()->GetActiveView();
if (pView &&
(pView->IsKindOf(RUNTIME_CLASS(CGraphView))
|| pView->IsKindOf(RUNTIME_CLASS(CRealTimeView))
|| pView->IsKindOf(RUNTIME_CLASS(CMultiSortView))
|| pView->IsKindOf(RUNTIME_CLASS(CSListView))))
pView->SetFocus();
}
}
return CTskMainFrame::PreTranslateMessage(pMsg);
}
1.4 键盘精灵数据初始化
G:\stock\TskingVS2019\src\Client\StkUI\StkUI.cpp
BOOL CStkUIApp::InitInstance()
{
...
//装载键盘精灵数据
((CMainFrame*)m_pMainWnd)->m_SearchBox.InitStocks( TRUE, TRUE, TRUE );
((CMainFrame*)m_pMainWnd)->m_SearchBox.SetCurrentWindowText();
....
}
G:\stock\TskingVS2019\src\Client\StkUI\StkUI.cpp
BOOL CALLBACK LoadProgram( HWND hWnd, int nMinProgress, int nMaxProgress )
{
...
CMainFrame * pMainFrame = AfxGetMainFrame();
...
pMainFrame->m_SearchBox.InitStocks( TRUE, TRUE, TRUE );//键盘精灵数据初始化
...
pMainFrame->m_SearchBox.SetCurrentWindowText( );////键盘精灵
}
第二部分 键盘精灵的实现
键盘精灵由G:\stock\TskingVS2019\src\Client\StkUI\SListCombos.cpp中的CSearchBox()类实现。
step 1: 键盘精灵窗口创建
//键盘精灵窗口创建
int CSearchBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CComboBox::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
// InitStocks( TRUE, TRUE, TRUE );
return 0;
}
step 2:键盘精灵的数据初始化
1.1首先获取全局变量container = AfxGetStockContainer();,然后从容器中获取股票信息(CStockInfo & info = container.ElementAt(i);),在下拉框中依次填入对应的股票代码和名称、简拼。
CStockContainer & container = AfxGetStockContainer()
for( int i=0; i<container.GetSize(); i++ ) //慢,需优化
{
CStockInfo & info = container.ElementAt(i);
1.2添加了技术指标
1.3 添加了快捷键
BOOL CSearchBox::InitStocks( BOOL bHasSTTTech, BOOL bShowOnSel, BOOL bDuplicate )
{
ResetContent( );
m_bShowOnSel = bShowOnSel;
CStockContainer & container = AfxGetStockContainer();
InitStorage( bDuplicate ? container.GetSize()*2 : container.GetSize(), 32 );
for( int i=0; i<container.GetSize(); i++ )
{
CStockInfo & info = container.ElementAt(i);
if( !info.IsValidStock() )
continue;
CString strTemp = info.GetStockCode();
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += info.GetStockName();
int nItem = AddString( strTemp );
SetItemData( nItem, i );
if( bDuplicate )
{
strTemp = info.GetStockShortName();
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += info.GetStockName();
if( CB_ERR == SelectString( 0, strTemp ) )
{
nItem = AddString( strTemp );
SetItemData( nItem, i );
}
}
}
if( bHasSTTTech )
{
// 技术指标项
UINT nTechUserCount = CTechUser::GetTechUserCount();
for( UINT i=STT_MIN; i <= STT_MAX+nTechUserCount; i ++ )
{
UINT nTech = i;
if( nTech > STT_MAX )
nTech = i-STT_MAX-1+STT_USER_MIN;
CString strTemp = AfxGetSTTShortName( nTech );
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += AfxGetSTTName( nTech );
int nItem = AddString( strTemp );
SetItemData( nItem, nTech | SEARCHBOX_SIGNBIT_STT );
}
// 快捷键项
for( UINT i = ACCE_MIN; i <= ACCE_MAX; i++ )
{
CString strTemp = AfxGetAccelerator( i, 8 );
SetItemData( AddString(strTemp), i | SEARCHBOX_SIGNBIT_ACCE );
}
}
return TRUE;
}
BOOL CSearchBox::InitStocks( CSPStringArray & astocks, BOOL bHasSTTTech, BOOL bShowOnSel, BOOL bDuplicate )
{
ResetContent( );
m_bShowOnSel = bShowOnSel;
CStockContainer & container = AfxGetStockContainer();
InitStorage( bDuplicate ? astocks.GetSize()*2 : astocks.GetSize(), 32 );
for( int i=0; i<astocks.GetSize(); i++ )
{
if( astocks.ElementAt(i).GetLength() <= 0 )
continue;
CStockInfo info;
int nAID = -1;
if( !container.GetStockInfo( astocks.ElementAt(i), &info, &nAID ) )
continue;
CString strTemp = info.GetStockCode();
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += info.GetStockName();
int nItem = AddString( strTemp );
SetItemData( nItem, nAID );
if( bDuplicate )
{
strTemp = info.GetStockShortName();
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += info.GetStockName();
if( CB_ERR == SelectString( 0, strTemp ) )
{
nItem = AddString( strTemp );
SetItemData( nItem, nAID );
}
}
}
if( bHasSTTTech )
{
// 技术指标项
UINT nTechUserCount = CTechUser::GetTechUserCount();
for( UINT i=STT_MIN; i <= STT_MAX+nTechUserCount; i ++ )
{
UINT nTech = i;
if( nTech > STT_MAX )
nTech = i-STT_MAX-1+STT_USER_MIN;
CString strTemp = AfxGetSTTShortName( nTech );
while( strTemp.GetLength() < 8 )
strTemp += ' ';
strTemp += AfxGetSTTName( nTech );
int nItem = AddString( strTemp );
SetItemData( nItem, nTech | SEARCHBOX_SIGNBIT_STT );
}
// 快捷键项
for( UINT i = ACCE_MIN; i <= ACCE_MAX; i++ )
{
CString strTemp = AfxGetAccelerator( i, 8 );
SetItemData( AddString(strTemp), i | SEARCHBOX_SIGNBIT_ACCE );
}
}
return TRUE;
}
step 3:键盘精灵按键处理
/////////////////////////////////////////////////////////////////////////////
// CSearchBox message handlers
//键盘精灵:按键处理 by freeman
BOOL CSearchBox::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message == WM_KEYDOWN )
{
if( IsWantChar( pMsg->wParam ) )
{
OnChangeStatus( pMsg->wParam, pMsg->lParam, TRUE );
return TRUE;
}
if( VK_RETURN == pMsg->wParam )
{
m_bDoNothing = TRUE;
m_hwndLastFocus = NULL;
m_bSegmentEnd = TRUE;
CString strCommand;
GetWindowText( strCommand );
int nSel = SelectString( 0, strCommand );
ShowDropDown( FALSE );
SetCurSel( nSel );
// Show Graph View
if( CB_ERR != nSel && m_bShowOnSel )
{
DWORD dwData = GetItemData( nSel );
CView * pView = AfxGetStaticDoc()->GetActiveView();
if( dwData & SEARCHBOX_SIGNBIT_STT )
AfxShowStockTech( dwData & ~SEARCHBOX_SIGNBIT_STT );
else if( dwData & SEARCHBOX_SIGNBIT_ACCE )
AfxExecuteAccelerator( dwData & ~SEARCHBOX_SIGNBIT_ACCE );
else if( IsCTRLpressed() )
AfxShowStockBase( dwData, FALSE );
else if( pView && pView->IsKindOf( RUNTIME_CLASS(CRealTimeView) ) )
AfxShowStockRealTime( dwData, FALSE );
else
AfxShowStockGraph( dwData, FALSE );
}
else if( CB_ERR == nSel && m_bShowOnSel )
{
AfxShowStockGraph( strCommand );
}
else
SetCurrentWindowText( );
m_bDoNothing = FALSE;
if( m_bAutoHide )
SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_HIDEWINDOW );
return TRUE;
}
else if( VK_ESCAPE == pMsg->wParam )
{
m_bDoNothing = TRUE;
if( m_hwndLastFocus )
::SetFocus( m_hwndLastFocus );
m_hwndLastFocus = NULL;
m_bSegmentEnd = TRUE;
CString strCommand;
GetWindowText( strCommand );
int nSel = SelectString( 0, strCommand );
ShowDropDown( FALSE );
SetCurSel( nSel );
SetCurrentWindowText( );
m_bDoNothing = FALSE;
if( m_bAutoHide )
SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_HIDEWINDOW );
return TRUE;
}
}
return CComboBox::PreTranslateMessage(pMsg);
}
可供选择
热键、快捷键
热键定义
G:\stock\TskingVS2019\src\Client\StkLib\Include\AfxCore.h
#define ACCE_MIN 1
#define ACCE_01 1 // 热键F1
#define ACCE_02 2 // 热键F2
#define ACCE_03 3 // 热键F3
#define ACCE_04 4 // 热键F4
#define ACCE_05 5 // 热键F5
#define ACCE_06 6 // 热键F6
#define ACCE_07 7 // 热键F7
#define ACCE_08 8 // 热键F8
#define ACCE_09 9 // 热键F9
#define ACCE_10 10 // 热键F10
#define ACCE_1 11 // 上A报价
#define ACCE_2 12 // 上B报价
#define ACCE_3 13 // 深A报价
#define ACCE_4 14 // 深B报价
#define ACCE_5 15 // 上债报价
#define ACCE_6 16 // 深债报价
#define ACCE_61 17 // 上A涨跌
#define ACCE_62 18 // 上B涨跌
#define ACCE_63 19 // 深A涨跌
#define ACCE_64 20 // 深B涨跌
#define ACCE_65 21 // 上债涨跌
#define ACCE_66 22 // 深债涨跌
#define ACCE_71 23 // 上证信息
#define ACCE_72 24 // 深证信息
#define ACCE_73 25 // 券商信息
#define ACCE_81 26 // 上A综合
#define ACCE_82 27 // 上B综合
#define ACCE_83 28 // 深A综合
#define ACCE_84 29 // 深B综合
#define ACCE_85 30 // 上债综合
#define ACCE_86 31 // 深债综合
#define ACCE_LBDK 32 // 显示分时行情量比多空指标
#define ACCE_MMLD 33 // 显示分时行情买卖力道指标
//#define ACCE_MAX 33 //最大值,后面创建数组时需要这个变量作为数组长度。old value before custom extend by freeman
//*****add by freeman 扩展周期快捷键
#define ACCE_MAX 41 //更改数组长度值
#define ACCE_91 34 // 1分钟K线图
#define ACCE_92 35 // 5分钟K线图
#define ACCE_93 36 // 15分钟K线图
#define ACCE_94 37 // 30分钟K线图
#define ACCE_95 38 // 60分钟K线图
#define ACCE_96 39 // 日K线图
#define ACCE_97 40 // 周K线图
#define ACCE_98 41 // 月K线图
键盘精灵消息定义
G:\stock\TskingVS2019\src\Client\StkUI\AfxCore.cpp
// 快捷键
//按下键盘精灵的快捷键,则发送对应的消息 by freeman
void AfxExecuteAccelerator(UINT nAcce)
{
HWND hWnd = AfxGetMainFrame()->GetSafeHwnd();
switch (nAcce)
{
case ACCE_01: // 热键F1
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_REPORTDETAIL, 0); //F1
break;
case ACCE_02: // 热键F2
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_SLIST, 0);
break;
case ACCE_03: // 热键F3
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_VIEWSZZS, 0);
break;
case ACCE_04: // 热键F4
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_VIEWSZNCZ, 0);
break;
case ACCE_05: // 热键F5 VK_F5
{
CView* pView = AfxGetStaticDoc()->GetActiveView();
if (pView && pView->IsKindOf(RUNTIME_CLASS(CGraphView)))
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_REALTIME, 0);
else
{
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_GRAPH, 0);
}
}
break;
case ACCE_06: // 热键F6
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_GROUPSELF, 0);
break;
case ACCE_07: // 热键F7
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_MULTISORT, 0);
break;
case ACCE_08: // 热键F8
break;
case ACCE_09: // 热键F9
break;
case ACCE_10: // 热键F10
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_F10, 0);
break;
case ACCE_1: // 上A报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHAA, 0);
break;
case ACCE_2: // 上B报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHAB, 0);
break;
case ACCE_3: // 深A报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNA, 0);
break;
case ACCE_4: // 深B报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNB, 0);
break;
case ACCE_5: // 上债报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHABOND, 0);
break;
case ACCE_6: // 深债报价
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNBOND, 0);
break;
case ACCE_61: // 上A涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHAASORTDP, 0);
break;
case ACCE_62: // 上B涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHABSORTDP, 0);
break;
case ACCE_63: // 深A涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNASORTDP, 0);
break;
case ACCE_64: // 深B涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNBSORTDP, 0);
break;
case ACCE_65: // 上债涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SHABONDSORTDP, 0);
break;
case ACCE_66: // 深债涨跌
::PostMessage(hWnd, WM_COMMAND, ID_SLIST_SZNBONDSORTDP, 0);
break;
case ACCE_71: // 上证信息
break;
case ACCE_72: // 深证信息
break;
case ACCE_73: // 券商信息
break;
case ACCE_81: // 上A综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZAG, 0);
break;
case ACCE_82: // 上B综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZBG, 0);
break;
case ACCE_83: // 深A综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZNAG, 0);
break;
case ACCE_84: // 深B综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZNBG, 0);
break;
case ACCE_85: // 上债综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZZQ, 0);
break;
case ACCE_86: // 深债综合
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MSSZNZQ, 0);
break;
//*****add by freeman 扩展周期快捷键********
case ACCE_91: // 1分钟K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMIN1, 0); //添加1分钟K线消息 by freeman
break;
case ACCE_92: // 5分钟K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMIN5, 0);
break;
case ACCE_93: // 15分钟K线图 ?
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMIN15, 0);
break;
case ACCE_94: // 30分钟K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMIN30, 0);
break;
case ACCE_95: // 60分钟K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMIN60, 0);
break;
case ACCE_96: // 日K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PDAY, 0);
break;
case ACCE_97: // 周K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PWEEK, 0);
break;
case ACCE_98: // 月K线图
::PostMessage(hWnd, WM_COMMAND, ID_VIEW_PMONTH, 0);
break;
//*******add end******
case ACCE_LBDK: // 量比多空
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_LBDK, 0);
break;
case ACCE_MMLD: // 买卖力道
::PostMessage(hWnd, WM_COMMAND, ID_REALTIME_MMLD, 0);
break;
default:
ASSERT(FALSE);
}
}
键盘精灵码表定义和根据汉字转拼音
src/Client/StkLib/Src/IMCode.cpp
#include "stdafx.h"
/*键盘精灵码表定义和根据汉字转拼音 by freeman*/
const int PYMUSICCOUNT = 405;
/* 汉字基本发音表 */
static char PyMusicCode[405][7] = {
c# 关闭中文输入法(系统级别)/开启中文输入法