社区
ATL
帖子详情
为什么我写的Activex控件,切换窗口后画的图就没有了
小崔爱读书
2010-02-04 12:08:36
各位,我用ATL做了一个Activex控件,用于在web页面上接受用户的手写签批输入,我可以做出这个Activex控件,也可以在上面用鼠标模拟画图签字,但只要我一切换窗口,或者这个ActiveX控件被其他窗口遮盖住,所有的背景、我画的图就都没了,我不知道是不重绘还是什么意思。或者是我取的DC错了?我使用的getDC(m_hWnd)取的DC,应该也没问题吧。希望谁给点儿知道意见。谢谢。
...全文
280
25
打赏
收藏
为什么我写的Activex控件,切换窗口后画的图就没有了
各位,我用ATL做了一个Activex控件,用于在web页面上接受用户的手写签批输入,我可以做出这个Activex控件,也可以在上面用鼠标模拟画图签字,但只要我一切换窗口,或者这个ActiveX控件被其他窗口遮盖住,所有的背景、我画的图就都没了,我不知道是不重绘还是什么意思。或者是我取的DC错了?我使用的getDC(m_hWnd)取的DC,应该也没问题吧。希望谁给点儿知道意见。谢谢。
复制链接
扫一扫
分享
转发到动态
举报
AI
作业
写回复
配置赞助广告
用AI写文章
25 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
sjdev
2010-02-04
打赏
举报
回复
没有。
你说的方法,除非是窗口一直在最上,不然一重绘就没了。
小崔爱读书
2010-02-04
打赏
举报
回复
这个有点儿不合适吧?我知道你这样说的可以实现,但不应该这么处理的。Windows窗口岂会没有自己的一块儿内存来保持它上面绘制的东西啊?还需要我手动来处理这个吗?并且如果我做的是一个普通windows应用,在上面手动画图,绝对不需要我组织一个链表的。
有没有更符合windows原理的一些方法?我觉得应该是某些项或参数我没有设置对,或者我没有继承和实现某些接口,谁能给点儿指导?
sjdev
2010-02-04
打赏
举报
回复
你如果StartPoint和EndPoint不记录下来,那当然没法显示了。
sjdev
2010-02-04
打赏
举报
回复
你得定义一个point的链表,每次操作时,把相应点放到链表中。
OnDraw函数中,不考虑操作。
只考虑把这些点显示出来。
当然了,最好把数据做一下封装。
譬如线,可以封装它的点。
譬如圆,可以封装它的圆心和半径。
小崔爱读书
2010-02-04
打赏
举报
回复
我试了一下,不行的,假设我先得处理背景吧,我应该在OnDraw中FillRect吧?如果我只是写FillRect这是可以的,因为每次切换或有窗口遮盖其上的时候,就不停的调用OnDraw,自然背景就总是正确的,但如果我是相应鼠标事件来绘图在上面的话,那么我把开始的Point和最终的Point发送给OnDraw,然后LineTo一下画出线,随着我的鼠标移动StartPoint和EndPoint都是不断变化的,一旦切换窗口或遮盖其上的时候,鼠标画出的东西是根本不会显示出来的。
小崔爱读书
2010-02-04
打赏
举报
回复
哦,你的意思是要把数据传递给onDraw方法来绘图?
谢谢。我试试啊。
小崔爱读书
2010-02-04
打赏
举报
回复
之前也写过几个窗口上绘图的程序,不过没写过web activex控件,没想到这个这么腻歪,不知怎么回事儿。
sjdev
2010-02-04
打赏
举报
回复
[Quote=引用 3 楼 cuipy 的回复:]
我是在OnLButtonDown OnLButtonUp onMouseMove这三个时间组合,来实现鼠标画图的。
是移开以后挡住部分消失了,但我用Invalidate也不行的。不知道什么原因。我调用Invalidate了。
[/Quote]
你在这三个函数中更新所绘制的数据是可以的,但真正把数据绘制成图像,应该在Draw(OnDraw)??函数中。
数据更新后,掉Invalidate就ok了。
小崔爱读书
2010-02-04
打赏
举报
回复
我是在OnLButtonDown OnLButtonUp onMouseMove这三个时间组合,来实现鼠标画图的。
是移开以后挡住部分消失了,但我用Invalidate也不行的。不知道什么原因。我调用Invalidate了。
数世纪
2010-02-04
打赏
举报
回复
是挡住的地方移开后没有了?还是挡住部分全部消失?
如果是部分没有,是没有重绘,invalidate就行了,全部消失要再分析一下
sjdev
2010-02-04
打赏
举报
回复
是在Draw函数中画的吗?
小崔爱读书
2010-02-04
打赏
举报
回复
我最后解决了。我想大家说的都是有道理的,不过就100分,平分吧。
我没用链表,将DC存在内存中,然后OnDraw的时候读的内存中的DC,再覆盖一下现在的DC。
fandouC
2010-02-04
打赏
举报
回复
需要用链表保存点坐标的
jameshooo
2010-02-04
打赏
举报
回复
还有好几个概念你还没弄明白,所以解释有点困难。
1、ATL制作的控件可以是有窗口的,也可以是无窗口的,你的是哪一类?
2、不管有没有窗口,你只需重载OnDraw方法,并且用参数提供的HDC来绘制,ATL库内部屏蔽了有窗口和无窗口控件绘制之间的区别,有窗口控件的绘制来源是WM_PAINT消息,无窗口控件的绘制来源是容器对 OnDraw 的调用。
3、无窗口控件重绘必须调用容器的 Invalidate 方法,由容器再次调用控件的 OnDraw 方法执行重绘,不能使用任何窗口相关的API,也不能在 OnDraw 外部绘制。
4、有窗口控件就是一个标准的窗口,所以按照 WM_PAINT 方式绘制一个窗口,可以使用所有的窗口API。
5、所有窗口在大多数情况下都应该在 WM_PAINT 里面执行所有的绘制任务,但不是绝对的,有一些特殊的需求一般在 WM_PAINT 之外绘制,例如用鼠标选择一段文字时文字的背景和前景色变成高亮状态、编辑控件的光标闪烁等等,请记住一个原则,只要是不怕被消掉的就可以在外部绘制,文字高亮在窗口失去焦点时就可以失效,闪烁的光标通过定时器触发时再绘制,它们都不怕被消掉。问题是你的需求不符合这个原则,所以不应该放到外部绘制。还是 SJDEV 说的,你的每一次鼠标操作都应该产生一些数据保存起来,在 OnDraw 中绘制这些数据,这种做法不会导致被擦除。
6、还有一些概念,我都不知道该如何解释起。至于 CS_OWNDC 的作用,在你搞明白基本概念后,再去看看MSDN的解释就能理解了。
小崔爱读书
2010-02-04
打赏
举报
回复
我是用vs.2008开发的,是不是在开始创建组件的时候需要选择什么特别的选项啊?
小崔爱读书
2010-02-04
打赏
举报
回复
是不是因为ATL创建的是一个控件,而不是继承自CWindowImpl的窗口?没有自己重绘DC的功能啊?
小崔爱读书
2010-02-04
打赏
举报
回复
CS_OWNDC 这个是什么啊?我是一个ATL创建的控件,继承的都是一堆接口,另外。。我可以在其他地方绘图,就是绘图完毕后,这个控件一被覆盖后就不自绘之前我画到上面的东西了。连背景都没了。
jameshooo
2010-02-04
打赏
举报
回复
看起来你的控件是有窗口句柄的,这个窗口类是什么?如果是自定义类的话,在RegisterClass时把WNDCLASS::style的值里面加上 CS_OWNDC 标记,你就可以在OnDraw或WM_PAINT之外绘图了。
小崔爱读书
2010-02-04
打赏
举报
回复
必须嘛?我什么也没操作也要调用吗?
wwgddx
2010-02-04
打赏
举报
回复
[Quote=引用 16 楼 cuipy 的回复:]
还有,我的控件不能处理WM_PAINT消息,我一旦创建了这个消息的处理方法,即便我什么代码也不写,cpu也持续100%,弄得我都几乎无法关闭ie窗口。
[/Quote]
WM_PAINT消息必须调用BeginPain();和EndPaint();这两个函数.
加载更多回复(5)
精彩编程与编程技巧-利用vb6开发
ActiveX
控件
...
精彩编程与编程技巧-利用vb6开发
ActiveX
控件
...
VB6.0动态加载
ActiveX
控件
漫谈
VB6.0动态加载
ActiveX
控件
漫谈 深圳 罗汉军 罗德昌 熟悉VB的朋友对使用
ActiveX
控件
一定不会陌生,众多
控件
极大地方便了编程, 但唯一的缺陷是不能动态加载
控件
,必须在设计时通过引用,将
控件
放置在窗体上。 VB6.0已能够解决该问题,只是帮助中
没有
明确说明,并且
没有
描述到一些关键功 能,由于以前的版本中可以动态创建进程外服务:如果对象是外部可创建的,可在 Set 语句中用 New 关键字、CreateObject 或 GetObject 从部件外面将对象引用赋予变 量。 如果对象是从属对象,则需使用高层对象的方法,在 Set 语句中指定一个对象引 用: Dim xlApp1 As Excel.Application Set xlApp1 = New Excel.Application 或 Dim xlApp As Object '定义存放引用对象的变量。 Set xlApp = CreateObject("excel.application") xlApp.Visible = True ---- 这些语法很容易造成误导,以为动态加载
ActiveX
控件
也是此方法,可能有朋 友也象我一样利用CreateObject尝试了无数次,却无功而返,不知微软公司是出于何种 考虑,动态加载
ActiveX
控件
是扩展
控件
集合的方式实现,通过实际摸索,终于就如 何实现动态
ActiveX
控件
找出了一条切实可行的方法,下面以一个具体的实例来详细说 明。 一、
ActiveX
控件
----
ActiveX
控件
是 Visual Basic 工具箱的扩充部分。使用
ActiveX
控件
的方 法与使用其它标准内装的
控件
,如 CheckBox
控件
,完全一样。在程序中加入
ActiveX
控件
后,它将成为开发和运行环境的一部分,并为应用程序提供新的功能。 ----
ActiveX
部件通过客户端/服务器关系与应用程序— 及与部件相互之间— 交 互作用。客户端是使用部件功能的应用程序代码或部件。服务器是部件及其关联的对象。 例如,假设应用程序使用
ActiveX
控件
来提供一个标准的雇员窗体,供公司的多种 应用程序使用。提供雇员窗体的
ActiveX
控件
就是服务器,使用这个
控件
的应用程序 就是服务器的客户端。 二、加载方法 ---- VB6.0中对Controls 集合进行了扩展,以前版本中Controls 集合在窗体上列 举出已加载的
控件
,这在迭代过程中是很有用的。Controls 集合标识一个叫做 Controls的内在窗体级变量。如果忽略可选的 object 所在处的整数,则关键字 Controls 必须包括在内。我们通常在
窗口
中使用如下代码: Text1.Text="Hello, world" 其实也可以使用如下代码达到同一目的: Controls(1).Text="Hello, world" ---- 在VB6.0中除了原来的Clear、Remove 方法外(很奇怪,为什么微软在VB5.0中 只提供这两种方法,而
没有
提供Add方法,因为
没有
Add,这两种方法也就没什么用处), 增加了Add方法,该方法就是用于动态加载
控件
的: Controls.Add(progid as String, Name as String); progid:
ActiveX
部件的ProgID,如:"VB.CheckBox"; Name:
ActiveX
部件加载后的名称,如: "MyCheckBox"; 若要在窗体上添加一个名为MyButton的按钮,可以使用: dim oControl as Object '窗体级变量 注意:这里声明为Object对象类型 Private Sub LoadControl() Set oControl = Controls.Add ("VB.CommandButton", "MyButton") oControl.Left = 10 oControl.Top = 10 oControl.Visible = True '使
控件
可见 End Sub ---- 这是VB6.0的标准语法,它在例程中也是如此演示的,不过该方法虽然现实了
控件
的动态加载,按钮显示在窗体上,可以象普通按钮一样按下去,但加载的
控件
不能 预先设计响应事件代码,如:事件Sub MyButton_Click()将是非法的,当然,可以将要 响应的事件封装在
控件
内部。就编程的观点来看该方法没什么大的用处,开发
ActiveX
控件
的目的是为了资源共享,为了被其他开发人员利用,所以要提供必要的事件接口, 显然利用该方法不行,通过分析VBControls等相关对象,找出VBControlExtender对象 与EventInfo相结合能提供事件陷井捕捉,VBControlExtender对象对动态添加
控件
特 别有用,它提供了一套通用的属性、方法、事件给开发人员,它的一个突出特点是能编 程设计
控件
的事件,熟习类编程的朋友对带事件的对象声明一定不会陌生: ---- Dim WithEvents objElemt as CElemtVBControlExtender也不例外,声明的 语法一样,只不过它有个特殊的事件ObjectEvent(Info As EventInfo),它能捕捉到对 象使用RaiseEvent产生的所有事件,EventInfo数据结构映射了事件的名称、参数个数 和参数的值。VBControlExtender和 EventInfo相结合,采用Select Case 就可以预先 将不同类对象的事件放置一起,各自独立运作。将上面的代码改
写
一下就能提供Click 事件了: ---- Dim WithEvents oControl As VBControlExtender '带事件声明声明之后您 就可以在代码
窗口
的左上角的对象下拉框中发现该对象出现了,也就是说,该对象有了 事件或方法了,它的事件有DragDrop,DragOver ,LostFocus ,GotFocus , ObjectEvent和Validate,其中ObjectEvent是通用的事件捕捉。 Private Sub LoadControl() Set oControl = Controls.Add ("VB. CommandButton", "MyButton") oControl.Visible = True End Sub Private Sub oControl_ObjectEvent(Info As EventInfo) Select Case Info.Name Case "Click" 'Click事件 '您可以添加处理Click事件代码 MsgBox "您按了MyButton!" Case Else ' 其他事件 ' Handle unknown events here. End Select End Sub ---- 当然对微软提供的标准
控件
能采用该方法添加,大家都不会怀疑,但自己开 发的
控件
也能吗?答案是肯定的,我们可以用一个实际的例子进行说明。 三、实例描述 ---- 假设一个本地网络的监控系统,需要在原理
图
与实物示意
图
间
切换
,原理
图
包括组网结构、传输资源、监控主机等,而实物示意
图
包括路由器、设备、采集器等, 当然两种
图
的事件要一致,如双击某个设备
图
形将显示给设备的实时数据等,为了简化 维护,将原理
图
与实物示意
图
封装成
ActiveX
控件
,由于每种
图
需要加载许多
图
形控 件,消耗资源较大,不能同时加载,需要将其分解为两个
控件
,在
切换
时首先卸载一个
控件
,然后加载另一个
控件
,所以要实现动态加载
ActiveX
控件
。 ---- 原理
图
控件
为--Theory.ocx ,对应工程为CTheory; ---- 实物
图
控件
为---Fact.ocx ,对应工程为CFact; ---- 注意:为了简化,在设计
控件
时不设置许可证关键字。 ---- 实物
图
控件
上的
图
形对象可以被拖动,拖动后的位置信息通过事件 ChangePosition来通知拥有该
控件
的窗体,以便下次加载能显示在最后位置,实物
图
和原理
图
控件
都有双击事件完成的工作相同,其他事件此处忽略。 ---- 四、具体示例 ---- 1、准备工作 ---- 对
控件
Theory.ocx 、Fact.ocx 进行注册(利用Regsvr32.exe注册); ---- 建立窗体frmTest.frm ,在窗体上放置按钮cmdLoadOcx—“原理
图
” ---- 2、声明窗体级变量与加载函数LoadControl Dim WithEvents oControl As VBControlExtender '地
图
仿真
控件
对象 Dim mblnTheory As Boolean '是否显示原理
图
Private Function LoadControl(intType As Integer) If Not oControl Is Nothing Then '首先判断对象是否存在,若存在则卸载 Controls.Remove("MapView") '卸载
控件
,此操作非常重要 End If If intType = 0 Then Set oControl = Controls.Add ("CTheory. Theory", "MapView") Else Set oControl = Controls.Add ("CFact.Fact", "MapView") End If oControl.Height = 3500 oControl.Width = 6500 oControl.Top = 100 oControl.Visible = True End Function Private Sub Form_Load() mblnTheory = True End Sub ---- 3、为按钮cmdLoadOcx编
写
代码 Private Sub cmdLoadOCX_Click() If mblnTheory Then Call LoadControl(0) mblnTheory = False cmdLoadOCX.Caption = "实物
图
" Else Call LoadControl(1) mblnTheory = True cmdLoadOCX.Caption = "原理
图
" End If End Sub ---- 4、为事件ChangePosition编
写
代码 Private Sub oControl_ObjectEvent (Info As EventInfo) Select Case Info.Name Case "ChangePosition" MsgBox CStr(Info.EventParamters.Item( 1).Value) + ":" + _ CStr(Info.EventParamters.Item(2).Value) Case "DbClick" '双击处理代码 Case Else ' End Select End Sub ---- 注意: EventInfo的参数EventParamters集合中是以1开始的,一般来说,微 软新的集合一般是以1开始的,而旧的是以0开始的,如RdoErrors.Item(0)。 ---- 5、关闭
窗口
前卸载
控件
Private Sub Form_Unload(Cancel As Integer) Controls.Remove("MapView") Set oControl = Nothing End Sub ---- 6、特别注意 ---- 通过Controls.Add方法添加的
ActiveX
控件
一定不能在该工程中有该
控件
的任 何引用,否则系统将出错。 四、小结 ---- 通过使用动态加载
ActiveX
控件
使用庞大的应用程序变得很小,将不同的
ActiveX
控件
进行各种组合,使应用程序更加灵活多变,如您的应用系统要处理三十种门禁, 而某个具体的用户可能只有一种或两种门禁,根本没必要首先将所有门禁包含到应用 中,可将各个门禁独立封装,只安装注册需要的组件,就象Windows的自定义安装一样。 微软的未来技术基础是分布式的组件技术(DCOM),将会把代码的重用发挥得淋漓尽致。 您不妨试一试动态加载,也许会产生令您惊喜的效果! ---- 本代码在Win98、VB6.0(英文版)上编译、运行。
曲线显示
ActiveX
控件
在软件实现工业控制或者其他领域,根据实时数据或者历史数据生成各种历史、实时曲线已经变得非常的重要.
防舞弊
ActiveX
控件
防舞弊
ActiveX
控件
源码下载:考试期间,在浏览器全屏基础上,通过下载安装
ActiveX
控件
,锁定键盘上的功能键,不能
切换
到其它界面,保持在考试界面上,实现防舞弊功能。
VC中如何调试和使用
ActiveX
控件
由于
控件
并不能单独运行,所以你必须利用另一个程序来装载
控件
并进行调试,VC中提供了
ActiveX
容器供使用,在工程/设置菜单(project/setting)中选择Debug页第一栏Executable for debug session,右侧箭头并选择
ActiveX
Container。
ATL
3,248
社区成员
48,529
社区内容
发帖
与我相关
我的任务
ATL
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
复制链接
扫一扫
分享
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章