MariaDB(MySQL) C API

C, C++ 2021. 8. 29. 15:44 |
반응형

MariaDB도 MySQL과 거의 비슷한 방식으로 C API를 사용할 수 있다.

2018.11.20 - [C, C++] - MySQL C API

기본적인 내용은 MySQL C API와 거의 같고 아래와 같이 Project Property Pages에 Include/Library Directories 및 파일 이름만 변경 된다.

 

  • Project - XXX Properties... - Configuration Properties - C/C++ - General - Additional Include Directories - C:\Program Files\MariaDB 10.6\include
  • Project - XXX Properties... - Configuration Properties - Linker - General - Additional Library Directories - C:\Program Files\MariaDB 10.6\lib

 

아래 두 파일은 프로젝트 폴더에 복사한다. (libmysql.lib, libmysql.dll 이 아니다)

  • libmariadb.lib
  • libmariadb.dll

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <mysql/mysql.h>
 
#pragma comment (lib, "libmariadb.lib")
 
int main()
{
    MYSQL mysql;            // MariaDB(MySQL) 정보를 담을 구조체
    MYSQL* mysqlPtr = NULL;    // MariaDB(MySQL) connection 핸들러
    MYSQL_RES* Result = NULL;        // 쿼리 성공시 결과를 담는 구조체 포인터
    MYSQL_ROW Row;            // 쿼리 성공시 결과로 나온 행의 정보를 담는 구조체
    int stat;                // 쿼리 요청 후 결과
 
    printf("MariaDB(MySQL) Client Version: %s\n\n", mysql_get_client_info());
    // Returns client version information as a string
 
    mysql_init(&mysql); // Gets or initializes a MYSQL structure 
 
    mysqlPtr = mysql_real_connect(&mysql, "127.0.0.1""root""password""database"3306, (char*)NULL0);
    // Connects to a MariaDB(MySQL) server
 
    if (mysqlPtr == NULL)
    {
        printf("MariaDB(MySQL) connection error: %s\n", mysql_error(&mysql));
        // Returns the error message for the most recently invoked MariaDB(MySQL) function
        return 1;
    }
 
    // MariaDB(MySQL)에서 사용하는 문자세트를 Visual Studio가 사용하는 euc-kr로 바꾸기
    mysql_query(mysqlPtr, "set session character_set_connection=euckr");
    mysql_query(mysqlPtr, "set session character_set_results=euckr");
    mysql_query(mysqlPtr, "set session character_set_client=euckr");
 
    const char* Query = "SELECT * FROM table";
    stat = mysql_query(mysqlPtr, Query);    // Executes an SQLquery specified as a null-terminated string
    if (stat != 0)
    {
        printf("MariaDB(MySQL) connection error: %s\n", mysql_error(&mysql));
        return 1;
    }
 
    Result = mysql_store_result(mysqlPtr);    // Retrieves a complete result set to the client
    printf("Number of rows: %I64d\nNumber of columns: %d\n\n", Result->row_count, Result->field_count);
    while ((Row = mysql_fetch_row(Result)) != NULL)    // Fetches the next row from the result set 
    {
        for (unsigned int i = 0; i < Result->field_count; i++)
        {
            printf("%s ", Row[i]);
        }
        printf("\n");
    }
    
    mysql_free_result(Result);    // Frees memory used by a result set
    mysql_close(mysqlPtr);    // Closes a server connection
 
    return 0;
}
 

 

반응형
Posted by J-sean
:

SQLite - C/C++

C, C++ 2021. 8. 27. 16:05 |
반응형

C/C++에서 SQLite를 사용해 보자.

 

C source code와 Precompiled Binaries for Windows를 다운로드 한다.

sqlite-amalgamation-XXX.zip과 sqlite-dll-win32-x86-XXX.zip를 다운로드하고 압축을 풀어 준다.

 

Visual Studio - Tools - Command Line - Developer Command Prompt를 실행 한다.

 

sqlite3.lib 파일을 생성 한다.

sqlite3.def, sqlite3.dll 파일이 있는 sqlite-dll-win32-x86-XXX 폴더에서 아래 명령어를 실행하면 sqlite3.lib 파일이 생성된다.

lib /def:sqlite3.def /machine:x86

 

sqlite-amalgamation-XXX 폴더에는 sqlite3.h 파일이 있다.

 

sqlite3.h, sqlite3.lib, sqlite3.dll 파일들을 프로젝트 폴더로 복사 한다.

 

 

