ã©ããããããããŠãŒã¶ãŒãèªåã®æã§çªãããšãã§ããã¢ã¯ãã£ãã¢ãã¿ãŒã®åœ¢ã§ã®ãããã®æ°ãããã¬ã³ãã¯ãã¹ãŠãç§ã«æ°ä»ãããã«ééããŸããã 3ãæåã«ãã¹ã2ã€ã®éšåïŒç»é¢ãããŒããŒãïŒã«åå²ã§ããã©ããããããè³Œå ¥ããªãã£ãå Žåããããã«ã€ããŠã¯ç¥ããŸãããMSã«ãã£ãŠæšé²ãããSurfaceã§ã¯ãªãã ASUS ãã¯ããã«å°ãªããéã§ïŒæ¯èŒçïŒã
ãããŠããã®ããã€ã¹ã¯çç±ã®ããã«è³Œå ¥ãããŸãã-ããããã¿ã¹ã¯ãæé·ãããããã圌ãã¯åŸ ã¡ãŸããã§ããã
ããžã¥ã¬ïŒç§ãã¡ã¯æã«èšå€§ãªæ°ã®ã»ãããŒãéå¬ããããã圌ãã«èª²ãããŠããã®ã§ãè¬åž«ãã¡ã¯ãã®æªåé«ãã¿ã³ãšãœãããŠã§ã¢ã®éäºææ§ãå®èšŒãå§ããŸããã
ããã¡ã¯ãïŒãã©ã³ãŠãŒã¶ãŒã®æãã®æçŽããµããŒãã¡ãŒã«ã«æ³šããå§ããŸãã-ãããŒãã2åé²é³ããŸããããã¿ããããŸããã§ããã
åœå±ã¯ãããããã¹ãŠããç Žãããã©ãããããã§ç¶¿å¯ã«ç£èŠããTKãæºåããŸããã
ãããŠããã®æ¥ãæ¥ãŸããã LGãã23ã€ã³ã ïŒ æ倧 10æ¬ã®æã§ã¿ããå ¥åããµããŒãïŒã®3çªç®ã®ã¢ãã¿ãŒããã¹ã¯ãããã«èšçœ®ãããã¿ã¹ã¯ãèšå®ãããŸãã-ããã¯3æ¥ä»¥å ã«æ©èœããã¯ãã§ãïŒ
ãããŠãç§ã¯XE4ã§åããŠããŸã-ãã©ãã«ã
0.åé¡åæ
幞ããªããšã«ãç§ã¯å€ãã®æèœãªä»²éïŒEmbarcadero MVPãå«ãïŒã«ç²ŸéããŠãããã©ã¡ãã®åŽã§ã¿ãããµããŒãã«ã¢ãããŒããããã«ã€ããŠçžè«ã§ããŸããã...ãã«ãã¿ããã®ãµããŒãã«é¢ããæè¡èšäºãžã®ãªã³ã¯ãèªãã§ãXE4äœãèŒããŠããªãã ç§ãå©çšã§ããVCLãªãã·ã§ã³ã¯éåžžã«éãããŠããŸãã
Embarcaderoã«ã³ãã¡ã¬ã³ã¹ãå°ãèªãã åŸãããã€ãã®å¶éã¯ãããã®ã®ããã«ãã¿ãããXE7ã§ã®ã¿å©çšå¯èœã«ãªã£ãããšãç¥ããŸããïŒãã ãïŒã
åé¡ã解決ããæãç°¡åãªæ¹æ³ãXE7ã®ã¢ããããŒãã®ããã ãšèšã£ãå ŽåïŒããã«ãapaåŸã«äºææ§ã³ãŒãããã§ãã¯ããã®ã«ãããæéïŒãäžåžãäœãè©äŸ¡ãããããããŸããã
ãããã£ãŠãXE4ã§å©çšã§ãããã®ã確èªããŸãã
ãã©ã¹ïŒ
-圌女ã¯ãžã§ã¹ãã£ãŒïŒãžã§ã¹ãã£ãŒïŒãç¥ã£ãŠããŸãã
çæïŒ
-圌女ã¯ã¿ããã«ã€ããŠã¯ç¥ããŸããïŒåœŒå¥³ã¯ç¥ã£ãŠããŸãããå€éšãã³ãã©ãŒã¯æäŸããŸããïŒã
-2ã€ã®å ¥åãã€ã³ãïŒ2æ¬ä»¥äžã®æïŒãæã€ãžã§ã¹ãã£ã«ã€ããŠã¯ç¥ããŸããã
次ã«ãå©çšã§ããªããã®ãèŠãŠã¿ãŸãããã
- ã¯ã©ã¹ã®å³å¯ãªãã©ã€ããŒãã¿ã€ãã»ã¯ã·ã§ã³ã§ãTPlatformGestureEngineå ã§é衚瀺ã«ãªã£ãŠããã ãã§ãIStylusAsyncPluginãžã®ããŒããžã®IRealTimeStylus3ã€ã³ã¿ãŒãã§ã€ã¹ã®ãµããŒããå°å ¥ããŠTRealTimeStylusã¯ã©ã¹ãæ¡åŒµããããšã¯ã§ããŸããã
- ãã®ã¡ãã»ãŒãžã¯TWinControl.WndProcå ã§åŠçãããŸãããæ¬æ ŒçãªWM_TOUCHã¡ãã»ãŒãžãã³ãã©ã¯æäŸãããŠããŸããã
WM_TOUCH: with FTouchManager do if (GestureEngine <> nil) and (efTouchEvents in GestureEngine.Flags) then GestureEngine.Notification(Message);
ã³ãŒããããããããã«ãã³ã³ãããŒã«ã¯ãžã§ã¹ãã£èªèãšã³ãžã³ã«çŽæ¥ç§»åããŸãã
ã©ããã-ãžã§ã¹ãã£ãèªèããªãé åºã§ãã£ã³ãã¹äžã®5ã€ã®åçã移åãããå Žåããªããžã§ã¹ãã£ãå¿ èŠã§ããïŒ
ãã¡ããã2çªç®ã®ã±ãŒã¹ã§ã¯WM_TOUCHãèªåã§ãããã¯ããããšãã§ããŸããã誰ãããããåŠçãå§ããŠããŒã¿ãååŸããã®ã§ãã³ãŒããåããã³ã°ããããšããéçºè ãæã£ãŠãã ããã
ããã§ã¯ãå察åŽããè¡ããŸãããã
1.åé¡ã®å£°æ
ãã ããåœç€Ÿã®ãœãããŠã§ã¢ã¯åºæ¬çã«éåžžã«é«åºŠãªExcelã§ãããç¹å®ã®ãŠãŒã¶ãŒïŒãã®å Žåã¯æšå®è ïŒã察象ãšããŠããŸãã ãã ããå°ãèšãçŽããŸãããœãããŠã§ã¢ã®æ©èœãšExcelã®éã®è·é¢ã¯ãMsPaintãšAdobe Photoshopã®éããšã»ãŒåãã§ãã
ãŠãŒã¶ãŒã¯ãç¹å®ã®ããã¥ã¡ã³ããMsPaintã®ç»åã ãã§ãªããèŠç©ããã®ââ圢åŒã§Excelã«å®è£ ããããšãã§ããŸãã ãã¹ãŠã®cimusã¯çµæã§ãã
ãã®ãããžã§ã¯ãã¯ãWYSIWYGã®ã€ããªãã®ãŒã«åŸã£ãŠéçºããããã®ã§ã90ïŒ ã®ã±ãŒã¹ã§ã¯ãéåžžã®çŽã®ææžãšåæ§ã«ããŠãŒã¶ãŒãäœæ¥ããã°ãªãããå®è£ ããäžçš®ã®ã«ã¹ã¿ã ã¯ã©ã¹ïŒTCustomControlããïŒã§ãã
ããã¯æ¬¡ã®ããã«ãªããŸãïŒïŒã¹ã¯ãªãŒã³ã·ã§ããã¯DragDropäœçœ®ã®æäœäžã«æ®åœ±ããããã®ã§ãç¢å°ã«æ³šæãæããªãã§ãã ãããåçãäžéšã®ãã¯ãã«ã«ãµããŒãããç Žããããããªã©ã®æµ®åãã³ããæããŠããããã§ãã
ãã®ã³ã³ãããŒã«ã«ã¯ã¹ã¯ããŒã«ãªã©ã®æšæºçãªæŠå¿µã¯ãããŸããã ãã¡ãããããã§ãããæ°Žå¹³æ¹åã®ç§»åã®å ŽåããŸãã¯åçŽæ¹åã®ç§»åã®å Žå-ã·ãŒãã®æ¬¡ã®è¡ãžã®é·ç§»ã§ãåã®æäœãæäœããŸãã
æšæºã®ã¹ã¯ããŒã«ã¡ãã»ãŒãžã¯åãä»ããŸããã
ïŒOSãçºè¡ããïŒåºæ¬ããŒãžã§ã³ã§ã¯ãã¿ããã¹ã¯ãªãŒã³ã®ã¿ãããä»ããŠã·ã¹ãã ã«ãã£ãŠãšãã¥ã¬ãŒããããããŠã¹ã¯ãªãã¯ã€ãã³ããšãã¿ãããä»ããŠã·ã¹ãã ã«ãã£ãŠãšãã¥ã¬ãŒããããWM_MOUSEMOVEãåä¿¡ã§ããŸãã
ãããŠå¿ èŠãªãã®ïŒ
- çŸåšã®ããŒãžã§ã³ã®ãžã§ã¹ãã£ãŒã§ã§ããããšã¯ã2æ¬ã®æã§ã¿ããããŠãã¿ããã®åº§æšã§PopupMenuãåŒã³åºãããšã ãã§ãã
- ã¿ããã¹ã¯ãªãŒã³äžã§2æ¬ã®æã§ã¹ã¯ã€ãããŠãå·Š/å³/äž/äžã«ã¹ã¯ããŒã«ããŸãã
- ã¿ããã¹ã¯ãªãŒã³äžã§3æ¬ã®æã§ã¹ã¯ã€ãããããšã«ãããã³ãã³ãããæ»ã/é²ãããšãã¥ã¬ãŒã·ã§ã³ã
XE4ã®ãžã§ã¹ãã£ã¯ããã«ãã¿ããã§ã¯ïŒã²ã¹ããšãã£ã¿ãŒã®ã¬ãã«ã§ãã£ãŠãïŒåºæ¬çã«ã·ã£ãŒãåãããŠããªãããåé¡ã解決ããå¿ èŠããããšããäºå®ãèãããšãå€äžãã£ãšæ²ãããªããæã«ãªã£ãŠä»äºãå§ããŸããã
2.䜿çšãããçšèª
å ã»ã©èšã£ãããã«ãç§ã¯ãããã®æ°ãããã¬ã³ããã¹ãŠã«ç²ŸéããŠããããã§ã¯ãªãã®ã§ãèšäºã§ã¯æ¬¡ã®å®çŸ©ã䜿çšããŸãïŒãããã¯ééã£ãŠããå¯èœæ§ããããŸãïŒã
ã¿ãã -ããŠã¹ã¯ãªãã¯ã®é¡äŒŒç©ãæã§ã¿ããã¹ã¯ãªãŒã³ã1åçãã¯ãªãã¯ãããšçºçããã€ãã³ãã
ã¿ãã ïŒãŸãã¯ã¿ãããã€ã³ãïŒã¯ãæãã¿ããã¹ã¯ãªãŒã³ã«æ¥è§ŠããŠããïŒããã³WM_TOUCHã¡ãã»ãŒãžãåŠçãããŠããïŒç¶æ³ãè¡šããã®ã§ãã
ã«ãŒã -ãŠãŒã¶ãŒãæãåããã座æšã®ãªã¹ãïŒåãããããã€ãŒã«ã®ãã€ã³ãïŒã
ã»ãã·ã§ã³ -æãã¿ããã¹ã¯ãªãŒã³ã«è§Šãããšéå§ãããŠãŒã¶ãŒãæãé¢ããã«ãã®äžã移åãããšç¶è¡ããæãé¢ããšçµäºããŸãã ã»ãã·ã§ã³å šäœãéããŠããã®ã«ãŒããæ§ç¯ãããŸãã
ãžã§ã¹ãã£ã¯ãã»ãã·ã§ã³ã«ãŒããšæ¯èŒãããã«ãŒãã®ãã³ãã¬ãŒããã³ãã¬ãŒãã§ãã ããšãã°ããŠãŒã¶ãŒãæãã€ãŸãã§ãå·Šã«åŒããŠé¢ããŸãã-ããã¯èå¥åsgiLeftã®ãžã§ã¹ãã£ãŒã§ãã
3. WM_TOUCHåŠçã«ã€ããŠ
æåã«æ±ºå®ããå¿ èŠããããŸã-ããŒããŠã§ã¢ã¯ãã«ãã¿ããããµããŒãããŠããŸããïŒ
ãããè¡ãã«ã¯ãSM_DIGITIZERãã©ã¡ãŒã¿ãŒãæå®ããŠGetSystemMetricsãåŒã³åºããNID_READYãšNID_MULTI_INPUTã®2ã€ã®ãã©ã°ã®çµæã確èªããŸãã
倧äœïŒ
tData := GetSystemMetrics(SM_DIGITIZER); if tData and NID_READY <> 0 then if tData and NID_MULTI_INPUT <> 0 then ... ,
æ®å¿µãªãããOS Windowsã§ãã«ãã¿ããããµããŒãããããã€ã¹ã䜿çšããŠããªãå Žåããã®èšäºã®æ®ãã®éšåã¯ãçµæã確èªããå¯èœæ§ã®ãªãçè«ã«éããŸããã Microsoft Surface 2.0 SDKãããã€ãŒã«ãšãã¥ã¬ãŒã¿ãŒã䜿çšããŠã¿ãããšãã§ããŸãããè©ŠããŠã¯ããŸããã
ããã!!! ããã€ã¹ããã«ãã¿ããããµããŒãããŠããå Žåã¯ãã¿ãããè©Šã¿ãããšãã§ããŸãã ãããè¡ãã«ã¯ãä»»æã®ãŠã£ã³ããŠïŒã¡ã€ã³ãã©ãŒã ãªã©ïŒãéžæããŠã次ã®ããã«èšããŸãã
RegisterTouchWindow(Handle, 0);
ãã®é¢æ°ãåŒã³åºããªããšãéžæãããŠã£ã³ããŠã¯WM_TOUCHã¡ãã»ãŒãžãåä¿¡ããŸããã
UnregisterTouchWindowé¢æ°ã¯ããŠã£ã³ããŠããã®ã¡ãã»ãŒãžãåä¿¡ããªãããã«ãåæãããã®ã«åœ¹ç«ã¡ãŸãã
ã¡ãã»ãŒãžãã³ãã©ãŒWM_TOUCHã宣èšããŸãã
procedure WmTouch(var Msg: TMessage); message WM_TOUCH;
ãããŠãç§ãã¡ã¯åœŒãäœãç§ãã¡ã«äžããŠãããããç解ãå§ããŸãã
ãã®ããããã®ã¡ãã»ãŒãžã®WParamãã©ã¡ãŒã¿ãŒã«ã¯ãã·ã¹ãã ãéç¥ããææŒãè»ã®ã¢ã¯ãã£ããã€ã³ãã®æ°ãå«ãŸããŠããŸãã ããã«ããã®æ°å€ã¯äžäœ2ãã€ãã«ã®ã¿æ ŒçŽãããŸããããã¯ãã·ã¹ãã ãæ倧65535ã®å ¥åãã€ã³ãããµããŒãããå¯èœæ§ã瀺åããŠããŸãã
ç§ã¯ãããç解ããããšããŸãã-ç§ã®ã¢ãã¿ãŒã¯æ倧10æ¬ã®æãä¿æããŠãããããããŸããããŸããã§ããã ãã ããããã¯çŸä»£ã®ç©ºæ³ç§åŠå°èª¬æ ç»ãèŠããšãã ã¹ã§ããã10åãã¹ãŠãçªãããšãã§ããå€ãã®äººã ãšé£æºããããŒã¿ãå«ãä»®æ³ããŒãã«ã瀺ããŠããŸãïŒããšãã°ãã¢ãã¿ãŒã¯åãããŸãã¯å¿åŽïŒã
ãããã£ãã圌ãã¯çŽæããããããããå€æããããã«ãããã¯é·ãéæ ç»ãªãã§åããŠããããç§ã¯åžžã«ãã¥ãŒã¹ã«åŸã£ãŠããªãã ããšãã°ãConsumer Electronics Show 2011ã§çºè¡šããããã®ãããª46ã€ã³ãããã€ã¹ã¯æ¬¡ã®ãšããã§ãã
ãã ããæ°ãæ£ãããšã¯ãããŸããã
ãã ãããã®ã¡ãã»ãŒãžã®LParamã¯ãGetTouchInputInfoé¢æ°ãåŒã³åºããŠã¡ãã»ãŒãžã«é¢ãã詳现æ å ±ãååŸã§ããäžçš®ã®ãã³ãã«ã§ãã
GetTouchInputInfoãåŒã³åºããåŸããã®é¢æ°ã®2åç®ã®åŒã³åºããäžèŠãªå ŽåãMSDNã¯CloseTouchInputHandleãæå®ããããšããå§ãããŸãããããã¯å¿ èŠãããŸããã ã³ã³ãããŒã«ãDefWindowProcã«è»¢éãããšãããŸãã¯SendMessage / PostMessageãä»ããŠããŒã¿ãéä¿¡ããããšãããšããããŒãäžã®ããŒã¿ã®ã¯ãªã¢ã¯èªåçã«è¡ãããŸãã
詳现ã¯ãã¡ã ã
GetTouchInputInfoé¢æ°ã«å¿ èŠãªãã®ïŒ
- 圌女ã¯ãã³ãã«èªäœãå¿ èŠã§ããããããšäžç·ã«äœæ¥ããŸãã
- 圌女ã¯ãTTouchInputèŠçŽ ã®é åã®åœ¢åŒã§å°çšã®ãããã¡ãå¿ èŠãšããããã«ã€ãã³ãã«é¢ãããã¹ãŠã®æ å ±ãé 眮ããŸãã
- ãã®é åã®ãµã€ãºã
- é åå ã®åèŠçŽ ã®ãµã€ãºã
ãããã£ãïŒ4çªç®ã®æ®µèœã®å©ããåããŠãOSã®å°æ¥ã®ããŒãžã§ã³ã§TTouchInputã®æ§é ãå€æŽããå¯èœæ§ãããã«æ±ºå®ããŸããïŒããã«é¢çœãããšã¯ãããŸããïŒ
éåžžã«å€±ç€Œãªå Žåã圌女ã®åŒã³åºãã¯æ¬¡ã®ããã«ãªããŸãã
var Count: Integer; Inputs: array of TTouchInput; begin Count := Msg.WParam and $FFFF; SetLength(Inputs, Count); if GetTouchInputInfo(Msg.LParam, Count, @Inputs[0], SizeOf(TTouchInput)) then // ... - CloseTouchInputHandle(Msg.LParam);
以äžã§ãã ããã§ãInputsé åã«æ ŒçŽãããŠããããŒã¿ãææ¡ããŠã¿ãŸãããã
4. TTouchInputãåŠçããŸã
ãã®ç¬éããã楜ãã¿ãå§ãŸããŸãã
TTouchInputé åã®ãµã€ãºã¯ãã¿ããã¹ã¯ãªãŒã³ã«æ¥ç¶ãããŠããæã®æ°ã«ãã£ãŠç°ãªããŸãã
ææŒãè»ïŒæïŒã®åãã€ã³ãã«å¯ŸããŠãã·ã¹ãã ã¯ã»ãã·ã§ã³å šäœïŒæã觊ããŠããåé€ãããŸã§ïŒãéããŠå€ãããªãäžæã®IDãçæããŸãã
ãã®IDã¯ãTTouchInputé åã®åèŠçŽ ã«ããããããdwIDãã©ã¡ãŒã¿ãŒã«æ ŒçŽãããŸãã
ã»ãã·ã§ã³ãšããã°ïŒ
ã»ãã·ã§ã³ãããã¯...ããŠããã®ããã«ããŸãããïŒ
åçã¯ïŒåæã«å¯ŸããŠïŒæ£ç¢ºã«10ã»ãã·ã§ã³ã瀺ãããã®ã«ãŒãïŒåã»ãã·ã§ã³å ã§æãäžã«ç§»åãããã€ã³ãã®é åïŒã瀺ããåã»ãã·ã§ã³ã¯ãŸã å®äºããŠããŸããïŒæã¯ã¿ããã¹ã¯ãªãŒã³ã«ãŸã æ¥ç¶ãããŠããŸãïŒã
ãã ããTTouchInputæ§é ã«æ»ããŸãã
å®éããã®æ§é ã®ã¿ã³ã䜿çšããéåžžã®æäœã§ã¯ãããã€ãã®ãã©ã¡ãŒã¿ãŒã®ã¿ãå¿ èŠã§ãã
TOUCHINPUT = record x: Integer; // y: Integer; // hSource: THandle; // , dwID: DWORD; // dwFlags: DWORD; // // dwMask: DWORD; dwTime: DWORD; dwExtraInfo: ULONG_PTR; cxContact: DWORD; cyContact: DWORD; end;
ãã¢ã¢ããªã±ãŒã·ã§ã³ãããã«å§ããŸãããã
æ°ãããããžã§ã¯ããäœæããã¡ã€ã³ãã©ãŒã ã«TMemoãé 眮ããŸããã¡ã€ã³ãã©ãŒã ã«ã¯ãã¿ã³ã§ã®äœæ¥ã®ãã°ã衚瀺ãããŸãã
ãã©ãŒã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ããããWM_TOUCHã¡ãã»ãŒãžã®åŠçã«æ¥ç¶ããŸãã
procedure TdlgSimpleTouchDemo.FormCreate(Sender: TObject); begin RegisterTouchWindow(Handle, 0); end;
次ã«ãã€ãã³ããã³ãã©ãäœæããŸãã
procedure TdlgSimpleTouchDemo.WmTouch(var Msg: TMessage); function FlagToStr(Value: DWORD): string; begin Result := ''; if Value and TOUCHEVENTF_MOVE <> 0 then Result := Result + 'move '; if Value and TOUCHEVENTF_DOWN <> 0 then Result := Result + 'down '; if Value and TOUCHEVENTF_UP <> 0 then Result := Result + 'up '; if Value and TOUCHEVENTF_INRANGE <> 0 then Result := Result + 'ingange '; if Value and TOUCHEVENTF_PRIMARY <> 0 then Result := Result + 'primary '; if Value and TOUCHEVENTF_NOCOALESCE <> 0 then Result := Result + 'nocoalesce '; if Value and TOUCHEVENTF_PEN <> 0 then Result := Result + 'pen '; if Value and TOUCHEVENTF_PALM <> 0 then Result := Result + 'palm '; Result := Trim(Result); end; var InputsCount, I: Integer; Inputs: array of TTouchInput; begin // InputsCount := Msg.WParam and $FFFF; // SetLength(Inputs, InputsCount); // if GetTouchInputInfo(Msg.LParam, InputsCount, @Inputs[0], SizeOf(TTouchInput)) then begin // ( ) CloseTouchInputHandle(Msg.LParam); // for I := 0 to InputsCount - 1 do Memo1.Lines.Add(Format('TouchInput â: %d, ID: %d, flags: %s', [I, Inputs[I].dwID, FlagToStr(Inputs[I].dwFlags)])); end; end;
以äžã§ãã
åæãã-äžå¯èœã«ã ãã ããªãã®ç®ã®åã®ãã¹ãŠã®ããŒã¿ã
ã¿ããã¹ã¯ãªãŒã³ã䜿çšããŠãã®ã³ãŒããè©ŠããŠã¿ãŠãã ãããéçºè ã«ã¯ãåãã€ãŒã«ããŒã®IDãžã®ãã€ã³ãã«å ããŠããã°ã«è¡šç€ºãããç¹å®ã®ãã©ã°ã»ãããäžããããŸãã
ãã°ããŒã¿ã«ããã°ãææŒãè»ã®ã»ãã·ã§ã³ã®éå§ïŒãã©ã°TOUCHEVENTF_DOWNïŒãã¿ããã¹ã¯ãªãŒã³äžã®åæã®åãïŒãã©ã°TOUCHEVENTF_MOVEïŒãããã³ã»ãã·ã§ã³ã®çµäºïŒãã©ã°TOUCHEVENTF_UPïŒãããã«å€æã§ããŸãã
次ã®ããã«ãªããŸãã
è¿·æè¡çºã«ã€ããŠããã«äºçŽããŸããã¿ããã¹ã¯ãªãŒã³ããTOUCHEVENTF_DOWNãŸãã¯TOUCHEVENTF_UPãã©ã°ãä»ããã¡ãã»ãŒãžãWM_TOUCHãã³ãã©ãŒã«å±ããšã¯éããŸããã ãã©ãããŒã¯ã©ã¹ããå®è£ ãããšãã¯ããã®ãã¥ã¢ã³ã¹ãèæ ®ããå¿ èŠããããŸããããã«ã€ããŠã¯ä»¥äžã§èª¬æããŸãã
äŸïŒ
çŸåšãã¢ããªã±ãŒã·ã§ã³ã¯PopupMenuã衚瀺ããŠããŸã-ã¿ããã¹ã¯ãªãŒã³ãã¯ãªãã¯ãããšéããŸãããTOUCHEVENTF_DOWNãã©ã°ã®ããWM_TOUCHã¡ãã»ãŒãžã¯å±ããŸããããTOUCHEVENTF_MOVEãã©ã°ã®ãã次ã®ã¡ãã»ãŒãžã¯æ£åžžã«åä¿¡ãããŸãã
TOUCHEVENTF_MOVEã€ãã³ããã³ãã©ãŒã§PopupMenuã衚瀺ããå Žåãåæ§ã§ãã
ãã®å Žåãã»ãã·ã§ã³ã¯äžæãããTOUCHEVENTF_UPãã©ã°ãèšå®ãããWM_TOUCHã¡ãã»ãŒãžã¯äºæãããŸããã
ãã®åäœã¯ãWindows 7ïŒ32/64ãããïŒã§ãèŠãããŸããWindows8以éã§ã¯ãäœããå€æŽãããŸããããä»ã§ã¯ç¢ºèªããæ©äŒããããŸããïŒæ lazã2çªç®ã§ãïŒã
ãã ãããã©ã®ããã«æ©èœãããããšããã¢ã€ãã¢ãåŸãã®ã§ããã£ãšé¢çœãããšãæžããŸãã
ãã®äŸã®ãœãŒã¹ã³ãŒãã¯ããœãŒã¹ã¢ãŒã«ã€ãã®ã ã\ Demos \ simple \ ããã©ã«ããŒã«ãããŸãã
5.å®éã«ãã«ãã¿ãããé©çšããŸãã
ç§ã®ã¢ãã¿ãŒã«ã¯åæã«10æ¬ã®æãããããã¢ãããšãã¥ã¬ãŒãããã¢ããªã±ãŒã·ã§ã³ãäœæããããšãã§ããŸãïŒãã ãããã¢ãã«ã¯ããã«ãšæŒå§åã«å¯Ÿããæ床ããããŸãïŒãããªãè€éãªãã®ããããã«è¡ãã®ã§ããããïŒ
ç§ã«èµ·ãã£ãæãç°¡åãªããšã¯ããã©ãŒã ã®ãã£ã³ãã¹äžã®10åã®æ£æ¹åœ¢ã§ãããææŒãè»ã®å©ããåããŠãã¹ãŠã®æ¹åã«ç§»åã§ããŸãã
ããã¯ãæãæåéãã®æå³ã§ãã«ãã¿ããããæãããã®ã«ååã§ãã
æ°ãããããžã§ã¯ããäœæããŸãã
åæ£æ¹åœ¢ã¯ããã®ãããªæ§é ãšããŠèª¬æãããŸãã
type TData = record Color: TColor; ARect, StartRect: TRect; StartPoint: TPoint; Touched: Boolean; TouchID: Integer; end;
å®éããã®æ§é ã®æãéèŠãªãã£ãŒã«ãã¯TouchIDã§ããããã以å€ã¯ãã¹ãŠã»ã«ã³ããªã§ãã
åæ£æ¹åœ¢ã®ããŒã¿ãã©ããã«ä¿åããå¿ èŠãããã®ã§ããã®ãããªé åãšããŠå®£èšããŸãããã
FData: array [0..9] of TData;
ããŠãåæåãããŸãããïŒ
procedure TdlgMultiTouchDemo.FormCreate(Sender: TObject); var I: Integer; begin DoubleBuffered := True; RegisterTouchWindow(Handle, 0); Randomize; for I := 0 to 9 do begin FData[I].Color := Random($FFFFFF); FData[I].ARect.Left := Random(ClientWidth - 100); FData[I].ARect.Top := Random(ClientHeight - 100); FData[I].ARect.Right := FData[I].ARect.Left + 100; FData[I].ARect.Bottom := FData[I].ARect.Top + 100; end; end;
ãŸãããã©ãŒã ã®ãã£ã³ãã¹äžã§ã®ã¬ã³ããªã³ã°ïŒä»ã®ãšãããFormPaintãã³ãã©ãŒãåæããã«ãå°ãäžã«ç§»åããŸãïŒïŒ
procedure TdlgMultiTouchDemo.FormPaint(Sender: TObject); var I: Integer; begin Canvas.Brush.Color := Color; Canvas.FillRect(ClientRect); for I := 0 to 9 do begin Canvas.Pen.Color := FData[I].Color xor $FFFFFF; if FData[I].Touched then Canvas.Pen.Width := 4 else Canvas.Pen.Width := 1; Canvas.Brush.Color := FData[I].Color; Canvas.Rectangle(FData[I].ARect); end; end;
å®è¡ãããšã次ã®ããã«ãªããŸãã
ããã£ãããã®æºåãã§ããŸããã次ã«ãWM_TOUCHã®åŠçãéããŠç»åãå€æŽããŠã¿ãŸãããã
ãã³ãã©ãŒã§å¿ èŠãªã®ã¯ããŠãŒã¶ãŒãã¯ãªãã¯ããæ£æ¹åœ¢ã®ã€ã³ããã¯ã¹ãååŸããããšã§ãã ããããæåã«ãææŒãè»ã®åãã€ã³ãããã®åº§æšããŠã£ã³ããŠã®åº§æšã«å€æããŸãã
pt.X := TOUCH_COORD_TO_PIXEL(Inputs[I].x); pt.Y := TOUCH_COORD_TO_PIXEL(Inputs[I].y); pt := ScreenToClient(pt);
æå¹ãªåº§æšãæã«å ¥ããããPtInRectãåŒã³åºãããšã§ãé åå ã®æ£æ¹åœ¢ã®ã€ã³ããã¯ã¹ãèŠã€ããããšãã§ããŸãã
function GetIndexAtPoint(pt: TPoint): Integer; var I: Integer; begin Result := -1; for I := 0 to 9 do if PtInRect(FData[I].ARect, pt) then begin Result := I; Break; end; end;
ãŠãŒã¶ãŒãæã§ã¿ããã¹ã¯ãªãŒã³ã«è§ŠãããšãïŒåãã€ã³ãã«åºæã®IDãããå ŽåïŒãèŠã€ãã£ãåè§åœ¢ã«ãã®IDãå²ãåœãŠãŸãã ããã¯å°æ¥åœ¹ã«ç«ã€ã§ãããïŒ
if Inputs[I].dwFlags and TOUCHEVENTF_DOWN <> 0 then begin Index := GetIndexAtPoint(pt); if Index < 0 then Continue; FData[Index].Touched := True; FData[Index].TouchID := Inputs[I].dwID; FData[Index].StartRect := FData[Index].ARect; FData[Index].StartPoint := pt; Continue; end;
ããã¯ãããšãã°ããªããžã§ã¯ãã®åæåãšææŒãè»ã®ã»ãã·ã§ã³ã®éå§ã§ãã
次ã®ã¡ãã»ãŒãžã¯ãTOUCHEVENTF_MOVEãã©ã°ãèšå®ãããWM_TOUCHã§ããå¯èœæ§ããããŸãã
ãã¥ã¢ã³ã¹ããããŸãïŒ
æåã®ã±ãŒã¹ã§ã¯ã座æšã§æ£æ¹åœ¢ãæ€çŽ¢ããŸãããããã©ãŒã äžã®æ£æ¹åœ¢ã®äœçœ®ã亀差ããå¯èœæ§ããããããæ£æ¹åœ¢ã¯ééãã«ãªããŸãã
ãããã£ãŠãMOVEã®å ŽåãTouchIDãã©ã¡ãŒã¿ãŒã§èšå®ããããã€ãŒã«ã®IDã§æ£æ¹åœ¢ãæ€çŽ¢ããŸãã
function GetIndexFromID(ID: Integer): Integer; var I: Integer; begin Result := -1; for I := 0 to 9 do if FData[I].TouchID = ID then begin Result := I; Break; end; end;
å¿ èŠãªæ£æ¹åœ¢ãèŠã€ããããã¿ããã»ãã·ã§ã³ã®éå§æã«æå®ãããæ§é ã«çŠç¹ãåœãŠãŠç§»åããŸãã
R := FData[Index].StartRect; OffsetRect(R, pt.X - FData[Index].StartPoint.X, pt.Y - FData[Index].StartPoint.Y); FData[Index].ARect := R;
ããŠããããŠTOUCHEVENTF_UPãã©ã°ãåŠçãã圢ã§çµããïŒ
if Inputs[I].dwFlags and TOUCHEVENTF_UP <> 0 then begin FData[Index].Touched := False; FData[Index].TouchID := -1; Continue; end;
æ£æ¹åœ¢ãã¿ããã»ãã·ã§ã³ããåæãããã£ã³ãã¹èªäœãåæç»ããŸãã
éåžžã«åçŽãªäŸã§ãããããã¯æ©èœãããéãèŠæ±ããŸããã
å®è¡ããŠãã¹ã-ããã¯éåžžã«é¢çœãããšãå€æããŸããïŒ
çŸããããããã«ãTDataæ§é äœã®Touchedãã©ã¡ãŒã¿ãŒã¯FormPaintå ã§äœ¿çšããã移åãããæ£æ¹åœ¢ã®åšå²ã«å€ªåã®ãã¬ãŒã ã衚瀺ããŸãã
ãã®äŸã®ãœãŒã¹ã³ãŒãã¯ããœãŒã¹ã¢ãŒã«ã€ãã®ã ã\ Demos \ multutouch \ ããã©ã«ãã«ãããŸãã
6.ãžã§ã¹ãã£ïŒãžã§ã¹ãã£ïŒãç解ãã
ãã«ãã¿ããã¯æåã®ã¹ãããã«éããŸããããã«ãã¿ãããžã§ã¹ãã£ã䜿çšãããã®ã§ãã...
ãŸãã1æ¬ã®ã¿ããã»ãã·ã§ã³ïŒ1æ¬ã®æïŒã«åºã¥ããŠVCLã§ãžã§ã¹ãã£èªèãã©ã®ããã«å®è£ ãããããèŠãŠã¿ãŸãããã
TGestureEngineã¯ã©ã¹ã¯ããã«è²¬ä»»ããããååãšããŠIsGestureïŒïŒé¢æ°ã®ã³ãŒãã®ã¿ãå¿ èŠã§ãã
ãã£ãšè©³ããèããŠã¿ãŸãããã
ããã¯æ£ç¢ºã«2ã€ã®éšåã«åãããŠãããæåã®éšåã¯ã«ãŒãå ã®æšæºãžã§ã¹ãã£ãŒããã§ãã¯ããŸãã
// Process standard gestures if gtStandard in GestureTypes then
2çªç®-ãŠãŒã¶ãŒãéä¿¡ããã«ã¹ã¿ã ãžã§ã¹ãã£ïŒ
// Process custom gestures if CustomGestureTypes * GestureTypes = CustomGestureTypes then
å®çŸ©äžãã«ã¹ã¿ã ãŠãŒã¶ãŒãžã§ã¹ãã£ã¯å¿ èŠãªããããé¢æ°ã®æåã®éšåã®ã¿ãèæ ®ããŸãã
ãã®äž»ãªã¢ã€ãã¢ã¯ãFindStandardGestureãåŒã³åºããRecognizer.Matchã䜿çšããŠæž¡ãããã«ãŒããšæ¯èŒããããšã«ããããžã§ã¹ãã£ãŒèšè¿°åãæ€çŽ¢ããããšã§ãã
å®éãIsGestureã«éããããã®ä»ã®ãã©ã¡ãŒã¿ãŒã¯ãã¹ãŠé€å€ã§ããŸãããããã¯ããã£ãããã®æ©èœã§ãã
ç§trickã¯ãRecognizerã¯IGestureRecognizerã€ã³ã¿ãŒãã§ã€ã¹ã§ã¯ãªããVCLã©ãããŒã§ãããšããããšã§ãã
ãããå¿ èŠãªãã®ã§ãã
ãããããã¢ã®äœæã«ç§»ãåã«ããžã§ã¹ãã£ãŒèªäœãäœã§ããããç解ããå¿ èŠããããŸãïŒGertureïŒïŒ
ããã¯ãã©ãŒã ã®æ§é ã§ãïŒ
TStandardGestureData = record Points: TGesturePointArray; GestureID: TGestureID; Options: TGestureOptions; Deviation: Integer; ErrorMargin: Integer; end;
ãã€ã³ãã¯ããŠãŒã¶ãŒã®ã¿ããã»ãã·ã§ã³ããã®åæ§ã®ã«ãŒããšæ¯èŒããããžã§ã¹ãã£ãŒã«ãŒãã§ãã
GestureIDã¯äžæã®ãžã§ã¹ãã£ãŒèå¥åã§ãã
XE4ã§ã¯ãVcl.Controlsã¢ãžã¥ãŒã«ã«ãªã¹ããããŠããŸãã
const // Standard gesture id's sgiNoGesture = 0; sgiLeft = 1; sgiRight = 2; ...
ãªãã·ã§ã³ -ãã®å Žåããããã«ã¯èå³ããããŸããã
DeviationãšErrorMarginã¯ãå€ã瀺ããã©ã¡ãŒã¿ãŒã§ããããšãã°ããžã§ã¹ãã£ãŒäžã®æã®ãæ¯æŠãã§ãã Y軞äžã®äœçœ®ãå€æŽããã«ãX軞ã«æ²¿ã£ãŠå®å šã«å¹³ããªç·ãå·Šã«æç»ã§ããå¯èœæ§ã¯äœããããDeviationãšErrorMarginã¯ããã€ã³ãã®ç§»åãæå¹ãªå¢çã瀺ããŸãã
æšæºã®ãžã§ã¹ãã£ãŒãã©ã¡ãŒã¿ãŒã®å®£èšã¯ãVcl.Touch.Gesturesã¢ãžã¥ãŒã«ã«ãããŸãã
{ Standard gesture definitions } const PDefaultLeft: array[0..1] of TPoint = ((X:200; Y:0), (X:0; Y:0)); CDefaultLeft: TStandardGestureData = ( GestureID: sgiLeft; Options: [goUniDirectional]; Deviation: 30; ErrorMargin: 20); PDefaultRight: array[0..1] of TPoint = ((X:0; Y:0), (X:200; Y:0)); CDefaultRight: TStandardGestureData = ( GestureID: sgiRight; Options: [goUniDirectional]; Deviation: 30; ErrorMargin: 20); PDefaultUp: array[0..1] of TPoint = ((X:0; Y:200), (X:0; Y:0)); CDefaultUp: TStandardGestureData = ( GestureID: sgiUp; Options: [goUniDirectional]; Deviation: 30; ErrorMargin: 20); ...
ãããã£ãŠããžã§ã¹ãã£ã®åœ¢åŒãç¥ã£ãŠãããšãã«ãŒãïŒãã€ã³ãïŒã«å ¥åããŠäžæã®IDãèšå®ããããšã§ãå®è¡æã«ç¬èªã®ããŒãžã§ã³ã®ãžã§ã¹ãã£ãåå¥ã«æºåã§ããŸãã
ãã ããä»ã¯å¿ èŠãããŸããã æšæºã®ãžã§ã¹ãã£ãŒã«åºã¥ããŠäœãã§ããããèŠãŠã¿ãŸãããã
Recognizerãèªèãããžã§ã¹ãã£ã®IDãè¿ãããšã§ãæãç°¡åãªäŸãäœæããŠããŸããããã§ã¯ããŠãŒã¶ãŒãã¿ããã¹ã¯ãªãŒã³ããå ¥åããã«ãŒãã«æè¡çã«é¡äŒŒãã4ã€ã®ãã€ã³ãã®é åãäœæããŸãã
ããšãã°ã次ã®ããã«ïŒ
program recognizer_demo; {$APPTYPE CONSOLE} {$R *.res} uses Windows, Vcl.Controls, SysUtils, TypInfo, Vcl.Touch.Gestures; type TPointArray = array of TPoint; function GetGestureID(Value: TPointArray): Byte; var Recognizer: TGestureRecognizer; GestureID: Integer; Data: TStandardGestureData; Weight, TempWeight: Single; begin Weight := 0; Result := sgiNone; Recognizer := TGestureRecognizer.Create; try for GestureID := sgiLeft to sgiDown do begin FindStandardGesture(GestureID, Data); TempWeight := Recognizer.Match(Value, Data.Points, Data.Options, GestureID, Data.Deviation, Data.ErrorMargin); if TempWeight > Weight then begin Weight := TempWeight; Result := GestureID; end; end; finally Recognizer.Free; end; end; const gesture_id: array [sgiNone..sgiDown] of string = ( 'sgiNone', 'sgiLeft', 'sgiRight', 'sgiUp', 'sgiDown' ); var I: Integer; Data: TPointArray; begin SetLength(Data, 11); // for I := 0 to 10 do begin Data[I].X := I * 10; Data[I].Y := 0; end; Writeln(gesture_id[GetGestureID(Data)]); // for I := 0 to 10 do begin Data[I].X := 500 - I * 10; Data[I].Y := 0; end; Writeln(gesture_id[GetGestureID(Data)]); // for I := 0 to 10 do begin Data[I].X := 0; Data[I].Y := 500 - I * 10; end; Writeln(gesture_id[GetGestureID(Data)]); // for I := 0 to 10 do begin Data[I].X := 0; Data[I].Y := I * 10; end; Writeln(gesture_id[GetGestureID(Data)]); Readln; end.
éå§åŸã次ã®å³ã衚瀺ãããŸãã
äºæ³éãã
ãã®äŸã®ãœãŒã¹ã³ãŒãã¯ããœãŒã¹ãå«ãã¢ãŒã«ã€ãå ã®ãã©ã«ããŒã ã\ Demos \èªèæ©èœ ãã«ãããŸãã
ãããŠä»...
7.ãã«ãã¿ãããžã§ã¹ãã£ïŒãžã§ã¹ãã£ïŒãèªèãã
ãã®ç« ã§ã¯ããã®èšäºã®äž»ãªã¢ã€ãã¢ã«ã€ããŠèª¬æããŸãããã®ããã«èšãã°ããã®ããã¹ãããã¹ãŠèŒã£ãŠãããããã§ãã
ä»-æè¡çãªè©³çŽ°ã¯ãªããã¢ãããŒãèªäœã®ã¿ïŒ
ãããã£ãŠãçŸåšå©çšå¯èœãªãã®ã¯æ¬¡ã®ãšããã§ãã
- åã¿ããã»ãã·ã§ã³ããããŒã¿ãååŸããæ¹æ³ãç¥ã£ãŠããŸãã
- åã¿ããã»ãã·ã§ã³ã®ãžã§ã¹ãã£ãèªèã§ããŸãã
äŸïŒ
- ãŠãŒã¶ãŒã¯ã¿ããã¹ã¯ãªãŒã³ãã¯ãªãã¯ããŠå·Šã«ã¹ã¯ã€ãããŸããã
- ON_TOUCH + TOUCHEVENTF_DOWNãã³ãã©ãŒã§ã»ãã·ã§ã³ã®éå§ãèšé²ããTOUCHEVENTF_MOVEã®å°çæã«ãã¹ãŠã®ãŠã§ã€ãã€ã³ããèšé²ããTOUCHEVENTF_UPãåãåã£ãç¬éã«ã以åã«èšé²ãããã€ã³ãé åãGetGestureIDé¢æ°ã«æž¡ããŸããã
- çµæãå°ãåºããŸããã
ãããããŠãŒã¶ãŒãäžåºŠã«2æ¬ã®æã§åãããšããããšæ³åããŠãã ããã
- åæã«ã€ããŠãç¬èªã®ã»ãã·ã§ã³ãéå§ããŸãã
- 圌女ã®ã«ãŒããæžããŸãã
- åã»ãã·ã§ã³ã®çµããã«ããžã§ã¹ãã£èªèã«è»¢éããŸãã
åããŠã£ã³ããŠã§å®è¡ããã2ã€ã®ã»ãã·ã§ã³ã®ãžã§ã¹ãã£IDãäžèŽããå ŽåïŒããšãã°ãsgiLeftïŒãçµè«ãåºãããšãã§ããŸã-2æ¬ã®æã§å·Šã«ã¹ã¯ã€ãããŸããã
ããããã»ãã·ã§ã³ã«ãŒãäžã®ãã¹ãŠã®ãã€ã³ãã«åã座æšãå«ãŸããŠããå Žåã¯ã©ãã§ããããïŒ
ãã®åŸããžã§ã¹ãã£ãŒã¯ãªããããããã¿ããïŒ1æ¬ãŸãã¯è€æ°ã®æïŒãçºçããŸããã
ããã«ãPopupMenuãé垞衚瀺ãããããã¬ã¹ã¢ã³ãã¿ããããžã§ã¹ãã£ããã®æ¡ä»¶ã«è©²åœããŸãã
ãããã£ãŠãåé¡ã®äž»ãªå®åŒåãèæ ®ããŠãå¿ èŠãªãã¹ãŠã®ãžã§ã¹ãã£ã1æ¬ã2æ¬ã3æ¬ã®æã§å¶åŸ¡ã§ããŸãïŒãã ããå°ãªããšã10æ¬ãã¹ãŠïŒã
ãŸãã2ã€ã®ã»ãã·ã§ã³ã®ãžã§ã¹ãã£ãŒãäžèŽããªãã£ãå Žåã¯ã©ããªããŸããïŒ
ããããåæããã«ã¯ãããã¯åé¡ã®çŸåšã®ã¹ããŒãã¡ã³ãã«ã¯å«ãŸããŠããŸããããæåã®ã»ãã·ã§ã³ã®sgiLeftãžã§ã¹ãã£ãŒãš2çªç®ã®ã»ãã·ã§ã³ã®sgiRightãžã§ã¹ãã£ãŒããºãŒã ãšããŠè§£éã§ãããšèšã£ãŠãå®å šã§ãã2åã®ã¿ããã»ãã·ã§ã³ã®ã¿ã«åºã¥ãsgiSemiCircleLeftãŸãã¯sgiSemiCircleRightãžã§ã¹ãã£ã«åºã¥ããŠãRotateã§ããæ€åºããããšãã§ããŸãã
貫éïŒ
ãã®æ¹æ³ã§ç°¡åã«ãšãã¥ã¬ãŒãã§ãããžã§ã¹ãã£ã®æ¢å®ã®ãªã¹ãã次ã«ç€ºããŸã
ãWindowsã¿ãããžã§ã¹ãã£ã®æŠèŠ
æ®å¿µãªãããäœããã®çç±ã§ããããã¯ãã¹ãŠXE4ã«å®è£ ãããŠãããã第7ããŒãžã§ã³ããã®ã¿å©çšå¯èœã«ãªããŸããïŒå®å šã«ç¢ºå®ãã©ããã¯ããããŸããïŒã
8.ãšã³ãžã³ã®æè¡èšç»
çè«éšåãçµäºããããä»åºŠã¯ããããã¹ãŠãå®è·µããéçºè ãçŽé¢ããŠããããã€ãã®åé¡ãããã«æ€èšããŸãã
åé¡ã®åæ°ïŒ
éåžžãã¢ããªã±ãŒã·ã§ã³ã«ã¯æ°çŸã®ãŠã£ã³ããŠããããŸããã»ãšãã©ã®å Žåãã·ã¹ãã ã¯WM_LBUTTONCLICKãã©ã³ã¡ãã»ãŒãžãªã©ãçæãããŠã£ã³ããŠã®éåžžã®åäœïŒãã¿ã³ãç·šéãã¹ã¯ããŒã«ãªã©ïŒã«ã¯ååã§ãããåãSysListView32ã«ã¯ååã§ãWM_SCROLLã¡ãã»ãŒãžãçæãããªãããã2æ¬ã®æã§ã®ãžã§ã¹ãã£ãŒã«ããã¹ã¯ããŒã«ã¯çºçããŸãããããããã«ã¹ã¿ã ã³ã³ãããŒã«ããããŸãã
åãŠã£ã³ããŠã®ãŠã£ã³ããŠããã·ãŒãžã£ãæ¡åŒµããã®ã¯éåžžã«æéãããããããäœããã®æ¹æ³ã§æ±ºå®ããå¿ èŠããããŸããã©ã®ãŠã£ã³ããŠããã«ãã¿ããããµããŒãããå¿ èŠãããããããæãæ®éçã«è¡ãå¿ èŠããããŸãã
ããã¯æ¬¡ã®ãšããã§ãããŠã£ã³ããŠãç»é²ããããã«ãã¿ããã®ãã¹ãŠã®äœæ¥ãæ åœããç¹å®ã®ãã«ãã¿ãããããŒãžã£ãŒãå¿ èŠã§ãã
åé¡ç¹2ïŒ
TWinControlã®åã€ã³ã¹ã¿ã³ã¹ãæžãæããã«å°ãæ®éçã«èšè¿°ããŠãããããRecreateWndã¯éåžžã®VCLã¡ã«ããºã ã®1ã€ãåŒã³åºãããããŠã£ã³ããŠã®åäœæãäœããã®æ¹æ³ã§è¿œè·¡ããå¿ èŠããããŸãããããè¡ããªããšãæåã«ãŠã£ã³ããŠãåäœæãããšãã«ã以åã«ç»é²ããTWinControlãWM_TOUCHã¡ãã»ãŒãžã®åä¿¡ãåæ¢ããããããããŒãžã£ãŒã®ãã¹ãŠã®äœæ¥ãå¹³æºåãããŸãã
åé¡çªå·3ïŒ
ãããŒãžã£ãŒã¯ãã¿ããã»ãã·ã§ã³ã«é¢ãããã¹ãŠã®ããŒã¿ãä¿åããã»ãã·ã§ã³ã®éå§ãšçµäºã®äžæã®ç¶æ³ãåŠçã§ããå¿ èŠããããŸãïŒããŠã³ãã©ã°ãšã¢ãããã©ã°ã®éç¥ãåžžã«éä¿¡ããããšã¯éããªãããïŒããŸããã»ãã·ã§ã³ã®é·ããéåžžã«é·ããªãå¯èœæ§ãããããšã«æ³šæããŠãã ããã»ãã·ã§ã³ã®ã«ãŒãã®ãã¹ãŠã®ãã€ã³ããä¿åããå Žåã®ã¡ã¢ãªæ¶è²»ã
ãŸãããã«ãã¿ãããããŒãžã£ãŒãç°ãªããŠã£ã³ããŠå ã®ãžã§ã¹ãã£ãåºå¥ã§ããããã«ããããšæããŸãã
ããšãã°ããŠãŒã¶ãŒãå·Šã®ãŠã£ã³ããŠã«2æ¬ã®æã眮ããå³ã«2æ¬ã®æã眮ããŠïŒ4ã€ã®ãã«ãã¿ããã»ãã·ã§ã³ïŒãäžå€®ã«æãæ¥ç¶ãããšãéç¥ã¯å³ã«2æ¬æã®ãžã§ã¹ãã£ãŒããå·Šã«2æ¬æã®ãžã§ã¹ãã£ãŒãåãåãã¯ãã§ãã
ããããæ®å¿µãªãããããã¯æ©èœããŸãããWM_TOUCHã¡ãã»ãŒãžã¯ãã»ãã·ã§ã³ãéå§ããããŠã£ã³ããŠã«ã®ã¿å±ããæ®ãã®ãŠã£ã³ããŠã¯ç¡èŠãããŸãã
9.ãã«ãã¿ãããšã³ãžã³ã®ããŒã¹ãã¬ãŒã ãæ§ç¯ãã
æåã«ãã¯ã©ã¹å®è£ ã®ãã¥ã¢ã³ã¹ã決å®ããŸãããã
æè¡çã«ã¯ãå€éšããã°ã©ããŒã®èŠ³ç¹ããæã䟿å©ãªã®ã¯ããã¹ãŠã®äœæ¥ãåŒãåããæçµã€ãã³ãã®åŒã³åºããé€ããŠéçºè ã«éç¥ãããŠãããŒãµã«ãšã³ãžã³ã®å®è£ ã§ãã
ãã®å Žåãéçºè ã¯å¿ èŠãªãŠã£ã³ããŠãäžåºŠãšã³ãžã³ã«ç»é²ããããããã®ãžã§ã¹ãã£ãŒãåæããŠïŒç¹å®ã®ãŠã£ã³ããŠã«åããŠïŒå¿ èŠãªãã®ãåŠçããã ãã§ããããšãã°ã2æ¬æã®ãžã§ã¹ãã£ãŒã§åãã¹ã¯ããŒã«ããšãã¥ã¬ãŒãããŸãã
ãšã³ãžã³èªäœã¯ã·ã³ã°ã«ãã³ãšããŠå®è£ ãããŸãã
第äžã«ãåžžã«åãããšãè¡ãã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãäœæããŠãæå³ããããŸãããããã¯ãããŒã¿ã¹ãã¬ãŒãžçšã«åŒ·åãããTStringListã§ã¯ãªãããã¹ãŠã®ãããžã§ã¯ããŠã£ã³ããŠã«å¯ŸããŠåäžã®äœæ¥ããžãã¯ãå®è£ ãããšã³ãžã³ã§ãã
次ã«ããšã³ãžã³èªäœã®å®è£ ã«ã¯ããããªãã¥ã¢ã³ã¹ããããŸãïŒããã«ã€ããŠã¯å°ãåŸã§ïŒããã®ãããã·ã³ã°ã«ãã³åœ¢åŒã®å®è£ ãæãç°¡åã«ãªããŸããããã§ãªãå Žåã¯ãã¯ã©ã¹ã®ããžãã¯ãæ ¹æ¬çã«åè€éåããå¿ èŠããããŸãã
ãããã£ãŠããšã³ãžã³ã¯ä»¥äžãæäŸããå¿ èŠããããŸãã
- ãŠã£ã³ããŠãç»é²ããç»é²ãããŠã£ã³ããŠãåé€ããæ¹æ³ïŒ
- éçºè ããã³ãã©ãŒãå®è£ ããå¿ èŠãããå€éšã€ãã³ãã®ã»ããã
å€éšã€ãã³ãã¯æ¬¡ã®ãããªãã®ã§ã
ãOnBeginTouch-ãã®ã€ãã³ãã¯ãWM_TOUCHã¡ãã»ãŒãžãåä¿¡ãããšãã«çºçããŸãã
説æãããŠãã ããïŒ4çªç®ã®ç« ã§ã¯ã次ã®ã³ãŒããäžããããŸããã
// InputsCount := Msg.WParam and $FFFF;
ã€ãŸãææŒãè»ã®ããã€ãã®å®éã®ãã€ã³ãããããŸãã
éçºè ã«èŠåããã®ã¯ããã®æ°ã«ã€ããŠã§ãã
OnTouch-ãã®ã€ãã³ãã§ã¯ãåTTouchInputæ§é ã«å«ãŸããããŒã¿ãéçºè ã«éç¥ããŸãããããå°ãã³ãŒãã³ã°ããŸãã ïŒãã€ã³ãã«é¢ããããŒã¿ããŠã£ã³ããŠåº§æšã«å€æããæ£ãããã©ã°ãèšå®ãããªã©ããªãéçºè ã«åé·ãªæ å ±ãããŒãããåé·ãªã³ãŒããæžãããã®ã§ããïŒïŒ
OnEndTouch-ããã«ãããWM_TOUCHã¡ãã»ãŒãžåŠçãµã€ã¯ã«ãå®äºãããšè¡šç€ºãããŸãã
OnGecture-ãžã§ã¹ãã£ãèªèããããšãšã³ãžã³ãå€æãããšãéçºè ã¯ãã®ã¡ãã»ãŒãžãåãåããŸãã
ã¯ã©ã¹ã¯ã·ã³ã°ã«ãã³ãšããŠå®è£ ããããã®äžã«è€æ°ã®ãŠã£ã³ããŠãç»é²ãããããã4ã€ã®ã€ãã³ããã¹ãŠãã¯ã©ã¹ããããã£ãšããŠå®£èšããããšã¯ã§ããŸããã
æ£ç¢ºã«èšããšãããã¯ãã¡ããå¯èœã§ããã2çªç®ã«ç»é²ããããŠã£ã³ããŠã¯ããã«ã€ãã³ããã³ãã©ãŒãèªåèªèº«ã«åå²ãåœãŠããæåã®ãŠã£ã³ããŠã¯éãã«åžããªããã°ãªããŸããã
ãããã£ãŠãç»é²ããããŠã£ã³ããŠã®ãªã¹ãã«å ããŠããããã«å²ãåœãŠããããšã³ãžã³ã€ãã³ããã³ãã©ãä¿æããå¿ èŠããããŸãã
ãã ããããã§ãã¹ãŠãå®è¡ããããšããŸãã
æ°ãããããžã§ã¯ããäœæããSimpleMultiTouchEngineãªã©ã®ååã®æ°ããã¢ãžã¥ãŒã«ãè¿œå ããŸãã
æåã«ãWM_TOUCHãåŠçãããšãã«é¢å¿ã®ãããã©ã°ã宣èšããŸãã
type TTouchFlag = ( tfMove, // tfDown, // tfUp // ); TTouchFlags = set of TTouchFlag;
åãã€ã³ãã«ã€ããŠå€éšéçºè ã«æž¡ãæ§é ã説æããŸãã
TTouchData = record Index: Integer; // TTouchInput ID: DWORD; // ID Position: TPoint; // Flags: TTouchFlags; // end;
OnTouchBeginã€ãã³ãã®å®£èšã¯æ¬¡ã®ããã«ãªããŸãã
TTouchBeginEvent = procedure(Sender: TObject; nCount: Integer) of object;
ãããŠããããOnTouchã®å€èŠ³ã§ãã
TTouchEvent = procedure(Sender: TObject; Control: TWinControl; TouchData: TTouchData) of object;
OnEndTouchã®å Žåãéåžžã®TNotifyEventã§ååã§ãã
ç»é²ãããåãŠã£ã³ããŠã«å²ãåœãŠãããå²ãåœãŠãããã€ãã³ããã³ãã©ã®ããŒã¿ã¯ã次ã®æ§é ã«æ ŒçŽãããŸãã
TTouchHandlers = record BeginTouch: TTouchBeginEvent; Touch: TTouchEvent; EndTouch: TNotifyEvent; end;
æ°ããã¯ã©ã¹ã宣èšããŸãïŒ
TSimleMultiTouchEngine = class private const MaxFingerCount = 10; private type TWindowData = record Control: TWinControl; Handlers: TTouchHandlers; end; private FWindows: TList<TWindowData>; FMultiTouchPresent: Boolean; protected procedure DoBeginTouch(Value: TTouchBeginEvent; nCount: Integer); virtual; procedure DoTouch(Control: TWinControl; Value: TTouchEvent; TouchData: TTouchData); virtual; procedure DoEndTouch(Value: TNotifyEvent); virtual; protected procedure HandleTouch(Index: Integer; Msg: PMsg); procedure HandleMessage(Msg: PMsg); public constructor Create; destructor Destroy; override; procedure RegisterWindow(Value: TWinControl; Handlers: TTouchHandlers); procedure UnRegisterWindow(Value: TWinControl); end;
é çªã«ïŒ
MaxFingerCountå®æ°ã«ã¯ãã¯ã©ã¹ã§äœ¿çšã§ããææŒãè»ã®æ倧æ°ãå«ãŸããŠããŸãã
æ§é TWindowData-ç»é²ããããŠã£ã³ããŠãšãããã°ã©ããŒãå²ãåœãŠããã³ãã©ãŒã®ãªã¹ããå«ãŸããŸãã
ãã£ãŒã«ãFWindowsïŒTList-ç»é²ããããŠã£ã³ããŠãšãã³ãã©ãŒã®ãªã¹ãã§ãããããã¯ã©ã¹ã§ã®äœæ¥ãéããŠèžããŸãã
FMultiTouchPresentãã£ãŒã«ãã¯ãã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§åæåããããã©ã°ã§ãã
ããŒããŠã§ã¢ããã«ãã¿ãããä¿æããŠããå Žåã¯Trueãå«ãŸããŸãããã®ãã©ã°ã«åºã¥ããŠãã¯ã©ã¹ã®ããžãã¯ã®äžéšãç¡å¹ã«ãªããŸãïŒãŸã å®è¡ã§ããªãã®ã«ããªãè¿œå ã®ãžã§ã¹ãã£ãŒãè¡ãã®ã§ããïŒïŒã
æåã®ä¿è·ãããã»ã¯ã·ã§ã³-䟿å®äžãå€éšã€ãã³ããžã®ãã¹ãŠã®åŒã³åºããè¡ãããŸãã
HandleTouchããã·ãŒãžã£ã¯ãšã³ãžã³ã®ã³ã¢ãšã³ãžã³ã§ãããWM_TOUCHã¡ãã»ãŒãžã®åŠçãæ åœããã®ã¯åœŒå¥³ã§ãã
HandleMessageããã·ãŒãžã£ã¯è£å©ã§ãããã®ã¿ã¹ã¯ã¯ãç»é²ãããŠãããŠã£ã³ããŠã®ã©ãã«ã¡ãã»ãŒãžãéä¿¡ãããããå€å¥ããHandleTouchãåŒã³åºããŠãèŠã€ãã£ããŠã£ã³ããŠã®ã€ã³ããã¯ã¹ãæž¡ãããšã§ãã
ãããªãã¯ã»ã¯ã·ã§ã³-ã³ã³ã¹ãã©ã¯ã¿ããã¹ãã©ã¯ã¿ããŠã£ã³ããŠã®ç»é²ããã³ç»é²è§£é€ã
ã¯ã©ã¹ã®å®è£
ãé²ããåã«ãããã«ã·ã³ã°ã«ãã³ããããäœæããŸãã
function MultiTouchEngine: TSimleMultiTouchEngine; implementation var _MultiTouchEngine: TSimleMultiTouchEngine = nil; function MultiTouchEngine: TSimleMultiTouchEngine; begin if _MultiTouchEngine = nil then _MultiTouchEngine := TSimleMultiTouchEngine.Create; Result := _MultiTouchEngine; end; ... initialization finalization _MultiTouchEngine.Free; end.
ãããŠããã¹ãŠã®æåŸã«ããšã³ãžã³ã«ç»é²ãããŠãããŠã£ã³ããŠã«éä¿¡ãããWM_TOUCHã¡ãã»ãŒãžãåä¿¡ããã³ãŒã«ããã¯ãã©ããã
var FHook: HHOOK = 0; function GetMsgProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall; begin if (nCode = HC_ACTION) and (WParam = PM_REMOVE) then if PMsg(LParam)^.message = WM_TOUCH then MultiTouchEngine.HandleMessage(PMsg(LParam)); Result := CallNextHookEx(FHook, nCode, WParam, LParam); end;
念ã®ããã䜿çšãããã¢ãžã¥ãŒã«ã®ãªã¹ãã¯æ¬¡ã®ããã«ãªããŸãã
uses Windows, Messages, Classes, Controls, Generics.Defaults, Generics.Collections, Vcl.Touch.Gestures;
ããã§ã¯ããšã³ãžã³èªäœã®å®è£ ã«ã€ããŠèŠãŠãããŸããããã³ã³ã¹ãã©ã¯ã¿ãŒããå§ããŸãããã
constructor TSimleMultiTouchEngine.Create; var Data: Integer; begin // , Data := GetSystemMetrics(SM_DIGITIZER); FMultiTouchPresent := (Data and NID_READY <> 0) and (Data and NID_MULTI_INPUT <> 0); // , if not FMultiTouchPresent then Exit; // FWindows := TList<TWindowData>.Create( // IndexOf Control // TComparer<twindowdata>.Construct( function (const A, B: TWindowData): Integer begin Result := Integer(A.Control) - Integer(B.Control); end) ); end;
食ãæ°ã®ãªãããªãã·ã³ãã«ãªãã¶ã€ããŒãã³ã¡ã³ãã§ãã¹ãŠã®ã¹ããããèŠãããšãã§ããŸãã
ãã ãããã¹ãã©ã¯ã¿ãç°¡åã§ãã
destructor TSimleMultiTouchEngine.Destroy; begin if FHook <> 0 then UnhookWindowsHookEx(FHook); FWindows.Free; inherited; end;
ãã¹ãã©ã¯ã¿ã®å¯äžã®ãã¥ã¢ã³ã¹ã¯ããã©ããã以åã«ã€ã³ã¹ããŒã«ãããŠããå Žåããã®é€å»ã§ãã
次ã«ãéçºè ãå€éšããå©çšã§ãã2ã€ã®åºæã®ãããªãã¯ããã·ãŒãžã£ã®å®è£ ã«ç§»ããŸãããã
ãšã³ãžã³ã§ã®ãŠã£ã³ããŠç»é²ïŒ
procedure TSimleMultiTouchEngine.RegisterWindow(Value: TWinControl; Handlers: TTouchHandlers); var WindowData: TWindowData; begin // - if not FMultiTouchPresent then Exit; // IndexOf , WindowData.Control := Value; // , // if FWindows.IndexOf(WindowData) < 0 then begin // WindowData.Handlers := Handlers; // RegisterTouchWindow(Value.Handle, 0); // FWindows.Add(WindowData); end; // if FHook = 0 then FHook := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, HInstance, GetCurrentThreadId); end;
ãã ããIndexOfãåŒã³åºãå Žåã®å¯äžã®ãã¥ã¢ã³ã¹ã¯ãã¹ãŠã³ã¡ã³ããããŸãã CompareMemã2ã€ã®æ§é ãçžäºã«æ¯èŒããã®ã§ã¯ãªããæ§é ã®1ã€ã®ãã£ãŒã«ãïŒControlïŒã®ã¿ã«å¯ŸããŠæ©èœããããã«ãTComparerã¯ãªã¹ãã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã«å®è£ ãããŸããã
ã³ãŒããããããããã«ãããžãã¯ã¯åçŽã§ãããŠã£ã³ããŠãäžè¬ãªã¹ãã«è¿œå ãããšãã¯ã©ã¹ã¯WH_GETMESSAGEãã©ãããéå§ãïŒä»¥åã«å®è¡ãããŠããªãå ŽåïŒãçŸåšã®ã¹ã¬ããå ã§ã®ã¿æ©èœããŸãã
å€æ°FMultiTouchPresentã«ã€ããŠã¯å¥ã«èª¬æããŸãã
ã³ãŒããããããããã«ãããã¯åã«ãã¥ãŒãºãšããŠæ©èœããæçšãªããšãã§ããªãå Žåã¯ã¯ã©ã¹ã®ããžãã¯å šäœãç¡å¹ã«ããŸãã
åé€ãããšãããŒããŠã§ã¢ã«ã¿ããã¹ã¯ãªãŒã³ããŸã£ãããªãå Žåã®ãã©ããã®èšå®ã«ãããã¢ããªã±ãŒã·ã§ã³ã®åãŠã£ã³ããŠã®ã¡ãã»ãŒãžååŸãµã€ã¯ã«ã«ããããªããªãŒããŒãããããçºçããŸããå¿ èŠã§ããïŒ
ç»é²ãããŠã£ã³ããŠãåé€ããããšãåãåçã«åŸãããŠã£ã³ããŠããããªãå Žåã¯ãã©ããããªãã«ãªããŸãã
procedure TSimleMultiTouchEngine.UnRegisterWindow(Value: TWinControl); var Index: Integer; WindowData: TWindowData; begin // - if not FMultiTouchPresent then Exit; // IndexOf , WindowData.Control := Value; // Index := FWindows.IndexOf(WindowData); if Index >= 0 then // , FWindows.Delete(Index); // , if FWindows.Count = 0 then begin // UnhookWindowsHookEx(FHook); FHook := 0; end; end;
å®éããšã³ãžã³ã®ããžãã¯å šäœã¯åçŽã§ããç»é²ã®ãŠã£ã³ããŠãåãå ¥ããWM_TOUCHã¡ãã»ãŒãžãåä¿¡ãããšãã¯ã©ã¹ã®ã·ã³ã°ã«ãã³ã«ã¢ã¯ã»ã¹ããŠHandleMessageããã·ãŒãžã£ãåŒã³åºããã©ãããèµ·åããŸããã
procedure TSimleMultiTouchEngine.HandleMessage(Msg: PMsg); var I: Integer; begin for I := 0 to FWindows.Count - 1 do // , if FWindows[I].Control.Handle = Msg^.hwnd then begin // HandleTouch(I, Msg); Break; end; end;
ãããŠããã«ãäœæ¥ã®è«çå šäœãå±éããã¯ã©ã¹ã®äžå¿çãªæé ããããŸãã
procedure TSimleMultiTouchEngine.HandleTouch(Index: Integer; Msg: PMsg); var TouchData: TTouchData; I, InputsCount: Integer; Inputs: array of TTouchInput; Flags: DWORD; begin // , InputsCount := Msg^.wParam and $FFFF; if InputsCount = 0 then Exit; // if InputsCount > MaxFingerCount then InputsCount := MaxFingerCount; // SetLength(Inputs, InputsCount); if not GetTouchInputInfo(Msg^.LParam, InputsCount, @Inputs[0], SizeOf(TTouchInput)) then Exit; CloseTouchInputHandle(Msg^.LParam); // // DoBeginTouch(FWindows[Index].Handlers.BeginTouch, InputsCount); for I := 0 to InputsCount - 1 do begin TouchData.Index := I; // ID // ( Down Up) // TouchData.ID := Inputs[I].dwID; // TouchData.Position.X := TOUCH_COORD_TO_PIXEL(Inputs[I].x); TouchData.Position.Y := TOUCH_COORD_TO_PIXEL(Inputs[I].y); TouchData.Position := FWindows[Index].Control.ScreenToClient(TouchData.Position); // TouchData.Flags := []; Flags := Inputs[I].dwFlags; if Flags and TOUCHEVENTF_MOVE <> 0 then Include(TouchData.Flags, tfMove); if Flags and TOUCHEVENTF_DOWN <> 0 then Include(TouchData.Flags, tfDown); if Flags and TOUCHEVENTF_UP <> 0 then Include(TouchData.Flags, tfUp); // DoTouch(FWindows[Index].Control, FWindows[Index].Handlers.Touch, TouchData); end; // // DoEndTouch(FWindows[Index].Handlers.EndTouch); end;
ããã«ã€ããŠã¯èšäºã®ç¬¬5ç« ã§ãã§ã«èª¬æããŠãããããã³ãŒãã«ã€ããŠããã«èª¬æããããšã¯æå³ããããŸãããçµæãšããŠåŸããããã«ãã¿ãããšã³ãžã³ã®æäœã«ç§»ããŸãããããœãŒã¹ã¢ãŒã«ã€ã
ã®ãã\ Demos \ multitouch_engine_demo \ããã©ã«ããŒã«ããSimleMultiTouchEngine.pasã¢ãžã¥ãŒã«ã®ãœãŒã¹ã³ãŒãã
10. TSimleMultiTouchEngineã®äœ¿çš
æ°ãããã®ãæãä»ãããšã¯ããã5çªç®ã®ç« ãããããžã§ã¯ããåçŸããŸããäž»ãªå€æŽç¹ã¯ãTSimleMultiTouchEngineããã«ãã¿ãããµããŒããæäŸããããšã§ãã
第9ç« ã§äœæãããããžã§ã¯ãã§ã第5ç« ã®TDataæ§é äœãšFDataé åã®å®£èšãè¿œå ããFormPaintãã³ãã©ãŒãã³ããŒããŸããããã¯ãã¹ãŠå€æŽãããŸããã
2ã€ã®ãã³ãã©ãŒã宣èšããŸãã
procedure OnTouch(Sender: TObject; Control: TWinControl; TouchData: TTouchData); procedure OnTouchEnd(Sender: TObject);
䜿çšããã¢ãžã¥ãŒã«ã§ãSimleMultiTouchEngineãæ¥ç¶ããã¯ã©ã¹ã³ã³ã¹ãã©ã¯ã¿ãŒããããã«å€æŽããŸãã
procedure TdlgMultiTouchEngineDemo.FormCreate(Sender: TObject); var I: Integer; Handlers: TTouchHandlers; begin DoubleBuffered := True; // RegisterTouchWindow(Handle, 0); Randomize; for I := 0 to 9 do begin FData[I].Color := Random($FFFFFF); FData[I].ARect.Left := Random(ClientWidth - 100); FData[I].ARect.Top := Random(ClientHeight - 100); FData[I].ARect.Right := FData[I].ARect.Left + 100; FData[I].ARect.Bottom := FData[I].ARect.Top + 100; end; ZeroMemory(@Handlers, SizeOf(TTouchHandlers)); Handlers.Touch := OnTouch; Handlers.EndTouch := OnTouchEnd; MultiTouchEngine.RegisterWindow(Self, Handlers); end;
å®éãå€æŽã¯æå°éã§ãããRegisterTouchWindowãåŒã³åºã代ããã«ãå®è£ ããã°ããã®MultiTouchEngineã«äœæ¥ãã·ããããŸãã
OnTouchEndãã³ãã©ãŒã¯ç°¡åã§ãã
procedure TdlgMultiTouchEngineDemo.OnTouchEnd(Sender: TObject); begin Repaint; end;
ãã£ã³ãã¹å šäœãåæç»ããã ãã§ãã
ããã§ãOnTouchãã³ãã©ãŒã®ã³ãŒãïŒä»¥åã¯WmTouchãã³ãã©ãŒã«å®è£ ãããŠããïŒãäœã«å€ãã£ãããèŠãŠã¿ãŸãããã
procedure TdlgMultiTouchEngineDemo.OnTouch(Sender: TObject; Control: TWinControl; TouchData: TTouchData); function GetIndexAtPoint(pt: TPoint): Integer; var I: Integer; begin Result := -1; for I := 0 to 9 do if PtInRect(FData[I].ARect, pt) then begin Result := I; Break; end; end; function GetIndexFromID(ID: Integer): Integer; var I: Integer; begin Result := -1; for I := 0 to 9 do if FData[I].TouchID = ID then begin Result := I; Break; end; end; var Index: Integer; R: TRect; begin if tfDown in TouchData.Flags then begin Index := GetIndexAtPoint(TouchData.Position); if Index < 0 then Exit; FData[Index].Touched := True; FData[Index].TouchID := TouchData.ID; FData[Index].StartRect := FData[Index].ARect; FData[Index].StartPoint := TouchData.Position; Exit; end; Index := GetIndexFromID(TouchData.ID); if Index < 0 then Exit; if tfUp in TouchData.Flags then begin FData[Index].Touched := False; FData[Index].TouchID := -1; Exit; end; if not (tfMove in TouchData.Flags) then Exit; if not FData[Index].Touched then Exit; R := FData[Index].StartRect; OffsetRect(R, TouchData.Position.X - FData[Index].StartPoint.X, TouchData.Position.Y - FData[Index].StartPoint.Y); FData[Index].ARect := R; end;
ã€ããªãã®ãŒã¯ããŸãå€åããŠããŸããããå€ãããŒãžã§ã³ãããã¯ããã«èªã¿ããããªã£ãŠããŸãã
ãããŠæãéèŠãªã®ã¯ã第5ç« ã®ã³ãŒããšåãããã«æ©èœããããšã§ãã
ãµã³ãã«ã®ãœãŒã¹ã³ãŒãã¯ããœãŒã¹ã¢ãŒã«ã€ãå ã®ãã©ã«ã㌠" ã\ Demos \ multitouch_engine_demo \ "ã«ãããŸãã
ããã§ãåããã ã¹ãšã¯äœã§ãããããããããªãã¯å°ããŸããçµå±ã®ãšãããã¡ã€ã³ãã©ãŒã ã®ã³ãŒãã®ãµã€ãºãšãã®æäœã®ã¢ã«ãŽãªãºã ã¯å®éã«ã¯å€æŽããããããã«ãè¿œå ã®ã¢ãžã¥ãŒã«ãSimleMultiTouchEngine.pasã®åœ¢åŒã§277è¡ã®ã³ãŒãïŒã³ã¡ã³ãä»ãïŒãšããŠçŸããŸããã
ãã®ãŸãŸã«ããŠãæ¬åœã«å¿ èŠãªå Žåã«ã®ã¿WM_TOUCHãã³ãã©ãŒãèªåã§å®è£ ããæ¹ãç°¡åãããããŸããã
ååãšããŠãããããã®æ¹æ³ã§ã-ãã®ãšã³ãžã³ã¯ã第8ç« ã§è¿°ã¹ã3ã€ã®æåã®åé¡ã®ã¿ã解決ããŸãããæ¬åœã§ãã
ãããŠãã·ã ã¹ã¯æ¬¡ã®éãã§ã...
11.ãšã³ãžã³ã«ãžã§ã¹ãã£ãŒã®ãµããŒããå«ããŸã
äžèšã§å®è£ ãããMultiTouchEngineã«ã¯ãèšç»ãããåé¡ã®æ®ãã®2ã€ã®ãã€ã³ãã«å¯Ÿãã解決çã¯ãããŸããããããªãã§ã¯ããããžã§ã¯ãéå±€ã®åãªãè¿œå ã¯ã©ã¹ã«ãªããŸãïŒãã¡ããããã®ã¯ã©ã¹ã¯ãã¹ãŠã®èŠããã§ãã人ã«ãã«ãã¿ãããæäŸã§ããŸãããæ¬è³ªã¯å€ãããŸããïŒã
åé¡3ããããã«å§ããŸãããã
ãŸãããžã§ã¹ãã£ãŒãšã³ãžã³ãšå€éšã€ãã³ããã³ãã©ãŒã«ãã£ãŠèªèãããåã宣èšããŸãã
// TGestureType = ( gtNone, // gtTap, gt2Tap, gt3Tap, // (1, 2, 3 ) gtLeft, gtRight, gtUp, gtDown, // gt2Left, gt2Right, gt2Up, gt2Down, // gt3Left, gt3Right, gt3Up, gt3Down // ); // TGestureEvent = procedure(Sender: TObject; Control: TWinControl; GestureType: TGestureType; Position: TPoint; Completed: Boolean) of object;
ãã®ã¯ã©ã¹ã§ã¯ã15çš®é¡ã®ãžã§ã¹ãã£ãŒãèªèã§ããå¿ èŠããããŸãïŒgtNoneãé€ãïŒã
TGestureEvent宣èšã®Completedãã©ã¡ãŒã¿ãŒã«æ³šæããŠãã ããããã®ãã©ã°ã¯ããžã§ã¹ãã£ã®å®äºãéçºè ã«éç¥ããŸãïŒWM_TOUCH + TOUCHEVENTF_UPã¡ãã»ãŒãžãå°çããŸãïŒã
ãããè¡ãããçç±ïŒããšãã°ããŠãŒã¶ãŒã2æ¬ã®æã§ã¿ããã¹ã¯ãªãŒã³ãã¯ãªãã¯ããŠå·Šã«ç§»åããå ŽåãååãšããŠãŠã£ã³ããŠãã¹ã¯ããŒã«ããå¿ èŠããããŸããããžã§ã¹ãã£ãå®äºããã®ãåŸ ã€ãšæ£ããåäœããªãããããã«ãã¿ãããšã³ãžã³ã¯å®æçã«å€éšOnGestureã€ãã³ããçæãããã®äžã§çºçããããšãã§ããŸãææŒãè»ã®ã»ãã·ã§ã³äžã«å¿ èŠãªå³ã¹ã¯ããŒã«ãéçºè ã¯ãã®ãã³ãã©ãŒã§ããžã§ã¹ãã£ãŒãå®äºãããã©ãããCompletedãã©ã¡ãŒã¿ãŒã«ãã£ãŠç解ã§ããŸãïŒããšãã°ãgtTapã衚瀺ãããCompletedãã©ã¡ãŒã¿ãŒãFalseã«èšå®ãããŠããå Žåãäœãããå¿ èŠã¯ãªããçµäºãåŸ ã€äŸ¡å€ããããŸãïŒã
ã»ãã·ã§ã³äžã«OnGestureã€ãã³ããçæãããé »åºŠã¯ã10ã«èšå®ããGesturePartSizeå®æ°ã«ãã£ãŠç°ãªããŸããã€ãŸããã»ãã·ã§ã³ãã€ã³ãã®æ°ãå®æ°ã®åæ°ã«ãªããšïŒé€ç®ã®å°äœã¯ãŒãã«ãªããŸãïŒãã€ãã³ããçæãããŸãã
åã»ãã·ã§ã³ã®ããŒã¿ã¯ããã®é åã«ä¿åãããŸãïŒ
TPointArray = array of TPoint;
ããŠã次ã®ããã«åã»ãã·ã§ã³ãèšè¿°ããæ§é ã宣èšããŸãã
TGestureItem = record ID, // ID , ControlIndex: Integer; // , Data: TList<TPoint>; // , Done: Boolean; // end;
ãããããåã¿ããã»ãã·ã§ã³ã®ããŒã¿ãæ ŒçŽããã¯ã©ã¹ã宣èšããããšã¯åŒãç¶ãå¯èœã§ãã
// , // 10 TGesturesData = class ... strict private // FData: array [0..MaxFingerCount - 1] of TGestureItem; ... public ... // procedure StartGesture(ID, ControlIndex: Integer; Value: TPoint); // function AddPoint(ID: Integer; Value: TPoint): Boolean; // procedure EndGesture(ID: Integer); // procedure ClearControlGestures(ControlIndex: Integer); // function GetGesturePath(ID: Integer): TPointArray; // OnEndAllGestures OnPartComplete property LastControlIndex: Integer read FLastControlIndex; // LastControlIndex property OnEndAllGestures: TGesturesDataEvent read FEndAll write FEndAll; // GesturePartSize LastControlIndex property OnPartComplete: TGesturesDataEvent read FPart write FPart; end;
ããã¯å®éã«ã¯ç¹å¥ãªããªã«ãå«ãŸãªãéåžžã«åçŽãªã¯ã©ã¹ã§ãããããèšäºã«æ²¿ã£ããã¢ãããžã§ã¯ãã®äŸã§ãã¹ãŠãèŠãããšãã§ãããããåé¢æ°ã®å®è£ ã«ã€ããŠã¯æ€èšããŸããã
圌ã®å šä»äºã¯ïŒ
- StartGestureããã³AddPointåŒã³åºããéããŠå€éšããã®ããŒã¿ãä¿åããŸãã
- AddPointãåŒã³åºããã³ã«ããªã¹ãã®ãµã€ãºã確èªããŸã
ããŒã¿ïŒTList <TPoint>
ControlIndexãŠã£ã³ããŠã«é¢é£ä»ããããã»ãã·ã§ã³ããšã«ãå¿ èŠã«å¿ããŠOnPartCompleteãåŒã³åºããŸãã - EndGestureãåŒã³åºããåŸãåãControlIndexãæã€ãã¹ãŠã®ã»ãã·ã§ã³ã確èªãããã¹ãŠå®äºããå Žåã¯ãOnEndAllGesturesãåŒã³åºããŸãã
ããã¯ãšã³ãžã³ã®åãªãã»ãã·ã§ã³ãªããžããªã§ãããTGestureRecognizerã¯ä¿åãããŠããããŒã¿ãåŠçããŸãã
次ã®2ã€ã®ãã£ãŒã«ããè¿œå ããŠãåºæ¬ã¯ã©ã¹ãæ¡åŒµããŸãã
// FGesturesData: TGesturesData; // FGestureRecognizer: TGestureRecognizer;
ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãã»ãã·ã§ã³ãªããžããªãäœæããŠåæåããŸãã
FGesturesData := TGesturesData.Create; FGesturesData.OnEndAllGestures := OnEndAllGestures; FGesturesData.OnPartComplete := OnPartComplete; FGestureRecognizer := TGestureRecognizer.Create;
ãã®åŸãHandleTouchïŒïŒã¡ãœããã«æ»ããŸããããã§ãTouchDataæ§é äœã®ãã©ã°ãèšå®ããã³ãŒããå°ãæ¡åŒµããå¿ èŠããããŸãã
TouchData.Flags := []; Flags := Inputs[I].dwFlags; if Flags and TOUCHEVENTF_MOVE <> 0 then begin Include(TouchData.Flags, tfMove); // , // , if not FGesturesData.AddPoint(TouchData.ID, TouchData.Position) then // , FGesturesData.StartGesture(TouchData.ID, Index, TouchData.Position); end; if Flags and TOUCHEVENTF_DOWN <> 0 then begin Include(TouchData.Flags, tfDown); // , // ID FGesturesData.StartGesture(TouchData.ID, Index, TouchData.Position); end; if Flags and TOUCHEVENTF_UP <> 0 then begin Include(TouchData.Flags, tfUp); // // - . // , // FGesturesData FGesturesData.EndGesture(TouchData.ID); end;
å®éãããã¯åã»ãã·ã§ã³ã®ããŒã¿ãŠã§ã¢ããŠã¹ã§ã®ã»ãŒãã¹ãŠã®ã¢ã¯ãã£ããªäœæ¥ã§ãã
ã¿ããã»ãã·ã§ã³ã®å®äºãšéšåçãªå®äºã®ã€ãã³ããã³ãã©ãŒã¯éåžžã«ç°¡åã§ãã
, :
, , , .
// // // Values ID , // // ============================================================================= procedure TTouchManager.OnPartComplete(Values: TBytes); var Position: TPoint; GestureType: TGestureType; begin // ? GestureType := RecognizeGestures(Values, Position); // , if GestureType <> gtNone then DoGesture( FWindows[FGesturesData.LastControlIndex].Control, FWindows[FGesturesData.LastControlIndex].Handlers.Gesture, GestureType, Position, // False); end;
, :
// // // Values ID // ============================================================================= procedure TTouchManager.OnEndAllGestures(Values: TBytes); var Position: TPoint; GestureType: TGestureType; begin try // ? GestureType := RecognizeGestures(Values, Position); // , if GestureType <> gtNone then DoGesture( FWindows[FGesturesData.LastControlIndex].Control, FWindows[FGesturesData.LastControlIndex].Handlers.Gesture, GestureType, Position, // True); finally // FGesturesData.ClearControlGestures(FGesturesData.LastControlIndex); end; end;
, , , .
ãã³ãã©ãŒã³ãŒããããããããã«ããã¹ãŠã®äž»èŠãªäœæ¥ã¯RecognizeGesturesé¢æ°ã§è¡ãããŸãããã®ããžãã¯ã«ã€ããŠã¯ã第7ç« ã§æ¢ã«èª¬æããŸããã
次ã®ããã«ãªããŸãã
// // TGesturesData // Values ID , // // ============================================================================= function TTouchManager.RecognizeGestures(Values: TBytes; var Position: TPoint): TGestureType; var I, A, ValueLen, GestureLen: Integer; GestureID: Byte; GesturePath: TPointArray; NoMove: Boolean; begin Result := gtNone; // , ValueLen := Length(Values); // ( ), if ValueLen > 3 then Exit; // : // ID ( GetGestureID), // sgiLeft // , ID , // - // // // , // GestureID := sgiNoGesture; NoMove := True; for I := 0 to ValueLen - 1 do begin // , TPoint GesturePath := FGesturesData.GetGesturePath(Values[I]); GestureLen := Length(GesturePath); // - , if GestureLen = 0 then Exit; // if NoMove then for A := 1 to GestureLen - 1 do if GesturePath[0] <> GesturePath[A] then begin NoMove := False; Break; end; // . // . , // , Position := GesturePath[GestureLen - 1]; // ID if I = 0 then GestureID := GetGestureID(GesturePath) else // ID , if GestureID <> GetGestureID(GesturePath) then Exit; end; // ID if (GestureID = sgiNoGesture) then begin if NoMove then case ValueLen of 1: Result := gtTap; 2: Result := gt2Tap; 3: Result := gt3Tap; end; end else begin Dec(ValueLen); Result := TGestureType(3 + GestureID + ValueLen * 4); end; end;
ãã®é¢æ°ã«ã¯ãè£å©çãªGetGestureIDãå¿ èŠã§ããããã«ã€ããŠã¯ã第6ç« ã§æ¢ã«èª¬æããŸããã
ããããã¹ãŠã®æäœã®åŸã第8ç« ã§è¡šæãããåé¡çªå·3ã¯è§£æ±ºããããšèšããŸããã€ãŸããåã»ãã·ã§ã³ã«é¢ããããŒã¿ãä¿åã§ããããã«ãã©ã®ãŠã£ã³ããŠã§ä¿æãããŠããããææ¡ã§ããŸãã
åé¡ã¯2ã€ç®ã§ãã
12.ãŠã£ã³ããŠã®åäœæãæ€åºããŸã
å ã»ã©èšã£ãããã«ãRecreateWndã®åŒã³åºãã¯åºæ¬çã«éåžžã®VCLã¡ã«ããºã ã§ãã
ãã ãããšã³ãžã³ã®ããžãã¯å šäœã倧ããæãªãå¯èœæ§ããããŸãããŠã£ã³ããŠãåäœæãããšããããŸã§ã®ãšãããæ°ããäœæããããã³ãã«ã§RegisterTouchWindowã2åç®ã«åŒã³åºã人ã¯ããŸããããããã£ãŠããŠã£ã³ããŠããšã³ãžã³ã«ç»é²ããç¶ãããšããŠããWM_TOUCHã¡ãã»ãŒãžã¯éä¿¡ãããªããªããŸãã
ãã®ã¿ã¹ã¯ã«ã¢ãããŒãããæ¹æ³ã¯ããã€ããããŸããããšãã°ããã©ãããèšå®ããã®ã§ãWM_CREATE / WM_DESTROYã¡ãã»ãŒãžãWM_TOUCHããŒãã«ãã£ããããŠã¿ãŸãããïŒ
ããããGUIã¹ããªãŒã å ã«ã¯ãã®ãããªã¡ãã»ãŒãžãå€æ°ãããããã¡ãã»ãŒãžãã§ãããµã€ã¯ã«ã«äžèŠãªãªãŒããŒããããå¿ èŠãªçç±ã¯ãããŸããã
ãããã£ãŠãå察åŽã«ç§»åããŠãç¹å®ã®ãããã·ãäœæããŸãããã®ãããã·ã¯ãé衚瀺ãŠã£ã³ããŠã«ãªããŸãããã®ãããã·ã«å¯ŸããŠã芪ããŠã£ã³ããŠãèšå®ããŸãããã®å Žåãã¡ã€ã³ãŠã£ã³ããŠãç Žæ£ããããšããããã·ã®ãŠã£ã³ããŠãç Žæ£ãããŸããããã¯ãDestroyHandleãã³ãã©ãŒã§æ€åºã§ããŸãããŸããæå¹ãªèŠªãã³ãã«ã«ã¢ã¯ã»ã¹ã§ããCreateWndã§ç Žæ£åŸã®ãŠã£ã³ããŠäœæãç解ããŸãã WM_TOUCHã¡ãã»ãŒãžã®åä¿¡ã
ãã®äžåèªã¯æ¬¡ã®ããã«ãªããŸãã
type // TWinControlProxy = class(TWinControl) protected procedure DestroyHandle; override; procedure CreateWnd; override; procedure CreateParams(var Params: TCreateParams); override; end; { TWinControlProxy } // // WS_EX_TRANSPARENT, . // ============================================================================= procedure TWinControlProxy.CreateParams(var Params: TCreateParams); begin inherited; Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT; end; // // // ============================================================================= procedure TWinControlProxy.CreateWnd; begin inherited CreateWnd; if Parent.HandleAllocated then RegisterTouchWindow(Parent.Handle, 0); Visible := False; end; // // , // ============================================================================= procedure TWinControlProxy.DestroyHandle; begin if Parent.HandleAllocated then UnregisterTouchWindow(Parent.Handle); Visible := True; inherited DestroyHandle; end;
ãã®ãããã·ã¯ãšã³ãžã³ã«ã€ããŠäœãç¥ããããµã€ã¬ã³ãã°ãªããã¯ãã£ã1ã€ã®ã¿ã¹ã¯ãå®è¡ããŸã-ãŠã£ã³ããŠãã¿ããã¹ã¯ãªãŒã³ããåæãããªãããã«ããããã§ãã
ãããã·ããµããŒãããã«ã¯ããŠã£ã³ããŠã«é¢é£ä»ãããããããã·ãžã®ãªã³ã¯ãè¿œå ããŠãTWindowDataæ§é ããããã«æ¡åŒµããå¿ èŠããããŸãã
TWindowData = record Control, Proxy: TWinControl;
次ã«ããŠã£ã³ããŠã®ç»é²æé ããããã«å€æŽããŸãã
if FWindows.IndexOf(WindowData) < 0 then begin // , // WindowData.Proxy := TWinControlProxy.Create(Value); WindowData.Proxy.Parent := Value; // WindowData.Handlers := Handlers; WindowData.LastClickTime := 0; // RegisterTouchWindow(Value.Handle, 0); FWindows.Add(WindowData); end;
ç»é²ãããŠã£ã³ããŠãåé€ããïŒ
if Index >= 0 then begin // , FWindows[Index].Proxy.Free; // // FWindows.Delete(Index); end;
ããã ãã§ãã
ä»çµã¿ãèŠãŠã¿ãŸãããã
13.ãã«ãã¿ãããšã³ãžã³ã®å¶åŸ¡ãã¹ã
ç¹°ãè¿ããŸãããæ°ãããããžã§ã¯ããäœæããã¡ã€ã³ãã©ãŒã ã«TMemoãã¹ããŒããŸããã¡ã€ã³ãã©ãŒã ã«ã¯ãäœæ¥ã®çµæãšãã¿ã³ã衚瀺ãããŸãã
ãã¿ã³ãã³ãã©ãŒã§ããããã·ããã¹ãããããã«ã¡ã€ã³ãã©ãŒã ãåäœæããŸãã
procedure TdlgGesturesText.Button1Click(Sender: TObject); begin RecreateWnd; end;
ãã©ãŒã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ããã«ãã¿ãããšã³ãžã³ã«æ¥ç¶ããŸãã
procedure TdlgGesturesText.FormCreate(Sender: TObject); var Handlers: TTouchHandlers; begin ZeroMemory(@Handlers, SizeOf(TTouchHandlers)); Handlers.Gesture := OnGesture; TouchManager.RegisterWindow(Self, Handlers); end;
次ã«ããã³ãã©ãŒèªäœãå®è£ ããŸãã
procedure TdlgGesturesText.OnGesture(Sender: TObject; Control: TWinControl; GestureType: TGestureType; Position: TPoint; Completed: Boolean); begin if not Completed then if not (GestureType in [gt2Left..gt2Down]) then Exit; Memo1.Lines.Add(Format('Control: "%s" gesture "%s" at %dx%d (completed: %s)', [ Control.Name, GetEnumName(TypeInfo(TGestureType), Integer(GestureType)), Position.X, Position.Y, BoolToStr(Completed, True) ])); end;
ãã«ããå®è¡-åºæ¥äžããã
ãããªã¯ããµããŒããããŠãã15åã®ãã¹ãŠã®ãžã§ã¹ãã£ã®èªèãšãç»é²ããããŠã£ã³ããŠã®å¶åŸ¡ã®ãããã·ãæ確ã«èªèããŸãã
å®éãããã¯ç¬¬10ç« ã®çµããã§è©±ããã®ãšåãtsimusã§ãããæåéãæ°åè¡ã®ã³ãŒãã§ããã¹ãŠãç®±ããåºããŠåäœããŸãã
ãã®äŸã®ãœãŒã¹ã³ãŒãã¯ããœãŒã¹ã¢ãŒã«ã€ãã®ãã\ Demos \ Gestures \ããã©ã«ãã«ãããŸãã
14.çµè«
ãã¡ããããã®æ©èœãXE4ã«ååšããªãã®ã¯æ®å¿µã§ãã
äžæ¹ããã®ç¬éã§ãªããã°ãããã§ã©ã®ããã«æ©èœããã®ãããããªãã£ãã®ã§ããã©ã¹ããããŸãã
ãã®ã¢ãããŒãã®æ¬ ç¹ã¯ãWM_GESTURE + WM_POINTSã¡ãã»ãŒãžã®åŠçãå®å šã«åãåããããžã§ã¹ãã£ãŒèªèããšã³ãžã³ã®ã³ãŒãã«è»¢éãããããšã§ãã
åæããŸãããããã¯æå³çã«è¡ãããŸãã
ããªãèªèº«ããã®æ¹åãæãäžãå§ãããã誰ãç¥ã£ãŠãããããããŸããããããããæçµçã«ç§ã®ã¢ãããŒãã«åæããã§ããããå°ãªããšãæ³ååã®ãã£ãŒã«ãããããŸãããã®ãããªåé¡ã®è§£æ±ºã«ä»ã«ã©ã®ããã«ã¢ãããŒãã§ããŸããã
ãã®èšäºã®ãã¢äŸã§æäŸãããŠããCommon.TouchManagerã¯ã©ã¹ã®ãœãŒã¹ã³ãŒãã¯æçµçãªãã®ã§ã¯ãªããå®æçã«éçºãããŸãããå ¬ã«åè¡ãããã©ããã¯ããããŸããããã ãããææ¡ãã³ã¡ã³ãã¯å€§æè¿ã§ãã
ãã€ãã®ããã«ãèšäºãæ ¡æ£ããŠãããDelphi Mastersãã©ãŒã©ã ã®åå è ã«æè¬ããŸãã
ãã¢ã®ãœãŒã¹ã³ãŒãã¯ããã®ãªã³ã¯ããå ¥æã§ããŸãã
é 匵ã£ãŠ
æŽæ°ïŒ
æ®å¿µãªããããŸãã¯å¹žããªããšã«ãWindows 8以éã®äžéšã®æ©èœã«ãããWH_GETMESSAGEãã©ããã¯WM_TOUCHã¡ãã»ãŒãžãã€ã³ã¿ãŒã»ããããªãããããã®ã³ãŒãã¯æ©èœããŸããã
ãã®ãããªè¿·æãä¿®æ£ããã«ã¯ããã©ããã®åŠçãåé€ããWM_TOUCHã¡ãã»ãŒãžã®åŠçããããã·ã«è»¢éããŠã次ã®ããã«æžãæããå¿
èŠããããŸãã
type // TWinControlProxy = class(TWinControl) private FOldWndProc: TWndMethod; procedure ParentWndProc(var Message: TMessage); protected procedure DestroyHandle; override; procedure CreateWnd; override; procedure CreateParams(var Params: TCreateParams); override; public destructor Destroy; override; procedure InitParent(Value: TWinControl); end; { TWinControlProxy } // // WS_EX_TRANSPARENT, . // ============================================================================= procedure TWinControlProxy.CreateParams(var Params: TCreateParams); begin inherited; Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT; end; // // // ============================================================================= procedure TWinControlProxy.CreateWnd; begin inherited CreateWnd; if Parent.HandleAllocated then RegisterTouchWindow(Parent.Handle, 0); Visible := False; end; // // , // ============================================================================= destructor TWinControlProxy.Destroy; begin if Parent <> nil then Parent.WindowProc := FOldWndProc; inherited; end; // // , // ============================================================================= procedure TWinControlProxy.DestroyHandle; begin if Parent.HandleAllocated then UnregisterTouchWindow(Parent.Handle); Visible := True; inherited DestroyHandle; end; // // , // ============================================================================= procedure TWinControlProxy.InitParent(Value: TWinControl); begin Parent := Value; FOldWndProc := Value.WindowProc; Value.WindowProc := ParentWndProc; end; // // WM_TOUCH // ============================================================================= procedure TWinControlProxy.ParentWndProc(var Message: TMessage); var Msg: TMsg; begin if Message.Msg = WM_TOUCH then begin Msg.hwnd := Parent.Handle; Msg.wParam := Message.WParam; Msg.lParam := Message.LParam; TouchManager.HandleMessage(@Msg); end; FOldWndProc(Message); end;
èšäºã®ã¢ãŒã«ã€ãã§ã¯ããããã®å€æŽã¯ãã§ã«è¡ãããŠããŸãã