- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Window 类,它包含一个方法来设置窗口句柄 (HWND) 的属性。该方法执行以下功能:
_hWnd = CreateWindowEx(dwExStyle, _wcex.lpszClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, _hInstance, this);
我传递 this 参数是因为我使用静态方法作为 WndProc() 函数的包装器,然后它将调用重定向到(非静态)方法。对 CreateWindowEx() 的调用应该将指针放入一个结构中,并在它调用 WndProc() 时将该结构的内存地址传回给我。但是当试图从 lParam 参数恢复对象指针时,我似乎无法恢复指向我的对象的指针,就好像 Windows API 传递给 lParam 的值是错误的。
我现在已经上传了完整的代码:
#include <Windows.h>
#include "Window.h"
LRESULT CALLBACK WndProc_main(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE prevInstance, _In_opt_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
const WCHAR szClassName_main[] = L"Main Window Class";
WNDCLASSEX wcex_main;
wcex_main.cbSize = sizeof(WNDCLASSEX);
wcex_main.style = CS_HREDRAW | CS_VREDRAW;
wcex_main.lpfnWndProc = NULL;
wcex_main.cbClsExtra = 0;
wcex_main.cbWndExtra = 0;
wcex_main.hInstance = hInstance;
wcex_main.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex_main.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex_main.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1); // MSDN: +1 should be added to chosen color.
wcex_main.lpszMenuName = NULL;
wcex_main.lpszClassName = szClassName_main;
wcex_main.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
Window window_main = Window(hInstance, wcex_main, WndProc_main);
window_main.setWindowHandle(WS_EX_CLIENTEDGE, L"Main Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, NULL);
window_main.DisplayWindow(nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int> (msg.wParam);
}
LRESULT CALLBACK WndProc_main(_In_ HWND hWnd, _In_ UINT msg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
case WM_DESTROY:
PostQuitMessage(EXIT_SUCCESS);
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return EXIT_SUCCESS;
}
窗口.h
#ifndef WINDOW_H
#define WINDOW_H
#include <Windows.h>
class Window
{
public:
// Constructors
Window(_In_ HINSTANCE, _In_ WNDCLASSEX, _In_ WNDPROC);
int setWindowHandle(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpWindowName,_In_ DWORD dwStyle, _In_ int x,
_In_ int y, _In_ int nWidth, _In_ int nHeight,_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu, _In_opt_ LPVOID lpParam);
void DisplayWindow(_In_ int nCmdShow);;
// Destructor
~Window();
// Public methods
int registerWindowClass();
int bindProcFunc(_In_ WNDPROC);
static LRESULT CALLBACK WndProcWrapper(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM);
protected:
private:
HINSTANCE _hInstance;
WNDCLASSEX _wcex;
WNDPROC _WndProc;
HWND _hWnd;
};
#endif // WINDOW_H
窗口.cpp
#include "Window.h"
Window::Window(HINSTANCE hInstance, WNDCLASSEX wcex, WNDPROC WndProc)
{
_hInstance = hInstance;
_wcex = wcex;
_wcex.lpfnWndProc = WndProcWrapper;
registerWindowClass();
bindProcFunc(WndProc);
}
Window::~Window()
{
// destructor
}
int Window::registerWindowClass()
{
if (!RegisterClassEx(&_wcex))
{
DWORD error = GetLastError();
if (error == ERROR_CLASS_ALREADY_EXISTS)
{
return EXIT_SUCCESS;
}
else
{
MessageBox(NULL, L"Window class registration failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
int Window::bindProcFunc(WNDPROC WndProc)
{
_WndProc = WndProc;
return EXIT_SUCCESS;
}
LRESULT CALLBACK Window::WndProcWrapper(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
Window* pThis;
if (msg = WM_NCCREATE)
{
pThis = static_cast<Window*> ((reinterpret_cast<CREATESTRUCT*>(lParam))->lpCreateParams);
SetLastError(0);
if (!SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis)))
{
if (GetLastError() != 0)
{
MessageBox(NULL, L"You messed up.", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
}
}
else
{
pThis = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
}
if(pThis)
{
return pThis->_WndProc(hWnd, msg, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int Window::setWindowHandle(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpWindowName,_In_ DWORD dwStyle, _In_ int x,
_In_ int y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu, _In_opt_ LPVOID lpParam)
{
_hWnd = CreateWindowEx(dwExStyle, _wcex.lpszClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, _hInstance, this);
if(_hWnd == NULL)
{
MessageBox(NULL, L"Window Handle creation failed", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void Window::DisplayWindow(_In_ int nCmdShow)
{
ShowWindow(_hWnd, nCmdShow);
UpdateWindow(_hWnd);
}
我在这里找到这段代码 https://stackoverflow.com/questions/21369256/how-to-use-wndproc-as-a-class-function在其他几个站点上,我检查了 CreateWindowEx() 的输入参数,但我似乎无法找到哪里出了问题。代码编译时没有任何警告。谁能帮我?我正在使用 Visual Studio 2013,为 64 位编译。
P.S:我也试过用 WM_CREATE 替换 WM_NCCREATE,但这似乎没有帮助。
最佳答案
我对这个问题产生了兴趣,花了一些时间调试它,在那个 CREATESTRUCT 中放置特殊标记并在内存窗口中寻找它们,等等。
然后我很幸运:当我让它运行时,我注意到 WM_NCCREATE 案例被重复输入,仔细观察我明白了:
if (msg = WM_NCCREATE)
这会获取第一条消息 (WM_GETMINMAXINFO),进行一些不恰当的转换,等等...
关于c++ - WndProc 作为类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35178779/
我有一个让我抓狂的问题。我花了一个星期的时间来追查这个错误,可能只是我对互操作的理解不如我想的那样。在这里: public class User { public const int GWL_W
我正在尝试处理 .NET WebBrowser 类型的 Close 事件,这似乎不是开箱即用的。 ( 编辑: 当在浏览器中运行的脚本中发出 window.close() 调用时,会发出此事件。) 我见
一天前,我开始重写我的一个旧组件,并决定提高其可读性。我的组件是一个典型的 TWinControl,它已重写 WndProc 来处理我自己的大量消息。每条消息都有很多代码,阅读代码成了一个问题。 因此
我正在阅读一些教程,遇到以下结构: protected override void WndProc( ref Message m ) { ... base.WndProc( ref m
我想在第二个线程上创建一个表单,该表单将在其 WndProc 方法中接收消息。创建这样的隐形表格的推荐方法是什么?设置“ShowInTaskbar=false”和“Visible=false”是否足够
我的表单中有以下 WndProc 处理程序。它应该防止水平移动表单(只允许垂直移动): protected override void WndProc(ref System.Windows.Forms
我被困住了。我有一个结构 vector ,其成员之一是 HWND。我使用这些 HWND 来处理消息,其他成员是特定于实例的参数。我使用 lpParam 将指向每个新创建的结构实例的指针传递给 WndP
我正在尝试创建一个自定义 GLWindow 类,其中包括我对 OpenGL 窗口的所有设置。但是,我还想在我的 GLWindow 类中包含用于发送到窗口的消息的 WndProc 回调函数。 GLWin
我创建了一个创建DLL 的项目。该项目使用WFS方法,它们访问一些硬件(设备)以获取信息或执行一些命令。 在我的项目中,我首先打开这些设备然后注册它们,然后我使用其他方法获取信息或执行。 HRESUL
我不是 C++ 的新手,但是 Win32 编程的概念对我来说是相当新的。无论如何,当 WM_NCHITTEST 消息通过 WndProc 传递时,我在获取 X 和 Y 坐标时遇到了一些麻烦。为了立即尝
我有一个 Window 类,它包含一个方法来设置窗口句柄 (HWND) 的属性。该方法执行以下功能: _hWnd = CreateWindowEx(dwExStyle, _wcex.lpszClass
我想在它自己的 wndproc 中处理所有 ListBox 消息传递,用于自己的透明项目绘画与 MainWindow 中显示的图像混合。不幸的是,现在只有 WM_PAINT、WM_ERASEBKGND
如果我有一个控制台应用程序,它的句柄是这样设置的; HWND hWnd = GetConsoleWindow(); 那我该如何为窗口设置一个新的wndProc呢? 我尝试使用 SetWindowLon
创建标准窗口控件(例如 "EDIT" 控件)时,其 WNDPROC 被定义为窗口类的一部分(即 "EDIT " 有一个特定的 WNDPROC,旨在使窗口显示并充当编辑控件。 MFC 允许您通过它们的包
当我创建一个新的 Win32 应用程序时,我注意到函数: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
我想知道是否有一种方法可以缩短这段代码,是否有办法制作一个 #define 来缩短我在消息开关中执行 if 语句的方式。我检查我是否已经设置了一个函数,如果有我就调用它这只是我的 wndproc 的一
我一直在四处寻找,并没有真正看到太多关于为什么有人会覆盖 wndproc 来处理消息的信息。 所以我想知道: 为什么要这样做? 什么时候做? 它在 C# 中的一般用途是什么? 当看到串行 COM 从计
这是我目前所拥有的...即使我实例化了一个 Window(WindowBase 的子类),我还是收到了一个错误,即试图调用一个纯虚函数。基本上,我的程序试图调用 WindowBase::WndProc
我有一个小问题希望有人能帮助我。有什么方法可以连接到其他应用程序 WNDPROC? 情况是我想在另一个应用程序菜单栏中插入一个菜单,并且我想为每个菜单项定义命令。 我能够使用一些 Win32 API
要与特定服务通信,我必须覆盖 WindProc。并接收窗口消息。 但是,当表单最小化时,我不再收到任何消息。我知道它必须是那样的,但是有解决方法吗?我不想有一个始终保持打开状态的隐藏表单... 最佳答
我是一名优秀的程序员,十分优秀!