处理 iOS 触摸以模拟鼠标以C++输入库



我有现有的跨平台C++代码来处理鼠标输入,方法如下:

onMouseDown(x,y,button)
onMouseUp(x,y,button)
onMouseMove(x,y,buttons)

我正在将功能移植到C++ iOS应用程序中......根据需要使用最小的Objective-C。我想处理单点触摸手势来模拟鼠标功能,以便我可以将参数传递到现有方法中(以及添加多点触控)。

理想情况下,作为最小的示例应用程序,代码会是什么样子 - 真正让我感到困惑的主要是 OBJ-C/C++ 交互?

以下是我将多点触控传递给 OpenGL 程序C++代码(用 1 或 2 根手指)的方法:

// Set this in your ViewController's init code
[self setMultipleTouchEnabled:YES];
// Implement these in ViewController
int touchCount = 0;
UITouch* touch[2];
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{ 
NSArray* array = [touches allObjects];  
UITouch* touchTemp; 
int t;
int touchedPixel[2];
for(int i = 0; i < [array count]; ++i){
touchTemp = [array objectAtIndex:i];
if(touchCount >= 2)
return;
if(touch[0] == NULL)    
t = 0;
else
t = 1;      
touch[t] = touchTemp;
CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view]; 
++touchCount;
touchedPixel[X] = touchLoc.x;
touchedPixel[Y] = touchLoc.y;
mainScreen->push(t, touchedPixel);  // mainScreen is a C++ object for GL drawing.
}
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event{
NSArray* array = [touches allObjects];
UITouch* touchTemp; 
int t;
int touchedPixel[2];
for(int i = 0; i < [array count]; ++i){
touchTemp = [array objectAtIndex:i];
for(t = 0; t < 2; ++t){         // Find the matching touch in the array
if(touchTemp == touch[t])
break;
}       
if(t == 2)                      // Return if touch was not found
continue;
CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view]; 
touchedPixel[X] = touchLoc.x;
touchedPixel[Y] = touchLoc.y;
mainScreen->move(t, touchedPixel);
}
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{ 
NSArray* array = [touches allObjects];
UITouch* touchTemp; 
int t;
int touchedPixel[2];
for(int i = 0; i < [array count]; ++i){
touchTemp = [array objectAtIndex:i];
for(t = 0; t < 2; ++t){         // Find the matching touch in the array
if(touchTemp == touch[t])
break;
}       
if(t == 2)                      // Return if touch was not found
continue;               
CGPoint touchLoc = [touch[t] locationInView:(EAGLView *)self.view];
touch[t] = NULL;
--touchCount;
touchedPixel[X] = touchLoc.x;
touchedPixel[Y] = touchLoc.y;
mainScreen->release(t, touchedPixel);
}
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event{
printf("Touch cancelledn");
[self touchesEnded:touches withEvent: event];
}

在这种情况下,我将实现touches开始,移动和结束并将调用转发到c ++鼠标向下/移动/向上代码

我会做什么的示例: 假设代码位于应用程序的视图控制器中!

static UITouch *_trackedTouch = nil;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
assert(!_trackedTouch && "no multitouch");
_trackedTouch = [touches anyObject];
CGPoint pt = [_trackedTouch locationInView:self.view];
mouseDown(pt.x,pt.y,0);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
assert(_trackedTouch && "no touch began");
if(![touches containsObject:_trackedTouch])
return;
CGPoint pt = [_trackedTouch locationInView:self.view];
mouseMoved(pt.x,pt.y,0);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
assert(_trackedTouch && "no touch began");
if(![touches containsObject:_trackedTouch])
return;
CGPoint pt = [_trackedTouch locationInView:self.view];
mouseUp(pt.x,pt.y,0);
}

关于书籍嗯...也许 : https://stackoverflow.com/questions/5308106/book-recommendations-for-objective-c-for-ios-development (但不是C++偏见...objC是基于C.C++只是除了ObjC之外你可以使用的东西,但是。知道C++只能为学习 ObjC 提供有限的帮助)

