00001 // $Id: keypress.cpp 1361 2006-06-25 16:43:38Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // Implementation of the KeyPress class that encapsulates key presses in camelot. 00099 00100 /* 00101 */ 00102 00103 #include "camtypes.h" 00104 #include "keypress.h" 00105 #include "vkextra.h" 00106 #include "camelot.h" 00107 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "hotkeys.h" 00109 #include "keymsg.h" 00110 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "ctrlhelp.h" 00113 //#include "basebar.h" 00114 //#include "dragmgr.h" 00115 #include "unicdman.h" 00116 00117 DECLARE_SOURCE("$Revision: 1361 $"); 00118 00119 CC_IMPLEMENT_MEMDUMP(KeyPressSysMsg,CC_CLASS_MEMDUMP) 00120 CC_IMPLEMENT_MEMDUMP(KeyPress, CC_CLASS_MEMDUMP) 00121 00122 CC_IMPLEMENT_DYNAMIC(KeyMsg,Msg) 00123 00124 // This will get Camelot to display the filename and linenumber of any memory allocations 00125 // that are not released at program exit 00126 #define new CAM_DEBUG_NEW 00127 00128 struct ExtraUnicode 00129 { 00130 UINT32 VirtKey; 00131 WCHAR Unicode; 00132 } ExtraUnicodes[] = 00133 { 00134 {CAMKEY(F1), CAMELOT_UNICODE_BASE + 0}, 00135 {CAMKEY(F2), CAMELOT_UNICODE_BASE + 1}, 00136 {CAMKEY(F3), CAMELOT_UNICODE_BASE + 2}, 00137 {CAMKEY(F4), CAMELOT_UNICODE_BASE + 3}, 00138 {CAMKEY(F5), CAMELOT_UNICODE_BASE + 4}, 00139 {CAMKEY(F6), CAMELOT_UNICODE_BASE + 5}, 00140 {CAMKEY(F7), CAMELOT_UNICODE_BASE + 6}, 00141 {CAMKEY(F8), CAMELOT_UNICODE_BASE + 7}, 00142 {CAMKEY(F9), CAMELOT_UNICODE_BASE + 8}, 00143 {CAMKEY(F10), CAMELOT_UNICODE_BASE + 9}, 00144 {CAMKEY(F11), CAMELOT_UNICODE_BASE + 10}, 00145 {CAMKEY(F12), CAMELOT_UNICODE_BASE + 11}, 00146 {CAMKEY(F13), CAMELOT_UNICODE_BASE + 12}, 00147 {CAMKEY(F14), CAMELOT_UNICODE_BASE + 13}, 00148 {CAMKEY(F15), CAMELOT_UNICODE_BASE + 14}, 00149 {CAMKEY(F16), CAMELOT_UNICODE_BASE + 15}, 00150 {CAMKEY(F17), CAMELOT_UNICODE_BASE + 16}, 00151 {CAMKEY(F18), CAMELOT_UNICODE_BASE + 17}, 00152 {CAMKEY(F19), CAMELOT_UNICODE_BASE + 18}, 00153 {CAMKEY(F20), CAMELOT_UNICODE_BASE + 19}, 00154 {CAMKEY(F21), CAMELOT_UNICODE_BASE + 20}, 00155 {CAMKEY(F22), CAMELOT_UNICODE_BASE + 21}, 00156 {CAMKEY(F23), CAMELOT_UNICODE_BASE + 22}, 00157 {CAMKEY(F24), CAMELOT_UNICODE_BASE + 23}, 00158 00159 {CAMKEY(SHIFT), CAMELOT_UNICODE_BASE + 24}, 00160 {CAMKEY(CONTROL), CAMELOT_UNICODE_BASE + 25}, 00161 {CAMKEY(MENU), CAMELOT_UNICODE_BASE + 26}, 00162 00163 {CAMKEY(DELETE), CAMELOT_UNICODE_BASE + 28}, 00164 {CAMKEY(NUMPAD_DELETE), CAMELOT_UNICODE_BASE + 28}, 00165 {CAMKEY(INSERT), CAMELOT_UNICODE_BASE + 27}, 00166 {CAMKEY(HOME), CAMELOT_UNICODE_BASE + 29}, 00167 {CAMKEY(END), CAMELOT_UNICODE_BASE + 30}, 00168 {CAMKEY(PRIOR), CAMELOT_UNICODE_BASE + 31}, // Page up 00169 {CAMKEY(NEXT), CAMELOT_UNICODE_BASE + 32}, // Page down 00170 00171 {CAMKEY(LEFT), CAMELOT_UNICODE_BASE + 33}, // Cursor left 00172 {CAMKEY(UP), CAMELOT_UNICODE_BASE + 34}, // Cursor up 00173 {CAMKEY(RIGHT), CAMELOT_UNICODE_BASE + 35}, // Cursor right 00174 {CAMKEY(DOWN), CAMELOT_UNICODE_BASE + 36}, // Cursor down 00175 00176 {CAMKEY(NUMLOCK), CAMELOT_UNICODE_BASE + 37}, 00177 {CAMKEY(SCROLL), CAMELOT_UNICODE_BASE + 38}, 00178 {CAMKEY(CAPITAL), CAMELOT_UNICODE_BASE + 39}, 00179 00180 {CAMKEY(ESCAPE), CAMELOT_UNICODE_BASE + 40}, 00181 {CAMKEY(CANCEL), CAMELOT_UNICODE_BASE + 41}, // Ctrl-break 00182 00183 {CAMKEY(PAUSE), CAMELOT_UNICODE_BASE + 42}, 00184 {CAMKEY(SELECT), CAMELOT_UNICODE_BASE + 43}, 00185 {CAMKEY(EXECUTE), CAMELOT_UNICODE_BASE + 44}, 00186 {CAMKEY(SNAPSHOT), CAMELOT_UNICODE_BASE + 45}, // Print screen 00187 {CAMKEY(HELP), CAMELOT_UNICODE_BASE + 46}, 00188 00189 {CAMKEY(MINUS), CAMELOT_UNICODE_BASE + 47}, // These two are placed in hear so that when you do ctrl+<key> 00190 {CAMKEY(EQUALS), CAMELOT_UNICODE_BASE + 48}, // a unicode value will be generated, allowing the keypress to be made 00191 00192 {CAMKEY(1), CAMELOT_UNICODE_BASE + 49}, 00193 {CAMKEY(2), CAMELOT_UNICODE_BASE + 50}, 00194 {CAMKEY(3), CAMELOT_UNICODE_BASE + 51}, 00195 {CAMKEY(4), CAMELOT_UNICODE_BASE + 52}, 00196 {CAMKEY(5), CAMELOT_UNICODE_BASE + 53}, 00197 00198 {CAMKEY(ADD), CAMELOT_UNICODE_BASE + 54}, 00199 {CAMKEY(SUBTRACT), CAMELOT_UNICODE_BASE + 55}, 00200 00201 {CAMKEY(0), CAMELOT_UNICODE_BASE + 56}, 00202 {CAMKEY(9), CAMELOT_UNICODE_BASE + 57}, 00203 {CAMKEY(8), CAMELOT_UNICODE_BASE + 58}, 00204 {CAMKEY(7), CAMELOT_UNICODE_BASE + 59}, 00205 00206 {CAMKEY(NUMPAD_ADD), _T('+')}, // These are need so we can get unicode version, and 00207 {CAMKEY(NUMPAD_SUBTRACT), _T('-')}, // hence get the hotkey handled 00208 00209 {CAMKEY(CC_NONE), 0} // Marks the end of the list 00210 }; 00211 00212 // The static member vars of KeyPress that will hold the current state of the modifier keys 00213 BOOL KeyPress::AdjustStateLeft = FALSE; 00214 BOOL KeyPress::AdjustStateRight = FALSE; 00215 BOOL KeyPress::ConstrainStateLeft = FALSE; 00216 BOOL KeyPress::ConstrainStateRight = FALSE; 00217 BOOL KeyPress::AlternativeStateLeft = FALSE; 00218 BOOL KeyPress::AlternativeStateRight = FALSE; 00219 BOOL KeyPress::OptionStateLeft = FALSE; 00220 BOOL KeyPress::OptionStateRight = FALSE; 00221 00222 // TRUE if one or more modifier keys changed on the last key event 00223 BOOL KeyPress::fModifierChanged = FALSE; 00224 00225 // Ascii generating vars used with Alt and numerical key presses 00226 INT32 KeyPress::AsciiVal = -1; 00227 BOOL KeyPress::ValidAsciiVal = FALSE; 00228 00229 BYTE KeyPress::LastLeadByte = 0; 00230 00231 // This was done by Tim 00232 // this macro returns TRUE if the machine does not support every key, which means 00233 // WinNT or not, basically 00234 #if WIN32 00235 #define INCOMPLETE_KEYS IsWin32s() 00236 #else 00237 #define INCOMPLETE_KEYS TRUE 00238 #endif 00239 00240 extern void Beep(); 00241 00242 List KeyPress::AdditionalVirtKeys; 00243 UINT32 KeyPressSysMsg::m_LastVirtKey = 0; 00244 00245 /******************************************************************************************** 00246 00247 > KeyPressSysMsg::KeyPressSysMsg(MSG* pMsg) 00248 00249 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00250 Created: 26/8/94 00251 Inputs: pMsg = Ptr to a Windows message block 00252 Outputs: - 00253 Returns: - 00254 Purpose: The constructor. 00255 Creates a key press message object from a raw Windows message block. 00256 A valid KeyPressSysMsg is constructed if the message was one of these: 00257 WM_KEYDOWN 00258 WM_KEYUP 00259 WM_SYSKEYDOWN 00260 WM_SYSKEYUP 00261 WM_CHAR 00262 00263 Errors: If the Windows message is not key-related, then the member function IsValid() 00264 will return FALSE 00265 SeeAlso: KeyPressSysMsg::IsValid 00266 00267 ********************************************************************************************/ 00268 00269 KeyPressSysMsg::KeyPressSysMsg(wxKeyEvent* pMsg) 00270 { 00271 // Assume the message is a key-related one that we want 00272 Valid = TRUE; 00273 00274 // There doesn't seem to be a need to distinguish between WM_KEY and WM_SYSKEY message 00275 // so map them to the same KM message 00276 if( wxEVT_KEY_DOWN == pMsg->GetEventType() ) 00277 { 00278 Message = KM_KEYDOWN; 00279 } 00280 else 00281 if( wxEVT_CHAR == pMsg->GetEventType() ) 00282 { 00283 Message = KM_CHAR; 00284 } 00285 else 00286 if( wxEVT_KEY_UP == pMsg->GetEventType() ) 00287 { 00288 Message = KM_KEYUP; 00289 } 00290 PORTNOTE("other", "Removed Windows IME usage" ) 00291 #ifndef EXCLUDE_FROM_XARALX 00292 case WM_IME_CHAR: 00293 TRACE( _T("IME\n")); 00294 break; 00295 #endif 00296 else 00297 { 00298 // Message was not one we're interested in, so the KeyPressSysMsg object is invalid 00299 Valid = FALSE; 00300 } 00301 00302 if (Valid) 00303 { 00304 // Now we have a valid Windows message to play with. 00305 // Extract the data and store in a more platform-indy way 00306 00307 // Get the virtual key code for the key pressed 00308 VirtKey = pMsg->GetKeyCode(); 00309 00310 // Get the key data flags word 00311 // INT32 KeyData = pMsg->lParam; 00312 00313 // We NEVER want to intercept Alt-Tab events, so filter them out here 00314 // (N.B. This was only ever a problem on Win16 - NT doesn't send us 00315 // Alt-Tab keydown events, only key-ups, which are ignored.) 00316 if ((VirtKey == CAMKEY(TAB)) && KeyPress::IsAlternativePressed()) 00317 { 00318 Valid=FALSE; 00319 return; 00320 } 00321 00322 PORTNOTE("other", "Removed some keypress mangling" ) 00323 #ifndef EXCLUDE_FROM_XARALX 00324 RepeatCount = KeyData & 0xffff; 00325 ScanCode = (KeyData >> 16) & 0xff; 00326 Extended = (KeyData & (1<<24)) != 0; 00327 PrevDown = (KeyData & (1<<30)) != 0; 00328 #else 00329 RepeatCount = 1; 00330 ScanCode = VirtKey; 00331 Extended = VirtKey >= WXK_START; 00332 PrevDown = m_LastVirtKey == VirtKey; 00333 #if FALSE != wxUSE_UNICODE 00334 m_Char = pMsg->GetUnicodeKey(); 00335 TRACEUSER( "jlh92", _T("m_Char = %04x Ext=%d\n"), m_Char, Extended ); 00336 #endif 00337 #endif 00338 // Update the last virtual keycode if not a modifier 00339 switch( VirtKey ) 00340 { 00341 case WXK_SHIFT: 00342 case WXK_ALT: 00343 case WXK_CONTROL: 00344 case WXK_MENU: 00345 // Skip 00346 break; 00347 00348 default: 00349 if( KM_KEYUP == Message ) 00350 m_LastVirtKey = 0; 00351 else 00352 m_LastVirtKey = VirtKey; 00353 break; 00354 } 00355 } 00356 } 00357 00358 /******************************************************************************************** 00359 00360 > BOOL KeyPressSysMsg::IsValid() 00361 00362 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00363 Created: 26/8/94 00364 Inputs: - 00365 Outputs: - 00366 Returns: TRUE if the KeyPressSysMsg object is a valid one. FALSE otherwise 00367 Purpose: Allows you to see if the KeyPressSysMsg was legally constructed. 00368 Errors: - 00369 SeeAlso: KeyPressSysMsg::KeyPressSysMsg 00370 00371 ********************************************************************************************/ 00372 00373 BOOL KeyPressSysMsg::IsValid() 00374 { 00375 return Valid; 00376 } 00377 00378 //------------------------------------------------------------------------------------------- 00379 //------------------------------------------------------------------------------------------- 00380 //------------------------------------------------------------------------------------------- 00381 //------------------------------------------------------------------------------------------- 00382 00383 /******************************************************************************************** 00384 00385 > static BOOL KeyPress::Init() 00386 00387 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00388 Created: 26/8/94 00389 Inputs: - 00390 Outputs: - 00391 Returns: TRUE if initialised correctly 00392 Purpose: Initialises the KeyPress class 00393 Errors: - 00394 SeeAlso: KeyPress::IsValid, KeyPress::GenerateKeyPress 00395 00396 ********************************************************************************************/ 00397 00398 // remove after testing 00399 #include "hotkeys.h" 00400 00401 BOOL KeyPress::Init() 00402 { 00403 return TRUE; 00404 } 00405 00406 00407 00408 /******************************************************************************************** 00409 00410 > static FilePath KeyPress::GetHotKeysFilename() 00411 00412 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00413 Created: 8/Jun/2006 00414 Inputs: - 00415 Outputs: - 00416 Returns: PathName reference to location of hotkeys config file 00417 Purpose: 00418 00419 ********************************************************************************************/ 00420 00421 FilePath KeyPress::GetHotKeysFilename() 00422 { 00423 FilePath result; 00424 00425 wxStandardPaths Paths; 00426 wxString strPath( Paths.GetUserConfigDir() ); 00427 strPath += _T("/.xaralx/hotkeys"); 00428 00429 if (wxFile::Exists(strPath)) 00430 result.SetPathName(strPath, FALSE); 00431 00432 return result; 00433 } 00434 00435 00436 00437 /******************************************************************************************** 00438 > static BOOL KeyPress::DispatchKeyEvent(UINT32 nMsgID, UINT32 nChar, UINT32 nRepCnt, UINT32 nFlags) 00439 00440 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00441 Created: 7/10/94 00442 Inputs: nMsgID the Windows ID of the key message, eg. WM_KEYDOWN 00443 nChar the virtual key code / char value (depending on you believe) 00444 nRepCnt repeat count 00445 nFlags keyboard state flags, eg. key down or up 00446 Outputs: - 00447 Returns: TRUE if the app processed the event. 00448 Purpose: Packages an MFC key-stroke message into a form suitable for the kernel 00449 and calls the keyboard system with the event. 00450 Errors: - 00451 SeeAlso: KeyPress::TranslateMessage 00452 ********************************************************************************************/ 00453 00454 BOOL KeyPress::DispatchKeyEvent(UINT32 nMsgID, UINT32 nChar, UINT32 nRepCnt, UINT32 nFlags) 00455 { 00456 // Make sure the kernel knows which view/doc the event applies to, if any. 00457 if (Document::GetSelected() != NULL) Document::GetSelected()->SetCurrent(); 00458 if (DocView::GetSelected() != NULL) DocView::GetSelected()->SetCurrent(); 00459 00460 PORTNOTETRACE("other,", "BaseTextClass::PreOpProcessing - do nothing" ); 00461 #ifndef EXCLUDE_FROM_XARALX 00462 // For compatibility with existing code we must repackage the unpacked message. 00463 // NB. the RHS of the lParam expression will work for Win16 as well. 00464 MSG msg; 00465 msg.message = nMsgID; 00466 msg.wParam = nChar; 00467 msg.lParam = (nRepCnt & 0xFFFF) | ((((LPARAM) nFlags) & 0xFFFF) << 16); 00468 00469 // Call the key-press system. 00470 return TranslateMessage(&msg); 00471 #else 00472 return true; 00473 #endif 00474 } 00475 00476 00477 00478 /******************************************************************************************** 00479 00480 > KeyPress::KeyPress() 00481 00482 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00483 Created: 24/8/94 00484 Inputs: - 00485 Outputs: - 00486 Returns: - 00487 Purpose: Default constructor. 00488 Creates an invalid keypress object. The KeyPress class will have one or more public 00489 constructors or static member functions for creating valid KeyPress objects. 00490 Errors: - 00491 SeeAlso: KeyPress::IsValid, KeyPress::GenerateKeyPress 00492 00493 ********************************************************************************************/ 00494 00495 KeyPress::KeyPress() 00496 { 00497 Initialise(); 00498 } 00499 00500 /******************************************************************************************** 00501 00502 > KeyPress::KeyPress(KeyPressSysMsg* pKeySysMsg,WCHAR UnicodeChar) 00503 00504 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00505 Created: 26/8/94 00506 Inputs: pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message 00507 UnicodeChar = The Unicode char this key press should have 00508 Outputs: - 00509 Returns: - 00510 Purpose: Constructs a KeyPress object from the given parameters 00511 Errors: - 00512 SeeAlso: KeyPress::IsValid, KeyPress::GenerateKeyPress 00513 00514 ********************************************************************************************/ 00515 00516 KeyPress::KeyPress(KeyPressSysMsg* pKeySysMsg,WCHAR UnicodeChar) 00517 { 00518 VirtKey = pKeySysMsg->VirtKey; 00519 Unicode = UnicodeChar; 00520 00521 Adjust = KeyPress::AdjustStateLeft | KeyPress::AdjustStateRight; 00522 Constrain = KeyPress::ConstrainStateLeft | KeyPress::ConstrainStateRight; 00523 Alternative = KeyPress::AlternativeStateLeft | KeyPress::AlternativeStateRight; 00524 Option = KeyPress::OptionStateLeft | KeyPress::OptionStateRight; 00525 00526 Extended = pKeySysMsg->Extended; 00527 00528 // Interpret Alt+Ctrl as Extended Alt, because AltGr (UK right hand Alt) produces an additional 00529 // Ctrl key press that is indistinguishable from a left hand Ctrl. 00530 // This means that left hand Alt+Ctrl will appear the same as right hand AltGr to Camelot. 00531 // E.g. Alt+Ctrl+Spacebar == AltGr+Spacebar 00532 if (Alternative && Constrain) 00533 { 00534 Extended = TRUE; 00535 Constrain = FALSE; 00536 } 00537 00538 Repeat = pKeySysMsg->PrevDown; 00539 RightHand = pKeySysMsg->Extended; 00540 Release = (pKeySysMsg->Message == KM_KEYUP); 00541 m_fIsChar = (pKeySysMsg->Message == KM_CHAR); 00542 00543 Valid = TRUE; // This is now a valid KeyPress object. 00544 } 00545 00546 /******************************************************************************************** 00547 00548 > KeyPress::KeyPress( UINT32 ThisVirtKey, 00549 BOOL PlusAdjust = FALSE, 00550 BOOL PlusConstrain = FALSE, 00551 BOOL PlusAlternative = FALSE, 00552 BOOL ExtendedKey = FALSE) 00553 00554 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00555 Created: 30/8/94 00556 Inputs: ThisVirtKey = The virtual key code of the key you want to use 00557 PlusAdjust = TRUE if the key should be modified by the Adjust key 00558 PlusConstrain = TRUE if the key should be modified by the Constrain key 00559 PlusAlternative = TRUE if the key should be modified by the Alternative key 00560 ExtendedKey = TRUE if you are specifying an extended key (e.g. "Enter" key instead of "Return") 00561 WorksInDragsKey = TRUE if you want this keypress to work in the middle of drags. 00562 Outputs: - 00563 Returns: - 00564 Purpose: Constructs a KeyPress object from the given parameters 00565 This constructor is for use by systems that deal with "hot keys", i.e. ones that are only 00566 interested in the physical key that is being pressed 00567 Errors: - 00568 SeeAlso: KeyPress::IsValid, KeyPress::GenerateKeyPress 00569 00570 ********************************************************************************************/ 00571 00572 KeyPress::KeyPress(UINT32 ThisVirtKey, BOOL PlusAdjust, BOOL PlusConstrain, BOOL PlusAlternative, BOOL ExtendedKey, 00573 BOOL WorksInDragsKey) 00574 { 00575 Initialise(); 00576 00577 VirtKey = ThisVirtKey; 00578 Adjust = PlusAdjust; 00579 Constrain = PlusConstrain; 00580 Alternative = PlusAlternative; 00581 Extended = ExtendedKey; 00582 WorksInDrag = WorksInDragsKey; 00583 Valid = TRUE; 00584 } 00585 00586 00587 00588 /******************************************************************************************** 00589 00590 > static KeyPress* ConstructVK(TCHAR ch); 00591 00592 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00593 Created: 11/10/95 00594 Inputs: ch - ASCII/Unicode value of required keypress 00595 Outputs: - 00596 Returns: - 00597 Purpose: Constructs a keypress that represents the keypress required to generate the 00598 specified character. The Virtual Code will be CAMKEY(CC_NONE) if the key cannot 00599 be generated 00600 Errors: - 00601 SeeAlso: - 00602 00603 ********************************************************************************************/ 00604 KeyPress* KeyPress::ConstructVK(TCHAR ch) 00605 { 00606 // PORTNOTETRACE( "other", "KeyPress::ConstructVK - do nothing" ); 00607 KeyPress* pNew = new KeyPress(); 00608 00609 #if !defined(EXCLUDE_FROM_XARALX) 00610 if (pNew != NULL) 00611 { 00612 INT8 Result = ::VkKeyScan(ch); 00613 BYTE LowByte = Result & 0xFF; 00614 BYTE HighByte = (Result >> 8) & 0xFF; 00615 00616 if ((HighByte == 0xFF) && (LowByte == 0xFF)) 00617 { 00618 pNew->VirtKey = CAMKEY(CC_NONE); 00619 } 00620 else 00621 { 00622 pNew->VirtKey = LowByte; 00623 pNew->Adjust = HighByte & 1; 00624 pNew->Constrain = HighByte & 2; 00625 pNew->Alternative = HighByte & 4; 00626 } 00627 } 00628 #endif 00629 00630 return pNew; 00631 } 00632 00633 00634 00635 /******************************************************************************************** 00636 00637 > KeyPress::Initialise() 00638 00639 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 00640 Created: 11/10/96 00641 Inputs: - 00642 Outputs: See below 00643 Returns: - 00644 Purpose: Initialises all member variables of the KeyPress object to sensible values 00645 Errors: - 00646 SeeAlso: KeyPress constructors 00647 00648 ********************************************************************************************/ 00649 void KeyPress::Initialise() 00650 { 00651 // Some highly unlikely Unicode char 00652 Unicode = 0xffff; 00653 00654 // A highly unlikely virtual key 00655 VirtKey = CAMKEY(CC_NONE); 00656 00657 // Set all the flags to FALSE 00658 Adjust = FALSE; 00659 Constrain = FALSE; 00660 Alternative = FALSE; 00661 Option = FALSE; 00662 00663 Extended = FALSE; 00664 00665 Repeat = FALSE; 00666 RightHand = FALSE; 00667 Release = FALSE; 00668 m_fIsChar = FALSE; 00669 00670 // This is an invalid KeyPress object at the moment 00671 Valid = FALSE; 00672 } 00673 00674 00675 00676 /******************************************************************************************** 00677 00678 > BOOL KeyPress::IsValid() 00679 00680 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00681 Created: 26/8/94 00682 Inputs: - 00683 Outputs: - 00684 Returns: TRUE if the KeyPress object is a valid one. FALSE otherwise 00685 Purpose: Allows you to see if the KeyPress is legal. 00686 The default KeyPress constuctor will always create invalid instances. It is up 00687 to other constructors, or member functions, to generate valid ones 00688 Errors: - 00689 SeeAlso: KeyPress::KeyPress, KeyPress::GenerateKeyPress 00690 00691 ********************************************************************************************/ 00692 00693 BOOL KeyPress::IsValid() 00694 { 00695 return Valid; 00696 } 00697 00698 /******************************************************************************************** 00699 00700 > static BOOL KeyPress::IsModifier(UINT32 VirtKey) 00701 00702 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00703 Created: 26/8/94 00704 Inputs: VirtKey = A Windows virtual key code 00705 Outputs: - 00706 Returns: TRUE if the key is one of the modifier keys 00707 FALSE otherwise 00708 Purpose: Central modifier key identifying routine. 00709 The modifiers are as follows : 00710 Both Alt keys 00711 Both Shift keys 00712 Both Ctrl keys 00713 Errors: - 00714 SeeAlso: - 00715 00716 ********************************************************************************************/ 00717 00718 BOOL KeyPress::IsModifier(UINT32 VirtKey) 00719 { 00720 return (VirtKey == CAMKEY(CC_MOD_ADJUST) || VirtKey == WXK_CC_MOD_CONSTRAIN || VirtKey == WXK_CC_MOD_ALTERNATIVE); 00721 } 00722 00723 /******************************************************************************************** 00724 00725 > static INT32 KeyPress::GenerateUnicode(UINT32 VirtKey,UINT32 ScanCode,BYTE* pKeyState,WCHAR* pWideCharBuf,INT32 WideCharBufSize) 00726 00727 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00728 Created: 25/8/94 00729 Inputs: VirtKey = a Windows virtual key code 00730 ScanCode = the scan code generated by the keyboard 00731 pKeyState = 256 byte array filled with the current keyboard state via GetKeyboardState 00732 pWideCharBuf = buffer to stick the Unicode char(s) into 00733 WideCharBufSize = the size of the wide char buffer (min value of 2) 00734 Outputs: pWideCharBuf will contain 1 WCHAR at index [0] 00735 Returns: The number of Unicode chars generated (see the Windows ToUnicode() function) 00736 Purpose: Converts a virtual key code into a Unicode char. 00737 This is a layer on top of the Windows ToUnicode() function that will generate Unicodes in the 00738 corporate user zone for keys that do not have a standard Unicode evivalent (e.g. function keys) 00739 00740 If the internal call to ToUnicode() fails, but the VirtKey is an alphabetic key, a Unicode code is 00741 generated that is equivalent to pressing Ctrl+<alphabetic key>, e.g. Ctrl+A = 1, Ctrl+B = 2. 00742 This happens when you press Ctrl+Alt+<alphabetic key>, which is only really used by the hot key system, 00743 so therefore the actual unicode code is not significant (correct at time of writing - Markn 11/1/95) 00744 Errors: - 00745 SeeAlso: KeyPress::IsValid 00746 00747 ********************************************************************************************/ 00748 00749 INT32 KeyPress::GenerateUnicode(UINT32 VirtKey,UINT32 ScanCode,BYTE* pKeyState,WCHAR* pWideCharBuf,UINT32 WideCharBufSize) 00750 { 00751 #if defined(__WXMSW__) 00752 // Make sure we have a buffer to use 00753 ENSURE(WideCharBufSize >= 2,"The wide char buffer size should be at least 2"); 00754 if (WideCharBufSize < 2) return 0; 00755 00756 INT32 NumChars = ToUnicode(VirtKey,ScanCode,pKeyState,pWideCharBuf,WideCharBufSize,0); 00757 00758 // NumChars == 0 if ToUnicode() failed to generate a code for the keypress 00759 00760 // If no direct eqivalent Unicode char, see if we can generate one with the ASCII value for the VirtKey 00761 // or look one up in our extra Unicode table 00762 if (NumChars == 0) 00763 { 00764 WORD pWordBuf[10]; 00765 00766 // See if ToAscii() can make a Latin I ASCII char out of it 00767 INT32 NumASCIIChars = ToAscii(VirtKey,ScanCode,pKeyState,pWordBuf,0); 00768 00769 if (NumASCIIChars == 1) 00770 { 00771 // Map the lower byte ASCII value onto the equivalent Unicode char 00772 pWideCharBuf[0] = pWordBuf[0] & 0xff; 00773 NumChars = 1; 00774 } 00775 } 00776 00777 if (NumChars == 0) 00778 { 00779 // ToAscii() failed, so lets have a look in our table 00780 00781 INT32 i=0; 00782 BOOL finished = FALSE; 00783 00784 do 00785 { 00786 // We've finished if we've reached the ungeneratable VK code 00787 finished = (ExtraUnicodes[i].VirtKey == CAMKEY(CC_NONE)); 00788 00789 if (!finished && ExtraUnicodes[i].VirtKey == VirtKey) 00790 { 00791 // We have found an entry in our table for the given virtual key 00792 00793 // Stuff the Unicode value into the buffer and set the num chars generated to 1 00794 pWideCharBuf[0] = ExtraUnicodes[i].Unicode; 00795 NumChars = 1; 00796 finished = TRUE; 00797 } 00798 i++; 00799 } while (!finished); 00800 00801 // Check the runtime list too 00802 if (NumChars != 1) 00803 { 00804 finished = FALSE; 00805 AdditionalVirtKey* pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetHead(); 00806 while (!finished && (pKey != NULL)) 00807 { 00808 if (pKey->VirtualKeyCode == VirtKey) 00809 { 00810 pWideCharBuf[0] = pKey->UnicodeValue; 00811 NumChars = 1; 00812 finished = TRUE; 00813 } 00814 00815 pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetNext(pKey); 00816 } 00817 } 00818 } 00819 00820 if (NumChars == 0) 00821 { 00822 // If the virt key is obviously one that should be handled (i.e. an alphabetical key), 00823 // we automatically generate a code. 00824 // This Unicode code will be the same as the one generated by Ctrl+<alphabetical key> 00825 // 00826 // "Why do we need this?" I hear you scream. This is because ToUnicode() fails when you do a 00827 // Ctrl+Alt+<key>. As this is an important modifier combo used by the hot key system, we need to make it work. 00828 // 00829 // Markn - 11/1/95 00830 00831 if (VirtKey >= 'A' && VirtKey <= 'Z') 00832 { 00833 pWideCharBuf[0] = VirtKey - 'A'; 00834 NumChars = 1; 00835 } 00836 } 00837 00838 #ifdef _DEBUG 00839 /* 00840 if (IsUserName("MarkN") && (NumChars == 0)) 00841 { 00842 Beep(); 00843 TRACE( _T("\n***\nVirtKey %lx has no Unicode equivalent!\n***\n"),VirtKey); 00844 } 00845 */ 00846 #endif 00847 00848 // Return the number of Unicode chars that have been dumped into the buffer 00849 return NumChars; 00850 #else 00851 return 0; 00852 #endif 00853 } 00854 00855 00856 /******************************************************************************************** 00857 00858 > static BOOL KeyPress::IgnoreKeyMessage(KeyPressSysMsg* pKeySysMsg) 00859 00860 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00861 Created: 25/8/94 00862 Inputs: pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message 00863 Outputs: - 00864 Returns: TRUE if the key press message should be ignored 00865 FALSE if the key press message should be processed 00866 Purpose: This filters out any invalid key messages that we may get from Windows, such as 00867 auto-repeated modifier (shift, ctrl, alt) keys. 00868 Errors: - 00869 SeeAlso: KeyPress::GenerateKeyPress 00870 00871 ********************************************************************************************/ 00872 00873 BOOL KeyPress::IgnoreKeyMessage(KeyPressSysMsg* pKeySysMsg) 00874 { 00875 // PORTNOTETRACE( "other", "KeyPress::IgnoreKeyMessage - do nothing" ); 00876 00877 ENSURE(pKeySysMsg->IsValid(),"Invalid KeyPressSysMsg given"); 00878 00879 // Ignore if it's a key down msg, and the key is a modifier, and it's an auto-repeat message 00880 BOOL Ignore = (pKeySysMsg->Message == KM_KEYDOWN && KeyPress::IsModifier(pKeySysMsg->VirtKey) && pKeySysMsg->PrevDown); 00881 00882 #if !defined(EXCLUDE_FROM_XARALX) 00883 KeyPress* pNew = new KeyPress(); 00884 if (UnicodeManager::IsDBCSOS()) 00885 { 00886 // handling for DBCS characters; they roll up as two sepearte WM_CHAR messages 00887 if (!Ignore && pKeySysMsg->Message==KM_CHAR) 00888 { 00889 if (LastLeadByte==0 && IsDBCSLeadByte(pKeySysMsg->VirtKey)) 00890 { 00891 // It's a lead byte so store it away for the next message and ignore this one 00892 TRACE( _T("Lead byte %d\n"), pKeySysMsg->VirtKey); 00893 LastLeadByte = pKeySysMsg->VirtKey; 00894 Ignore = TRUE; 00895 } 00896 } 00897 } 00898 #endif 00899 00900 return Ignore; 00901 } 00902 00903 /******************************************************************************************** 00904 00905 > static void KeyPress::UpdateModifierStatus(KeyPressSysMsg* pKeySysMsg) 00906 00907 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00908 Created: 26/8/94 00909 Inputs: pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message 00910 Outputs: - 00911 Returns: - 00912 Purpose: If the message is a modifier key press, the static status vars for the modifier keys 00913 in the KeyPress class are updated. 00914 Errors: - 00915 SeeAlso: KeyPress::GenerateKeyPress 00916 00917 ********************************************************************************************/ 00918 00919 void KeyPress::UpdateModifierStatus(KeyPressSysMsg* pKeySysMsg) 00920 { 00921 ENSURE(pKeySysMsg->IsValid(),"Invalid KeyPressSysMsg given"); 00922 00923 // pKeySysMsg is not used at the moment 00924 // The modifier key state is read via GetKeyState() 00925 00926 BOOL AdjL = KeyPress::AdjustStateLeft; BOOL AdjR = KeyPress::AdjustStateRight; 00927 BOOL ConL = KeyPress::ConstrainStateLeft; BOOL ConR = KeyPress::ConstrainStateRight; 00928 BOOL AltL = KeyPress::AlternativeStateLeft; BOOL AltR = KeyPress::AlternativeStateRight; 00929 BOOL OptL = KeyPress::OptionStateLeft; BOOL OptR = KeyPress::OptionStateRight; 00930 00931 KeyPress::AdjustStateLeft = wxGetKeyState(CAMKEY(CC_MOD_ADJUST)); 00932 KeyPress::AdjustStateRight = KeyPress::AdjustStateLeft; 00933 00934 KeyPress::ConstrainStateLeft = wxGetKeyState(CAMKEY(CC_MOD_CONSTRAIN)); 00935 KeyPress::ConstrainStateRight = KeyPress::ConstrainStateLeft; 00936 00937 KeyPress::AlternativeStateLeft = wxGetKeyState(CAMKEY(CC_MOD_ALTERNATIVE)); 00938 KeyPress::AlternativeStateRight = KeyPress::AlternativeStateLeft; 00939 00940 KeyPress::OptionStateLeft = FALSE; 00941 KeyPress::OptionStateRight = FALSE; 00942 00943 KeyPress::fModifierChanged =(AdjL != KeyPress::AdjustStateLeft) || (AdjR != KeyPress::AdjustStateRight) || 00944 (ConL != KeyPress::ConstrainStateLeft) || (ConR != KeyPress::ConstrainStateRight) || 00945 (AltL != KeyPress::AlternativeStateLeft)|| (AltR != KeyPress::AlternativeStateRight)|| 00946 (OptL != KeyPress::OptionStateLeft) || (OptR != KeyPress::OptionStateRight); 00947 } 00948 00949 /******************************************************************************************** 00950 00951 > static KeyPress* KeyPress::MakeKeyPress(KeyPressSysMsg* pKeySysMsg) 00952 00953 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 00954 Created: 26/8/94 00955 Inputs: pKeySysMsg = Ptr to a platform indepenent version of a Windows key press message 00956 Outputs: - 00957 Returns: Ptr to a valid KeyPress object 00958 OR NULL if not enough memory 00959 Purpose: Makes a KeyPress from a KeyPressSysMsg. 00960 Errors: - 00961 SeeAlso: KeyPress::GenerateKeyPress,KeyPress::GenerateUnicode 00962 00963 ********************************************************************************************/ 00964 00965 KeyPress* KeyPress::MakeKeyPress(KeyPressSysMsg* pKeySysMsg) 00966 { 00967 // PORTNOTETRACE( "other", "KeyPress::MakeKeyPress - do nothing" ); 00968 KeyPress* pKeyPress = NULL; // This will point to the key press object 00969 00970 // Try and get a Unicode char to represent the key press 00971 WCHAR pWideChar[10]; 00972 INT32 NumChars = 0; 00973 00974 if (pKeySysMsg->Message == KM_CHAR) 00975 { 00976 #if FALSE != wxUSE_UNICODE 00977 NumChars = 1; 00978 pWideChar[0] = pKeySysMsg->m_Char; 00979 00980 TRACEUSER( "jlh92", _T("Unicode = %c\n"), pKeySysMsg->m_Char ); 00981 #else 00982 // If the message is a CHAR message, then we need to generate a Unicode value ourselves 00983 // using the char code (which is stored in the VirtKey field of the KeyPressSysMsg class) 00984 // 00985 // These codes are generated by holding down Alt and typing the ASCII value of a character 00986 // on the numerical key pad. The Virt key codes generated when doing this fail to produce 00987 // Uncode chars, so the key presses never get passed on. However, if after this sequence an 00988 // ASCII char is specified (e.g. 'A' via Alt+ '6' '5') a WM_CHAR message is posted, so we need 00989 // to trap this and pass the Unicode equivalent of the ASCII char onto Camelot. 00990 // 00991 // The fake VirtKey code (CAMKEY(CC_NONE)) is specified so that the receiver of this key message 00992 // will not process it on the VirtKey code. However, anyone interested in just the Unicode 00993 // value (e.g. the text tool) will process it successfully. 00994 00995 TRACE( _T("Trail byte %d\n"), pKeySysMsg->VirtKey); 00996 00997 char pants[3]; 00998 00999 if (UnicodeManager::IsDBCSOS()) 01000 { 01001 // See if we have a lead byte 01002 if (LastLeadByte != 0) 01003 { 01004 pants[0] = LastLeadByte; 01005 pants[1] = pKeySysMsg->VirtKey; 01006 pants[2] = 0; 01007 pWideChar[0] = UnicodeManager::MultiByteToUnicode(UnicodeManager::ComposeMultiBytes(LastLeadByte, pKeySysMsg->VirtKey)); 01008 } 01009 else 01010 { 01011 pants[0] = pKeySysMsg->VirtKey; 01012 pants[1] = 0; 01013 pWideChar[0] = pKeySysMsg->VirtKey; 01014 } 01015 LastLeadByte = 0; 01016 } 01017 else 01018 { 01019 pants[0] = pKeySysMsg->VirtKey; 01020 pants[1] = 0; 01021 pWideChar[0] = pKeySysMsg->VirtKey; 01022 } 01023 01024 TRACE( _T("Entered character %s\n"),pants); 01025 TRACE( _T("Unicode value = %X\n"),pWideChar[0]); 01026 01027 pKeySysMsg->VirtKey = CAMKEY(CC_NONE); 01028 NumChars = 1; 01029 #endif 01030 } 01031 else 01032 { 01033 #if FALSE != wxUSE_UNICODE 01034 NumChars = 1; 01035 pWideChar[0] = pKeySysMsg->m_Char; 01036 01037 // We still have to try our custom translations (for VirtKey >= WXK_START) 01038 if( pKeySysMsg->VirtKey >= WXK_START ) 01039 { 01040 INT32 i; 01041 for( i = 0; ExtraUnicodes[i].VirtKey != CAMKEY(CC_NONE); ++i ) 01042 { 01043 // We have found an entry in our table for the given virtual key 01044 if( ExtraUnicodes[i].VirtKey == pKeySysMsg->VirtKey ) 01045 { 01046 // Stuff the Unicode value into the buffer and set the num chars generated to 1 01047 pWideChar[0] = ExtraUnicodes[i].Unicode; 01048 break; 01049 } 01050 } 01051 01052 // Don't pass on unknown function keys 01053 if( ExtraUnicodes[i].VirtKey == CAMKEY(CC_NONE) ) 01054 NumChars = 0; 01055 } 01056 01057 // Windows translates Ctrl+char to control codes, I don't think we need too. Hopefully 01058 // just using CR will be enought. 01059 if( IsConstrainPressed() ) 01060 pWideChar[0] = _T('\n'); 01061 01062 #elif defined(__WXMSW__) 01063 BYTE pKeyState[256]; // Array to hold the current state of the keyboard 01064 if (GetKeyboardState(pKeyState)) // Scan the current keyboard state 01065 { 01066 NumChars = GenerateUnicode( pKeySysMsg->VirtKey, pKeySysMsg->ScanCode, pKeyState, pWideChar, 10 ); 01067 } 01068 #else 01069 // This should never happen, but just in case we'll use a dumb implementation 01070 NumChars = 1; 01071 mbtowc( pWideChar, pKeySysMsg->VirtKey ); 01072 #endif 01073 } 01074 01075 if (NumChars == 1) // Make a KeyPress object if we have a valid associated Unicode character 01076 { 01077 // Construct a KeyPress object 01078 pKeyPress = new KeyPress(pKeySysMsg,pWideChar[0]); 01079 01080 // If we make an invalid one, delete it and make sure we return NULL 01081 if (pKeyPress != NULL && !pKeyPress->IsValid()) 01082 { 01083 delete pKeyPress; 01084 pKeyPress = NULL; 01085 } 01086 } 01087 01088 return pKeyPress; 01089 } 01090 01091 /******************************************************************************************** 01092 01093 > static BOOL KeyPress::GenerateKeyPress(MSG* pMsg,KeyPress** ppKeyPress) 01094 01095 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01096 Created: 24/8/94 01097 Inputs: pMsg = A Windows message 01098 Outputs: *ppKeyPress = ptr to the generated KeyPress object, or NULL if not enough memory 01099 Returns: TRUE if the message was to do with a key press. 01100 FALSE if the message wasn't to do with the keyboard at all & *ppKeyPress is unspecified 01101 Purpose: Generates a legal, platform-independent key press object from the raw platform-dependent 01102 data provided. 01103 Errors: If the virtual key code doesn't have an equivalent Unicode value (either standard, or one that 01104 we have allocated to it), then KeyPress::IsValid() will return FALSE. 01105 SeeAlso: KeyPress::IsValid 01106 01107 ********************************************************************************************/ 01108 01109 BOOL KeyPress::GenerateKeyPress(wxKeyEvent* pMsg,KeyPress** ppKeyPress) 01110 { 01111 // Ensure *ppKeyPress is valid, just in case we have to exit the function early 01112 *ppKeyPress = NULL; 01113 01114 // Create a platform-indy key press message object 01115 KeyPressSysMsg KeySysMsg(pMsg); 01116 01117 if (KeySysMsg.IsValid()) 01118 { 01119 // If it's a key press message that we can ignore, then ignore it, pretending we have processed it 01120 01121 if (!IgnoreKeyMessage(&KeySysMsg)) 01122 { 01123 // We like the look of this key press event 01124 01125 // Ensure the modifier key states are up to date 01126 UpdateModifierStatus(&KeySysMsg); 01127 01128 // Make a KeyPress object 01129 *ppKeyPress = MakeKeyPress(&KeySysMsg); 01130 01131 // If the mods have changed, and we were able to make a keypress object, send 01132 // a "modifiers have changed message" 01133 if (KeyPress::fModifierChanged && *ppKeyPress != NULL) 01134 { 01135 BROADCAST_TO_ALL(KeyMsg(KeyMsg::MODIFIERCHANGED,*ppKeyPress)); 01136 } 01137 } 01138 01139 #ifdef _DEBUG 01140 /* 01141 if (*ppKeyPress != NULL) 01142 { 01143 char s[1000]; 01144 _stprintf(s,"Mess = %d, Virtkey = 0x%lx, Ext = %d, PrevD = %d, Shift = %d, Ctrl = %d, Alt = %d, AShift = 0x%x, ACtrl = 0x%x, AAlt = 0x%x, IsAd = %d, IsCon = %d, IsAlt = %d", 01145 KeySysMsg.Message, 01146 KeySysMsg.VirtKey, 01147 KeySysMsg.Extended, 01148 KeySysMsg.PrevDown, 01149 KeyPress::AdjustStateLeft | KeyPress::AdjustStateRight, 01150 KeyPress::ConstrainStateLeft | KeyPress::ConstrainStateRight, 01151 KeyPress::AlternativeStateLeft | KeyPress::AlternativeStateRight, 01152 AsyncShift, 01153 AsyncCtrl, 01154 AsyncAlt, 01155 (*ppKeyPress)->IsAdjust(), 01156 (*ppKeyPress)->IsConstrain(), 01157 (*ppKeyPress)->IsAlternative() 01158 ); 01159 ENSURE(FALSE,s); 01160 } 01161 */ 01162 //DumpKeyMessage(pMsg); 01163 01164 #endif // _DEBUG 01165 01166 // Return TRUE to say that it really was a keyboard message 01167 return TRUE; 01168 } 01169 else 01170 return FALSE; // Not a keybaord type event that we're interested in 01171 } 01172 01173 01174 /******************************************************************************************** 01175 01176 > static void KeyPress::ResetModifiers() 01177 01178 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Equivalent to Tim's ResetModifierKeys() routine) 01179 Created: 26/08/94 01180 Purpose: Maintain integrity of our key modifier status. Win32S doesn't always 01181 tell us what key events have occured - notably when the user uses Alt-TAB 01182 to switch tasks. Hence this gets called whenever our main window is 01183 deactivated or activated. The temporary tool is updated if required. 01184 SeeAlso: UpdateTemporaryTool 01185 01186 ********************************************************************************************/ 01187 01188 void KeyPress::ResetModifierKeys() 01189 { 01190 //ENSURE(FALSE,"KeyPress::ResetModifierKeys() called"); 01191 01192 // We can't trust Win32S to tell us about all keypreses we need to know about, 01193 // so set all modifiers to ff to avoid weird effects. 01194 if (INCOMPLETE_KEYS) 01195 { 01196 KeyPress::AdjustStateLeft = FALSE; 01197 KeyPress::AdjustStateRight = FALSE; 01198 KeyPress::ConstrainStateLeft = FALSE; 01199 KeyPress::ConstrainStateRight = FALSE; 01200 KeyPress::AlternativeStateLeft = FALSE; 01201 KeyPress::AlternativeStateRight = FALSE; 01202 KeyPress::OptionStateLeft = FALSE; 01203 KeyPress::OptionStateRight = FALSE; 01204 } 01205 01206 // Temporary tool may have changed - update it. 01207 //UpdateTemporaryTool(); 01208 } 01209 01210 01211 01212 /******************************************************************************************** 01213 > static BOOL KeyPress::IsAdjustPressed() 01214 01215 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01216 Created: 1/12/94 01217 Inputs: - 01218 Outputs: - 01219 Returns: TRUE if the "Adjust" key is currently depressed. 01220 Purpose: Tests status of the "Adjust" key. 01221 Errors: - 01222 SeeAlso: - 01223 ********************************************************************************************/ 01224 01225 BOOL KeyPress::IsAdjustPressed() 01226 { 01227 return ::wxGetKeyState(CAMKEY(CC_MOD_ADJUST)); 01228 } 01229 01230 01231 01232 /******************************************************************************************** 01233 > static BOOL KeyPress::IsConstrainPressed() 01234 01235 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01236 Created: 1/12/94 01237 Inputs: - 01238 Outputs: - 01239 Returns: TRUE if the "Constrain" key is down. 01240 Purpose: Tests status of the "Constrain" key. 01241 Errors: - 01242 SeeAlso: - 01243 ********************************************************************************************/ 01244 01245 BOOL KeyPress::IsConstrainPressed() 01246 { 01247 return ::wxGetKeyState(CAMKEY(CC_MOD_CONSTRAIN)); 01248 } 01249 01250 01251 01252 /******************************************************************************************** 01253 > static BOOL KeyPress::IsAlternativePressed() 01254 01255 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01256 Created: 1/12/94 01257 Inputs: - 01258 Outputs: - 01259 Returns: TRUE if the "Alternative" key is down. 01260 Purpose: Tests status of the "Alternative" key. 01261 Errors: - 01262 SeeAlso: - 01263 ********************************************************************************************/ 01264 01265 BOOL KeyPress::IsAlternativePressed() 01266 { 01267 return ::wxGetKeyState(CAMKEY(CC_MOD_ALTERNATIVE)); 01268 } 01269 01270 /******************************************************************************************** 01271 > static BOOL KeyPress::IsKeyPressed(UINT32 VirtKey) 01272 01273 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01274 Created: 26/7/94 01275 Inputs: VirtKey = key to check 01276 Outputs: - 01277 Returns: TRUE if the VirtKey key is down. 01278 Purpose: General async keypress func call. 01279 Errors: - 01280 SeeAlso: - 01281 ********************************************************************************************/ 01282 01283 BOOL KeyPress::IsKeyPressed(UINT32 VirtKey) 01284 { 01285 return ::wxGetKeyState( wxKeyCode(VirtKey) ); 01286 } 01287 01288 01289 /******************************************************************************************** 01290 01291 > static BOOL KeyPress::IsGalleryShiftPressed(void) 01292 01293 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01294 Created: 9/2/95 01295 01296 Returns: TRUE if the "Gallery Shift" key is down. 01297 01298 Purpose: Tests status of the "Gallery Shift" key 01299 This is a special method for use by galleries, which must emulate the 01300 action of windows list boxes. "Gallery Shift" is the key used to select 01301 multiple items at once. 01302 01303 Notes: SHOULD NOT be used outside the gallery system 01304 01305 ********************************************************************************************/ 01306 01307 BOOL KeyPress::IsGalleryShiftPressed(void) 01308 { 01309 return ::wxGetKeyState(CAMKEY(SHIFT)); 01310 } 01311 01312 01313 01314 /******************************************************************************************** 01315 01316 > static BOOL KeyPress::IsGalleryCtrlPressed(void) 01317 01318 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01319 Created: 9/2/95 01320 01321 Returns: TRUE if the "Gallery Ctrl" key is down. 01322 01323 Purpose: Tests status of the "Gallery Ctrl" key 01324 This is a special method for use by galleries, which must emulate the 01325 action of windows list boxes. "Gallery Ctrl" is the key used to add/remove 01326 single items to/from a selection 01327 01328 Notes: SHOULD NOT be used outside the gallery system 01329 01330 ********************************************************************************************/ 01331 01332 BOOL KeyPress::IsGalleryCtrlPressed(void) 01333 { 01334 return ::wxGetKeyState(CAMKEY(CONTROL)); 01335 } 01336 01337 01338 01339 01340 01341 /******************************************************************************************** 01342 01343 > static BOOL KeyPress::IsEscapePressed() 01344 01345 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01346 Created: 16/9/94 01347 Inputs: - 01348 Outputs: - 01349 Returns: TRUE - if an escape key is being pressed, or was pressed since the last call 01350 to this routine 01351 FALSE - no escape key has been pressed 01352 Purpose: Lets you see if an escape key combination is currently being pressed, or has been pressed 01353 since the last call to this routine 01354 01355 It does a GetAsyncKeyState() on certain key combinations, currently - 01356 CAMKEY(ESCAPE) 01357 CAMKEY(CANCEL) (Ctrl-Pause, or Break) 01358 01359 GetAsyncKeyState() returns the current key state AND whether the key was pressed since 01360 the last call to GetAsyncKeyState(). 01361 01362 Note: If TRUE is returned, all pending key messages will have been removed before hand. 01363 using PeekMessage(...WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) 01364 SeeAlso: 01365 01366 ********************************************************************************************/ 01367 01368 BOOL KeyPress::IsEscapePressed() 01369 { 01370 PORTNOTE("other", "KeyPress::IsEscapePressed - do nothing" ) 01371 #ifndef EXCLUDE_FROM_XARALX 01372 // TRACE( _T("Warning - KeyPress::IsEscapePressed called") ); 01373 /* BOOL EscapePressed = (GetAsyncKeyState(CAMKEY(ESCAPE)) != 0); 01374 BOOL Pressed = EscapePressed || (GetAsyncKeyState(CAMKEY(CANCEL)) != 0); 01375 01376 if (Pressed) 01377 { 01378 BOOL EscapeKeyDown = FALSE; 01379 01380 // Throw away all pending key messages 01381 MSG msg; 01382 while(PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE )) 01383 { 01384 // If we the actual Escape key has been pressed, see if we got an Escape Key Down event. 01385 if (EscapePressed) 01386 { 01387 KeyPressSysMsg KeyMsg(&msg); 01388 if (KeyMsg.IsValid() && (KeyMsg.Message == KM_KEYDOWN) && (KeyMsg.VirtKey == CAMKEY(ESCAPE))) 01389 EscapeKeyDown = TRUE; 01390 } 01391 } 01392 01393 // Alt+Tab Esc fix - i.e. Aborting a task switch via Alt+Tab using the Escape key. 01394 // 01395 // If the actual Escape key has been pressed, only allow it if we have been posted a KeyDown event 01396 // for the Escape key. 01397 // 01398 // When you do Alt+Tab while in Studio, then hit Escape, unfortunately we get posted an Escape Key Up event 01399 // which also means that the line above that reads "GetAsyncKeyState(CAMKEY(ESCAPE)) != 0" will return TRUE. 01400 // Obviously we want to ignore the Escape key being pressed in this circumstance, but it seems the only way 01401 // to identify the Escape key press as one we don't want is to see if we *don't* have a corresponding 01402 // key down event. 01403 // 01404 // if (GetAsyncKeyState(CAMKEY(ESCAPE)) != 0) // i.e. the Escape key has been pressed 01405 // { 01406 // if (App received a Escape KeyDown message) 01407 // Legitimate Escape key press, so Pressed = TRUE 01408 // else 01409 // Escape hit outside our app, so ignore it 01410 // } 01411 01412 // If the ActualEscape key has been pressed, then Pressed should only be TRUE if we have received a 01413 // Escape Key Down event. 01414 if (EscapePressed) 01415 Pressed = EscapeKeyDown; 01416 } 01417 01418 return (Pressed); */ 01419 #endif 01420 return false; 01421 } 01422 01423 /******************************************************************************************** 01424 01425 > static BOOL KeyPress::EscapePressed(KeyPress* pKeyPress) 01426 01427 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01428 Created: 15/9/94 01429 Inputs: pKeyPress = ptr to a key press 01430 Outputs: - 01431 Returns: TRUE - the key was an escape event (e.g. Escape, Break, etc) 01432 FALSE - the key was not an escape key, nothing happened 01433 Purpose: Deals with an Escape key press 01434 01435 If the key press was NOT an escape key, (i.e. not Escape or Ctrl+Pause (Break)), 01436 nothing happens, and FALSE is returned 01437 01438 if it was an escape key press, it is processed in a relevent way 01439 At the moment, this just means that the current drag is terminated, if there is one. 01440 01441 If it's an escape key press, and it was acted upon (e.g. a drag was terminated), TRUE is returned. 01442 Otherwise FALSE is returned 01443 SeeAlso: 01444 01445 ********************************************************************************************/ 01446 01447 BOOL KeyPress::EscapePressed(KeyPress* pKeyPress) 01448 { 01449 ENSURE(pKeyPress->IsValid(),"Invalid KeyPress given"); 01450 01451 BOOL Processed = FALSE; 01452 UINT32 VirtKey = pKeyPress->GetVirtKey(); 01453 01454 // Only check non-auto-repeat "key down" key presses 01455 if (pKeyPress->IsPress() && !pKeyPress->IsRepeat()) 01456 { 01457 if (VirtKey == CAMKEY(ESCAPE) || VirtKey == WXK_CANCEL) 01458 { 01459 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 01460 // MarkN I've moved this code in an attempt to stop the selection being 01461 // cleared after a bar drag cancel - Chris. 01462 if (!Processed) 01463 Processed = BaseBar::EscPressed(TRUE); 01464 01465 // cancel any drag manager drags (and say that we have done so!!!) 01466 // stops the selection being cleared when you cancel a 01467 // colour or sprite (or any) DragManagerOp drag 01468 if(!Processed && DragManagerOp::GetCurrentManager() != NULL) 01469 { 01470 DragManagerOp::AbortDrag(); 01471 Processed = TRUE; 01472 } 01473 #endif 01474 01475 if (!Processed && Operation::GetCurrentDragOp() != NULL) 01476 { 01477 OilCoord PointerPos(0,0); 01478 ClickModifiers ClickMods; 01479 // Spread* pSpread = NULL; 01480 01481 DocView* pDocView = DocView::GetSelected(); 01482 if (pDocView) 01483 pDocView->DragFinished(Operation::GetCurrentDragOp(), PointerPos, ClickMods, FALSE); 01484 01485 // We've done something with this escape key press so set Processed to TRUE 01486 // to prevent it from being passed on 01487 Processed = (Operation::GetCurrentDragOp() == NULL); 01488 } 01489 01490 if (!Processed && Operation::GetCurrentDragOp() != NULL) 01491 { 01492 DocCoord PointerPos(0,0); 01493 ClickModifiers ClickMods; 01494 Spread* pSpread = NULL; 01495 01496 Operation::GetCurrentDragOp()->DragFinished(PointerPos, ClickMods, pSpread, FALSE, FALSE); 01497 01498 // We've done something with this escape key press so set Processed to TRUE 01499 // to prevent it from being passed on 01500 Processed = TRUE; 01501 } 01502 01503 // This gives Chris a chance to terminate his bar dragging. This was necessary as his former 01504 // way of detecting Escape (via KeyMsg broadcasts) no longer works because Escape is now a hot key, and 01505 // as such gets in there before a KeyMsg is broadcast. 01506 // (MarkN 27/4/95) 01507 /*if (!Processed) 01508 Processed = BaseBar::EscPressed(TRUE); 01509 */ 01510 // Throw away all pending key messages 01511 PORTNOTE( "other", "Remove PeekMessage" ) 01512 #if !defined(EXCLUDE_FROM_XARALX) 01513 MSG msg; 01514 while(PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE )) 01515 ; 01516 #endif 01517 } 01518 } 01519 01520 return Processed; 01521 } 01522 01523 /******************************************************************************************** 01524 01525 > static BOOL KeyPress::GenerateCharMessage(MSG* pMsg) 01526 01527 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01528 Created: 10/3/95 01529 Inputs: pMsg = A Windows keypress message 01530 Outputs: - 01531 Returns: TRUE if the message was processed 01532 FALSE if the message wasn't processed 01533 Purpose: This tries to see if the keypress message can generate a WM_CHAR message. 01534 01535 It does this by trapping numerical key pad entry of the ASCII value of the char while 01536 the Alt ky is held down. (e.g. hold down ALT, type '6' then '5' on the num key pad, then release 01537 Alt - you should get 'A' appearing at the input focus). If, on a Alt key up event we have a 01538 valid ASCII value that's been entered, we post ourselves a WM_CHAR message containing the ASCII 01539 char. 01540 01541 We have to do this ourselves because we get less messages generated in Win 3.1 than we do in 01542 NT, so the NT solution (act upon the auto generated WM_CHAR message) won't work an all target 01543 platforms (pain in the butt or what?). The ideal solution is to find out exactly why we don't 01544 get this extra WM_CHAR message in Win3.1, but I've traced paths of key press messages under NT 01545 and have found no obvious reason why the Win3.1 should behave differently. As we don't have single 01546 stepping technology under Win3.1, it's almost impossible to determine what's going on. 01547 01548 So, the time honoured CC tradition, if the OS doesn't do it, we'll do it ourselves. 01549 01550 01551 Errors: - 01552 SeeAlso: KeyPress::TranslateMessage 01553 01554 ********************************************************************************************/ 01555 01556 BOOL KeyPress::GenerateCharMessage(wxKeyEvent* pMsg) 01557 { 01558 BOOL Processed = FALSE; 01559 01560 // Get the virtual key code for the key pressed 01561 UINT32 VirtKey = pMsg->GetKeyCode(); 01562 01563 //DumpKeyMessage(pMsg); 01564 01565 if( wxEVT_KEY_DOWN == pMsg->GetEventType() ) 01566 { 01567 if (VirtKey == CAMKEY(MENU)) 01568 { 01569 // Trap ALL Alt key down messages 01570 01571 if (!KeyPress::ValidAsciiVal) 01572 { 01573 // Initialise a ASCII value entry 01574 //TRACE( _T("-*-*-*-- Starting valid ascii val\n")); 01575 KeyPress::ValidAsciiVal = TRUE; 01576 KeyPress::AsciiVal = -1; 01577 } 01578 } 01579 else if (KeyPress::ValidAsciiVal && ((VirtKey < CAMKEY(NUMPAD0)) || (VirtKey > WXK_NUMPAD9))) 01580 { 01581 // If the key down message is not a num pad key between '0' and '9' 01582 // invalidate the ASCII value 01583 //TRACE( _T("-*-*-*-- (keydown) Invalidating ascii val\n")); 01584 KeyPress::ValidAsciiVal = FALSE; 01585 } 01586 } 01587 else 01588 if( wxEVT_KEY_UP == pMsg->GetEventType() ) 01589 { 01590 if (KeyPress::ValidAsciiVal) 01591 { 01592 // Only try to produce an ASCII value if the last set of key presses has generated 01593 // a valid value 01594 01595 if (VirtKey == CAMKEY(MENU)) 01596 { 01597 // We've received a Alt key up message, so post ourselves a WM_CHAR message that 01598 // contains the generated ASCII value 01599 01600 if (KeyPress::AsciiVal >= 0) 01601 { 01602 // Only post the ASCII value if one's been specified via the Num key pad 01603 // (i.e. the value >= 0) 01604 //TRACE( _T("-*-*-*-- Posting WM_CHAR. Val = %ld\n"),KeyPress::AsciiVal); 01605 PORTNOTE("other", "Removed PostMessage usage - WM_CHAR from ascii code" ) 01606 #ifndef EXCLUDE_FROM_XARALX 01607 Processed = ::PostMessage(pMsg->hwnd,WM_CHAR,KeyPress::AsciiVal % 256,1); 01608 #endif 01609 } 01610 //TRACE( _T("-*-*-*-- (keyup) Invalidating ascii val. Val = %ld\n"),KeyPress::AsciiVal); 01611 KeyPress::ValidAsciiVal = FALSE; 01612 } 01613 else if ((VirtKey >= CAMKEY(NUMPAD0)) && (VirtKey <= WXK_NUMPAD9)) 01614 { 01615 // We've got a num key pad key up event 01616 // We have to do this bit on key up events, because for some reason under NT (and possibly 01617 // other OSs) we don't get a key down event for the first key that's pressed while the 01618 // Alt key is auto-repeating (wierd - any ideas welcome) 01619 01620 // If this is the first one (i.e. ASCII val is currently < 0), reset the value to 0 01621 if (KeyPress::AsciiVal < 0) 01622 KeyPress::AsciiVal = 0; 01623 01624 // Shift the current value up, and add in the digit of the num key pad key. 01625 KeyPress::AsciiVal = ((KeyPress::AsciiVal*10)+(VirtKey-CAMKEY(NUMPAD0))); 01626 01627 // We've processed this key press 01628 Processed = TRUE; 01629 01630 //TRACE( _T("-*-*-*-- ascii val digit received. Val = %ld\n"),KeyPress::AsciiVal); 01631 } 01632 } 01633 } 01634 01635 return Processed; 01636 } 01637 01638 /******************************************************************************************** 01639 01640 > static BOOL KeyPress::TranslateMessage(MSG* pMsg) 01641 01642 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01643 Created: 26/08/94 01644 Inputs: pMsg = A Windows message 01645 Outputs: - 01646 Returns: TRUE if the message was to do with a key press AND was processed 01647 FALSE if the message wasn't to do with the keyboard at all OR key press was not processed 01648 Purpose: Called from a low-level PreTranslateMessage() routine to allow key presses to be processed 01649 If it is a key press message, it generates a KeyPress object and sends it off to 01650 Application::OnKeyPress() 01651 Errors: - 01652 SeeAlso: Application::OnKeyPress 01653 01654 ********************************************************************************************/ 01655 01656 BOOL KeyPress::TranslateMessage(wxKeyEvent* pMsg) 01657 { 01658 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) 01659 // What kind of message is it? 01660 BOOL KeyDown = wxEVT_KEY_DOWN == pMsg->GetEventType(); 01661 BOOL KeyUp = wxEVT_KEY_UP == pMsg->GetEventType(); 01662 01663 // If it's a key event, lose the bubble help. 01664 if (KeyDown || KeyUp) 01665 ControlHelper::BubbleHelpDisable(); 01666 #endif 01667 01668 TRACEUSER( "jlh92", _T("TM - %s\n"), wxEVT_KEY_DOWN == pMsg->GetEventType() ? _T("KDN") : 01669 wxEVT_KEY_UP == pMsg->GetEventType() ? _T("KUP") : wxEVT_CHAR == pMsg->GetEventType() ? _T("KCH") : 01670 _T("K??") ); 01671 01672 // Normal key processing. 01673 KeyPress* pKeyPress; 01674 BOOL Processed = FALSE; 01675 01676 // See if we can generate an WM_CHAR message from the key press 01677 if (!Processed) 01678 Processed = GenerateCharMessage(pMsg); 01679 01680 // Can we make a key press event from this message? 01681 if (!Processed && KeyPress::GenerateKeyPress(pMsg,&pKeyPress)) 01682 { 01683 if (pKeyPress != NULL) 01684 { 01685 // The message was a key press and we have a key press object at pKeyPress 01686 01687 // check for an escape key press 01688 if (!Processed) 01689 Processed = EscapePressed(pKeyPress); 01690 01691 // Now see if Camelot wants to use it 01692 if (!Processed) 01693 Processed = GetApplication()->OnKeyPress(pKeyPress); 01694 01695 // Don't process Alt key presses. By always returning FALSE on Alt key presses, we get 01696 // normal functionality from single press/releases of Alt, even in the Selector tool 01697 if (Processed && pKeyPress->VirtKey == CAMKEY(MENU)) 01698 Processed = FALSE; 01699 01700 //TRACE( _T("Processed = %d\n"),Processed); 01701 01702 // Must delete the key press after use 01703 delete pKeyPress; 01704 } 01705 } 01706 01707 if (!Processed) 01708 { 01709 // MFC ISSUES... 01710 // If we have had a key press we wish to ignore totally (i.e. repeated modifier key presses) 01711 // then return TRUE so that it doesn't get passed onto the rest of MFC. 01712 // 01713 // This is mainly for performance improvements during a drag AND modifier key press op, e.g. Alt held down 01714 // in the freehand tool for drawing straight lines. 01715 // 01716 // This fix makes modified drags usable in retail builds. In debug builds, you get an extra hit with 01717 // AfxValidateObject (or what ever it's called), which takes about 50% of the time. 01718 // 01719 // During Drags: 01720 // We want to prevent key presses getting to MFC during drags. In particular things like 01721 // Ctrl-Tab (i.e. switch to new doc) 01722 01723 KeyPressSysMsg KeySysMsg(pMsg); 01724 if (KeySysMsg.IsValid()) 01725 { 01726 // We have a keypress message 01727 // Prevent it getting to MFC if we are dragging or it's one we wish to ignore 01728 Processed = ((Operation::GetCurrentDragOp()!=NULL) || IgnoreKeyMessage(&KeySysMsg)); 01729 } 01730 } 01731 01732 return Processed; 01733 } 01734 01735 /******************************************************************************************** 01736 01737 > INT32 KeyPress::operator==(const KeyPress& other) 01738 01739 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01740 Created: 26/8/94 01741 Inputs: other = the key press you wish to check for equivalence with this key press 01742 Outputs: - 01743 Returns: TRUE if equal, FALSE otherwise 01744 Purpose: KeyPress == operator 01745 Two KeyPress objects are equal if 01746 1) They have the same virtual key code 01747 2) Have the same modifier settings 01748 3) Have the same extended flag settings 01749 4) Have the same validity (i.e. both valid OR both invalid) 01750 01751 THIS DOES NOT COMPARE THE UNICODE COMPONENTS OF THE TWO KeyPress OBJECTS. 01752 To compare Unicode values, use the KeyPress::GetUnicode() func. 01753 Errors: - 01754 SeeAlso: KeyPress::GetUnicode() 01755 01756 ********************************************************************************************/ 01757 01758 INT32 KeyPress::operator==(const KeyPress& other) 01759 { 01760 return ( 01761 VirtKey == other.VirtKey && 01762 Adjust == other.Adjust && 01763 Constrain == other.Constrain && 01764 Alternative == other.Alternative && 01765 Option == other.Option && 01766 Extended == other.Extended && 01767 Valid == other.Valid 01768 ); 01769 } 01770 01771 01772 01773 /******************************************************************************************** 01774 01775 > static BOOL KeyPress::AddVirtualKeyCode(UINT32 VCode, WCHAR Unicode) 01776 01777 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01778 Created: 11/10/95 01779 Inputs: VCode - the virtual key code to add 01780 Unicode - the unicode value generated when this key is pressed 01781 Outputs: - 01782 Returns: TRUE/FALSE for success/failure 01783 Purpose: Adds the given virtual key code to the list that Camelot knows about and 01784 send around internally (rather than ignoring) 01785 Errors: - 01786 SeeAlso: - 01787 01788 ********************************************************************************************/ 01789 BOOL KeyPress::AddVirtualKeyCode(UINT32 VCode, WCHAR Unicode) 01790 { 01791 // Construct a list item 01792 AdditionalVirtKey* pNew = new AdditionalVirtKey; 01793 01794 if (pNew != NULL) 01795 { 01796 pNew->VirtualKeyCode = VCode; 01797 pNew->UnicodeValue = Unicode; 01798 01799 AdditionalVirtKeys.AddHead(pNew); 01800 } 01801 01802 return (pNew != NULL); 01803 } 01804 01805 01806 01807 /******************************************************************************************** 01808 01809 > void KeyPress::RemoveVirtualKeyCode(UINT32 VCode, WCHAR Unicode) 01810 01811 Author: Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com> 01812 Created: 11/10/95 01813 Inputs: VCode - the virtual key code to remove 01814 Unicode - the unicode value generated when this key is pressed 01815 Outputs: - 01816 Returns: - 01817 Purpose: Removes the given virtual key code that generates the givne unicode value 01818 from the list of additional virtual key codes. Only the first occurace is 01819 removed. 01820 Errors: - 01821 SeeAlso: - 01822 01823 ********************************************************************************************/ 01824 void KeyPress::RemoveVirtualKeyCode(UINT32 VCode, WCHAR Unicode) 01825 { 01826 // Loop through the list until we find the list item 01827 BOOL finished = FALSE; 01828 AdditionalVirtKey* pKey = (AdditionalVirtKey*)AdditionalVirtKeys.GetHead(); 01829 01830 while (!finished && (pKey != NULL)) 01831 { 01832 AdditionalVirtKey* pNext = (AdditionalVirtKey*)AdditionalVirtKeys.GetNext(pKey); 01833 01834 if ((pKey->VirtualKeyCode == VCode) && (pKey->UnicodeValue == Unicode)) 01835 { 01836 AdditionalVirtKeys.RemoveItem(pKey); 01837 delete pKey; 01838 finished = TRUE; 01839 } 01840 01841 pKey = pNext; 01842 } 01843 } 01844 01845 01846 01847 //---------------------------------------------------------------------------------------------------- 01848 01849 #if defined(_DEBUG) && defined(__WXMSW__) 01850 01851 void KeyPress::DumpKeyMessage(wxKeyEvent* pMsg) 01852 { 01853 PORTNOTETRACE("other", "KeyPress::DumpKeyMessage - do nothing" ); 01854 #ifndef EXCLDUE_FROM_XARALX 01855 //if (!IsUserName("Markn")) return; 01856 01857 KeyPressSysMsg KeySysMsg(pMsg); 01858 WCHAR c = 1; 01859 KeyPress k1(&KeySysMsg,c); 01860 KeyPress k2(&KeySysMsg,c); 01861 01862 BOOL tits = (k1 == k2); 01863 01864 BOOL KeyMsg = ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST)); 01865 01866 if (KeyMsg) 01867 { 01868 if (pMsg->message == WM_KEYDOWN) TRACE( _T("*** WM_KEYDOWN")); 01869 if (pMsg->message == WM_KEYUP) TRACE( _T("*** WM_KEYUP")); 01870 if (pMsg->message == WM_SYSKEYDOWN) TRACE( _T("*** WM_SYSKEYDOWN")); 01871 if (pMsg->message == WM_SYSKEYUP) TRACE( _T("*** WM_SYSKEYUP")); 01872 if (pMsg->message == WM_CHAR) TRACE( _T("*** WM_CHAR")); 01873 if (pMsg->message == WM_DEADCHAR) TRACE( _T("*** WM_DEADCHAR")); 01874 if (pMsg->message == WM_SYSCHAR) TRACE( _T("*** WM_SYSCHAR")); 01875 if (pMsg->message == WM_SYSDEADCHAR) TRACE( _T("*** WM_SYSDEADCHAR")); 01876 01877 UINT32 VirtKey = pMsg->wParam; 01878 INT32 KeyData = pMsg->lParam; 01879 01880 if (TRUE) 01881 { 01882 TRACE( _T(" VK=%lx\n"),VirtKey); 01883 } 01884 else 01885 { 01886 TRACE( _T("\n")); 01887 TRACE( _T("KeyData = %lx\n"),KeyData); 01888 TRACE( _T("VirtKey = %lx\n"),VirtKey); 01889 TRACE( _T("Repeat = %lx\n"),KeyData & 0xffff); 01890 TRACE( _T("ScanCode= %lx\n\n"),(KeyData >> 16) & 0xff); 01891 01892 TRACE( _T("Bit 24 (extended) = %lx\n"),KeyData & 1<<24); 01893 TRACE( _T("Bit 29 (context) = %lx\n"),KeyData & 1<<29); 01894 TRACE( _T("Bit 30 (prev state) = %lx\n"),KeyData & 1<<30); 01895 TRACE( _T("Bit 31 (trans stat) = %lx\n"),KeyData & 1<<31); 01896 01897 //TRACE( _T("\nBit 25 (reserved) = %lx\n"),KeyData & 1<<25); 01898 //TRACE( _T("Bit 26 (reserved) = %lx\n"),KeyData & 1<<26); 01899 //TRACE( _T("Bit 27 (reserved) = %lx\n"),KeyData & 1<<27); 01900 //TRACE( _T("Bit 28 (reserved) = %lx\n"),KeyData & 1<<28); 01901 01902 TRACE( _T("KeyPress::AdjustStateLeft = %lx\n"),KeyPress::AdjustStateLeft); 01903 TRACE( _T("KeyPress::AdjustStateRight = %lx\n"),KeyPress::AdjustStateRight); 01904 TRACE( _T("KeyPress::ConstrainStateLeft = %lx\n"),KeyPress::ConstrainStateLeft); 01905 TRACE( _T("KeyPress::ConstrainStateRight = %lx\n"),KeyPress::ConstrainStateRight); 01906 TRACE( _T("KeyPress::AlternativeStateLeft = %lx\n"),KeyPress::AlternativeStateLeft); 01907 TRACE( _T("KeyPress::AlternativeStateRight = %lx\n"),KeyPress::AlternativeStateRight); 01908 } 01909 } 01910 #endif 01911 } 01912 #endif // _DEBUG 01913 01914 01915