我自己的个人 MFC
Posted
技术标签:
【中文标题】我自己的个人 MFC【英文标题】:My Own Personal MFC 【发布时间】:2011-08-18 09:47:00 【问题描述】:我似乎在 msdn 上找不到这个,一直在搜索(如下所述)。
请原谅贴的代码量,我会按顺序粘贴。你真的可以跳过大部分。但我只是想把它全部放在那里,这样我的要求就很清楚了。
假设我想做一个非常简单的 MFC。所以我有以下抽象和具体的类(粘贴在下面),我想要在我非常糟糕的框架中。
我还假设(尽管尚未实现)WinMain 将调用用户定义的主函数(如 Qt)。我需要做什么才能在我尝试编写的所有其他小的蹩脚 Win32 程序中重用我的代码。更清楚地说,我想知道是否将其编译为 DLL 或库。如果是这样,我该怎么做?如何在 DLL 中包含 WinMain 函数?
#ifndef IAPPLICATION_H_
#define IAPPLICATION_H_
#include <Windows.h>
namespace nApplication
class IController;
class IWindow;
class IApplication
public:
virtual int Run( ) = 0;
virtual HINSTANCE gethInstance( ) = 0;
virtual int getnCmdShow( ) = 0;
virtual IController* getMainControl( ) = 0;
protected:
IWindow *main_window;
IController *main_control;
private:
virtual int MessageLoop() = 0;
;
#endif /* IAPPLICATION */
-
#ifndef APPLICATION_H_
#define APPLICATION_H_
#include <Windows.h>
#include "IApplication.h"
#include "IWindow.h"
#include "IController.h"
#include "Controller.h"
namespace nApplication
class Application : public IApplication
public:
Application( HINSTANCE hInstance, int nCmdShow );
virtual ~Application( );
virtual int Run( );
virtual int getnCmdShow( ) return mnCmdShow;
virtual HINSTANCE gethInstance( ) return mhInstance;
virtual IController* getMainControl( ) return main_control;
private:
int mnCmdShow;
HINSTANCE mhInstance;
int MessageLoop();
Application( Application &app );
Application& operator= ( const Application &app );
;
#endif /* IAPPLICATION */
-
#include "Application.h"
#include "MainWindow.h"
namespace nApplication
Application::Application( HINSTANCE hInstance, int nCmdShow )
: mhInstance( hInstance ), mnCmdShow( nCmdShow )
Application::~Application( )
int Application::Run( )
main_window = new MainWindow( this );
main_control = new Controller( this );
main_window->Init( );
main_window->Display( );
MessageLoop( );
delete main_window;
return 0;
int Application::MessageLoop()
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) != 0)
TranslateMessage(&msg);
DispatchMessage(&msg);
return (int)msg.wParam;
-
#ifndef IWINDOW_H_
#define IWINDOW_H_
#include <Windows.h>
#include "IController.h"
namespace nApplication
class IWindow
public:
virtual void Init() = 0;
virtual void Display( ) = 0;
private:
;
#endif /* IWINDOW_H_ */
-
#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include <windows.h>
#include "IWindow.h"
#include "IController.h"
#include "IApplication.h"
namespace nApplication
class MainWindow : public IWindow
public:
MainWindow( IApplication *iApp);
~MainWindow();
void Init();
void Display( );
private:
WNDCLASSEX wc;
HWND hWnd;
IApplication *iApp;
;
#endif //MAINWINDOW_H_
-
#include "MainWindow.h"
namespace nApplication
namespace
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
HDC hDC;
PAINTSTRUCT ps;
static IController *cntrl;
cntrl = (IController*)::GetWindowLongPtr(hWnd, GWL_USERDATA);
if(uMsg == WM_NCCREATE)
cntrl = (IController*)(((CREATESTRUCT*)lParam)->lpCreateParams);
::SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)cntrl);
cntrl->CheckStatus();
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
switch(uMsg)
case WM_CREATE:
case WM_PAINT:
hDC = BeginPaint( hWnd, &ps );
TextOut( hDC, 10, 10, TEXT("Hello, Windows!"), 15 );
EndPaint( hWnd, &ps );
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
MainWindow::MainWindow( IApplication* iApp ) : iApp( iApp )
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = iApp->gethInstance( );
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = TEXT( "GenericAppMenu");
wc.lpszClassName = TEXT( "myWindowClass" );
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
MainWindow::~MainWindow()
void MainWindow::Init()
if( !RegisterClassEx(&wc) )
MessageBox(NULL, TEXT( "Window Registration Failed!" ), TEXT( "Error!" ), MB_ICONEXCLAMATION | MB_OK);
exit(0);
void MainWindow::Display( )
hWnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("myWindowClass"),
TEXT("The title of my window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
240, 120, NULL, NULL, iApp->gethInstance( ), iApp->getMainControl( ) );
if(hWnd == NULL)
::MessageBox( NULL, TEXT( "Window Creation Failed!" ),
TEXT( "Error!" ), MB_ICONEXCLAMATION | MB_OK );
exit(0);
::ShowWindow( hWnd, iApp->getnCmdShow( ) );
::UpdateWindow(hWnd);
-
#ifndef ICONTROLLER_H_
#define ICONTROLLER_H_
#include <windows.h>
namespace nApplication
class IController
public:
virtual int CheckStatus() = 0;
;
#endif ICONTROLLER_H_
-
#ifndef CONTROLLER_H_
#define CONTROLLER_H_
#include <windows.h>
#include "IController.h"
#include "IApplication.h"
namespace nApplication
class Controller : public IController
public:
Controller( IApplication *iApp );
virtual ~Controller();
virtual int CheckStatus();
private:
Controller( Controller &c );
Controller& operator= ( Controller &c );
IApplication *iApp;
;
#endif //CONTROLLER_H_
-
#include "Controller.h"
namespace nApplication
Controller::Controller( IApplication *iApp ) : iApp( iApp )
Controller::~Controller()
int Controller::CheckStatus()
return 0;
-
#include <windows.h>
#include "Application.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
nApplication::Application app( hInstance, nCmdShow );
return app.Run( );
-
main.exe : main.cpp
cl /EHsc main.cpp Application.cpp Controller.cpp MainWindow.cpp user32.lib gdi32.lib
del *.obj
#/link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup
【问题讨论】:
【参考方案1】:如果你正在创建一个库,你没有WinMain
,你有一个用于动态库的DllMain
,或者没有用于静态库。
在您的情况下,您需要 export dll 中的所有类功能,然后在使用您的库的任何应用程序中,您需要包含项目的标头并链接到 .lib
库,然后在您需要 GUI 功能的应用程序中使用它:
nApplication::Application app( hInstance, nCmdShow );
return app.Run( );
当然,这会忽略所有细节,例如注册事件回调和设置这些行,但是 Qt 是免费和开源的,您可能想在重新发明***之前研究一下,或者帮助自己制作***圆一点。
【讨论】:
我在 Qt 表单上有两个线程来解决这个问题,那里的成员说 WinMain 通过链接到类似于 MFC 的 Qts DLL 被“包含”在其中。例如,请参阅此处的最后几篇帖子,developer.qt.nokia.com/forums/viewthread/8908/#51775。当我正在研究源代码时,我仍然有点困惑。这是我正在努力理解的第一个开源项目。这是我做我正在做的事情的主要动机。 @Matthew:Qt 的工作方式略有不同,因为它是为多平台 UI 开发人员构建的:它使用main
作为程序入口点(在您的代码中),但在寡妇上,它将创建自己的自己的伪'WinMain
'(虽然它实际上不需要,它只需要确保在没有请求时不创建控制台)
我现在有两个相互矛盾的解释。我知道nmake Makefile 中的#/link /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup 允许您在非控制台应用程序中将入口点指定为main()。但是,当您设置 WndClassEx 时,您需要一个 hInstance,如果您使用 main,则不提供该实例。没有其他方法可以创建一个窗口。此外,如果您查看 Qt 的源代码,您会发现 WinMain 实际上调用了您的 main 函数。所以 main 不是程序的入口点,它只是对非 Windows 程序员的一种方便。在被称为入口的linux中并非如此。
@Matthew: GetModuleHandle(NULL)
如果从您的主线程(也就是启动的应用程序)调用,会为您获取 hInstance,还有其他一些获取它的方法。如果从您的主线程调用实例线程(又名启动的应用程序),还有其他一些获取它的方法。以上是关于我自己的个人 MFC的主要内容,如果未能解决你的问题,请参考以下文章
VS2013生成Release版本MFC程序在其他机器上运行
我自己的 C++ 框架(类似 MFC),我可以创建子窗口,但在 WM_CREATE 时无法创建编辑框