Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95

Некорректная работа курсора

23.04.2016, 15:54. Показов 735. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Есть след. код

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
209
210
CWindow::CWindow() { pWindow = this; }
    bool CWindow::InitializeWindow(const std::wstring& windowName, HCURSOR cursor, ECreateWindowConfiguration config, uint32 width, uint32 height)
    {
        m_HInstance = GetModuleHandle(NULL);
        m_ClassName = windowName;
        m_HCursor = cursor;
        if(config == WC_CREATE_WINDOW_CONFIG_1)
        {
            m_WindowWidth = 640U;
            m_WindowHeight = 480U;
        }
        else if(config == WC_CREATE_WINDOW_CONFIG_2)
        {
            m_WindowWidth = 800U;
            m_WindowHeight = 600U;
        }
        else if(config == WC_CREATE_WINDOW_CONFIG_3)
        {
            m_WindowWidth = 1920U;
            m_WindowHeight = 1080U;
        }
        else if(config == WC_CREATE_WINDOW_WITH_USER_SETTINGS)
        {
            m_WindowWidth = width;
            m_WindowHeight = height;
        }
        else if(config == WC_CREATE_WINDOW_FULLSCREEN)
        {
            m_WindowWidth = GetSystemMetrics(SM_CXSCREEN);
            m_WindowHeight = GetSystemMetrics(SM_CYSCREEN);
            m_WindowPosX = m_WindowPosY = 0U;
            m_Fullscreen = true;
        }
        if(config != WC_CREATE_WINDOW_FULLSCREEN)
        {
            m_WindowPosX = (GetSystemMetrics(SM_CXSCREEN) - m_WindowWidth) / 2;
            m_WindowPosY = (GetSystemMetrics(SM_CYSCREEN) - m_WindowHeight) / 2;
        }
 
        if(FAILED(m_RegisterWindowClass()))
            return false;
        if(FAILED(m_CreateAppWindow()))
            return false;
 
        SetCursor(m_HCursor);
        return true;
    }
    
    MSG CWindow::ProcessMessage()
    {
        MSG msg;
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg;
    }
    bool CWindow::IsRun() const
    {
        return m_IsRunWindow;
    }
    void CWindow::ChangeCursor(HCURSOR cursor)
    {
        m_HCursor = cursor;
        SetCursor(m_HCursor);
    }
 
    void CWindow::ShowAppCursor()
    {
        while(ShowCursor(TRUE) < 0);
        m_VisibleCursor = true;
    }
    void CWindow::HideAppCursor()
    {
        while(ShowCursor(FALSE) >= 0);
        m_VisibleCursor = false;
    }
 
    HWND& CWindow::GetHWND()            { return m_HWnd; }
    uint8 CWindow::GetWidth() const     { return m_WindowWidth; }
    uint8 CWindow::GetHeight() const    { return m_WindowHeight; }
    uint8 CWindow::GetXPos() const      { return m_WindowPosX; }
    uint8 CWindow::GetYPos() const      { return m_WindowPosY; }
 
    POINT CWindow::GetMouseCoordinates() const
    {
        POINT pt;
        pt.x = m_CurPosX;
        pt.y = m_CurPosY;
        return pt;
    }
 
    void CWindow::SystemAlert(const wchar_t* msg, const wchar_t* head)
    {
        MessageBox(NULL, msg, head, MB_OK);
    }
 
    LRESULT CALLBACK CWindow::MessageHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_CLOSE:
            m_IsRunWindow = false;
            return 0;
 
        case WM_MOUSEMOVE:
            m_UpdateCursorCoordinates();
            return 0;
 
        case WM_MOVE:
        case WM_SIZE:
            GetClientRect(m_HWnd, &m_WindowRect);
            m_WindowPosX = m_WindowRect.left;
            m_WindowPosY = m_WindowRect.top;
            return 0;
 
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
        }
        
    }
    void CWindow::Stop()
    {
        m_IsRunWindow = false;
    }
    void CWindow::Shutdown()
    {
        PostQuitMessage(0);
        if(m_Fullscreen)
            ChangeDisplaySettings(NULL, 0);
        DestroyWindow(m_HWnd);
        UnregisterClass(m_ClassName.c_str(), m_HInstance);
    }
    HRESULT CWindow::m_RegisterWindowClass()
    {
        WNDCLASSEX wc;
        ZeroMemory(&wc, sizeof(wc));
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.hInstance = m_HInstance;
        wc.lpfnWndProc = WndProc;
        wc.lpszClassName = m_ClassName.c_str();
        wc.lpszMenuName = NULL;
        wc.hIcon = wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
        wc.hCursor = NULL;
        wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
        wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        if(!RegisterClassEx(&wc))
            return E_FAIL;
        return S_OK;
    }
    HRESULT CWindow::m_CreateAppWindow()
    {
        if(m_Fullscreen)
        {
            DEVMODE dmScreenSettings;
            memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
            dmScreenSettings.dmSize = sizeof(dmScreenSettings);
            dmScreenSettings.dmPelsWidth = (unsigned long)m_WindowWidth;
            dmScreenSettings.dmPelsHeight = (unsigned long)m_WindowHeight;
            dmScreenSettings.dmBitsPerPel = 32;
            dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
            ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
            m_HWnd = CreateWindowEx(WS_EX_APPWINDOW, m_ClassName.c_str(), m_ClassName.c_str(), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
                m_WindowPosX, m_WindowPosY, m_WindowWidth, m_WindowHeight, NULL, NULL, m_HInstance, NULL);
            if(m_HWnd)
            {
                ShowWindow(m_HWnd, SW_SHOW);
                SetForegroundWindow(m_HWnd);
                SetFocus(m_HWnd);
                m_IsRunWindow = true;
                GetWindowRect(m_HWnd, &m_WindowRect);
                m_UpdateCursorCoordinates();
                m_VisibleCursor = true;
                return S_OK;
            }
        }
        else
        {
            m_HWnd = CreateWindowEx(WS_EX_APPWINDOW, m_ClassName.c_str(), m_ClassName.c_str(), WS_OVERLAPPEDWINDOW, m_WindowPosX, m_WindowPosY,
                m_WindowWidth, m_WindowHeight, NULL, NULL, m_HInstance, NULL);
            if(m_HWnd)
            {
                ShowWindow(m_HWnd, SW_SHOW);
                SetForegroundWindow(m_HWnd);
                SetFocus(m_HWnd);
                m_IsRunWindow = true;
                GetWindowRect(m_HWnd, &m_WindowRect);
                m_UpdateCursorCoordinates();
                m_VisibleCursor = true;
                return S_OK;
            }
        }
        return E_FAIL;
    }
    void CWindow::m_UpdateCursorCoordinates()
    {
        POINT pt;
        GetCursorPos(&pt);
        m_CurPosX = pt.x - m_WindowPosX;
        m_CurPosY = pt.y - m_WindowPosY;
    }
 
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        return pWindow->MessageHandler(hWnd, msg, wParam, lParam);
    }
