Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

KeePass Password Safe

, 1 Oct 2014 CPOL
KeePass is a free, open-source, light-weight and easy-to-use password safe.
KeePass.zip
KeePass.chm
KeePass.exe
KeePass_Src.zip
Build
Docs
Ext
Icons
Finals
Finals2
plock-blu.ico
plock-dis.ico
plock.ico
plockb.ico
key-blu.png
key-bw.png
key-grn.ico
key-grn.png
plock-blu.ico
plock-blu.png
plock-bw.png
plock-dis.ico
plock-grn.ico
plock-grn.png
plock.ico
plock.png
plockb.png
plockbw-r.png
plockbw.png
Untitled.ico
key-org.ico
keyhole-grn.ico
lockblue.ico
lockgreen.ico
lockred.ico
lockyellow.ico
plockb.ico
plockb2.ico
plockbw.ico
plockg.ico
plocko.ico
plockr.ico
plocky.ico
Icons_Nuvola
KeePass.ini
KeePass.iss
KeePassMsi
KeePassMsi.vdproj
KeePassLibC
KeePassLibCpp
Crypto
SHA2
DataExchange
Details
IO
PasswordGenerator
SDK
Details
SysSpec_Windows
Util
KeePassAPI
KeePassLib.def
res
WinGUI
NewGUI
TaskbarListEx
TaskDialog
VistaMenu
Plugins
res
autotype.bmp
cancel.bmp
clienticex.bmp
clock.bmp
disk.bmp
document.bmp
entry_ed.ico
file.bmp
help_sma.bmp
help_smp.bmp
iconpic.ico
infoicon.bmp
infoiconex.bmp
KeePass.png
key.ico
keyhole.ico
key_smal.bmp
language.bmp
locked.ico
lock_ovr.ico
MostPopularPasswords.bin
mouse_sm.bmp
ok.bmp
optionicex.bmp
options.ico
plugins.ico
PwSafe.ico
randomke.bmp
random_b.bmp
search.ico
tb_about.bmp
tb_adden.bmp
tb_copyp.bmp
tb_copyu.bmp
tb_defau.bmp
tb_delet.bmp
tb_edite.bmp
tb_find.bmp
tb_lock.bmp
tb_new.bmp
tb_open.bmp
tb_save.bmp
tb_save1.bmp
tb_saved.bmp
toolssma.bmp
unlocked.ico
winprops.bmp
world.ico
Util
CmdLine
SprEngine
// This is a modified version of lallous CSendKeys class.
// Edited by: Dominik Reichl

#include "../StdAfx.h"
#include "SendKeys.h"

/*
* -----------------------------------------------------------------------------
* Copyright (c) 2004 lallous <lallousx86@yahoo.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* -----------------------------------------------------------------------------


The Original SendKeys copyright info
---------------------------------------
SendKeys (sndkeys32.pas) routine for 32-bit Delphi.
Written by Ken Henderson
Copyright (c) 1995 Ken Henderson <khen@compuserve.com>

History
----------
04/19/2004
  * Initial version development
04/21/2004
  * Added number of times specifier to special keys
  * Added {BEEP X Y}
  * Added {APPACTIVATE WindowTitle}
  * Added CarryDelay() and now delay works properly with all keys
  * Added SetDelay() method
  * Fixed code in AppActivate that allowed to pass both NULL windowTitle/windowClass

05/21/2004
  * Fixed a bug in StringToVKey() that caused the search for RIGHTPAREN to be matched as RIGHT
  * Adjusted code so it compiles w/ VC6
05/24/2004
  * Added unicode support

Todo
-------
* perhaps add mousecontrol: mousemove+mouse clicks
* allow sending of normal keys multiple times as: {a 10}

*/

const WORD CSendKeys::VKKEYSCANSHIFTON = 0x01;
const WORD CSendKeys::VKKEYSCANCTRLON  = 0x02;
const WORD CSendKeys::VKKEYSCANALTON   = 0x04;
const WORD CSendKeys::INVALIDKEY       = 0xFFFF;