SQLite 라이브러리 버전을 표시하는 간단한 프로그램을 작성하고 빌드해 보자.

 

SQLite 라이브러리 버전이 표시 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include "sqlite3.h"
 
#pragma comment(lib, "sqlite3.lib")
 
using namespace std;
 
int main()
{
    sqlite3* db;
    char* ErrMsg = 0;
    int rc;
 
    rc = sqlite3_open("test.db"&db);
    if (rc == SQLITE_OK) {
        cout << "Database opened successfully." << endl;
    }
    else {
        cout << "Can't open database: " << sqlite3_errmsg(db) << endl;
        return -1;
    }
        
    const char* sql1 = "CREATE TABLE COMPANY(" \
        "ID INT PRIMARY KEY NOT NULL, " \
        "NAME TEXT NOT NULL, " \
        "AGE INT NOT NULL, " \
        "ADDRESS CHAR(50), " \
        "SALARY REAL);";
 
    rc = sqlite3_exec(db, sql1, NULLNULL&ErrMsg);
    if (rc != SQLITE_OK) {
        cout << "SQL error: " << ErrMsg << endl;
        sqlite3_free(ErrMsg);
    }
    else {
        cout << "Table created successfully." << endl;
    }
    
    const char* sql2 = "INSERT INTO COMPANY VALUES(1, 'Paul', 32, 'California', 20000.00);" \
        "INSERT INTO COMPANY VALUES(2, 'Allen', 25, 'Texas', 15000.00);" \
        "INSERT INTO COMPANY VALUES(3, 'Teddy', 23, 'Norway', 20000.00);" \
        "INSERT INTO COMPANY VALUES(4, 'Mark', 25, 'Rich-Mond ', 65000.00);";
        
    rc = sqlite3_exec(db, sql2, NULLNULL&ErrMsg);
    if (rc != SQLITE_OK) {
        cout << "SQL error: " << ErrMsg << endl;
        sqlite3_free(ErrMsg);
    }
    else {
        cout << "Records created successfully." << endl;
    }
    
    sqlite3_close(db);
 
    return 0;
}
 

 

데이터베이스 생성, 테이블 생성, 레코드 삽입.

 

test.db 파일이 생성 된다.

 

 

 
#include <iostream>
#include "sqlite3.h"
 
#pragma comment(lib, "sqlite3.lib")
 
using namespace std;
 
/*
typedef int (*sqlite3_callback)(
    void*,    // Data provided in the 4th argument of sqlite3_exec()
    int,    // The number of columns in row
    char**,    // An array of strings representing fields in the row
    char**    // An array of strings representing column names
    );
*/
static int callback(void* data, int argc, char** argv, char** azColName) {
    int i;
    cout << (const char*)data << ":" << endl;
 
    for (i = 0; i < argc; i++) {
        cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL"<< endl;
    }
    cout << endl;
 
    return 0;
}
 
int main()
{
    sqlite3* db;
    char* ErrMsg = 0;
    int rc;
 
    rc = sqlite3_open("test.db"&db);
    if (rc == SQLITE_OK) {
        cout << "Database opened successfully." << endl;
    }
    else {
        cout << "Can't open database: " << sqlite3_errmsg(db) << endl;
        return -1;
    }
    
    const char* sql = "SELECT * FROM COMPANY;";
    const char* data = "Callback function called";
    
    rc = sqlite3_exec(db, sql, callback, (void*)data, &ErrMsg);
    if (rc != SQLITE_OK) {
        cout << "SQL error: " << ErrMsg << endl;
        sqlite3_free(ErrMsg);
    }
    else {
        cout << "Operation done successfully." << endl;
    }
    
    sqlite3_close(db);
 
    return 0;
}
 

 

데이터 읽기.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include "sqlite3.h"
 
#pragma comment(lib, "sqlite3.lib")
 
using namespace std;
 
/*
typedef int (*sqlite3_callback)(
    void*,    // Data provided in the 4th argument of sqlite3_exec()
    int,    // The number of columns in row
    char**,    // An array of strings representing fields in the row
    char**    // An array of strings representing column names
    );
*/
static int callback(void* data, int argc, char** argv, char** azColName) {
    int i;
    cout << (const char*)data << ":" << endl;
 
    for (i = 0; i < argc; i++) {
        cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL"<< endl;
    }
    cout << endl;
 
    return 0;
}
 
