C ++ / CLI:将MFC嵌入WinForm

编程入门 行业动态 更新时间:2024-10-14 08:24:25
本文介绍了C ++ / CLI:将MFC嵌入WinForm的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

您好,

几个星期以来,我们试图将MFC对话框转换为可以嵌入到WinForm用户控件中的 MFC表单 。

Since a few weeks, we are trying to "transform" a MFC dialog into a "MFC form" which can be embedded into a WinForm User Control.

我们成功做到了:

  • 我们制作了WinForm用户控件,称为 Dlg_WU_MFC_Container
  • 创建后,UC会创建名为 CDlgEdgeType
  • 然后,每次调整UC大小或移动UC时,我们也会移动并调整MFC表单的大小

下面是代码(试图删除很多不必要的东西..):

Here is the code (I tried to remove a lot of unnecessary stuff..):

Dlg_WU_MFC_Container.h:

Dlg_WU_MFC_Container.h:

#pragma once public ref class Dlg_WU_MFC_Container : public System::Windows::Forms::UserControl { private: CDlgEdgeType* _dialog; CWnd *_wnd; private: //---Local Controls System::ComponentModel::IContainer^ components; public: Dlg_WU_MFC_Container(); ~Dlg_WU_MFC_Container(); !Dlg_WU_MFC_Container(); template<class T, class HP> void InitializeContainer() { CDlgEdgeType = } private: void RefreshEmbeddedSize(); #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> void InitializeComponent(void) { this->SuspendLayout(); // // Dlg_WU_MFC_Container // this->AutoScaleDimensions = System::Drawing::SizeF(96, 96); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Dpi; this->ForeColor = System::Drawing::SystemColors::WindowText; this->Margin = System::Windows::Forms::Padding(0); this->Name = L"Dlg_WU_MFC_Container"; this->Size = System::Drawing::Size(816, 480); this->SizeChanged += gcnew System::EventHandler(this, &Dlg_WU_MFC_Container::evSizeChanged); this->VisibleChanged += gcnew System::EventHandler(this, &Dlg_WU_MFC_Container::evVisibleChanged); this->ResumeLayout(false); } #pragma endregion private: System::Void evSizeChanged(System::Object^ sender, System::EventArgs^ e); private: System::Void evVisibleChanged(System::Object^ sender, System::EventArgs^ e); };

Dlg_WU_MFC_Container.cpp:

Dlg_WU_MFC_Container.cpp:

#include "Dlg_WU_MFC_Container.h" #include "DlgEdgeType.h" Dlg_WU_MFC_Container::Dlg_WU_MFC_Container() { InitializeComponent(); _wnd = NULL; _dialog = new CDlgEdgeType(); } Dlg_WU_MFC_Container::~Dlg_WU_MFC_Container() { if (components) { delete components; } this->!Dlg_WU_MFC_Container(); } Dlg_WU_MFC_Container::!Dlg_WU_MFC_Container() { // We need to detach the handle to free it for other usage if (_wnd) { _wnd->Detach(); delete _wnd; _wnd = NULL; } if (_dialog) { delete _dialog; _dialog = NULL; } } System::Void Dlg_WU_MFC_Container::evSizeChanged(System::Object^ sender, System::EventArgs^ e) { RefreshEmbeddedSize(); } // Inform the embedded form to adapt to its new size void Dlg_WU_MFC_Container::RefreshEmbeddedSize() { if (_dialog && _isShown) { CRect containerWnd; containerWnd.left = this->Left; containerWnd.right = this->Right; containerWnd.top = this->Top; containerWnd.bottom = this->Bottom; _dialog->ReplaceEmbeddedForm(containerWnd); } } System::Void Dlg_WU_MFC_Container::evVisibleChanged(System::Object^ sender, System::EventArgs^ e) { // _isShown basically useless.. ! if (Visible != _isShown) { _isShown = Visible; if (_dialog) { if (Visible) { void *handle = Handle.ToPointer(); if (handle) { // We need to create a new CWnd which will contain // the handle of the current WinForm control where // the embedded MFC will be contained _wnd = new CWnd(); _wnd->Attach((HWND)handle); _dialog->Create(_wnd); RefreshEmbeddedSize(); } } else { // When the control is not shown anymore, we need to free // the handle so another control can use it (the handle // is stored in the MFC permanent map) _wnd->Detach(); _dialog->DestroyWindow(); delete _wnd; _wnd = NULL; } } } }

