急!新手求助:在MFC中,如何使用struct?

shuishoumiaomiao 2009-06-16 12:17:02
我在Visual Studio.NET 2008 平台,想向MFC中的CView类添加一个自定义的数据结构 struct, 结果被告之:“无效类型名 struct”,何解?
...全文
538 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
北京之光 2009-06-17
  • 打赏
  • 举报
回复
MFC和ATL在翻译处理上是相似的。在每一个框架里,实现控件的类具有一个名为OnDraw的虚函数。你只需将你的翻译代码添加到OnDraw函数里。然而,在各框架里,OnDraw函数得工作有所不同。

MFC的OnDraw在两种上下文下调用。第一个上下文发生在控件响应一个WM_PAINT消息时。此时,传递给OnDraw函数的设备上下文代表了真实的设备上下文。如果控件正被要求render它自己作为对客户调用IViewObjectEx::Draw的响应,设备上下文或者是一个元设备上下文,或者是一个常规设备上下文。下面的代码说明了基于MFC的控件是怎样被render的:

void CMFCMsgTrafficCtrl::OnDraw(CDC* pdc, const CRectamp; rcBounds,

const CRectamp; rcInvalid)

{

// TODO: 用你自己的绘图代码代替下面的代码

pdc->FillRect(rcBounds,

CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

ShowGraph(*pdc, const_cast(rcBounds), nMessagesToShow);

}

COleControl::OnDraw的签名包括一个代表控件大小的矩形和一个代表控件非法区域的矩形。MFC调用控件的OnDraw函数来响应一个WM_PAINT消息。此时,OnDraw函数接受一个真实的设备上下文来绘图。MFC还调用控件的OnDraw函数来响应IViewObject::Draw中的一个调用。MFC的实现调用COleControl::OnDrawMetafile,它的缺省OnDrawMetafile调用COleControl::OnDraw。当然,这暗示了控件的实时翻译是与控件的元文件表示相同的,该元文件在设计时与包容器一块存储。你可以使得控件的实时的翻译与设计时的翻译不同,这通过重载COleControl::OnDrawMetafile来实现。通过调用你的控件的InvalidateControl方法,你可以强制进行一个重绘。ATL的翻译机制非常类似于MFC。CComControlBase::OnPaint建立一个ATL_DRAWINFO结构,包括创建一个绘图设备上下文。然后ATL调用控件的OnDrawAdvanced函数。OnDrawAdvanced生成元文件,接着调用你的控件的OnDraw方法,它使用ATL_DRAWINFO结构中的信息来知道怎样在屏幕上绘图。下面是ATL_DRAWINFO结构:

struct ATL_DRAWINFO

{

UINT cbSize;

DWORD dwDrawAspect;

LONG lindex;

DVTARGETDEVICE* ptd;

HDC hicTargetDev;

HDC hdcDraw;

LPCRECTL prcBounds; //在其中绘图的矩形

LPCRECTL prcWBounds; //WindowOrg and Ext if metafile

BOOL bOptimize;

BOOL bZoomed;

BOOL bRectInHimetric;

SIZEL ZoomNum; //ZoomX = ZoomNum.cx/ZoomNum.cy

SIZEL ZoomDen;

};

ATL为你填写此结构。当你正在屏幕上绘图时,你所感兴趣的最重要的域是hdcDraw 和 prcBounds。如果你对在一个元文件里绘图感兴趣,或者你需要注意缩放因子等等,那么其它域也是重要的。下面的代码显示了基于ATL的消息流控件是怎样处理绘图的:

HRESULT CATLMsgTrafficCtl::OnDraw(ATL_DRAWINFOamp; di)

{

RECTamp; rc = *(RECT*)di.prcBounds;

HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));

FillRect(di.hdcDraw, rc, hBrush);

DeleteObject(hBrush);

Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

ShowGraph(di.hdcDraw, rc, nMessagesToShow);

return S_OK;

}

注意当你使用ATL的时候,你必须处理设备和GDI句柄。在ATL中,你调用你的控件的FireViewChange函数来强制控件的一次重画。

开发一个流入接口

当开发一个基于MFC的ActiveX控件时,缺省的流入接口是一个分发接口。Visual C++ 和 MFC使得开发一个流入分发接口变得十分简单——只需使用ClassWizard来生成方法和属性。每次你使用ClassWizard添加一个新的属性或方法,它就插入一个入口到你的控件的分发映射中。MFC使用分发映射来满足客户的调用请求。

MFC的缺点是在你的控件中增加一个常规的COM接口是一个枯燥无味的过程。此过程包括使用MFC的COM宏来建立实现接口的嵌套的类。

当为你的基于ATL的COM控件开发主流入接口时,类视是添加属性和方法的最好的手段。一当你为控件生成了代码,ATL ObjectWizard即添加一个缺省的流入接口。这可以是一个双端接口,也可以是一个常规的自定义接口,取决于你先前设定的工程选项。

Visual Studio的类视向你显示了你的工程中包含的所有的类和接口,在类视中右击一个接口的定义时,即可添加一个属性或者方法。使用类视来定义接口非常方便,因为每次你添加一个方法或者属性的时候,类视都会更新IDL,类源代码以及头文件。

不象MFC,给控件添加一个常规COM接口是非常容易的。在ATL中,你只要简单的添加新的接口样板文件连接(goo)(一个GUID,关键字对象和关键字接口)。类视将会显示新的接口,你可以继续添加新的成员。

添加属性

一个ActiveX控件经常包含属性,它们是描述控件的状态的成员变量。给一个基于MFC的控件添加属性的最好的手段是利用ClassWizard。ClassWizard的自动为你添加成员变量,将它们映射到缺省的分发接口。ClassWizard给你提供了两种选择:你可以添加一个成员变量,包括一个变化通告函数,或者你可以添加一对Get/Set函数,手动的添加成员变量。除了给控件添加你自己的定制属性,ClassWizard使你象添加背景和标题一样的添加库存。ClassWizard甚至自动为你的类添加一个成员变量。

为一个基于ATL的控件添加属性有一点不同,你为控件中的每个属性添加单独的存取程序和变异因子函数(propget 和 propput函数)。然而,类视只是定义了接口函数。你还要手工添加数据成员到类中,然后简单的实现这些函数。

基于ATL的控件还支持stock属性,ATL ControlWizard预先要求你确定希望哪些stock属性包括在你的控件中。添加至少一个stock属性到控件中使得控件继承自ATL的CstockPropImpl类。CstockPropImpl是Idispatch的一个实现,优化来显示ActiveX控件的stock属性,为每个标准的stock属性包含了兼容Idispatch的get 和 put函数。

ControlWizard还给控件添加代表stock属性的数据成员,例如,如果你添加了背景颜色的stock属性,ControlWizard添加一个名为m_clrBackColor的数据成员到你的类中。CstockPropImple一次性的为所有标准的stock属性的get 和 put函数添加实现。所有这些函数期望在你的类中看到合适的成员变量(象对应背景颜色的m_clrBackColor)。

编译器将在stock属性没有包括的那些get和put函数上阻塞。实现过程希望在你的类中看到成员变量。为了消除编译器错误,CcomControlBase添加了一个联合结构,它包括了stock的get 和 put函数希望看到的所有成员的名字。然而,给控件添加数据成员重载了联合类型中的名字,CstopPropImpl类在它的get 和 put函数中使用控件的成员变量

如果你忘记了使用ControlWizard预先添加stock属性,你总可以手工添加相关代码——即,从CstockPropImpl继承,然后为你想要显示的属性添加成员变量。
  • 打赏
  • 举报
回复
你怎么写的?应该是你的写法不对
HelloDan 2009-06-16
  • 打赏
  • 举报
回复
struct与class是一样的啊。 只要在使用之前定义好就行了。
wssdr0905 2009-06-16
  • 打赏
  • 举报
回复
用嚮導,好像是不能添加struct的,最好還是在.h文件中自己寫。。
shuishoumiaomiao 2009-06-16
  • 打赏
  • 举报
回复
我刚才没有通过“添加成员函数向导”加入“struct Data{...}”,直接添加到 “View.h”中,程序通过了编译!但我还是很想知道在MFC中,struct 应如何通过 IDE 添加?
请指教,谢谢!
shuishoumiaomiao 2009-06-16
  • 打赏
  • 举报
回复
我是想在CView中添加一个自定义的数据,处理过程如下:
在CView按鼠标右键,选“添加函数”,然后在“添加成员函数向导”中,在“返回类型”填入“struct”,在“函数名”填入“Data”,接着就是填入一系列的“参数类型”和“参数名”,完成后,当按“确定”时,出现“无效类型名 struct”!
不知如何处理?因为原来的程序是在同一平台的 “VC++ 2008”运行的,但在MFC中,我不知道如何定义和应该定义在那个文件中?如我上面的操作步骤,struct Data{...} 就定义在 View.h 中,这样应该反应较快!
请各位指教,谢谢!
fengrx 2009-06-16
  • 打赏
  • 举报
回复
应该是语法问题。
youhao1999 2009-06-16
  • 打赏
  • 举报
回复
语法问题
  • 打赏
  • 举报
回复
还有这事?
ok1234567 2009-06-16
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 walker_mk 的回复:]
结构体定义
typedef struct TAG_IDENTIFIER_LABEL{
int group;
int nID;
} IDENTIFER_LABEL;

变量定义
IDENTIFER_LABEL label;
[/Quote]

通常采用数据类型的定义方式,方便管理使用
shuishoumiaomiao 2009-06-16
  • 打赏
  • 举报
回复
非常多谢上面各位的指教!我不大会给分(想给各位多些分,但分太小!不够分!),多有得罪,敬请原谅!再次多谢各位热心的大虾给予的帮助,谢谢!!!
walker_mk 2009-06-16
  • 打赏
  • 举报
回复
结构体定义
typedef struct TAG_IDENTIFIER_LABEL{
int group;
int nID;
} IDENTIFER_LABEL;

变量定义
IDENTIFER_LABEL label;
dengxuxing 2009-06-16
  • 打赏
  • 举报
回复
struct A{
int i;
int j;
};


struct A s;//定义一个结构体变量
w29468 2009-06-16
  • 打赏
  • 举报
回复
[Quote=引用楼主 shuishoumiaomiao 的帖子:]
我在Visual Studio.NET 2008 平台,想向MFC中的CView类添加一个自定义的数据结构 struct, 结果被告之:“无效类型名 struct”,何解?
[/Quote]

写错了,语法错误。
ZOthello 2009-06-16
  • 打赏
  • 举报
回复
从CView派生自己的类~~
shuirh 2009-06-16
  • 打赏
  • 举报
回复
一般不用结构体,都直接封装成类.
菜牛 2009-06-16
  • 打赏
  • 举报
回复
例如:
struct {
...
} a;
肯定是你语法错误。最好贴出代码。

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