这适用于单点触控和多点触控用例。我写了一个名为oldlib的存根 c++ 库,我在下面的 obj-c 文件中使用了它。

您可以根据需要传递任何内容button.我的代码传递触摸 ID。我想你需要检查你的图书馆在那里的期望,并相应地改变它。

这是我的代码:

老利布·

#ifndef Quick_oldlib_h
#define Quick_oldlib_h
void onMouseDown(int x,int y,int button);
void onMouseUp(int x,int y,int button);
void onMouseMove(int x,int y,int buttons);
#endif

奥尔德利布.cpp

#include "oldlib.h"
#include <stdio.h>
void onMouseDown(int x,int y,int button)
{
printf("onMouseDown:%d,%d button:%dn", x, y, button);
}
void onMouseUp(int x,int y,int button)
{
printf("onMouseUp:%d,%d button:%dn", x, y, button);
}
void onMouseMove(int x,int y,int button)
{
printf("onMouseMove:%d,%d button:%dn", x, y, button);
}

QViewController.h

#import <UIKit/UIKit.h>
@interface QViewController : UIViewController
@end

QViewController.mm <- 请注意 MM 扩展,它可以将其与C++标头一起编译

#import "QViewController.h"
#include "oldlib.h"
@interface QViewController ()
@property (nonatomic, retain) NSMutableSet* active_touches;
@end
@implementation QViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.active_touches = [[NSMutableSet alloc] init];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch* touch in touches) {
[self.active_touches addObject:touch];
onMouseDown([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch);
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch* touch in touches) {
if ([self.active_touches containsObject:touch]) {
onMouseUp([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch);
[self.active_touches removeObject:touch];
}
}
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch* touch in touches) {
if ([self.active_touches containsObject:touch]) {
onMouseMove([touch locationInView:self.view].x, [touch locationInView:self.view].y, (int)(__bridge void*)touch);
}
}
}
- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch* touch in touches) {
[self.active_touches removeObject:touch];
NSLog(@"cancelled: %@", touch);
}
}
@end

为此,您需要实现触摸转发,并确保刚刚检测到的触摸由C++代码使用,而不是响应器链中的任何 Cocoa Touch 对象。例如,在视图的touchesBegan:withEvent:选择器中,您将包含对onMouseDown(int, int, void*)方法的调用。touchesMoved:withEvent:touchesEnded:withEvent:将具有类似的逻辑。

不过也有一些困难。根据 HIG 的说法,当实现其他touches*:withEvent:选择器时,应始终实现touchesCancelled:withEvent:,并且您必须包含处理该逻辑的逻辑。

您可能遇到的另一个问题是UIGestureRecognizer子类。我之前提到过,你必须确保你的C++代码消耗触摸。但是,如果您使用手势识别器,如果您还实现了touches*:WithEvent:选择器,您的整个响应器链可能会变得混乱。有一些优秀的WWDC视频对此进行了解释。简而言之,如果您的手势识别器消耗了触摸,它将永远不会发送到您的C++方法。简单的解决方案是不使用手势识别器,但它们是迄今为止处理多点触控的最简单方法。

这给我们带来了最后一种可能性(如果您希望使用手势识别器)。你可以将手势识别器的操作设置为Objective-C选择器,而不是仅仅实现touches*:withEvent:选择器,它只是包装对C++代码的调用。例如,UITapGestureRecogniser的动作可以是一个名为onTap的方法,它只是调用onMouseDown(...)。如果您选择走这条路,请务必观看 WWDC 视频('11 和 '12),其中更详细地解释了触摸处理和响应器链。

关于处理Objective-C++的书籍主题,Apple自己已经删除了用于解释ObjC ++的注意事项的页面。然而,谢天谢地,它在这里可用。处理交叉的最简单方法是在Objective-C中实现应用层的基本要素,并将所有适当的调用转发到C++引擎。就我个人而言,我会用Pure Objective-C编写应用程序代表,但是一旦你进入你的ViewController,你就有了自由支配权。

最新更新