const BYTE CSendKeys::ExtendedVKeys[MaxExtendedVKeys] =
{
    VK_UP,
    VK_DOWN,
    VK_LEFT,
    VK_RIGHT,
    VK_HOME,
    VK_END,
    VK_PRIOR, // PgUp
    VK_NEXT,  //  PgDn
    VK_INSERT,
    VK_DELETE,
	VK_RCONTROL,
	VK_RMENU
};

CSendKeys::CSendKeys()
{
  m_nDelayNow = m_nDelayAlways = 0;
}

// Delphi port regexps:
// ---------------------
// search: .+Name:'([^']+)'.+vkey:([^\)]+)\)
// replace: {"\1", \2}
//
// **If you add to this list, you must be sure to keep it sorted alphabetically
// by Name because a binary search routine is used to scan it.**
//
CSendKeys::key_desc_t CSendKeys::KeyNames[CSendKeys::MaxSendKeysRecs] =
{
  {_T("ADD"), VK_ADD},
  {_T("APPS"), VK_APPS},
  {_T("AT"), '@', true},
  {_T("BACKSPACE"), VK_BACK},
  {_T("BKSP"), VK_BACK},
  {_T("BREAK"), VK_CANCEL},
  {_T("BS"), VK_BACK},
  {_T("CAPSLOCK"), VK_CAPITAL},
  {_T("CARET"), '^', true},
  {_T("CLEAR"), VK_CLEAR},
  {_T("DECIMAL"), VK_DECIMAL},
  {_T("DEL"), VK_DELETE},
  {_T("DELETE"), VK_DELETE},
  {_T("DIVIDE"), VK_DIVIDE},
  {_T("DOWN"), VK_DOWN},
  {_T("END"), VK_END},
  {_T("ENTER"), VK_RETURN},
  {_T("ESC"), VK_ESCAPE},
  {_T("ESCAPE"), VK_ESCAPE},
  {_T("F1"), VK_F1},
  {_T("F10"), VK_F10},
  {_T("F11"), VK_F11},
  {_T("F12"), VK_F12},
  {_T("F13"), VK_F13},
  {_T("F14"), VK_F14},
  {_T("F15"), VK_F15},
  {_T("F16"), VK_F16},
  {_T("F2"), VK_F2},
  {_T("F3"), VK_F3},
  {_T("F4"), VK_F4},
  {_T("F5"), VK_F5},
  {_T("F6"), VK_F6},
  {_T("F7"), VK_F7},
  {_T("F8"), VK_F8},
  {_T("F9"), VK_F9},
  {_T("HELP"), VK_HELP},
  {_T("HOME"), VK_HOME},
  {_T("INS"), VK_INSERT},
  {_T("INSERT"), VK_INSERT},
  {_T("LEFT"), VK_LEFT},
  {_T("LEFTBRACE"), '{', true},
  {_T("LEFTPAREN"), '(', true},
  {_T("LWIN"), VK_LWIN},
  {_T("MULTIPLY"), VK_MULTIPLY},
  {_T("NUMLOCK"), VK_NUMLOCK},
  {_T("NUMPAD0"), VK_NUMPAD0},
  {_T("NUMPAD1"), VK_NUMPAD1},
  {_T("NUMPAD2"), VK_NUMPAD2},
  {_T("NUMPAD3"), VK_NUMPAD3},
  {_T("NUMPAD4"), VK_NUMPAD4},
  {_T("NUMPAD5"), VK_NUMPAD5},
  {_T("NUMPAD6"), VK_NUMPAD6},
  {_T("NUMPAD7"), VK_NUMPAD7},
  {_T("NUMPAD8"), VK_NUMPAD8},
  {_T("NUMPAD9"), VK_NUMPAD9},
  {_T("PERCENT"), '%', true},
  {_T("PGDN"), VK_NEXT},
  {_T("PGUP"), VK_PRIOR},
  {_T("PLUS"), '+', true},
  {_T("PRTSC"), VK_PRINT},
  {_T("RIGHT"), VK_RIGHT},
  {_T("RIGHTBRACE"), '}', true},
  {_T("RIGHTPAREN"), ')', true},
  {_T("RWIN"), VK_RWIN},
  {_T("SCROLL"), VK_SCROLL},
  {_T("SEPARATOR"), VK_SEPARATOR},
  {_T("SNAPSHOT"), VK_SNAPSHOT},
  {_T("SPACE"), VK_SPACE},
  {_T("SUBTRACT"), VK_SUBTRACT},
  {_T("TAB"), VK_TAB},
  {_T("TILDE"), '~', true},
  {_T("UP"), VK_UP},
  {_T("WIN"), VK_LWIN}
};