CDlgEdgeType .cpp:

CDlgEdgeType.cpp:

void CDlgEdgeType::ReplaceEmbeddedForm(CRect &rect) { if (!GetSafeHwnd()) { return; } SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); }

这些东西很棒: CDlgEdgeType 可以很好地显示在我们的应用程序中,并且在调整应用程序大小或移动应用程序时,一切正常。

This stuff is working "great" : CDlgEdgeType is well shown in our application and when the application is resized or moved, everything goes well.

这是我的问题: CDlgEdgeType 具有 Dlg_WU_MFC_Container 作为父级,太好了。但是后者不知道MFC表单是子级 ..因此焦点有点丢失,箭头键和Tab键根本不起作用。

Here is my issue: CDlgEdgeType has Dlg_WU_MFC_Container as parent, great. But the latter doesn't know that the MFC form is a "child".. so the focus is kind of lost and the Arrow keys and the Tab keys simply do not work.

您应该知道的是,已将 Dlg_WU_MFC_Container 添加到自定义 TabControl 的 TabPages 中。因此,如果用户尝试通过MFC窗体的控件进行导航,或者他尝试使用方向键通过TreeView进行导航,则TabControl似乎将接管焦点并更改选项卡。.这不方便D:

A thing you should know is that Dlg_WU_MFC_Container is added to TabPages of a custom TabControl. So, if the user tries to navigate through MFC form's controls or he tries to navigate through a TreeView with the Arrow keys, the TabControl seems to take over the focus and will change tab.. which is not convenient D:

我也不知道如何解决这个问题,我的同事们也不知道。

I have no idea how to solve that issue, neither my colleagues.

也许我们集成MFC的方式是错误的,但是没有真正的话题(我们看到更多将WinForm表单嵌入MFC)。另外,由于我们的软件历史悠久,因此我们不能简单地重新创建CDlgEdgeType。这是一个很大的对话框,实际上,我们有7个这样的对话框,代码实现了模板,但是为了清楚起见,我删除了它们。.

Maybe the way we integrate the MFC is wrong, but there are no really topics about that (we see more "Embedding WinForm forms into MFC"..). Also, as our software has a big history, we cannot simply recreate CDlgEdgeType. It's a big dialog and, in fact, we have 7 dialogs like that, the code implements template but I removed them for the clarity of this message..

谢谢!

Sbizz。

推荐答案

好吧,我们找到了出路。

Well, we find a way out.. this may not be the best way to do it, but it is working (or at least, it seems to work !).

起初,我已经设法做到这一点。将键发送到MFC表单:

At first, I've managed to send the keys to the MFC form:

bool Dlg_WU_MFC_Container::ProcessDialogKey(Keys keyData) { ::SendMessage(CWnd::GetFocus()->GetSafeHwnd(), WM_KEYDOWN, (WPARAM)keyData, (LPARAM)0); return true; }

由于TabControl正在通过WM_ACTIVATE进行控制,因此我们试图覆盖,同时将WM_ACTIVATE发送到MFC表单,因此结果如下:

Since the TabControl is taking the control through an WM_ACTIVATE, we tried to "override" it by sending also WM_ACTIVATE to the MFC form, so the result is the following:

bool Dlg_WU_MFC_Container::ProcessDialogKey(Keys keyData) { ::SendMessage(CWnd::GetFocus()->GetSafeHwnd(), WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), (LPARAM)0); ::SendMessage(CWnd::GetFocus()->GetSafeHwnd(), WM_KEYDOWN, (WPARAM)keyData, (LPARAM)0); return true; }

唯一的问题是 Tab键似乎不起作用但是经过调查,我们的用户并不需要它,所以...:D但是我认为它仅与WM_ACTIVATE(先前的控件)的第三个参数有关。必须使用它来知道在按下Tab后必须聚焦哪个控件。

The only thing is that the "Tab" key doesn't seems to work but after investigation, it is not needed by our users, so... :D But I think it's just related to the third parameter of WM_ACTIVATE (previous control). It must be used to know which control must be focused after Tab is pressed.

Sbizz

更多推荐

C ++ / CLI:将MFC嵌入WinForm

本文发布于:2023-11-05 18:39:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1561565.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:CLI   MFC   WinForm

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!