GLEW与WinAPI窗口大小及鼠标点击坐标不一致问题排查
高DPI缩放场景下GLFW与WinAPI窗口坐标差异问题
在150%显示器缩放设置下,WinAPI创建的窗口比GLFW创建的大1.5倍,两者官方文档均明确宽高参数采用屏幕坐标。排查后确认是系统高DPI缩放导致该差异。通过设置glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);可以解决窗口大小不匹配的问题,但此时GLFW鼠标回调返回的点击坐标仍为物理像素值,与WinAPI返回的逻辑坐标存在150%的缩放差异。
相关代码片段
GLFW鼠标回调代码片段
glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods) { if (action == GLFW_RELEASE) { double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); cout << "release x:"<<xpos<<" y:"<< ypos << endl; } } );
WinAPI(ATL)鼠标回调代码片段
LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { using std::cout; using std::endl; POINT c{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; cout<< c<< endl; InvalidateRect(0, false); return 0; }
完整代码示例
完整GLFW代码
// GLFW #include <GL/glew.h> // 注意:GLEW必须在GLFW之前包含 #include <GLFW/glfw3.h> #include <iostream> using namespace std; const int width = 1280, height = 720; int main(int argc, char* argv[]) { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); GLFWwindow* window = glfwCreateWindow(width, height, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); GLenum err = glewInit(); if (GLEW_OK != err) { cerr << "GLEW Error: " << glewGetErrorString(err) << endl; return -1; } // 初始化OpenGL程序 glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods) { if (action == GLFW_RELEASE) { double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); cout << "release x:"<<xpos<<" y:"<< ypos << endl; } } ); glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, true); } ); while (!glfwWindowShouldClose(window)) { /// 绘制OpenGL内容 glfwSwapBuffers(window); glfwPollEvents(); } glfwDestroyWindow(window); exit(EXIT_SUCCESS); }
完整WinAPI(ATL)代码
// WinAPI #include <GL/glew.h> #include <Windows.h> #include <Windowsx.h> #include <atlbase.h> #include <atlwin.h> #include <iostream> using std::cout; using std::endl; std::ostream& operator<< (std::ostream& os, POINT pt) { os << "{x:" << pt.x << " y:" << pt.y << "}"; return os; } int glProgramInit() { // 在此初始化OpenGL程序 } class CMyWindow : public CWindowImpl<CMyWindow> { public: CMyWindow() {} virtual ~CMyWindow() {} /////////////////////////// 消息处理函数 ///////////////////////////////// LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HDC hdc; // display(); SwapBuffers(hdc = this->GetWindowDC()); ReleaseDC(hdc); return 0; } LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // glProgramDestroy(); PostQuitMessage(0); return 0; } HGLRC initOpenGL(HDC hdc) { using std::cerr; using std::endl; PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // 标志位 PFD_TYPE_RGBA, // 帧缓冲类型:RGBA或调色板 32, // 帧缓冲颜色深度 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, // 深度缓冲位数 8, // 模板缓冲位数 0, // 辅助缓冲数量 PFD_MAIN_PLANE, 0, 0, 0, 0 }; int newPixelFormat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, newPixelFormat, &pfd); HGLRC hglrc = wglCreateContext(hdc); wglMakeCurrent(hdc, hglrc); GLenum err = glewInit(); if (GLEW_OK != err) { cerr << "GLEW Error: " << glewGetErrorString(err) << endl; return 0; } return hglrc; } LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { RECT rc = CWindow::rcDefault; this->GetWindowRect(&rc); rc.right = rc.left + width; rc.bottom = rc.top + height; this->SetWindowPos(HWND_TOP, &rc, SWP_NOZORDER); HDC hdc; this->initOpenGL(hdc = this->GetWindowDC()); ReleaseDC(hdc); glProgramInit(); return 0; } LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { using std::cout; using std::endl; POINT c{ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; cout<< c<< endl; InvalidateRect(0, false); return 0; } BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) END_MSG_MAP() }; using namespace std; int main() { CMyWindow cwnd; HWND hWnd = cwnd.Create(NULL, CWindow::rcDefault, L"Hello", WS_OVERLAPPEDWINDOW); cwnd.ShowWindow(SW_SHOW); MSG msg; while (GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg); } return 0; }
内容的提问来源于stack exchange,提问作者armagedescu
相关产品推荐
相关产品推荐