// calls keybd_event() and waits, if needed, till the sent input is processed
void CSendKeys::KeyboardEvent(BYTE VKey, BYTE ScanCode, LONG Flags)
{
  MSG KeyboardMsg;

  keybd_event(VKey, ScanCode, Flags, 0);

  if (m_bWait)
  {
    while (::PeekMessage(&KeyboardMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
    {
      ::TranslateMessage(&KeyboardMsg);
      ::DispatchMessage(&KeyboardMsg);
    }
  }
}

// Checks whether the specified VKey is an extended key or not
bool CSendKeys::IsVkExtended(BYTE VKey)
{
  for (int i=0;i<MaxExtendedVKeys;i++)
  {
    if (ExtendedVKeys[i] == VKey)
      return true;
  }
  return false;
}

// Generates KEYUP
void CSendKeys::SendKeyUp(BYTE VKey)
{
  BYTE ScanCode = LOBYTE(::MapVirtualKey(VKey, 0));

  KeyboardEvent(VKey,
                ScanCode,
                KEYEVENTF_KEYUP | (IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0));
}

void CSendKeys::SendKeyDown(BYTE VKey, WORD NumTimes, bool GenUpMsg, bool bDelay)
{
  WORD Cnt = 0;
  BYTE ScanCode = 0;
  bool NumState = false;

  if (VKey == VK_NUMLOCK)
  {
    DWORD dwVersion = ::GetVersion();

    for (Cnt=1; Cnt<=NumTimes; Cnt++)
    {
      if (bDelay)
        CarryDelay();
      // snippet based on:
      // http://www.codeproject.com/cpp/togglekeys.asp
      if (dwVersion < 0x80000000)
      {
        ::keybd_event(VKey, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
        ::keybd_event(VKey, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
      }
      else
      { /*
        // Win98 and later
        if ( ((DWORD)(HIBYTE(LOWORD(dwVersion))) >= 10) )
        {
          // Define _WIN32_WINNT > 0x0400
          // to compile
          INPUT input[2] = {0};
          input[0].type = input[1].type = INPUT_KEYBOARD;
          input[0].ki.wVk = input[1].ki.wVk = VKey;
          input[1].ki.dwFlags = KEYEVENTF_KEYUP;
          ::SendInput(sizeof(input) / sizeof(INPUT), input, sizeof(INPUT));
        }
        // Win95
        else */
        {
          KEYBOARDSTATE_t KeyboardState;
          NumState = ((GetKeyState(VK_NUMLOCK) & 1) ? true : false);
          GetKeyboardState(&KeyboardState[0]);
          if (NumState)
            KeyboardState[VK_NUMLOCK] &= ~1;
          else
            KeyboardState[VK_NUMLOCK] |= 1;

          SetKeyboardState(&KeyboardState[0]);
        }
      }
    }
    return;
  }

  // Get scancode
  ScanCode = LOBYTE(::MapVirtualKey(VKey, 0));

  // Send keys
  for (Cnt=1; Cnt<=NumTimes; Cnt++)
  {
    // Carry needed delay ?
    if (bDelay)
      CarryDelay();

    KeyboardEvent(VKey, ScanCode, IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0);
    if (GenUpMsg)
      KeyboardEvent(VKey, ScanCode, (IsVkExtended(VKey) ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP);
  }
}

// Checks whether a bit is set
bool CSendKeys::BitSet(BYTE BitTable, UINT BitMask)
{
  return BitTable & BitMask ? true : false;
}

// Sends a single key
void CSendKeys::SendKey(WORD MKey, WORD NumTimes, bool GenDownMsg)
{
  // Send appropriate shift keys associated with the given VKey
  if (BitSet(HIBYTE(MKey), VKKEYSCANSHIFTON))
    SendKeyDown(VK_SHIFT, 1, false);

  if (BitSet(HIBYTE(MKey), VKKEYSCANCTRLON))
    SendKeyDown(VK_CONTROL, 1, false);

  if (BitSet(HIBYTE(MKey), VKKEYSCANALTON))
    SendKeyDown(VK_MENU, 1, false);

  // Send the actual VKey
  SendKeyDown(LOBYTE(MKey), NumTimes, GenDownMsg, true);

  // toggle up shift keys
  if (BitSet(HIBYTE(MKey), VKKEYSCANSHIFTON))
    SendKeyUp(VK_SHIFT);

  if (BitSet(HIBYTE(MKey), VKKEYSCANCTRLON))
    SendKeyUp(VK_CONTROL);

  if (BitSet(HIBYTE(MKey), VKKEYSCANALTON))
    SendKeyUp(VK_MENU);
}

// Implements a simple binary search to locate special key name strings
WORD CSendKeys::StringToVKey(LPCTSTR KeyString, int &idx)
{
  bool Found = false, Collided;
  int  Bottom = 0,
       Top = MaxSendKeysRecs,
       Middle = (Bottom + Top) / 2;
  WORD retval = INVALIDKEY;

  idx    = -1;

  do
  {
    Collided = (Bottom == Middle) || (Top == Middle);
    // int cmp = _tcsnicmp(KeyNames[Middle].keyName, KeyString, _tcslen(KeyString));
	int cmp = _tcsicmp(KeyNames[Middle].keyName, KeyString);
    if (cmp == 0)
    {
      Found = true;
      retval = KeyNames[Middle].VKey;
      idx    = Middle;
      break;
    }
    else
    {
      if (cmp < 0)
        Bottom = Middle;
      else
        Top = Middle;
      Middle = (Bottom + Top) / 2;
    }
  } while (!(Found || Collided));

  return retval;
}

// Releases all shift keys (keys that can be depressed while other keys are being pressed
// If we are in a modifier group this function does nothing
void CSendKeys::PopUpShiftKeys()
{
  if (!m_bUsingParens)
  {
    if (m_bShiftDown)
      SendKeyUp(VK_SHIFT);
    if (m_bControlDown)
      SendKeyUp(VK_CONTROL);
    if (m_bAltDown)
      SendKeyUp(VK_MENU);
    if (m_bWinDown)
      SendKeyUp(VK_LWIN);
    m_bWinDown = m_bShiftDown = m_bControlDown = m_bAltDown = false;
  }
}

// Sends a key string
bool CSendKeys::SendKeys(LPCTSTR KeysString, bool Wait)
{
  WORD MKey, NumTimes = 0;
  TCHAR KeyString[300] = {0};
  int  keyIdx;

  LPTSTR pKey = (LPTSTR) KeysString;
  TCHAR  ch;

  m_bWait = Wait;

  m_bWinDown = m_bShiftDown = m_bControlDown = m_bAltDown = m_bUsingParens = false;

  while ((ch = *pKey) != 0)
  {
    switch (ch)
    {
    // begin modifier group
    case _TXCHAR('('):
      m_bUsingParens = true;
      break;

    // end modifier group
    case _TXCHAR(')'):
      m_bUsingParens = false;
      PopUpShiftKeys(); // pop all shift keys when we finish a modifier group close
      break;

    // ALT key
    case _TXCHAR('%'):
      m_bAltDown = true;
      SendKeyDown(VK_MENU, 1, false);
      break;

    // SHIFT key
    case _TXCHAR('+'):
      m_bShiftDown = true;
      SendKeyDown(VK_SHIFT, 1, false);
      break;

    // CTRL key
    case _TXCHAR('^'):
      m_bControlDown = true;
      SendKeyDown(VK_CONTROL, 1, false);
      break;

    // WINKEY (Left-WinKey)
    case '@':
      m_bWinDown = true;
      SendKeyDown(VK_LWIN, 1, false);
      break;

    // enter
    case _TXCHAR('~'):
      SendKeyDown(VK_RETURN, 1, true);
      PopUpShiftKeys();
      break;

    // begin special keys
    case _TXCHAR('{'):
      {
        LPTSTR p = pKey+1; // skip past the beginning '{'
        size_t t;

        // find end of close
        while (*p && *p != _TXCHAR('}'))
          p++;

        t = p - pKey;
        // special key definition too big?
        if (t > sizeof(KeyString))
          return false;

        // Take this KeyString into local buffer
        _tcsncpy_s(KeyString, _countof(KeyString), pKey+1, t);

        KeyString[t-1] = _TXCHAR('\0');
        keyIdx = -1;

        pKey += t; // skip to next keystring

        // Invalidate key
        MKey = INVALIDKEY;

        // sending arbitrary vkeys?
        if (_tcsnicmp(KeyString, _T("VKEY"), 4) == 0)
        {
          p = KeyString + 4;
          MKey = (WORD)_ttoi(p);
		  NumTimes = 1;
        }
        else if (_tcsnicmp(KeyString, _T("BEEP"), 4) == 0)
        {
          p = KeyString + 4 + 1;
          LPTSTR p1 = p;
          DWORD frequency, delay;

          if ((p1 = _tcsstr(p, _T(" "))) != NULL)
          {
            *p1++ = _TXCHAR('\0');
            frequency = _ttoi(p);
            delay = _ttoi(p1);
            ::Beep(frequency, delay);
          }
        }
        // Should activate a window?
        else if (_tcsnicmp(KeyString, _T("APPACTIVATE"), 11) == 0)
        {
          p = KeyString + 11 + 1;
          AppActivate(p);
        }
        // want to send/set delay?
        else if (_tcsnicmp(KeyString, _T("DELAY"), 5) == 0)
        {
          // Advance to parameters
          p = KeyString + 5;
          // set "sleep factor"
          if (*p == _TXCHAR('='))
            m_nDelayAlways = _ttoi(p + 1); // Take number after the '=' character
          else
            // set "sleep now"
            m_nDelayNow += _ttoi(p); // DR: consecutive delays add up
        }
        // not command special keys, then process as keystring to VKey
        else
        {
          MKey = StringToVKey(KeyString, keyIdx);
          // Key found in table
          if (keyIdx != -1)
          {
            NumTimes = 1;

            // Does the key string have also count specifier?
            t = _tcslen(KeyNames[keyIdx].keyName);
            if (_tcslen(KeyString) > t)
            {
              p = KeyString + t;
              // Take the specified number of times
              NumTimes = (WORD)_ttoi(p);
            }

            if (KeyNames[keyIdx].normalkey)
              MKey = ::VkKeyScan(KeyNames[keyIdx].VKey);
          }
        }

        // A valid key to send?
        if (MKey != INVALIDKEY)
        {
          SendKey(MKey, NumTimes, true);
          PopUpShiftKeys();
        }
      }
      break;

      // a normal key was pressed
    default:
      // Get the VKey from the key
      MKey = ::VkKeyScan(ch);
      SendKey(MKey, 1, true);
      PopUpShiftKeys();
    }
    pKey++;
  }

  m_bUsingParens = false;
  PopUpShiftKeys();
  return true;
}

bool CSendKeys::AppActivate(HWND wnd)
{
  if (wnd == NULL)
    return false;

  ::SendMessage(wnd, WM_SYSCOMMAND, SC_HOTKEY, (LPARAM) wnd);
  ::SendMessage(wnd, WM_SYSCOMMAND, SC_RESTORE, (LPARAM) wnd);

  ::ShowWindow(wnd, SW_SHOW);
  ::SetForegroundWindow(wnd);
  ::SetFocus(wnd);

  return true;
}

BOOL CALLBACK CSendKeys::enumwindowsProc(HWND hwnd, LPARAM lParam)
{
  enumwindow_t *t = (enumwindow_t *) lParam;

  LPTSTR wtitle = 0, wclass = 0, str = t->str;

  if (!*str)
    str++;
  else
  {
    wtitle = str;
    str += _tcslen(str) + 1;
  }

  if (*str)
    wclass = str;

  bool bMatch(false);

  if (wclass)
  {
    TCHAR szClass[300];
    if (::GetClassName(hwnd, szClass, sizeof(szClass)/sizeof(TCHAR)))
      bMatch |= (_tcsstr(szClass, wclass) != 0);
  }

  if (wtitle)
  {
    TCHAR szTitle[300];
    if (::GetWindowText(hwnd, szTitle, sizeof(szTitle)/sizeof(TCHAR)))
      bMatch |= (_tcsstr(szTitle, wtitle) != 0);
  }

  if (bMatch)
  {
    t->hwnd = hwnd;
    return false;
  }
  return true;
}

// Searchs and activates a window given its title or class name
bool CSendKeys::AppActivate(LPCTSTR WindowTitle, LPCTSTR WindowClass)
{
  HWND w;

  w = ::FindWindow(WindowClass, WindowTitle);
  if (w == NULL)
  {
    // Must specify at least a criteria
    if (WindowTitle == NULL && WindowClass == NULL)
      return false;

    // << Code to serialize the windowtitle/windowclass in order to send to EnumWindowProc()
    size_t l1(0), l2(0);
    if (WindowTitle)
      l1 = _tcslen(WindowTitle);
    if (WindowClass)
      l2 = _tcslen(WindowClass);

    LPTSTR titleclass = new TCHAR [l1 + l2 + 5];

    memset(titleclass, '\0', l1 + l2 + 5);

    if (WindowTitle)
      _tcscpy_s(titleclass, l1 + l2 + 5, WindowTitle);

    titleclass[l1] = 0;

    if (WindowClass)
      _tcscpy_s(titleclass+l1+1, l1 + l2 + 5 - l1 - 1, WindowClass);

    // >>

    enumwindow_t t;

    t.hwnd = NULL;
    t.str  = titleclass;
    ::EnumWindows(enumwindowsProc, (LPARAM) & t);
    w = t.hwnd;
    delete [] titleclass;
  }

  if (w == NULL)
    return false;

  return AppActivate(w);
}

// Carries the required delay and clears the m_nDelaynow value
void CSendKeys::CarryDelay()
{
  // Should we delay once?
  if (!m_nDelayNow)
    // should we delay always?
    m_nDelayNow = m_nDelayAlways;

  // No delay specified?
  if (m_nDelayNow)
    ::Sleep(m_nDelayNow); //::Beep(100, m_nDelayNow);

  // clear SleepNow
  m_nDelayNow = 0;
}

/*
Test Binary search
void CSendKeys::test()
{
  WORD miss(0);
  for (int i=0;i<MaxSendKeysRecs;i++)
  {
    char *p = (char *)KeyNames[i].keyName;
    WORD v = StringToVKeyB(p);
    if (v == INVALIDKEY)
    {
      miss++;
    }
  }
}
*/

/*
Search in a linear manner
WORD CSendKeys::StringToVKey(const char *KeyString, int &idx)
{
for (int i=0;i<MaxSendKeysRecs;i++)
{
size_t len = strlen(KeyNames[i].keyName);
if (strnicmp(KeyNames[i].keyName, KeyString, len) == 0)
{
idx = i;
return KeyNames[i].VKey;
}
}
idx = -1;
return INVALIDKEY;
}
*/

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dominik Reichl
Software Developer
Germany Germany
Dominik started programming in Omikron Basic, a programming language for the good old Atari ST. After this, there was some short period of QBasic programming on the PC, but soon he began learning C++, which is his favorite language up to now.
 
Today, his programming experience includes C / C++ / [Visual] C++ [MFC], C#/.NET, Java, JavaScript, PHP and HTML and the basics of pure assembler.
 
He is interested in almost everything that has to do with computing, his special interests are security and data compression.
 
You can find his latest freeware, open-source projects and all articles on his homepage: http://www.dominik-reichl.de/

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141223.1 | Last Updated 1 Oct 2014
Article Copyright 2003 by Dominik Reichl
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid