谁能给我一个win32窗口程序mfc调用dll大漠插件的例子(不是MFC的)

实现 Win32 程序的消息映射宏(类似 MFC ) - ~怪^_*兽~ - 博客园
评论 - 515
  对于消息映射宏,不用多说了,用过 MFC 的人都很清楚。但目前有不少程序由于各种原因并没有使用 MFC,所以本帖讨论一下如何在 Win32 程序中实现类似MFC的消息映射宏。其实 Windows 的头文件 &WindowsX.h&(注意:不是&Windows.h&) 中提供了一些有用的宏来帮助我们实现消息映射。本座是也基于这个头文件实现消息映射,首先看看宏定义文件:
#pragma once#include &windowsx.h&/************************************************************************//*
消息映射帮助宏
*//************************************************************************//* see: WindowsX.h */#define HANDLE_SYS_MSG(hwnd, message, fn)
HANDLE_MSG(hwnd, message, fn)/* LRESULT Cls_OnMessage(HWND hwnd, WPARAM wParam, LPARAM lParam) */#define HANDLE_USER_MSG(hwnd, message, fn)
case (message): return (LRESULT)(fn)((hwnd), (wParam), (lParam))#define FORWARD_USER_MSG(hwnd, message, wParam, lParam, fn)
(LRESULT)(fn)((hwnd), (message), (wParam), (lParam))#define GET_WND_PROC_INTERNAL(theClass, flag)
((WNDPROC)theClass##flag##WndProc)#define GET_DLG_PROC_INTERNAL(theClass, flag)
((DLGPROC)theClass##flag##DlgProc)#define DECLARE_MSG_MAP_INTERNAL(theClass, flag)
static LRESULT CALLBACK theClass##flag##WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);#define DECLARE_DLG_MSG_MAP_INTERNAL(theClass, flag)
static BOOL CALLBACK theClass##flag##DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);#define BEGIN_MSG_MAP_INTERNAL(theClass, flag)
LRESULT theClass##flag##WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
LRESULT result = 0;
switch(msg)
{#define BEGIN_DLG_MSG_MAP_INTERNAL(theClass, flag)
BOOL theClass##flag##DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
retVal = TRUE;
LRESULT result = 0;
switch(msg)
{// 窗口过程为类中的静态成员函数#define GET_WND_PROC(theClass)
GET_WND_PROC_INTERNAL(theClass, ::)#define GET_DLG_PROC(theClass)
GET_DLG_PROC_INTERNAL(theClass, ::)#define DECLARE_MSG_MAP(theClass)
DECLARE_MSG_MAP_INTERNAL(theClass, ::)#define DECLARE_DLG_MSG_MAP(theClass)
DECLARE_DLG_MSG_MAP_INTERNAL(theClass, ::)#define BEGIN_MSG_MAP(theClass)
BEGIN_MSG_MAP_INTERNAL(theClass, ::)#define BEGIN_DLG_MSG_MAP(theClass)
BEGIN_DLG_MSG_MAP_INTERNAL(theClass, ::)/* 消息处理函数的声明请参考: &WindowsX.h& 的 HANDLE_MSG */#define ADD_MSG_MAP(msg, fn)
case (msg): result = HANDLE_##msg((hWnd), (wParam), (lParam), (fn));
break;/* LRESULT Cls_OnMessage(HWND hwnd, WPARAM wParam, LPARAM lParam) */#define ADD_USER_MSG_MAP(msg, fn)
case (msg): result = (LRESULT)(fn)((hWnd), (wParam), (lParam));
break;#define END_MSG_MAP()
result = ::DefWindowProc(hWnd, msg, wParam, lParam);
}#define END_DLG_MSG_MAP()
retVal = FALSE;
if(retVal)
SetDlgMsgResult(hWnd, msg, result);
return retV
}// 窗口过程为全局函数#define GET_GLOBAL_WND_PROC(theClass)
GET_WND_PROC_INTERNAL(theClass,
_)#define DECLARE_GLOBAL_MSG_MAP(theClass)
DECLARE_MSG_MAP_INTERNAL(theClass,
_)#define BEGIN_GLOBAL_MSG_MAP(theClass)
BEGIN_MSG_MAP_INTERNAL(theClass,
_)#define END_GLOBAL_MSG_MAP()
END_MSG_MAP()#define GET_GLOBAL_DLG_PROC(theClass)
GET_DLG_PROC_INTERNAL(theClass,
_)#define DECLARE_GLOBAL_DLG_MSG_MAP(theClass)
DECLARE_DLG_MSG_MAP_INTERNAL(theClass,
_)#define BEGIN_GLOBAL_DLG_MSG_MAP(theClass)
BEGIN_DLG_MSG_MAP_INTERNAL(theClass,
_)#define END_GLOBAL_DLG_MSG_MAP()
END_DLG_MSG_MAP()// 绑定对象指针到窗口#define ATTACH_OBJ_PTR_TO_WINDOW(hwnd, objPtr)
::SetWindowLong(hwnd, GWL_USERDATA, (LONG_PTR)objPtr)#define GET_OBJ_PTR_FROM_WINDOW(hwnd, theClass)
(theClass*)(LONG_PTR)::GetWindowLong(hwnd, GWL_USERDATA)#define DEFINE_OBJ_PTR_FROM_WINDOW(hwnd, theClass, pObj)
theClass* pObj = (theClass*)(LONG_PTR)::GetWindowLong(hwnd, GWL_USERDATA);
ASSERT(pObj);
  先介绍一下几个重要的宏定义:
DECLARE_MSG_MAP(theClass):声明窗口过程函数,其中窗口过程函数实现为类的静态方法
DECLARE_GLOBAL_MSG_MAP(theClass):声明窗口过程函数,其中窗口过程函数实现为全局函数,因此&theClass&参数可以任意写,不一定是类名
DECLARE_DLG_MSG_MAP(theClass):声明对话框的窗口过程函数,其中窗口过程函数实现为类的静态方法
DECLARE_GLOBAL_DLG_MSG_MAP(theClass):声明对话框窗口过程函数,其中窗口过程函数实现为全局函数,因此&theClass&参数可以任意写,不一定是类名
BEGIN_MSG_MAP(theClass):定义窗口过程函数,其中窗口过程函数实现为类的静态方法
BEGIN_GLOBAL_MSG_MAP(theClass):定义窗口过程函数,其中窗口过程函数实现为全局函数,因此&theClass&参数可以任意写,不一定是类名
BEGIN_DLG_MSG_MAP(theClass):定义对话框的窗口过程函数,其中窗口过程函数实现为类的静态方法
BEGIN_GLOBAL_DLG_MSG_MAP(theClass):定义对话框窗口过程函数,其中窗口过程函数实现为全局函数,因此&theClass&参数可以任意写,不一定是类名
ADD_MSG_MAP(msg, fn):添加 Windows 内部消息映射
ADD_USER_MSG_MAP(msg, fn):添加用户自定义消息映射
END_MSG_MAP():结束消息映射,对应 BEGIN_MSG_MAP
END_GLOBAL_MSG_MAP():结束消息映射,对应 BEGIN_GLOBAL_MSG_MAP
END_DLG_MSG_MAP():结束消息映射,对应 BEGIN_DLG_MSG_MAP
END_GLOBAL_DLG_MSG_MAP():结束消息映射,对应 BEGIN_GLOBAL_DLG_MSG_MAP
GET_WND_PROC(theClass):获取窗口过程函数的地址,对应 DECLARE_MSG_MAP
GET_GLOBAL_WND_PROC(theClass):获取窗口过程函数的地址,对应 DECLARE_GLOBAL_MSG_MAP
GET_DLG_PROC(theClass):获取对话框窗口过程函数的地址,对应 DECLARE_DLG_MSG_MAP
GET_GLOBAL_DLG_PROC(theClass):获取对话框窗口过程函数的地址,对应 DECLARE_GLOBAL_DLG_MSG_MAP
ATTACH_OBJ_PTR_TO_WINDOW(hwnd, objPtr):把对象指针与窗口句柄进行绑定
GET_OBJ_PTR_FROM_WINDOW(hwnd, theClass):从窗口句柄中获取对象指针
DEFINE_OBJ_PTR_FROM_WINDOW(hwnd, theClass, pObj):从窗口句柄中获取对象指针,并赋值给局部变量 pObj
&  这里说明一下:对话框的消息映射与普通窗口的消息映射使用不同的宏进行定义;另外,窗口过程可以实现为类的静态方法或全局函数。例如,如果要定义一个对话框的窗口过程,并实现为全局函数则使用 DECLARE_GLOBAL_DLG_MSG_MAP、BEGIN_GLOBAL_DLG_MSG_MAP、END_GLOBAL_DLG_MSG_MAP 和 GET_GLOBAL_DLG_PROC 系列宏。
  下面以一个普通窗口的消息映射为例子演示如何使用这些宏:
/*** MyClass.h ***/
class MyClass{
  // 其它方法
  virtual void OnDraw(const paint_dc& dc);
  virtual BOOL Destroy();
  // 系统消息
static BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
static void OnDestroy(HWND hwnd);
static void OnPaint(HWND hWnd);
static void OnClose(HWND hwnd);
static void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
static void OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags);
static void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags);
static void OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized);
  // 用户自定义消息