int main()
{
    sqlite3* db;
    char* ErrMsg = 0;
    int rc;
 
    rc = sqlite3_open("test.db"&db);
    if (rc == SQLITE_OK) {
        cout << "Database opened successfully." << endl;
    }
    else {
        cout << "Can't open database: " << sqlite3_errmsg(db) << endl;
        return -1;
    }
    
    const char* sql = "UPDATE COMPANY SET SALARY = 25000.00 WHERE ID = 1; " \
        "DELETE FROM COMPANY WHERE ID = 2; " \
        "SELECT * FROM COMPANY;";
    const char* data = "Callback function called";
    
    rc = sqlite3_exec(db, sql, callback, (void*)data, &ErrMsg);
    if (rc != SQLITE_OK) {
        cout << "SQL error: " << ErrMsg << endl;
        sqlite3_free(ErrMsg);
    }
    else {
        cout << "Operation done successfully." << endl;
    }
    
    sqlite3_close(db);
 
    return 0;
}
 

 

데이터 수정 및 삭제.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 이미지를 디스플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <QApplication>
#include <QWidget>
#include <QPainter>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass
    // to receive paint events passed in event.
    void drawPicture(QPainter* qp);
 
private:
    int height;
    int width;
    QImage image;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    image.load("Barbara Palvin.png");
    height = image.height();
    width = image.width();
 
    this->resize(width, height);
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the
    // specified name is not used in the body of a function.
    // This can be used to suppress compiler warnings while
    // allowing functions to be defined with meaningful
    // parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, image);
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Picture Example");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

소스를 입력한다. (qt.cpp)

 

컴파일(빌드)하고 실행하면 이미지가 디스플레이된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 GUI 프로그래밍을 해 보자.

 

Qt5를 설치한다.

 

단순한 window를 만드는 소스를 입력한다. (qt.cpp)

 

-fPIC 옵션과 함께 컴파일(빌드)하고 생성된 파일을 실행하면 Simple Example 윈도우가 나타난다.

 

이번엔 같은 소스를 qmake를 이용해 컴파일(빌드)해 보자. -project 옵션과 함께 실행하면 c.pro 파일이 생성된다. (디렉토리 이름.pro)

 

 

c.pro 파일의 내용을 보면 Qt Widgets 모듈이 포함되지 않았다.

 

파일의 끝에 Qt Widgets 모듈을 포함시킨다.

 

qmake, make 명령을 차례로 실행하면 컴파일(빌드)이 완료된다.

 

컴파일(빌드)된 파일을 실행하면 윈도우가 나타난다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+를 이용해 이미지를 디스플레이 해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <gtk/gtk.h>
 
static gboolean button_press_callback(GtkWidget* event_box, GdkEventButton* event, gpointer data)
{
    g_print("Event box clicked at coordinates %f,%f\n", event->x, event->y);
 
    return TRUE;
}
 
static void activate(GtkApplication* app, gpointer user_data)
{
    GtkWidget* window;
    GtkWidget* image;
    GtkWidget* event_box;
 
    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Window");
    gtk_window_set_default_size(GTK_WINDOW(window), 300300);
 
    event_box = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(window), event_box);
 
    image = gtk_image_new_from_file("Barbara Palvin.jpg");
    gtk_container_add(GTK_CONTAINER(event_box), image);
 
    g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(button_press_callback), image);
 
    gtk_widget_show_all(window);
}
 
int main(int argc, char** argv)
{
    GtkApplication* app;
    int status;
 
    app = gtk_application_new("sean.s-engineer.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(app), argc, argv);
    g_object_unref(app);
 
    return status;
}
 
 
 

 

컴파일(빌드)하고 실행하면 창에 이미지가 디스플레이 된다. 클릭하면 좌표가 터미널에 표시된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 GTK+3를 이용해 GUI 프로그래밍을 해 보자.

 

GTK+3를 설치한다.

 

단순한 window를 만드는 예제 소스를 입력한다.

 

컴파일(빌드)하고 실행하면 창이 나타나다. 단순한 창이지만 이동, 종료등의 모든 기본적인 기능을 갖고 있다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <gtk/gtk.h>
 
/* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello World\n");
}
 
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    /* If you return FALSE in the "delete-event" signal handler,
     * GTK will emit the "destroy" signal. Returning TRUE means
     * you don't want the window to be destroyed.
     * This is useful for popping up 'are you sure you want to quit?'
     * type dialogs. */
 
    g_print ("delete event occurred\n");
 
    /* Change TRUE to FALSE and the main window will be destroyed with
     * a "delete-event". */
 
    return TRUE;
}
 
/* Another callback */
static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}
 
int main( int   argc,
          char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    
    /* This is called in all GTK applications. Arguments are parsed
     * from the command line and are returned to the application. */
    gtk_init (&argc, &argv);
    
    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    /* When the window is given the "delete-event" signal (this is given
     * by the window manager, usually by the "close" option, or on the
     * titlebar), we ask it to call the delete_event () function
     * as defined above. The data passed to the callback
     * function is NULL and is ignored in the callback function. */
    g_signal_connect (window, "delete-event",
              G_CALLBACK (delete_event), NULL);
    
    /* Here we connect the "destroy" event to a signal handler.  
     * This event occurs when we call gtk_widget_destroy() on the window,
     * or if we return FALSE in the "delete-event" callback. */
    g_signal_connect (window, "destroy",
              G_CALLBACK (destroy), NULL);
    
    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    
    /* Creates a new button with the label "Hello World". */
    button = gtk_button_new_with_label ("Hello World");
    
    /* When the button receives the "clicked" signal, it will call the
     * function hello() passing it NULL as its argument.  The hello()
     * function is defined above. */
    g_signal_connect (button, "clicked",
              G_CALLBACK (hello), NULL);
    
    /* This will cause the window to be destroyed by calling
     * gtk_widget_destroy(window) when "clicked".  Again, the destroy
     * signal could come from here, or the window manager. */
    g_signal_connect_swapped (button, "clicked",
                  G_CALLBACK (gtk_widget_destroy),
                              window);
    
    /* This packs the button into the window (a gtk container). */
    gtk_container_add (GTK_CONTAINER (window), button);
    
    /* The final step is to display this newly created widget. */
    gtk_widget_show (button);
    
    /* and the window */
    gtk_widget_show (window);
    
    /* All GTK applications must have a gtk_main(). Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    gtk_main ();
    
    return 0;
}
 

 

GTK+2 스타일의 예제 소스를 입력해 보자.

 

GTK+2 스타일의 소스를 빌드해도 문제 없다. Hello World 버튼을 클릭한다.

 

터미널 출력까지 잘 된다.

 

반응형
Posted by J-sean
:
반응형

The SendInput function inserts the events in the INPUT structures serially into the keyboard or mouse input stream.

마우스 입력을 보낸다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <Windows.h>
#include <iostream>
 
using namespace std;
 
void PrintMenu()
{
    cout << "--- Mouse sender ---" << endl << endl;
    cout << "0: End" << endl;
    cout << "1: Get cursor position" << endl;
    cout << "2: Send left button click" << endl;
    cout << "3: Send right button click" << endl;
    cout << "4: Send cursor move" << endl;
    cout << "Choose: ";
}
 
void GetCursorPosition()
{
    Sleep(2000);    // Wait for 2 seconds before get the cursor position.
 
    POINT cursorPos;
    GetCursorPos(&cursorPos);
 
    cout << "Current cursor position : (x: " << cursorPos.x << ", y: " << cursorPos.y << ")" << endl;
}
 
void SendLeftClick()
{
    Sleep(5000);
 
    INPUT input;
    ZeroMemory(&input, sizeof(INPUT));
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    SendInput(1&input, sizeof(INPUT));
 
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(1&input, sizeof(INPUT));
}
 
void SendRightClick()
{
    Sleep(5000);
 
    INPUT input;
    ZeroMemory(&input, sizeof(INPUT));
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
    SendInput(1&input, sizeof(INPUT));
 
    input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
    SendInput(1&input, sizeof(INPUT));
}
 
void SendMove()
{
    int x, y;
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
 
    cout << "Screen size: (" << screenWidth << ", " << screenHeight << ")" << endl;
    cout << "[x: 0~" << screenWidth - 1 << ", y: 0~" << screenHeight - 1 << "]" << endl;
    cout << "x: ";
    cin >> x;
    cout << "y: ";
    cin >> y;
 
    INPUT input;
    ZeroMemory(&input, sizeof(INPUT));
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
    // If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates
    // between 0 and 65,535. The event procedure maps these coordinates onto the display surface.
    // Coordinate (0,0) maps onto the upper-left corner of the display surface; coordinate (65535,65535)
    // maps onto the lower-right corner. In a multimonitor system, the coordinates map to the primary monitor.
    //
    // If the MOUSEEVENTF_ABSOLUTE value is not specified, dxand dy specify movement relative to the previous
    // mouse event(the last reported position).Positive values mean the mouse moved right(or down); negative
    // values mean the mouse moved left(or up).
    float dx = x * (65535.0f / (screenWidth - 1));
    float dy = y * (65535.0f / (screenHeight - 1));
    input.mi.dx = LONG(dx);
    input.mi.dy = LONG(dy);
    SendInput(1&input, sizeof(INPUT));
}
 
int main()
{
    int choice = 1;
 
    while (choice)
    {
        PrintMenu();
        cin >> choice;
 
        switch (choice)
        {
        case 1:
            GetCursorPosition();
 
            break;
        case 2:
            SendLeftClick();
 
            break;
        case 3:
            SendRightClick();
 
            break;
        case 4:
            SendMove();
 
            break;
        default:
 
            return 0;
        }
    }
 
    return 0;
}



Run the program and choose the event you want to send.


반응형
Posted by J-sean
:
반응형

The SendInput function inserts the events in the INPUT structures serially into the keyboard or mouse input stream.

키보드 입력을 보낸다.


2020/10/17 - [Raspberry Pi & Arduino] - Turn your Arduino Pro Micro into a USB Keyboard - 아두이노 프로 마이크로 USB 키보드 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <Windows.h>
#include <iostream>
 
using namespace std;
 
void PrintMenu()
{
    cout << "--- Key sender ---" << endl << endl;
    cout << "0: End" << endl;
    cout << "1: Send left key" << endl;
    cout << "2: Send right key" << endl;
    cout << "3: Send up key" << endl;
    cout << "4: Send down key" << endl;
    cout << "5: Send enter key" << endl;
    cout << "6: Send 'aA'" << endl;
    cout << "Choose: ";
}
 
// Virtual-Key Codes: https://docs.microsoft.com/ko-kr/windows/win32/inputdev/virtual-key-codes
void SendVKcodes(BYTE vk)
{
    Sleep(5000); // Wait for 5 seconds before sending a keycode.
 
    INPUT input;
    ZeroMemory(&input, sizeof(INPUT));
    input.type = INPUT_KEYBOARD;
    input.ki.wVk = vk;
    // A virtual-key code. The code must be a value in the range 1 to 254. If the dwFlags member
    // specifies KEYEVENTF_UNICODE, wVk must be 0.
 
    // input.ki.wScan = vk;
    // A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies
    // a Unicode character which is to be sent to the foreground application.
 
    SendInput(1&input, sizeof(INPUT));
 
    input.ki.dwFlags = KEYEVENTF_KEYUP;
    // If specified, the key is being released. If not specified, the key is being pressed.
    SendInput(1&input, sizeof(INPUT));
}
 
void SendaA()
{
    Sleep(5000);
 
    // Send 'a'
    INPUT input;
    ZeroMemory(&input, sizeof(INPUT));
    input.type = INPUT_KEYBOARD;
    input.ki.wVk = 0x41;    // a key
    SendInput(1&input, sizeof(INPUT));
 
    input.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1&input, sizeof(INPUT));
 
    // Sned 'A'
    input.ki.dwFlags = 0;
    input.ki.wVk = VK_SHIFT;
    SendInput(1&input, sizeof(INPUT));
 
    input.ki.wVk = 0x41;    // a key
    SendInput(1&input, sizeof(INPUT));
 
    input.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1&input, sizeof(INPUT));
 
    input.ki.wVk = VK_SHIFT;
    SendInput(1&input, sizeof(INPUT));
}
 
int main()
{
    int choice = 1;
 
    while (choice)
    {
        PrintMenu();
        cin >> choice;
 
        switch (choice)
        {
        case 1:
            SendVKcodes(VK_LEFT);
 
            break;
        case 2:
            SendVKcodes(VK_RIGHT);
 
            break;
        case 3:
            SendVKcodes(VK_UP);
 
            break;
        case 4:
            SendVKcodes(VK_DOWN);
 
            break;
        case 5:
            SendVKcodes(VK_RETURN);
 
            break;
 
        case 6:
            SendaA();
 
            break;
        default:
 
            return 0;
        }
    }
 
    return 0;
}




Run the program and choose the key you want to send.


※ Adjust key down duration by adding Sleep() between KEYEVENTF_KEYDOWN and KEYEVENTF_KEYUP.

For short key down duration, give 60~100 to Sleep() for the better result although some keys don't need Sleep() at all for very short key down duration.


반응형
Posted by J-sean
: