📄 keyboarddialog.cpp
字号:
/* * Roadnav * KeyboardDialog.cpp * * Copyright (c) 2004 - 2007 Richard L. Lynch <rllynch@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *////////////////////////////////////////////////////////////////////////////////// \file////// Contains a dialog containing an onscreen keyboard, allowing text to be/// entered into a wxTextCtrl without using a physical keyboard./////////////////////////////////////////////////////////////////////////////////#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <wx/wx.h>#include "KeyboardDialog.h"#define TIMER_AUTOCOMPLETE 6enum{ idAutoComplete, idThisTextCtrl};//////////////////////////////////////////////////////////////////////////////////// \brief KeyboardDialog event table/////////////////////////////////////////////////////////////////////////////////BEGIN_EVENT_TABLE(KeyboardDialog, wxDialog) EVT_BUTTON(wxID_OK, KeyboardDialog::OnOk) EVT_BUTTON(wxID_CANCEL, KeyboardDialog::OnCancel) EVT_BUTTON(idAutoComplete, KeyboardDialog::OnAutoCompleteButton) EVT_CUSTOM_RANGE(wxEVT_COMMAND_BUTTON_CLICKED, 0, 255, KeyboardDialog::OnKBButtonPress) EVT_TIMER(TIMER_AUTOCOMPLETE, KeyboardDialog::OnAutoCompleteTimer) EVT_TEXT(idThisTextCtrl, KeyboardDialog::OnThisTextControlChanged)END_EVENT_TABLE()//////////////////////////////////////////////////////////////////////////////////// \brief KeyboardDialog constructor////// Creates the various controls in the dialog box/////////////////////////////////////////////////////////////////////////////////KeyboardDialog::KeyboardDialog(wxWindow *parent, wxString strTitle, wxTextCtrl * pctlText, wxColour clrBackground, wxColour clrForeground, IAutoComplete * pcAutoComplete) : wxDialog(parent, -1, strTitle, wxDefaultPosition, wxSize(630, 450)){ int iLine; int iClientWidth; int iClientHeight; bool bUseFullScreen = true; SetBackgroundColour(clrBackground); SetForegroundColour(clrForeground); m_pcAutoComplete = pcAutoComplete; m_bAutoCompleteThreadRunning = false; m_bAutoCompleteThreadRunAgain = false; m_ptmrAutoComplete = new wxTimer(this, TIMER_AUTOCOMPLETE); // X offset of leftmost key int iKeyboardX = 10; // Y offset of topmost key (should be greater than iKeyVerticalSpacing to accommodate text entry area int iKeyboardY = 90; // Width of a single key int iKeyWidth = 50; // Vertical spacing for button controls int iKeyVerticalSpacing = 50; char * pszLines[] = {"1234567890\b", "QWERTYUIOP", "ASDFGHJKL\r", "ZXCVBNM,.", NULL}; int iLineOffset[] = {0, iKeyWidth / 3, iKeyWidth * 2 / 3, iKeyWidth, 0}; GetClientSize(&iClientWidth, &iClientHeight); // Actual vertical size of the button control#ifdef __DARWIN__ int iKeyHeight = 22;#else int iKeyHeight = 50;#endif if (bUseFullScreen) { int iScreenWidth = wxSystemSettings::GetMetric(wxSYS_SCREEN_X); int iScreenHeight = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y); if (iScreenWidth > 0 && iScreenHeight > 0) { int iTotalWidth; int iTotalHeight; int iEdgeWidth; int iEdgeHeight; GetSize(&iTotalWidth, &iTotalHeight); iEdgeWidth = iTotalWidth - iClientWidth; iEdgeHeight = iTotalHeight - iClientHeight; iClientWidth = (int) ((iScreenWidth - iEdgeWidth) * 0.95);#ifdef __DARWIN__ iClientHeight = (int) ((iScreenHeight - iEdgeHeight - 150) * 0.9);#else iClientHeight = (int) ((iScreenHeight - iEdgeHeight) * 0.8);#endif iKeyWidth = (iClientWidth - iKeyboardX * 2) / 12; iKeyVerticalSpacing = iClientHeight / 9;#ifndef __DARWIN__ iKeyHeight = iKeyVerticalSpacing;#endif iKeyboardY = (int) (10 + iKeyVerticalSpacing * 2.5); SetSize( (iScreenWidth - (iClientWidth + iEdgeWidth)) / 2, (iScreenHeight - (iClientHeight + iEdgeHeight)) / 2, iClientWidth + iEdgeWidth, iClientHeight + iEdgeHeight); } } m_fntThis = *wxNORMAL_FONT; m_fntThis.SetPointSize(18); SetFont(m_fntThis); m_pctlText = pctlText; m_pctlThisText = new wxTextCtrl(this, idThisTextCtrl, m_pctlText->GetValue(), wxPoint(10, 10), wxSize(iClientWidth - 20, iKeyVerticalSpacing)); m_pctlThisText->SetBackgroundColour(clrBackground); m_pctlThisText->SetForegroundColour(clrForeground); m_pbtnAutoComplete = new wxButton(this, idAutoComplete, wxT(""), wxPoint(10, 10 + iKeyVerticalSpacing), wxSize(iClientWidth - 20, iKeyVerticalSpacing)); m_pbtnAutoComplete->SetBackgroundColour(clrBackground); m_pbtnAutoComplete->SetForegroundColour(clrForeground); for (iLine = 0; pszLines[iLine]; iLine++) { int iChar; for (iChar = 0; pszLines[iLine][iChar]; iChar++) { wxString strLabel; int iThisKeyWidth; if (pszLines[iLine][iChar] == '\b') { strLabel = wxT("<-"); iThisKeyWidth = iKeyWidth * 2; } else if (pszLines[iLine][iChar] == '\r') { strLabel = wxT("Enter"); iThisKeyWidth = iKeyWidth * 2; } else { strLabel = wxString::Format(wxT("%c"), pszLines[iLine][iChar]); iThisKeyWidth = iKeyWidth; } wxButton * pbtnThis = new wxButton(this, pszLines[iLine][iChar], strLabel, wxPoint(iKeyboardX + iKeyWidth * iChar + iLineOffset[iLine], iKeyboardY + iKeyVerticalSpacing * iLine), wxSize(iThisKeyWidth, iKeyHeight)); pbtnThis->SetBackgroundColour(clrBackground); pbtnThis->SetForegroundColour(clrForeground); } } wxButton * pbtnSpace = new wxButton(this, ' ', wxT("Spacebar"), wxPoint(iKeyboardX + iKeyWidth * 2, iKeyboardY + iKeyVerticalSpacing * iLine), wxSize(iKeyWidth * 8, iKeyHeight)); pbtnSpace->SetBackgroundColour(clrBackground); pbtnSpace->SetForegroundColour(clrForeground); wxButton * btnOk = new wxButton(this, wxID_OK, wxT("&OK"), wxPoint(iClientWidth / 2 - iKeyWidth * 4, iClientHeight - iKeyHeight - 10), wxSize(iKeyWidth * 3, iKeyHeight)); btnOk->SetBackgroundColour(clrBackground); btnOk->SetForegroundColour(clrForeground); wxButton * btnCancel = new wxButton(this, wxID_CANCEL, wxT("&Cancel"), wxPoint(iClientWidth / 2 + iKeyWidth, iClientHeight - iKeyHeight - 10), wxSize(iKeyWidth * 3, iKeyHeight)); btnCancel->SetBackgroundColour(clrBackground); btnCancel->SetForegroundColour(clrForeground); m_pbtnAutoComplete->SetDefault(); if (!bUseFullScreen) Center();}//////////////////////////////////////////////////////////////////////////////////// \brief A key on the keyboard was pressed. Take the appropriate action./////////////////////////////////////////////////////////////////////////////////void KeyboardDialog::OnKBButtonPress(wxEvent & event){ wxString strText; long lStart, lEnd; if (event.GetId() == '\r') { wxCommandEvent evOk(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK); OnOk(evOk); return; } m_pctlThisText->GetSelection(&lStart, &lEnd); m_pctlThisText->Remove(lStart, lEnd); strText = m_pctlThisText->GetValue(); if (event.GetId() != '\b') { strText = strText.Left(lStart) + wxString::Format(wxT("%c"), event.GetId()) + strText.Mid(lStart); } else { if (lStart == lEnd) if (lStart > 0) { strText = strText.Left(lStart - 1) + strText.Mid(lStart); lStart -= 2; } } m_pctlThisText->SetValue(strText); m_pctlThisText->SetFocus(); m_pctlThisText->SetSelection(lStart + 1, lStart + 1);}void KeyboardDialog::OnThisTextControlChanged(wxCommandEvent & event){ if (m_pcAutoComplete) { m_bAutoCompleteThreadRunAgain = true; m_ptmrAutoComplete->Start(m_pcAutoComplete->GetUpdateDelay(), true); }}//////////////////////////////////////////////////////////////////////////////////// \brief Cancel button was pressed./////////////////////////////////////////////////////////////////////////////////void KeyboardDialog::OnCancel(wxCommandEvent & event){ m_ptmrAutoComplete->Stop(); while (m_bAutoCompleteThreadRunning) wxMilliSleep(100); EndModal(wxID_CANCEL);}//////////////////////////////////////////////////////////////////////////////////// \brief Ok button was pressed. Copy the contents of the keyboard back/// to the original wxTextCtrl./////////////////////////////////////////////////////////////////////////////////void KeyboardDialog::OnOk(wxCommandEvent & event){ m_pctlText->SetValue(m_pctlThisText->GetValue()); m_ptmrAutoComplete->Stop(); while (m_bAutoCompleteThreadRunning) wxMilliSleep(100); EndModal(wxID_OK);}//////////////////////////////////////////////////////////////////////////////////// \brief /////////////////////////////////////////////////////////////////////////////////void KeyboardDialog::OnAutoCompleteButton(wxCommandEvent & event){ if (m_pbtnAutoComplete->GetLabel() != wxT("")) m_pctlText->SetValue(m_pbtnAutoComplete->GetLabel()); else m_pctlText->SetValue(m_pctlThisText->GetLabel()); m_ptmrAutoComplete->Stop(); while (m_bAutoCompleteThreadRunning) wxMilliSleep(100); EndModal(wxID_OK);}class KeyboardDialogAutoCompleteThread : public wxThread{ public: KeyboardDialogAutoCompleteThread(KeyboardDialog * pParent, IAutoComplete * pcAutoComplete, wxString strLookup); virtual void * Entry(); private: KeyboardDialog * m_pParent; IAutoComplete * m_pcAutoComplete; wxString m_strLookup;};KeyboardDialogAutoCompleteThread::KeyboardDialogAutoCompleteThread(KeyboardDialog * pParent, IAutoComplete * pcAutoComplete, wxString strLookup){ m_pParent = pParent; m_pcAutoComplete = pcAutoComplete; m_strLookup = strLookup;}void * KeyboardDialogAutoCompleteThread::Entry(){ wxString strResult; strResult = m_pcAutoComplete->ClosestMatch(m_strLookup); m_pParent->m_mtxAutoCompleteThreadControl.Lock(); m_pParent->m_strAutoCompleteThreadResult = strResult; m_pParent->m_bAutoCompleteThreadRunning = false; m_pParent->m_mtxAutoCompleteThreadControl.Unlock(); return NULL;}void KeyboardDialog::OnAutoCompleteTimer(wxTimerEvent& event){ wxASSERT(m_pcAutoComplete); if (m_pcAutoComplete) { wxMutexLocker mlLock(m_mtxAutoCompleteThreadControl); if (m_bAutoCompleteThreadRunning) { // try again later m_ptmrAutoComplete->Start(1000, true); return; } m_pbtnAutoComplete->SetLabel(m_strAutoCompleteThreadResult); if (m_bAutoCompleteThreadRunAgain) { m_bAutoCompleteThreadRunAgain = false; m_bAutoCompleteThreadRunning = true; KeyboardDialogAutoCompleteThread * pThd = new KeyboardDialogAutoCompleteThread(this, m_pcAutoComplete, m_pctlThisText->GetValue()); pThd->Create(); pThd->Run(); // check back for the result m_ptmrAutoComplete->Start(100, true); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -