Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
123
36 / 0 / 1
Регистрация: 18.03.2015
Сообщений: 221

Не работает клик мыши

06.03.2026, 06:52. Показов 7849. Ответов 66
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Отрисовываю треугольник на openGL.

Переменная qf должна при клике увеличиваться на 3 таким образом меняется координата нижней правой точки треугольника.
Но даже не рендерится...

C++
1
2
3
4
5
6
 case WM_LBUTTONDOWN:
        {
            //int xPos = GET_X_LPARAM(lParam);
          //  int yPos = GET_Y_LPARAM(lParam);
 
           // qf = qf*3;

||=== Build: Debug in quad+ (compiler: GNU GCC Compiler) ===|
++\quad+\main.c||In function 'WindowProc':|
++\quad+\main.c|125|error: implicit declaration of function 'GET_X_LPARAM'; did you mean 'GET_SC_WPARAM'? [-Wimplicit-function-declaration]|
++\quad+\main.c|126|error: implicit declaration of function 'GET_Y_LPARAM'; did you mean 'GET_SC_WPARAM'? [-Wimplicit-function-declaration]|
++\quad+\main.c|128|error: 'q' undeclared (first use in this function)|
++\quad+\main.c|128|note: each undeclared identifier is reported only once for each function it appears in|
++\quad+\main.c|126|warning: unused variable 'yPos' [-Wunused-variable]|
++\quad+\main.c|125|warning: unused variable 'xPos' [-Wunused-variable]|
||=== Build failed: 3 error(s), 2 warning(s) (0 minute(s), 3 second(s)) ===|
Могу уточнить детали если нужно.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.03.2026, 06:52
Ответы с готовыми решениями:

Клик мыши, как сделать?
Нужна просто команда или функция которая бы кликалы мыш в часть экрана где она установлена. Можно...

Клик мыши на пиксел
хочу написать код, который будет в заданных координатах кликать левой кнопкой мыши на пиксели...

Перемещение курсора мыши на заданные координаты и клик
Добрый день. Подскажите, пожалуйста, как можно реализовать сабж. Гугление выдает некоторые...

66
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13235 / 6867 / 1827
Регистрация: 18.10.2014
Сообщений: 17,400
30.03.2026, 02:17
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от 8Observer8 Посмотреть сообщение
если точно, то нужно вызвать DestroyWindow() при обработке WM_CLOSE
... или просто разрешить WM_CLOSE провалиться дальше в обработчик по умолчанию, то есть в DefWindowProc. Дело вкуса.
1
9992 / 2964 / 497
Регистрация: 05.10.2013
Сообщений: 8,147
Записей в блоге: 244
30.03.2026, 03:37

Не по теме:

Я нашёл как вы выделяете текст - это тег [inline]



Я удалил строку case WM_CLOSE:, чтобы событие WM_CLOSE провалилось в обработчик по умолчанию:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            g_running = false;
            PostQuitMessage(0);
            return 0;
 
        /* ... */
 
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Добавил защиту для функции glViewport(x, y, width, height), чтобы не было ситуации передачи нулевых значений ширины и высоты вьюпорта. Вьюпорт это рамка, внутри которой рисует видеокарта. Нежелательно, чтобы высота или ширина рамки была равна нулю. При сворачивании окна размер приходит событие WM_SIZE и размеры клиентской области окна (то есть холста), равны нулю. Эта защита пригодится и для пересчёта матрицы проекции, чтобы не было деления на ноль внутри функции glm_ortho(left, right, bottom, top, near, far, projection):

C++
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
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            g_running = false;
            PostQuitMessage(0);
            return 0;
        case WM_SIZE:
            int width = LOWORD(lParam);
            int height = HIWORD(lParam);
 
            // printf("Size: %d, %d\n", width, height);
 
            if (width == 0 || height == 0)
                return 0;
 
            if (g_hRC != NULL)
            {
                glViewport(0, 0, width, height);
 
                // Здесь можно пересчитать матрицу проекции, 
                // чтобы треугольник не растягивался
            }
            return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
Исправил код вращающегося треугольника из сообщения #58, чтобы он компилировался C++ компилятором. Основная правка коснулась передачи векторов в функции cglm (такие как glm_translate, glm_rotate). Поскольку C++ не поддерживает C-style составные литералы в аргументах функций, я вынес векторы в отдельные переменные vec3:

C++
1
2
3
// Пример исправления:
vec3 camera_pos = { 0.0f, 0.0f, -3.0f };
glm_translate(view, camera_pos);
main.cpp

C++
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <cglm/cglm.h>
#include <glad/glad.h>
#include <stdbool.h>
#include <windows.h>
#include <stdio.h>
 
const char *vertexShaderSource =
    "#version 330 core\n"
    "layout (location = 0) in vec3 aPosition;\n"
    "uniform mat4 mvp;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = mvp * vec4(aPosition, 1.0);\n"
    "}\n";
 
const char *fragmentShaderSource =
    "#version 330 core\n"
    "out vec4 fragColor;\n"
    "void main()\n"
    "{\n"
    "   fragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n";
 
HWND g_hWnd = NULL;
HDC g_hDC = NULL;
HGLRC g_hRC = NULL;
bool g_running = true;
 
typedef BOOL(WINAPI *PFNWGLSWAPINTERVALEXTPROC)(int interval);
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            g_running = false;
            PostQuitMessage(0);
            return 0;
        case WM_SIZE:
            int width = LOWORD(lParam);
            int height = HIWORD(lParam);
 
            // printf("Size: %d, %d\n", width, height);
 
            if (width == 0 || height == 0)
                return 0;
 
            if (g_hRC != NULL)
            {
                glViewport(0, 0, width, height);
 
                // Здесь можно пересчитать матрицу проекции, 
                // чтобы треугольник не растягивался
            }
            return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "Sample Window Class";
    wc.style = CS_OWNDC;
    RegisterClass(&wc);
 
    g_hWnd = CreateWindowEx(0, wc.lpszClassName, "OpenGL 3.3, WinAPI, C++",
        WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 350, 350,
        NULL, NULL, hInstance, NULL);
 
    ShowWindow(g_hWnd, nShowCmd); 
    UpdateWindow(g_hWnd);
 
    g_hDC = GetDC(g_hWnd);
    PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32 };
    SetPixelFormat(g_hDC, ChoosePixelFormat(g_hDC, &pfd), &pfd);
 
    g_hRC = wglCreateContext(g_hDC);
    wglMakeCurrent(g_hDC, g_hRC);
 
    if (!gladLoadGL())
        return -1;
 
    // Compile vertex shader
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
 
    // Compile fragment shader
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
 
    // Link shader program
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
 
    // Setup triangle data
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f, 0.5f, 0.0f
    };
 
    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
 
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);
 
    int mvpLoc = glGetUniformLocation(shaderProgram, "mvp");
 
    glClearColor(50.f / 255.f, 50.f / 255.f, 50.f / 255.f, 1.f);
 
    // Get the function from the driver
    PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT =
        (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
 
    // Enable VSync (1 = On, 0 = Off)
    if (wglSwapIntervalEXT)
    {
        wglSwapIntervalEXT(1);
    }
 
    float rotation = 0.0f;
 
    // Setup a timer
    LARGE_INTEGER frequency, lastTime, currentTime;
    QueryPerformanceFrequency(&frequency);
    QueryPerformanceCounter(&lastTime);
 
    MSG msg = { 0 };
    while (g_running)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
 
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(shaderProgram);
 
        QueryPerformanceCounter(&currentTime);
        float deltaTime = (float)(currentTime.QuadPart - lastTime.QuadPart) / frequency.QuadPart;
        lastTime = currentTime;
 
        // Rotate 1 radian per second
        rotation += 1.0f * deltaTime;
 
        // Model Matrix
        mat4 model;
        glm_mat4_identity(model);
 
        vec3 model_pos = { 0.2f, 0.0f, 0.0f };
        glm_translate(model, model_pos);
 
        vec3 axis_z = { 0.0f, 0.0f, 1.0f };
        glm_rotate(model, rotation, axis_z);
 
        vec3 model_scale = { 1.5f, 1.5f, 1.0f };
        glm_scale(model, model_scale);
 
        mat4 view;
        glm_mat4_identity(view);
 
        vec3 camera_pos = { 0.0f, 0.0f, -3.0f }; // Move camera back
        glm_translate(view, camera_pos);
 
        mat4 projection;
        // Arguments: left, right, bottom, top, near, far
        glm_ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 100.f, projection);
 
        mat4 mvp;
        glm_mat4_mul(projection, view, mvp);
        glm_mat4_mul(mvp, model, mvp); // Final MVP = P * V * M
 
        // Send the final matrix to shader
        glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, (float *)mvp);
 
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
 
        SwapBuffers(g_hDC);
    }
 
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
 
    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(g_hRC);
    ReleaseDC(g_hWnd, g_hDC);
 
    return 0;
}
0
9992 / 2964 / 497
Регистрация: 05.10.2013
Сообщений: 8,147
Записей в блоге: 244
30.03.2026, 03:59
Файлы проекта для примера вращающегося треугольника из предыдущего сообщения:
Вложения
Тип файла: zip transformed-triangle-opengl33-winapi-cpp.zip (4.1 Кб, 2 просмотров)
0
123
36 / 0 / 1
Регистрация: 18.03.2015
Сообщений: 221
06.04.2026, 13:01  [ТС]
000d60
Основы не мотивируют пока что. Пресные они...
3д именно и задумывается, но если не осилю то ок. Сомнительно но окэй.