И проблема следующая, допустим при создании она 800 на 600, при выходе курсора за границы экрана и заходе обратно в эти границы, курсор, проходя через рамку окна меняется на стрелки и обратно не восстанавливается. Каким образом это решить? Не знаю причину, но вобще как вариант можно отлавливать вхождение курсора в область окна и менять курсор обратно, а как реализовать не знаю.
Миниатюры
Некорректная работа курсора  
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.04.2016, 15:54
Ответы с готовыми решениями:

Некорректная работа DialogBox'a
Диалоговое окно,в котором программа должна при нажатии на кнопку &quot;OK&quot; записывать текст из EditBox1 в EditBox2, ошибок при этом не...

Некорректная работа GetOpenFileName
Здравствуйте, столкнулся с одной проблемой, которую самостоятельно решить не смог, хотя вроде бы все верно, если сравнивать с мануалами и...

Работа с файлом (корректный код, некорректная работа программы)
Для записи и чтения файла использую разные функции. По одиночке они работают нормально. Вставляю их прототипы в функцию main() и нижняя...

4
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
23.04.2016, 16:14  [ТС]
При регистрации класса по умолчанию курсор не ставил, т.к. будет меняться в процессе работы.

Добавлено через 18 минут
C++
1
2
3
4
5
case WM_MOUSEMOVE:
            m_UpdateCursorCoordinates();
            if(m_HCursor != GetCursor())
                SetCursor(m_HCursor);
            return 0;
Решил пока таким образом, думаю более грамотный способ есть, чтобы не вызывать постоянно SetCursor()...
0
 Аватар для rao
903 / 424 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
24.04.2016, 10:26
Думаю правильнее это делать в WM_SETCURSOR, он же для этого и предназначен.
И GetCursor() делать не надо: установил какой нужно и все.
1
26 / 26 / 15
Регистрация: 30.12.2015
Сообщений: 95
24.04.2016, 13:59  [ТС]
rao, В таком случае как его правильно использовать? Если вызывать SetCursor() в WM_SETCURSOR, курсор при масштабировании окна не изменяется. Пока что визуально полностью рабочий вариант это первый, но слишком много лишних вызовов получается..
0
 Аватар для rao
903 / 424 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
24.04.2016, 16:56
Тут дело такое, если при регистрации оконного класса ты сказал wc.hCursor = NULL; то система не знает какой курсор использовать "по умолчанию" и поэтому не может его поменять после "стрелочек". (Т.е. ничего некорректного в таком поведении нет).
Если же ты объявляешь свой обработчик WM_SETCURSOR, то надо его реализовывать полноценно - с "отловом" положений мыши на рамке окна и ручным показом курсоров-стрелочек. Не трудно, но громоздко.

Может быть тебе для переключения курсора делать не много раз SetCursor(), а один раз
C++
1
SetClassLong(hWnd, GCL_HCURSOR, (LONG)hНужногоКурсора);
?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
24.04.2016, 16:56
Помогаю со студенческими работами здесь

Работа с INI: некорректная работа пользовательской функции
Ранее нашел код для работы с ini-файлами: public class INI { /// &lt;summary&gt; /// Чтение...

Некорректная работа
Подскажите пожалуйста. Поставил win10, как-то сразу криво пошла установка anaconda. Запуск только через bat .... теперь выполняю...

Некорректная работа
Здравствуйте. Есть триггер который удаляет запись и сохраняет ее в другую таблицу.(из таблицы билет в таблицу архив) Но если зайти в...

Некорректная работа
Type TArray = array of integer; function MultiplicationMatrix(Matrix1k, Matrix2k: TArray): TArray; Var i, j, index:...

Некорректная работа
Не могу разобраться в чём ошибка,пользователь вводит имя,и ссайт должен его поприветствовать,но вместо этого выводитсяя фигня hiUser.html...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru