#include "includes.h" #define IMAGECLASS KB2Images #define IMAGEFILE #include KeyBuddy2* KeyBuddy2::pKB2=NULL; LineEdit* KeyBuddy2::pdisplay=NULL; // pointer to the display keyButton* KeyBuddy2::pKeyButton[256]={0}; // pointers to gui key buttons BYTE KeyBuddy2::keyFinger[256]={0}; // which finger is associated to this key (=style index) bool KeyBuddy2::neoLevelsActive=true; // whether the additional layers of neo are active bool KeyBuddy2::neoRemapActive=false; // false=qwertz layout, true=neo layout bool KeyBuddy2::cyrillicActive=false; // if roman letters are translated into cyrillic bool KeyBuddy2::capslockActive=false; // if capital letters shall be sent bool KeyBuddy2::lockLayer4Active=false; // if neo layer 4 is locked bool KeyBuddy2::mouseControlActive=false; // if mouse control via keyboard is active bool KeyBuddy2::dummySwitch=false; // that is switched by badly assigned switch pointers to prevent memory access violation bool KeyBuddy2::keyPressed[256]={0}; // key states wchar KeyBuddy2::lastDeadKey; // buffer that stores which dead key was pressed wchar KeyBuddy2::ruDeadChar[2]; // the dead characters for the russian keyboard (small and capital) wchar KeyBuddy2::map[256][7]={0}; // character to send = map[vkCode][mod] wchar KeyBuddy2::symbolMap[256][7]={0}; // character to draw on keyboard = symbolMap[vkCode][mod] BYTE KeyBuddy2::neoRemap[256]={0}; // vkNeoKey = neoRemap[vkQWERTZKey] wchar KeyBuddy2::rumap[256][2]={0}; // cyrillic character = rumap[ansi of latin character][ruDeadKey toggled] bool* KeyBuddy2::pSwitch[256]={0}; // pointer to the switches WString KeyBuddy2::keyNames[256]; // names of unmodified keys wchar KeyBuddy2::upperCaseMap[1023][2]={0}; // mapping lowercase unicode characters to uppercase KeyBuddy2::KeyBuddy2() { pKB2 = this; #ifdef DEBUG pdisplay = &display; #endif STARTLOG(SRCPATH "log.html"); loadMaps(); hotString::loadHotStrings(); int i; for(i=0;i<=255;i++){ pSwitch[i]=&dummySwitch; } pSwitch[1]=&neoLevelsActive; pSwitch[2]=&neoRemapActive; pSwitch[3]=&cyrillicActive; pSwitch[4]=&capslockActive; pSwitch[5]=&lockLayer4Active; pSwitch[6]=&mouseControlActive; KeyBuddy2::Zoomable(); Icon(KB2Images::tray(),KB2Images::tray()); trayicon.Icon(KB2Images::tray()); trayicon.WhenBar=THISBACK(traymenu); trayicon.WhenLeftDown=THISBACK(trayclick); trayicon.Tip("KeyBuddy2 (verändert Tastatur)"); CtrlLayout(*this, "KeyBuddy2"); releaseAllKeys(); SetHook(); initKeyButtons(); NoAccessKeysDistribution(); #ifndef DEBUG WhenClose=THISBACK(Hide); #endif ToolWindow(); TopMost(); } KeyBuddy2::~KeyBuddy2() { releaseAllKeys(); RemoveHook(); ENDLOG; } bool KeyBuddy2::ProcessKbdEvent( WPARAM upDownInfo, DWORD vkCode, DWORD scanCode, bool isExtended, bool isInjected, bool isAltDown, bool isReleased, ULONG_PTR dwExtraInfo) { if(scanCode==0x21d){ // AltGr also presses left Strg but with scancode 0x21d, filter that out, it sucks return false; } if(!isInjected){ // memorize physical key states keyPressed[vkCode]=!isReleased; if(isReleased){pKeyButton[vkCode]->simUp();} else{pKeyButton[vkCode]->simDown();} } // log information about captured event: char udi[14]; // up down info string char buffer[512]; //bool forceRedraw=false; // force keyboard redraw switch(upDownInfo){ case WM_KEYDOWN: sprintf(udi,"WM_KEYDOWN"); break; case WM_KEYUP: sprintf(udi,"WM_KEYUP"); break; case WM_SYSKEYDOWN: sprintf(udi,"WM_SYSKEYDOWN"); break; case WM_SYSKEYUP: sprintf(udi,"WM_SYSKEYUP"); break; default: sprintf(udi,"UNKNOWN"); } sprintf(buffer,"upDownInfo: %s\tvkCode: %d (0x%X)\tscanCode: %d (0x%X)\textended: %d\tinjected: %d\taltdown: %d\tup: %d\tdwExtraInfo: %d", udi,vkCode,vkCode,scanCode,scanCode,(int)isExtended,(int)isInjected,(int)isAltDown,(int)isReleased,dwExtraInfo); LOGG(buffer); LOGGNL; if(dwExtraInfo==HOTSTRING){ // a hotstring is being sent, dont do anything return true; } // flush the hotstring buffer if certain navi or special keys are pressed (even if they are injected) if(vkCode==VK_UP || vkCode==VK_LEFT || vkCode==VK_RIGHT || vkCode==VK_DOWN || vkCode==VK_PRIOR || vkCode==VK_NEXT || vkCode==VK_END || vkCode==VK_HOME || keyPressed[VK_LCONTROL] || keyPressed[VK_RCONTROL] || keyPressed[VK_LWIN] || keyPressed[VK_RWIN] || keyPressed[VK_LMENU]){ hotString::clearBuffer(); } // delete one key from hotstring buffer if backspace is pushed if(vkCode==VK_BACK && !isReleased){ int i; for(i=hotString::bufferLen-1;i>0;i--){ hotString::hsBuffer.Set(i,(int)hotString::hsBuffer[i-1]); } hotString::hsBuffer.Set(0,(int)0); } if(isInjected){ // dont stop or change generated key events return true; } // check if the key combination would activate the neo levels if(!neoLevelsActive && !isReleased){ neoLevelsActive=true; // only simulative to fool getNeoMod int mod=getNeoMod(); WORD vkCode_neo; if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){ vkCode_neo=neoRemap[vkCode]; } else{ vkCode_neo=vkCode; } if(map[vkCode_neo][mod-1]!=0xF801){ // keystroke would not activate layers, leave true otherwise neoLevelsActive=false; // deactivate again } else{ // leave activated pKB2->drawKeyButtons(); return false; } } // check if the key combination turns off mouse control if(mouseControlActive && !isReleased){ int mod=getNeoMod(); WORD vkCode_neo; if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){ vkCode_neo=neoRemap[vkCode]; } else{ vkCode_neo=vkCode; } if(map[vkCode_neo][mod-1]==0xF806){ // keystroke deactivates mouse control mouseControlActive=false; // deactivate again pKB2->drawKeyButtons(); return false; } } // dont do substitutions if neolevels are off or // certain functional keys are being pressed or held (getNeoMod returns 0) // this means that ctrl+a/x/c/v/z... remain on their standard position // also clear hotstring buffer then if(getNeoMod()==0 || vkCode==VK_LCONTROL || vkCode==VK_RCONTROL || vkCode==VK_LWIN || vkCode==VK_RWIN || vkCode==VK_LMENU){ // redraw keyboard pKB2->drawKeyButtons(); return true; } // capslock if(keyPressed[VK_LSHIFT] && keyPressed[VK_RSHIFT] && (vkCode==VK_LSHIFT || vkCode==VK_RSHIFT) && !isReleased){ capslockActive=!capslockActive; pKB2->drawKeyButtons(); } // lock 4th layer if(keyPressed[VK_MOD_41] && keyPressed[VK_MOD_42] && (vkCode==VK_MOD_41 || vkCode==VK_MOD_42) && !isReleased){ lockLayer4Active=!lockLayer4Active; pKB2->drawKeyButtons(); } // number keys, letter keys, ",", "-", ".", dead keys, space if((vkCode>=VK_A && vkCode<=VK_Z) || (vkCode>=VK_0 && vkCode<=VK_9) || vkCode==VK_AE || vkCode==VK_OE || vkCode==VK_UE || vkCode==VK_SZ || vkCode==VK_COMMA || vkCode==VK_DASH || vkCode==VK_DOT || vkCode==VK_CIRCUMFLEX || vkCode==VK_ACUT || vkCode==VK_PLUS || vkCode==VK_SPACE || vkCode==VK_TAB){ if(mouseControlActive){ mouseController::mouseEvent(vkCode,isReleased); return false; } WORD vkCode_neo; int mod=getNeoMod(); if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){ vkCode_neo=neoRemap[vkCode]; } else{ vkCode_neo=vkCode; } LOGG("vkCode: "); LOGG((int)vkCode); LOGG(" vkCode_neo: "); LOGG((int)vkCode_neo); LOGG(" mod: "); LOGG(mod); if(mod>=1 && mod<=7){ wchar charToSend=map[vkCode_neo][mod-1]; if(cyrillicActive){ if(charToSend==ruDeadChar[0] || charToSend==ruDeadChar[1]){ lastDeadKey=charToSend; pKB2->drawKeyButtons(); return false; } if(charToSend>0 && charToSend<256){ if(lastDeadKey==ruDeadChar[0] || lastDeadKey==ruDeadChar[1]){ charToSend=rumap[charToSend][1]; lastDeadKey=0; pKB2->drawKeyButtons(); } else{ charToSend=rumap[charToSend][0]; lastDeadKey=0; } } } if(capslockActive){ charToSend=upperCase(charToSend); } LOGG(" sending: "); LOGG(charToSend); LOGG(" (U+"); LOGG((int)charToSend); LOGG(")"); LOGGNL; SendUNIKey(charToSend,isReleased); if(!isReleased){ long focusPtr=hotString::getFocusWindowPtr(); if(focusPtr!=hotString::lastFocusPtr){ // if a new window has the focus, clear the buffer hotString::clearBuffer(); hotString::lastFocusPtr=focusPtr; } hotString::appendBuffer(charToSend); hotString::checkHotStrings(); } } return false; } if(!neoLevelsActive){ return true; } // redraw keyboard if(vkCode==VK_LSHIFT || vkCode==VK_RSHIFT || vkCode==VK_MOD_31 || vkCode==VK_MOD_32 || vkCode==VK_MOD_41 || vkCode==VK_MOD_42 || vkCode==VK_LCONTROL || vkCode==VK_RCONTROL){ pKB2->drawKeyButtons(); } // block mod keys that have symbols if(vkCode==VK_MOD_32 || vkCode==VK_MOD_41){ return false; } return true; } WString KeyBuddy2::buttonLabel(DWORD vkCode){ wchar res=0; if(getNeoMod()==0){ return keyNames[vkCode]; } // number keys, letter keys, ",", "-", ".", dead keys, tab, space if((vkCode>=VK_A && vkCode<=VK_Z) || (vkCode>=VK_0 && vkCode<=VK_9) || vkCode==VK_AE || vkCode==VK_OE || vkCode==VK_UE || vkCode==VK_SZ || vkCode==VK_COMMA || vkCode==VK_DASH || vkCode==VK_DOT || vkCode==VK_CIRCUMFLEX || vkCode==VK_ACUT || vkCode==VK_PLUS || vkCode==VK_TAB || vkCode==VK_SPACE){ WORD vkCode_neo; int mod=getNeoMod(); if(mouseControlActive){ int i; for(i=0;i<9;i++){ if(vkCode==mouseController::mouseKeys[i]){ res=mouseController::mouseSymbols[i]; return WString((int)res,1); } } return ""; } if(neoRemapActive && (mod==1 || mod==2 || mod==5 || mod==6) || mod==3 || mod==4 || mod==7){ vkCode_neo=neoRemap[vkCode]; } else{ vkCode_neo=vkCode; } if(mod>=1 && mod<=7){ res=symbolMap[vkCode_neo][mod-1]; if(cyrillicActive){ if(res==ruDeadChar[0] || res==ruDeadChar[1]){ return WString((int)res,1); } if(res>0 && res<256){ if(lastDeadKey==ruDeadChar[0] || lastDeadKey==ruDeadChar[1]){ res=rumap[res][1]; } else{ res=rumap[res][0]; } } } if(capslockActive){ res=upperCase(res); } return WString((int)res,1); } } switch(vkCode){ // layer-independent keys case VK_LSHIFT: case VK_RSHIFT: return WString(0x21e7,1); break; case VK_MOD_31: case VK_MOD_32: return WString("Mod3"); break; case VK_MOD_41: case VK_MOD_42: return WString("Mod4"); break; case VK_RETURN: return WString(0x23cE,1); break; case VK_BACK: return WString(0x232b,1); break; case VK_LCONTROL: case VK_RCONTROL: return WString("Strg"); break; case VK_LMENU: return WString("Alt"); break; case VK_LWIN: case VK_RWIN: return WString(0x229e,1)+WString(0x224b,1); break; case VK_APPS: return WString(0x2338,1)+WString(0x21d6,1); break; } return WString(""); } int KeyBuddy2::getNeoMod(){ if(keyPressed[VK_LCONTROL] || keyPressed[VK_RCONTROL] // functional keys, disable neo stuff || keyPressed[VK_LWIN] || keyPressed[VK_RWIN] || keyPressed[VK_LMENU] || !neoLevelsActive){ return 0; } bool kp2=keyPressed[VK_MOD_21] || keyPressed[VK_MOD_22]; bool kp3=keyPressed[VK_MOD_31] || keyPressed[VK_MOD_32]; bool kp4=keyPressed[VK_MOD_41] || keyPressed[VK_MOD_42] || lockLayer4Active; if(!kp2 && !kp3 && !kp4){return 1;} // small letters if( kp2 && !kp3 && !kp4){return 2;} // capital letters if(!kp2 && kp3 && !kp4){return 3;} // special characters if(!kp2 && !kp3 && kp4){return 4;} // numbers/navi if( kp2 && kp3 && !kp4){return 5;} // small greek if(!kp2 && kp3 && kp4){return 6;} // capital greek/math if( kp2 && !kp3 && kp4){return 7;} // pseudo layer return 0; } void KeyBuddy2::loadMaps(){ FILE* pFile; int i; BYTE buffer; wchar unibuffer; #define FGETUC(pbuf,pfile) fread(pbuf,sizeof(wchar),1,pfile) // QWERTZ keycode -> neo keycode pFile = fopen(SRCPATH "neomap.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read neomap.txt"); exit(1);} neoRemap[0]=0; for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in map.txt does not match the keycode buffer=fgetc(pFile); if(buffer==13){ // line break, no mapping neoRemap[i]=i; fgetc(pFile); // skip second line break character } else{ neoRemap[i]=buffer; fgetc(pFile); // skip line break characters fgetc(pFile); } LOGG("neoRemap ");LOGG(i);LOGG("->");LOGG(neoRemap[i]);LOGGNL; } fclose(pFile); // keycode -> unicode character to send pFile = fopen(SRCPATH "sendmap.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read sendmap.txt"); exit(1);} fgetc(pFile); // skip BOM fgetc(pFile); memset(map[0],0,7); for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in sendmap.txt does not match the keycode fread(map[i],sizeof(wchar),7,pFile); // read from file fgetc(pFile); // skip line break (make sure to have a line break at the end of the file) fgetc(pFile); fgetc(pFile); fgetc(pFile); LOGG("key ");LOGG(i);LOGG(": ");LOGG(map[i][0]);LOGG(map[i][1]);LOGG(map[i][2]);LOGG(map[i][3]);LOGG(map[i][4]);LOGG(map[i][5]);LOGG(map[i][6]);LOGGNL; } fclose(pFile); // keycode -> unicode character to draw on keyboard pFile = fopen(SRCPATH "symbolmap.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read symbolmap.txt"); exit(1);} fgetc(pFile); // skip BOM fgetc(pFile); memset(symbolMap[0],0,7); for(i=1;i<=255;i++){ // assuming that no key has keycode 0. Otherwise the linenumber in symbolmap.txt does not match the keycode fread(symbolMap[i],sizeof(wchar),7,pFile); // read from file fgetc(pFile); // skip line break (make sure to have a line break at the end of the file) fgetc(pFile); fgetc(pFile); fgetc(pFile); LOGG("key ");LOGG(i);LOGG(": ");LOGG(map[i][0]);LOGG(map[i][1]);LOGG(map[i][2]);LOGG(map[i][3]);LOGG(map[i][4]);LOGG(map[i][5]);LOGG(map[i][6]);LOGGNL; } fclose(pFile); // latin character -> cyrillic character pFile = fopen(SRCPATH "rumap.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read rumap.txt"); exit(1);} fgetc(pFile); // skip BOM fgetc(pFile); rumap[0][0]=0; rumap[0][1]=0; int idead=0; for(i=1;i<=255;i++){ FGETUC(&unibuffer,pFile); if(unibuffer==13){ // line break, no mapping rumap[i][0]=i; rumap[i][1]=i; FGETUC(&unibuffer,pFile); // skip second line break character } else{ if(unibuffer==0x2020){ // dagger, symbol for the dead character rumap[i][0]=0; rumap[i][1]=0; ruDeadChar[idead]=i; idead++; FGETUC(&unibuffer,pFile); // skip line break characters FGETUC(&unibuffer,pFile); } else{ rumap[i][0]=unibuffer; rumap[i][1]=unibuffer; FGETUC(&unibuffer,pFile); if(unibuffer==13){ // line break, no special character if dead key is toggled FGETUC(&unibuffer,pFile); // skip second line break character } else{ // special character if cyrillic dead key is toggled rumap[i][1]=unibuffer; FGETUC(&unibuffer,pFile); // skip line break characters FGETUC(&unibuffer,pFile); } } } LOGG("russianRemap ");LOGG(i);LOGG("->");LOGG(rumap[i][0]);LOGG("/");LOGG(rumap[i][1]);LOGGNL; } fclose(pFile); // keycode -> keyname pFile = fopen(SRCPATH "keynames.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read keynames.txt"); exit(1);} fgetc(pFile); // skip BOM fgetc(pFile); keyNames[0]=""; for(i=1;i<=255;i++){ keyNames[i]=""; FGETUC(&unibuffer,pFile); while(unibuffer!=13){ // line break keyNames[i]=keyNames[i]+unibuffer; FGETUC(&unibuffer,pFile); } FGETUC(&unibuffer,pFile); // skip second line break character } fclose(pFile); // lowercase -> uppercase pFile = fopen(SRCPATH "uppercase.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read uppercase.txt"); exit(1);} fgetc(pFile); // skip BOM fgetc(pFile); i=0; while(!feof(pFile) && i<1023){ FGETUC(&(upperCaseMap[i][0]),pFile); FGETUC(&(upperCaseMap[i][1]),pFile); i++; } fclose(pFile); while(i<1023){ upperCaseMap[i][0]=0xFFFF; upperCaseMap[i][1]=0xFFFF; i++; } // keycode -> mouseevent pFile = fopen(SRCPATH "mousemap.txt", "rb"); if (pFile==NULL) {PromptOK("Can't read mousemap.txt"); exit(1);} fread(mouseController::mouseKeys,sizeof(byte),9,pFile); fclose(pFile); } void KeyBuddy2::SendUNIKey(wchar key, bool release, ULONG_PTR extraInfo){ // use unicodes Personal Usage Area (E000-F8FF) specially if(key/256>=0xE0 && key/256<=0xF8){ // send keystroke instead of unicode byte flags=key/256; bool onlyDown=flags<=0xE7; bool onlyUp=flags>=0xE8 && flags<=0xEF; bool swtch=(flags==0xF8); bool shift=(flags & 1)!=0; bool ctrl=(flags & 2)!=0; bool alt=(flags & 4)!=0; // E0-E7: only down event gets sent // E8-EF: only up event gets sent (but if key is pushed down) // F0-F7: down and up according to release parameter // F8: switch // unicode AND 0x0100 = shift also pressed // unicode AND 0x0200 = ctrl also pressed // unicode AND 0x0400 = alt also pressed if(swtch && !release){ if(key % 256==0){ // end program KeyBuddy2::pKB2->Break(); } if(key % 256==7){ // show / hide GUI KeyBuddy2::pKB2->Show(!KeyBuddy2::pKB2->IsShown()); return; } *(KeyBuddy2::pSwitch[key % 256])=!*(KeyBuddy2::pSwitch[key % 256]); return; } if((onlyDown || onlyUp) && release){return;} // first release all other keys byte keyboardStateBuffer[256]; byte allUp[256]; DWORD unused; memset(keyboardStateBuffer,0,256); memset(allUp,0,256); long myThread=GetWindowThreadProcessId(KeyBuddy2::pKB2->GetHWND(),&unused); long otherThread=GetWindowThreadProcessId(GetForegroundWindow(),&unused); if(myThread!=otherThread){ AttachThreadInput(otherThread,myThread,true); } GetKeyboardState(keyboardStateBuffer); SetKeyboardState(allUp); // then send the key INPUT in[4]; int iIn=0; for(iIn=0;iIn<4;iIn++){ in[iIn].type=INPUT_KEYBOARD; in[iIn].ki.dwExtraInfo=extraInfo; in[iIn].ki.time=0; in[iIn].ki.wScan=0; in[iIn].ki.dwFlags=0; if(release){in[iIn].ki.dwFlags=KEYEVENTF_KEYUP;} } iIn=0; if(release){ // if we release the buttons, release the key of interest first, then ctrl, alt or shift in[iIn].ki.wVk=key % 256; iIn++; } if(ctrl){ in[iIn].ki.wVk=VK_LCONTROL; iIn++; } if(shift){ in[iIn].ki.wVk=VK_LSHIFT; iIn++; } if(alt){ in[iIn].ki.wVk=VK_LMENU; iIn++; } if(!release){ // if we push the buttons, push ctrl alt shift first, then the key of interest in[iIn].ki.wVk=key % 256; iIn++; } SendInput(iIn,in,sizeof(INPUT)); Sleep(1); // otherwise the other thread does not see the changed keyboard state // revert keyboard to its original state SetKeyboardState(keyboardStateBuffer); if(myThread!=otherThread){ AttachThreadInput(otherThread,myThread,false); } } else{ // only send unicode character INPUT in[1]; in[0].type=INPUT_KEYBOARD; in[0].ki.dwExtraInfo=extraInfo; in[0].ki.wVk=0; in[0].ki.wScan=key; in[0].ki.dwFlags=KEYEVENTF_UNICODE; if(release){in[0].ki.dwFlags=in[0].ki.dwFlags | KEYEVENTF_KEYUP;} SendInput(1,in,sizeof(INPUT)); } } void KeyBuddy2::releaseAllKeys(){ BYTE zeros[256]={0}; SetKeyboardState(zeros); for(int i=0;i<256;i++){ keyPressed[i]=false; } } void KeyBuddy2::initKeyButtons(){ int i,j; for(i=0; i<7; i++){ buttonStyle[i] = Button::StyleNormal(); for(j=0;j<4;j++){ buttonStyle[i].look[j] = KB2Images::Get(i); } buttonStyle[i].look[2] = KB2Images::Get(1); buttonStyle[i].pressoffset = Point(0,0); } for(i=0;i<256;i++){ pKeyButton[i]=&but_invis; keyFinger[i]=0; } but_invis.Hide(); #include "keybuttons.inc" int bfid=buttonFont.FindFaceNameIndex("unifont"); buttonFont.Face(bfid); buttonFontU.Face(bfid); buttonFontU.Underline(); smallButtonFont.Face(bfid); buttonFont.Height(32); buttonFontU.Height(32); smallButtonFont.Height(16); for(i=0;i<256;i++){ pKeyButton[i]->SetStyle(buttonStyle[keyFinger[i]]); if(i==VK_MOD_31 || i==VK_MOD_32 || i==VK_MOD_41 || i==VK_MOD_42 || i==VK_LMENU || i==VK_LCONTROL || i==VK_RCONTROL){ pKeyButton[i]->SetFont(smallButtonFont); } else{ if(i==VK_A || i==VK_S || i==VK_D || i==VK_F || i==VK_J || i==VK_K || i==VK_L || i==VK_OE){ pKeyButton[i]->SetFont(buttonFontU); } else{ pKeyButton[i]->SetFont(buttonFont); } } pKeyButton[i]->SetLabel(ToUtf8(buttonLabel(i))); //pKeyButton[i]->Disable(); } } void KeyBuddy2::drawKeyButtons(){ int i; String newLabel,oldLabel; for(i=0;i<256;i++){ newLabel=ToUtf8(buttonLabel(i)); oldLabel=pKeyButton[i]->GetLabel(); if(!newLabel.IsEqual(oldLabel)){ if(!pKeyButton[i]->isPushed()){ pKeyButton[i]->SetLabel(newLabel); } else{ pKeyButton[i]->simUp(); pKeyButton[i]->SetLabel(newLabel); pKeyButton[i]->simDown(); } } } } wchar KeyBuddy2::upperCase(wchar letter){ int a=0,b=1022,c; while(a<=b){ c=(a+b)/2; if( letter< upperCaseMap[c][0] ){b=c-1; continue;} if( letter> upperCaseMap[c][0] ){a=c+1; continue;} if( letter==upperCaseMap[c][0] ){return upperCaseMap[c][1];} } return letter; } GUI_APP_MAIN { KeyBuddy2().Run(); }