static LRESULT OnLockScreen(HWND hwnd, WPARAM wParam, LPARAM lParam);
  static LRESULT OnMenuBtnDown(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT OnSensorUp(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT OnSensorDown(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT OnSensorLeft(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT OnSensorRight(HWND hwnd, WPARAM wParam, LPARAM lParam);
  // 声明窗口过程  DECLARE_MSG_MAP(MyClass)};
/*** MyClass.cpp ***/#include "MyClass.h"
// 定义消息映射BEGIN_MSG_MAP(MyClass)
ADD_MSG_MAP(WM_CREATE,
ADD_MSG_MAP(WM_CLOSE,
ADD_MSG_MAP(WM_DESTROY,
OnDestroy)
ADD_MSG_MAP(WM_PAINT,
ADD_MSG_MAP(WM_LBUTTONDOWN,
OnLButtonDown)
ADD_MSG_MAP(WM_LBUTTONUP,
OnLButtonUp)
ADD_MSG_MAP(WM_MOUSEMOVE,
OnMouseMove)
ADD_MSG_MAP(WM_ACTIVATE,
OnActivate)
ADD_USER_MSG_MAP(MSG_MENU_BTN_DOWN,
OnMenuBtnDown)
ADD_USER_MSG_MAP(MSG_SENSOR_UP,
OnSensorUp)
ADD_USER_MSG_MAP(MSG_SENSOR_DOWN,
OnSensorDown)
ADD_USER_MSG_MAP(MSG_SENSOR_LEFT,
OnSensorLeft)
ADD_USER_MSG_MAP(MSG_SENSOR_RIGHT,
OnSensorRight)
ADD_USER_MSG_MAP(SHELL_MSG_LOCK_SCREEN,
OnLockScreen)END_MSG_MAP()
// 实现消息处理函数BOOL MyClass::OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct){
  // 把 lpCreateStruct-&lpCreateParams 绑定到 hwnd。
  // 通常 lpCreateStruct-&lpCreateParams 设置 MyClass 对象的 this 指针,在 ::CreateWindowEx() 函数中指定。
ATTACH_OBJ_PTR_TO_WINDOW(hwnd, lpCreateStruct-&lpCreateParams);
return TRUE;}void MyClass::OnClose(HWND hwnd){
  // 获取 hwnd 绑定的对象指针,并赋值给局部变量 pvShell
DEFINE_OBJ_PTR_FROM_WINDOW(hwnd, MyClass, pvShell);
pvShell-&Destroy();}void MyClass::OnDestroy(HWND hwnd){
::PostQuitMessage(0);}void MyClass::OnPaint(HWND hwnd){
  // 获取 hwnd 绑定的对象指针,并赋值给局部变量 pvShell
DEFINE_OBJ_PTR_FROM_WINDOW(hwnd, MyClass, pvShell);
paint_dc dc(hwnd);
pvShell-&OnDraw(dc);}void MyClass::OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags){
// ...}void MyClass::OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags){
// ...}// 其它消息处理方法// 。。。。。。
  重要说明:不知大家是否注意到,我们的消息处理函数与 MFC 的消息处理函数是有区别的。区别就在于我们的消息处理函数是 static 类型的,而 MFC 的消息处理函数则不是。因此,MFC 的消息处理函数很容易获得 this 指针,而我们的函数就没那么直接了,因此需要使用了比较迂回的方法获取 this 指针,具体方法是:
在 ::CreateWindowEx(... , lpParam) 方法中,把 MyClass 的 this 指针作为参数传入。
&处理 WM_CREATE 消息时调用 ATTACH_OBJ_PTR_TO_WINDOW(hwnd, lpCreateStruct-&lpCreateParams),把 this 指针绑定到 hwnd。
在其他消息处理方法中用 GET_OBJ_PTR_FROM_WINDOW 或 DEFINE_OBJ_PTR_FROM_WINDOW 获取 this 指针。[转载]win32和MFC下如何使用控制台窗口(转自csdn)
学习了,谢谢博主!
在win32和MFC程序中,有时需要输出一些调试信息,本文介绍在win32和MFC程序中使用控制台输出信息的方法。我们可以在应用程序里使用AllocConsole()函数自己开一个控制台(就像DOS窗口一样),然后重定向输入输出,就可以用printf函数向控制台输出信息了,具体方法如下:
在CWinApp的重载函数InitInstance()中输入如下语句,开辟一个控制台并重定向输出
AllocConsole();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
开辟控制台
SetConsoleTitle(_T("Debug
Output"));&&&&&
// 设置控制台窗口标题
freopen("CONOUT$","w",stdout);&&&&&&&&&&&
&// 重定向输出
注意在VS2008下重定向可能需要如下这么写,没有试验过,大家可以试一下。
&freopen_s(&pf,"CONOUT$","w",stdout);
记着,一定要在CWinApp的重载函数ExitInstance()中调用如下语句释放控制台。
FreeConsole();
下面是基于一个简单的对话框程序(工程名:TestConsole)的测试例子,在CTestConsoleApp类中重载InitInstance()并在该函数中输入:
AllocConsole();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
开辟控制台
SetConsoleTitle(_T("Debug
Output"));&&&&&
// 设置控制台窗口标题
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
freopen_s(&pf,"CONOUT$","w",stdout);&&
// 重定向输出
然后在CTestConsoleApp类中重载ExitInstance()并在该函数中输入:
FreeConsole();
&&通过资源编辑器为对话框添加一个测试按钮,并在按钮响应函数CTestConsoleDlg::OnBnClickedTest()函数中输入:
printf("%sn", "TestConsole!");
& 程序启动后会看到一个对话框和一个控制台窗口,如下所示:
点击"Test"按钮后将在控制台中输出"TestConsole!",如下所示
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。首先来一张类结构层次图
然后我们进入讨论的正题吧!
&CWinApp* pApp = AfxGetApp(),GfxGetApp是取得当前CMyApp的对象的一个函数 这样我们用当前的App对象(派生类)附值给CWinApp指针(父类)。这样下面pApp.InitInstance()
调用的就是派生类的因为它是虚函数,如果派生类没有重写那就调用基类一层一层往上找
标号为3,4处:
&&&&&&&&&&& 首先InitApplication和InitInstance都是虚函数所以如果子类APP也就是自己的程序对这两个函数重载那么实际上运行的是自己的App类定义重写后的函数,一般情况下我们不重载InitApplication这个函数,但是InitInstance是一个空的虚函数,所以我们的程序一定要重载它!所以这里我们的pApp-&InitInstance()是调用的CMyWinApp-&InitInstance()这个函数。
InitInstance()这个函数是初始化窗口的,在本例子里更是在App类里面调用初始化的是一个主窗口,在win32程序中它是用CreateWindow(...)创建窗口中,但在mfc中我们用不着这么做,只要初始化相关窗口类(基类为CWnd)的实例就会调用相关类型的Create()的,图中初始化的是CMyFrameWnd这个类的对象的,当然我们可以用别的窗口类比如说对话框类。&&&
&&&&& 在win32程序中我们把"注册窗口类"的相关操作放在InitApplication这个函数里面,但是MFC中不是这样的,让我们看看这个函数吧:
你看这个函数并没有注册窗口类,那么我们程序运行完这个函数就运行到&InitInstance中开始初始化相关的类型的窗口了,按道理说createwindow()前一定要先注册窗口类的啊?没有窗口类名称怎么创建窗口呢?还有窗口过程也没指名啊?这就到了问题的关键点了:
程序进入到了InitInstance()中--〉CMyFrameWnd对象的构造函数--〉这个窗口的Create()函数---〉然后不知道是怎么指定的就到了CMYFrameWnd::CreateEx()--&因为这个类没有重写这个函数就到了CWnd::CreateEx() ,其实就是这个构造函数构造我们现在要创建的这个窗口的!让我们看看真身:
我们看到这里给窗口类的结构体cs先附了一些东西但缺少窗口类名和窗口过程的指向这两个东西,然后由于这个函数在子类CFrameWnd中被重写所以进入CFrameWnd::PreCreateWindow(cs)中,玄机就在这个函数了,这个函数将给cs没有附的窗口类名和窗口过程的指向附值。这个过程比较繁琐。我这里就描述一下吧,深入浅出中很详细的。
在这个函数中判断cs这个窗口类是不是进行注册过的,如果进行注册过就什么都不做,如果没有注册就调用一个函数来对cs的窗口类型和窗口过程附值然后注册它,简写一个这个函数:
BOOL AFXAPI AfxEndDeferRegisterClass(short cs){cs.lpfnWndProc = DefWindowP//现在窗口过程用DefWindowProc,一会在AfxHookWindowCreate(this)中进行了改写cs.hInstance = AfxGetInstanceHandle();cs.hCursor = afxData.hcurA//这里根据判断不同类型的窗口注册了几种不同窗口类(比如工具条之类的好像和其它的窗口类不一样),我们这里先不管//,只写出WND这个类是怎么注册的cs.style = CS_DBLCIKS|CS_HREDRAW|CS_VREDRAW;cs.lpzClassName = _//_afxwndbResult = AfxRegisterClass(&cs);//要的就是这个AfxRegisterClass,这下子是真的注册成功了。}这下子我们要创建的这个窗口的窗口类型就注册成功了,现在可以用这个窗口类进行创建窗口了!但还要注意在CreateWindowEx之前还有AfxHOOKWindowCreate(this)这个函数之前还有一个叫做AfxHookWindowCreate(this)这个函数,这是一个钩子函数,作用是利用SetWindowLong设置窗口过程为AfxWndProc,然后AfxWndProc()--&AfxCallWndProc--&WindowProc .没错!当捕捉到该窗口类对象的消息后首先就跑到WindowProc里了!
AfxHOOKWindowCreate(this)运行完了!那么创建一个窗口的"前戏"就都ok了!下面就走到CreateWindowEx创建这个窗口了~!~
注意:本例子讲的是程序从进入主函数到它的第一个窗口----主窗口创建的详细流程,这个主窗口是一个CFrameWnd类的实例。我想说的是其它Wnd类的子类的初始化也应该是这样,比如说我们创建一个对话框CMyDialog,也是大概上面所述的那个流程,我们一初始化CMyDialog就会走到CDialog::CreateEx()这个函数然后PreCreateWindow中注册窗口类指定类名和窗口过程函数,然后CreateWindowEX..........反正这都封装好了!我们只要初始化就行了!
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:55451次
积分:1106
积分:1106
排名:第17414名
原创:52篇
转载:42篇
(1)(8)(17)(3)(6)(2)(7)(1)(1)(12)(23)(9)(2)(2)
最近想读......28293031123456789101112131415161718192021222324252627282930311234567
随笔 - 105
随笔分类(109)
随笔档案(105)
玩音频播放器的猫咪
Useful Webs
积分与排名
阅读排行榜
评论排行榜win32和MFC下如何使用控制台窗口(转自csdn)
在win32和MFC程序中,有时需要输出一些调试信息,本文介绍在win32和MFC程序中使用控制台输出信息的方法。我们可以在应用程序里使用AllocConsole()函数自己开一个控制台(就像DOS窗口一样),然后重定向输入输出,就可以用printf函数向控制台输出信息了,具体方法如下:
在CWinApp的重载函数InitInstance()中输入如下语句,开辟一个控制台并重定向输出
AllocConsole();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
开辟控制台
SetConsoleTitle(_T("Debug
Output"));&&&&&
// 设置控制台窗口标题
freopen("CONOUT$","w",stdout);&&&&&&&&&&&
&// 重定向输出
注意在VS2008下重定向可能需要如下这么写,没有试验过,大家可以试一下。
&freopen_s(&pf,"CONOUT$","w",stdout);
记着,一定要在CWinApp的重载函数ExitInstance()中调用如下语句释放控制台。
FreeConsole();
下面是基于一个简单的对话框程序(工程名:TestConsole)的测试例子,在CTestConsoleApp类中重载InitInstance()并在该函数中输入:
AllocConsole();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
开辟控制台
SetConsoleTitle(_T("Debug
Output"));&&&&&
// 设置控制台窗口标题
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
freopen_s(&pf,"CONOUT$","w",stdout);&&
// 重定向输出
然后在CTestConsoleApp类中重载ExitInstance()并在该函数中输入:
FreeConsole();
&&通过资源编辑器为对话框添加一个测试按钮,并在按钮响应函数CTestConsoleDlg::OnBnClickedTest()函数中输入:
printf("%s\n", "TestConsole!");
& 程序启动后会看到一个对话框和一个控制台窗口,如下所示:
点击"Test"按钮后将在控制台中输出"TestConsole!",如下所示
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 如何调用mfc dll 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信