【发布时间】:2010-07-30 18:15:11
【问题描述】:
好的,这是一个非常奇怪的问题。我想首先说我不是 C++ 的初学者,而且我当然不是高级的。我在中间的某个地方。我想要做的是制作 Win32 API 的 C++ OOP 包装库 (dll)。这是我图书馆的课程。我用 Mingw 编译它,使用命令:
g++ -shared -o bin\win32oop.dll src\Application.cpp src\Form\Form.cpp -Wall
src\Application.h:
#ifndef WOOP_APPLICATION_H_
#define WOOP_APPLICATION_H_
namespace Woop
{
class Application
{
public:
bool Init(void);
virtual bool OnInit(void);
};
}
#endif // WOOP_APPLICATION_H_
src\Application.cpp
#include <windows.h>
#include "Application.h"
#include "Form\Form.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
namespace Woop
{
bool Application::Init(void)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "woop";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(RegisterClassEx(&wc) == 0)
{
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return false;
}
this->OnInit();
return true;
}
bool Application::OnInit(void)
{
return true;
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Woop::Form *wnd = 0;
if (uMsg == WM_NCCREATE)
{
SetWindowLong (hwnd, GWL_USERDATA, long((LPCREATESTRUCT(lParam))->lpCreateParams));
}
wnd = (Woop::Form *)(GetWindowLong (hwnd, GWL_USERDATA));
if (wnd) return wnd->WndProc(hwnd, uMsg, wParam, lParam);
return ::DefWindowProc (hwnd, uMsg, wParam, lParam);
}
src\Form\Form.h
#ifndef WOOP_FORM_FORM_H_
#define WOOP_FORM_FORM_H_
namespace Woop
{
class Form
{
public:
bool Show(void);
virtual LRESULT WndProc(HWND, UINT, WPARAM, LPARAM);
protected:
HWND _handle;
};
}
#endif // WOOP_FORM_FORM_H_
src\Form\Form.cpp
#include <windows.h>
#include "Form.h"
namespace Woop
{
bool Form::Show(void)
{
_handle = CreateWindowEx(WS_EX_CLIENTEDGE, "woop", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, GetModuleHandle(NULL), this);
if(_handle == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return false;
}
ShowWindow(_handle, SW_SHOWNORMAL);
return true;
}
LRESULT Form::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
这是我用来测试库的程序:
class SampleApp : public Woop::Application
{
bool OnInit(void)
{
Form form;
form.Show();
return true;
}
};
INT APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
SampleApp application;
if(application.Init() == false) return 0;
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
好的,现在问题来了。您在 Form 类中看到那个虚拟窗口过程了吗?如果我从声明中删除虚拟,程序编译并运行良好。但是当我重新添加它时,它会崩溃。臭名昭著的“不要发送”对话框出现了。我不确定它什么时候崩溃,我会尝试使用 MessageBox() 来解决这个问题(哈哈,这是我没有学习如何使用 gdb 进行调试的结果)。我正在尝试这样做,以便我可以创建诸如 LoginForm 之类的类并从 Form 派生并覆盖窗口过程。我希望我能很好地解释这个问题:D。这可能是编译器错误或我的愚蠢:P。无论如何,提前谢谢。
【问题讨论】:
-
您从
GetWindowLong()获得并转换为Form*(在全局WndProc()中)实际上是指向Form的有效指针吗?如果没有,那么虚拟呼叫就会爆炸。 -
看看你在这里尝试做什么很好地解释了 MS 为了让他们的 MFC C++ OO API 在 Win32 窗口系统上运行而采取的措施。
-
感谢参考马丁。我正在寻找一本关于在 c++ OOP 中包装 Win32 的好书。
标签: c++ windows debugging winapi crash