2011-05-11 57 views
3

所以我一直在嘗試使用CGPostMouseEvent和CGEventPostToPSN發送鼠標點擊到mac遊戲,不幸的是一直非常不成功。試圖發送鼠標點擊遊戲窗口,mac

我希望有人能夠幫助我以不同的方式思考,或者意識到我錯過了什麼。谷歌沒有太多的幫助。

我的猜測是,這是因爲我試圖將點擊事件發送到遊戲窗口(openGL),而不是普通窗口。

這是我想發送的另一個示例: CGEventRef CGEvent; NSEvent * customEvent; NSPoint位置; location.x = 746; location.y = 509;

customEvent = [NSEvent mouseEventWithType: NSLeftMouseDown 
            location: location 
           modifierFlags: NSLeftMouseDownMask 
            timestamp: time(NULL) 
           windowNumber: windowID 
             context: NULL 
            eventNumber: 0 
            clickCount: 1 
            pressure: 0]; 

    CGEvent = [customEvent CGEvent]; 
    CGEventPostToPSN(&psn, CGEvent); 

有趣的是,我可以移動鼠標罰款(CGDisplayMoveCursorToPoint(kCGDirectMainDisplay,clickPt);),我只是無法發送任何點擊:/

任何幫助將不勝感激。

編輯:這裏有一點很奇怪,一旦我使用CGDisplayMoveCursorToPoint移動鼠標,我實際上不得不在身體上移動鼠標,然後才能點擊,這很奇怪。遊戲不接受任何輸入,除非我將其向上/向下移動(並且指針隨之改變)。

謝謝!

回答

5

那麼你試圖建立的是「機器人」或「機器人」,它基本上是以有序的方式向遊戲發送命令。基本上它會爲你效力,因爲你是afk。這對於強迫你玩礦石,商品或任何可以讓你在遊戲中獲得收益的遊戲非常有用。這真是無聊。我已經成功地完成了這個流行的遊戲,儘管我不能提及遊戲,因爲它打破了所有這些類型的遊戲針對「機器人」的用戶協議。所以要小心你正在做的事情,因爲它可能會打破許多MMPG的用戶協議。但是我在這裏成功地發佈了這個,因爲Mac有更少的機器人,沒有我能夠研究的,而我發現很多的PC。所以爲了平整比賽場地......這裏是代碼。我建議將它編譯爲命令行,然後在AppleScript中執行宏(邏輯將駐留在如何模擬遊戲點擊鼠標,移動和發送密鑰,基本上是您的AI)。運行類,它將獲得所有遊戲所擁有的psn「進程序列號」,基本上它運行的線程是什麼,你可以在Mac上找到名爲「活動監視器」的進程名稱,也可以是在AppleScript的容易。 一旦你的名字,這個類會找到並還給你的PSN。

#import <Cocoa/Cocoa.h> 
#include <Carbon/Carbon.h> 
#include <stdio.h> 

@interface gamePSN : NSObject 
{ 
    ProcessSerialNumber gamePSN; 
    ProcessInfoRec gameProcessInfo; 
    pid_t gameUnixPID;  
} 

- (ProcessSerialNumber) gamePSN; 
- (ProcessInfoRec) gameProcessInfo; 
- (pid_t) gameUnixPID; 
- (void) getPSN; 
@end 

@implementation gameSN 

- (ProcessSerialNumber) gamePSN { return gamePSN; } 
- (ProcessInfoRec) gameProcessInfo { return gameProcessInfo; } 
- (pid_t) gameUnixPID; { return gameUnixPID; } 

- (void) getPSN 
{ 
    auto OSErr osErr = noErr; 
    auto OSErr otherErr = noErr; 
    auto ProcessSerialNumber process; 
    auto ProcessInfoRec procInfo; 
    auto Str255 procName;  
    auto FSSpec appFSSpec; 
    auto char cstrProcName[34]; 
    auto char one ='G'; // FIRST CHARCTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES 
    auto char two ='A'; // SECOND CHARACTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES 
    auto char three = 'M'; // THIRD CHARACTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES 
    auto unsigned int size; 

    process.highLongOfPSN = kNoProcess; 
    process.lowLongOfPSN = kNoProcess; 
    procInfo.processInfoLength = sizeof(ProcessInfoRec); 
    procInfo.processName = procName; 
    procInfo.processAppSpec = &appFSSpec; 

    while (procNotFound != (osErr = GetNextProcess(&process))) { 

    if (noErr == (osErr = GetProcessInformation(&process, &procInfo))) { 
     size = (unsigned int) procName[0]; 
     memcpy(cstrProcName, procName + 1, size); 
     cstrProcName[size] = '\0'; 

     // NEEDS TO MATCH THE SIGNATURE OF THE GAME..FIRST THREE LETTERS 
     // IF YOU CANT FIND IT WITH THE ACTIVITY MONITOR UTILITY OF APPLE MAC OS 
     // THEN RUN THIS SAME CLASS WITH AN NSLOG AND IT WILL LIST ALL YOUR RUNNING PROCESSES. 

     if ( (((char *) &procInfo.processSignature)[0]==one) && 
       (((char *) &procInfo.processSignature)[1]==two) && 
       (((char *) &procInfo.processSignature)[2]==three) && 
       (((char *) &procInfo.processSignature)[3]==two)) 
     { 
      gamePSN = process; 
      otherErr = GetProcessInformation(&gamePSN, &gameProcessInfo); 
      otherErr = GetProcessPID(&process, &gameUnixPID); 
     } 

     } 

    } 
} 

一旦你有了這個進程號,很容易發的重要事件,以及鼠標連TS。這裏是鼠標事件點擊發送。

// mouseClicks.h 
// ClickDep 
// Created by AnonymousPlayer on 9/9/11. 


#import <Foundation/Foundation.h> 

@interface mouseClicks : NSObject 

- (void) PostMouseEvent:(CGMouseButton) button eventType:(CGEventType) type fromPoint:(const CGPoint) point; 
- (void) LeftClick:(const CGPoint) point; 
- (void) RightClick:(const CGPoint) point; 
- (void) doubleLeftClick:(const CGPoint) point; 
- (void) doubleRightClick:(const CGPoint) point; 

@end 

/
// mouseClicks.m 
// ClickDep 
// Created by AnonymousPlayer on 9/9/11.v 


#import "mouseClicks.h" 

@implementation mouseClicks 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     // Initialization code here if you need any. 
    } 

    return self; 
} 

- (void) PostMouseEvent:(CGMouseButton) button eventType:(CGEventType) type fromPoint:(const CGPoint) point; 
{ 
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, point, button); 
    CGEventSetType(theEvent, type); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    CFRelease(theEvent); 
} 

- (void) LeftClick:(const CGPoint) point; 
{ 
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventMouseMoved fromPoint:point]; 
    NSLog(@"Click!"); 
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventLeftMouseDown fromPoint:point]; 
    sleep(2); 
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventLeftMouseUp fromPoint:point]; 
} 

- (void) RightClick:(const CGPoint) point; 
{ 
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point]; 
    NSLog(@"Click Right"); 
    [self PostMouseEvent:kCGMouseButtonRight eventType: kCGEventRightMouseDown fromPoint:point]; 
    sleep(2); 
    [self PostMouseEvent:kCGMouseButtonRight eventType: kCGEventRightMouseUp fromPoint:point]; 
} 

- (void) doubleLeftClick:(const CGPoint) point; 
{ 
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point]; 
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, kCGMouseButtonLeft); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    sleep(2); 
    CGEventSetType(theEvent, kCGEventLeftMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 

    CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, 2); 

    CGEventSetType(theEvent, kCGEventLeftMouseDown); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    sleep(2); 
    CGEventSetType(theEvent, kCGEventLeftMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    CFRelease(theEvent); 
} 

- (void) doubleRightClick:(const CGPoint) point; 
{ 
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point]; 
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, kCGMouseButtonRight); 
    CGEventPost(kCGHIDEventTap, theEvent); 
     sleep(2); 
    CGEventSetType(theEvent, kCGEventRightMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 

    CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, 2); 

    CGEventSetType(theEvent, kCGEventRightMouseDown); 
    CGEventPost(kCGHIDEventTap, theEvent); 
     sleep(2); 
    CGEventSetType(theEvent, kCGEventRightMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    CFRelease(theEvent); 
} 
@end 

您可能需要使用睡眠,即按下鼠標按鈕並釋放它之間的時間間隔。我發現使用1秒有時它不會這樣做。放置2秒使其始終工作。 所以你的主要將以下。

int main(int argc, char *argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; 

    // Grabs command line arguments -x, -y, -clicks, -button 
    // and 1 for the click count and interval, 0 for button ie left. 
    int x  = [args integerForKey:@"x"]; 
    int y  = [args integerForKey:@"y"]; 
    int clicks = [args integerForKey:@"clicks"]; 
    int button = [args integerForKey:@"button"]; 
    //int interval= [args integerForKey:@"interval"]; 
    int resultcode; 

    // PUT DEFAULT VALUES HERE WHEN SENT WITH EMPTY VALUES 
    /*if (x==0) { 
     x= 1728+66; 
     y= 89+80; 
     clicks=2; 
     button=0; 
    } 
    */ 
    // The data structure CGPoint represents a point in a two-dimensional 
    // coordinate system. Here, X and Y distance from upper left, in pixels. 
    CGPoint pt; 
    pt.x = x; 
    pt.y = y; 



    // Check CGEventPostToPSN Posts a Quartz event into the event stream for a specific application. 
    // only added the front lines plus changed null in Create Events to kCGHIDEventTap 

    gamePSN *gameData = [[gamePSN alloc] init]; 
    [gameData getPSN]; 
    ProcessSerialNumber psn = [gameData gamePSN]; 
    resultcode = SetFrontProcess(&psn); 

    mouseClicks *mouseEvent =[[mouseClicks alloc] init]; 

    if (button == 0) 
    { 
     if (clicks==1) { 
      [mouseEvent LeftClick:pt]; 
     } else { 
      [mouseEvent doubleLeftClick:pt]; 
     } 
    } 
    if (button == 1) 
    { 
     if (clicks==1) { 
      [mouseEvent RightClick:pt]; 
     } else { 
      [mouseEvent doubleRightClick:pt]; 
     } 
    } 

    [gameData release]; 
    [mouseEvent release]; 

    [pool drain]; 
    return 0; 
} 

希望這是有幫助....請記住,您可以通過發送以下命令在終端或AppleScript中執行此操作。

do shell script "/...Path to Compiled Program.../ClickDep" & " -x " & someX & " -y " & someY & " -clicks 1 -button 1" 

遊戲愉快!!!!

+0

僅供參考,現在不推薦使用SetFrontProcess。這是一個有趣的選擇,雖然:http://stackoverflow.com/a/2334362/880837 – Tiago 2017-04-09 23:08:29