在我的 DIalog 中使用 CEdit 的派生类
我正在使用 MFC 做一个应用程序。我刚刚创建了一个从 CEdit 派生的类,这样我就可以拦截 OnChar() 并进行数据验证。如何用我制作的派生控件替换应用程序中的编辑控件?
I'm doing an application using MFC. I just made a class that is derived from CEdit so I could intercept OnChar() and do data validation. How do I substitute the edit control in my application with the derived one I made?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要不要使用
GetDlgItem
!GetDlgItem()
返回一个CWnd
指针,仅此而已。这意味着您有一个切片的CMyCustomEdit
指针。当然,它适用于您的方法向底层HWND
发送消息的所有情况。但这只是纯粹的运气!您可以在此处了解有关该问题的更多信息。正确的解决方案是使用 DDX_Control 对编辑控件进行子类化。
Do NOT use
GetDlgItem
!!GetDlgItem()
returns aCWnd
-pointer and nothing else. This means you have a slicedCMyCustomEdit
pointer. Sure, it works in all cases where your method sends a message to the underlyingHWND
. But that's just pure luck! You can read more about the problem here.The right solution is to subclass your edit control using DDX_Control.
我找到了解决方案。我之所以如此困难,是因为我没有使用类向导来创建新类,使事情变得非常复杂。如果您仅使用类向导,则可以选择将控制变量添加到派生类,就像它们是常规类一样,只要基类是适合您的元素的类。但这不是必需的。您所要做的就是创建一个派生类类型的指针,并转换您试图获取的项,就像通常对非派生类所做的那样。
使用从 CEdit 派生的类访问编辑控件的示例
正如下面另一位成员提到的(谢谢),使用 GetDlgItem 不是一个好主意。实际上,在我的代码中,我最终对其进行了子类化,这样我就可以将我的新类与已经存在的编辑控件一起使用。如前所述,我不明白编辑控件不一定附加到 CEdit,因此上面的示例应该清楚地表明您的 IDC_EDIT 可以用作 CMyCustomEdit 以及 CWnd 等;只要您使用正确的类引用它,它就会自然地运行。
现在进行子分类。如果您确实想让编辑控件始终在基类之前调用派生类,则必须将其设为子类。不要将其视为面向对象的概念,这只是为了让消息(如 WN_CHAR)首先通过派生类,然后调用基类。
在编辑控件上子类化 CMyCustomEdit 的示例:
首先,您需要将新类的 .h 文件包含在对话框的 .cpp 和 .h 中。这些通常与您的项目同名。这里是 MyMainDialog。
在派生对话框类中包含新派生类类型的变量:
然后在派生对话框类 (MyMainDialog) 的 OnInitDialog() 中对编辑控件进行子类化。为了安全起见,请将此代码添加到函数中的常规代码之后和返回之前(像往常一样):
完成此操作后,当您在编辑控件中使用 ID IDC_EDIT1 执行任何操作时,消息将先通过 CMyCustomEdit,然后再转到 CEdit。当您需要覆盖来自基类的消息时,这通常是必要的。
希望它对有类似问题的人有所帮助。
I found the solution. The reason why I was having such a hard time is because I didn't use the Class Wizard to create the new class, making things very complicated. If you simply use the Class Wizard, you have the option to add control variables to your derived classes like if they were regular classes, as long as the base class is the right class for your element. This is not necessary though. All you have to do is create a pointer of the type of your derived class and cast the item you are trying to get, like you would normally do with a non-derived class.
Example of accessing an Edit Control using a class derived from CEdit
As mentioned below by another member (Thanks for that), using GetDlgItem is not a good idea. I actually, in my code, ended up Sub-Classing it so I could use my new class with my Edit Controls that already existed. As mentioned before, I did not understand that an Edit Control was not necessarily attached to CEdit, so the example above should give a clear idea that your IDC_EDIT can be used as CMyCustomEdit as well as a CWnd and so on; it will behave naturally as long as you reference it with the right classes.
Now for the Sub-Classing. If you actually want to make you Edit Control to always call your derived class before your base class, you will have to make it a Sub Class. Don't think of it as an Object Oriented concept, this is only so the messages (Like WN_CHAR) will go through your derived class first and then call the base class.
Example of Sub-Classing CMyCustomEdit on an Edit Control:
First you need to include the .h file of your new class in the .cpp and .h of your dialog box. Those are the ones that usually has the same name as your project. Here it will be MyMainDialog.
In the derived dialog class include a variable of the type of your new derived class:
Then in the OnInitDialog() of your derived dialog class (MyMainDialog) Sub-Class your edit control. For safety, add this after the regular code in the function and before the return (As usual):
After this is done, when you do anything in your Edit Control with the ID IDC_EDIT1, the messages will go trough CMyCustomEdit before going to CEdit. This usually is necessary when you need to overwrite messages from the base classes.
Hope it helps anyone with a similar question.