8Observer8
Какая задумка для xPos и yPos?

Выдрал с сайта. Думал важно раз в них параметры.
0
Заблокирован
06.04.2026, 13:32
Цитата Сообщение от Андрей1926 Посмотреть сообщение
Основы не мотивируют пока что. Пресные они...
Без воды не сделать омлет.
Без кирпича не выловишь и рыбку.
Ты понял
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,365
06.04.2026, 15:07
Вот сочинил... Ничего что не по русски?

C++
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
bool ClickMouse(DWORD mouse_keys_DOWN, POINT cur_Pos, RECT rect)
{
    bool n_enter{ true };
 auto control{ [&n_enter](DWORD mouse_keys, RECT rect)->bool {
    if (SetCursorPos(rect.left, rect.top)) {
            POINT cursorPos{};
            if (GetCursorPos(&cursorPos)) {
                HWND chrom_hwnd = WindowFromPoint(cursorPos);
                char className[64]{};
                GetClassNameA(chrom_hwnd, className, sizeof(className));
 
    if ((mouse_keys == MOUSEEVENTF_RIGHTDOWN && strcmp(className + 7, "WindowClass") != 0) ||
            (mouse_keys == MOUSEEVENTF_LEFTDOWN && strcmp(className + 7, "DropShadowWindowClass") != 0))
                {
                return false;
                }
                return true;
            }   }
      n_enter= false;// Будет вылет по ошибке, а нажатия не будет..
      return false;
 }   };
 
 //==================================================
    if (mouse_keys_DOWN == MOUSEEVENTF_LEFTDOWN) {
        Sleep(200);
        rect.top += 90;
        // Менюшник короткий по нему не попал.
        if (!control(MOUSEEVENTF_LEFTDOWN, rect))rect.top -= 90;
        else rect.top -= 58;// Менюшник длинный
    SetCursorPos(rect.left, rect.top);
    }
    else if (!control(MOUSEEVENTF_RIGHTDOWN, rect)) {
        
        SetCursorPos(cur_Pos.x, cur_Pos.y);
        MessageBox(NULL, L"Не попал!", L"Error", MB_OK |
            MB_ICONQUESTION | MB_SETFOREGROUND | MB_SYSTEMMODAL);   
        return false;
        }
if (n_enter) {
        INPUT input = { 0 };
        input.type = INPUT_MOUSE;
        input.mi.dwFlags = mouse_keys_DOWN; // Нажать кнопку
        SendInput(1, &input, sizeof(INPUT));
        Sleep(2);
        // Подготовка структуры ввода для отпускания левой кнопки
        ZeroMemory(&input, sizeof(INPUT));
        input.type = INPUT_MOUSE;
        //----------------------------
        if (mouse_keys_DOWN == MOUSEEVENTF_RIGHTDOWN)
            input.mi.dwFlags = MOUSEEVENTF_RIGHTUP; // Отпустить кнопку
        else input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
        SendInput(1, &input, sizeof(INPUT));
    return true;
    }
else {
    SetCursorPos(cur_Pos.x, cur_Pos.y);
    MessageBox(NULL, L"Не понятная ошибка!", L"Error", MB_OK |
        MB_ICONQUESTION | MB_SETFOREGROUND | MB_SYSTEMMODAL);
   return false;
}   }
Одна задержка в строке 25.
Как не странно работает корректно.
0
9992 / 2964 / 497
Регистрация: 05.10.2013
Сообщений: 8,147
Записей в блоге: 244
06.04.2026, 15:46
Цитата Сообщение от Андрей1926 Посмотреть сообщение
Какая задумка для xPos и yPos?
Выдрал с сайта. Думал важно раз в них параметры.
Главное, чтобы вы сейчас понимали, что это локальные переменные, то есть они видимы только в пределах фигурных скобок. Код из вашего сообщения #6:

C++
1
2
3
4
5
6
7
8
9
10
       case WM_LBUTTONDOWN:
        {
            int xPos = GET_X_LPARAM(lParam);
          int yPos = GET_Y_LPARAM(lParam);
 
        q = q*3.0f;
              // InvalidateRect(hWnd, NULL, TRUE);
 
            return 0; // Message processed
        }
Вы удалили весь код, который использовал xPos и yPos. Вы видите, что перед ними стоят объявления int. Это значит, что они локальные и вы оставляете эти объявления, думая, что они где-то пригодятся в других местах программы. Не могут эти локальные переменные где-то пригодиться, так как для них область видимости - это фигурные скобки между которыми они находятся. Эти локальные переменные невидимы за пределами фигурных скобок. Вам надо срочно взять книгу или туториал по основам C++ и прочитать первые главы про объявления переменных локальными и глобальными и про области видимости.

В xPos и yPos считываются координаты клика мыши. Придумывайте маленькие упражнения для практики - как использовать эти данные. Например, для начала, можно менять положение треугольника по клику мыши, то есть выводить треугольник, где вы кликнули. Потом можно будет дописать программу, чтобы можно было определять был ли клик внутри треугольника или снаружи. Можно цвет треугольника менять на зелёный если вы кликнули по треугольнику и на красный, если вы кликнули вне треугольника. Из комбинаций множества маленьких упражнений вырастают всё более крупные программы. Практиковаться надо регулярно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.04.2026, 15:46

Клик мыши
Доброго времени суток. Помогите дойти до истины. Полазив по некоторым ресурсам, по раздумав сам я...

Клик мыши в координатах
Всем Привет, необходимо программно кликнуть допустим по координате (X;Y). Как это реализовать....

Реализовать движение мыши по какой-нибудь траектории, и в конце ее - клик левой кнопкой
Здравствуйте. Подскажите как реализовать движение мыши по какой-нибудь траектории и в конце вызвать...

Как сделать, чтобы клик мыши дублировался?
Как сделать так чтобы клик дублировался? То есть когда я нажал мышкой в координатах x,y , этот...

Клик мыши программно
Как заставить мышь кликнуть программно


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
67
Ответ Создать тему
Новые блоги и статьи
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru