-1

I embedded a wpf control to an mfc app using Hwndsource and c++cli technology. SiteToContent was setted to WidthAndHeight.
A wrong resize occures on different computers. When mfc control is created, wpf is oversized a lot.

c++cli.h

#pragma once

#if _MANAGED

ref class ControlManager
{
public:
  ControlManager() { }
  ~ControlManager() {}
  Sharp::Control^ Current;

  System::Windows::Interop::HwndSource^ HwndSource;
  void Init(LPCREATESTRUCT lp, HANDLE Hwdn);
  void SetSize(int w, int h);
};

#endif

class AFX_EXT_CLASS CXbimWnd final 
{
public:
  int OnCreate(LPCREATESTRUCT lpCreateStruct, HANDLE hwnd);
  void OnSize(UINT nId, int h, int w);
  
private:

#ifdef _MANAGED
  // current 3d view
  gcroot<ControlManager^ > m_ObjHandle;
#else
  intptr_t m_ObjHandle;
  intptr_t HwndSource;
#endif
};

c++cli.cpp

int CXbimWnd::OnCreate(LPCREATESTRUCT lp, HANDLE hwnd)
{
  m_ObjHandle = gcnew ControlManager(m_Log);
  m_ObjHandle->Init(lp, hwnd);

  return 0;
}

void ControlManager::Init(LPCREATESTRUCT lp, HANDLE hwnd)
{
  System::Windows::Interop::HwndSourceParameters sourceParams("XbimXplorer");
  sourceParams.PositionX = lp->x;
  sourceParams.PositionY = lp->y;
  sourceParams.Height = lp->cy;
  sourceParams.Width = lp->cx;
  sourceParams.ParentWindow = (System::IntPtr)hwnd; 
  sourceParams.WindowStyle = WS_VISIBLE | WS_CHILD | WS_MAXIMIZE;

  HwndSource = gcnew System::Windows::Interop::HwndSource(sourceParams);
  HwndSource->SizeToContent = System::Windows::SizeToContent::WidthAndHeight;

  Current = gcnew Sharp::Control();
  HwndSource->RootVisual = Current;
}


void CXbimWnd::OnSize(UINT /*nId*/, int h, int w)
{
  m_ObjHandle->SetSize(h, w);
}

void ControlManager::SetSize(int h, int w)
{
  Current->Height = h;
  Current->Width = w;
}

mfc.h

class CBIMXBimBar : public CBCGPDockingControlBar
{
public:
  CBIMXBimBar();

  void AdjustLayout();
  virtual ~CBIMXBimBar();

  // Generated message map functions
protected:
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnSize(UINT nType, int cx, int cy);
  DECLARE_MESSAGE_MAP()
  CXbimWnd xbim;
};

mfc.cpp

BEGIN_MESSAGE_MAP(CBIMXBimBar, CBCGPDockingControlBar)
  ON_WM_CREATE()
  ON_WM_SIZE()
END_MESSAGE_MAP()


int CBIMXBimBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CBCGPDockingControlBar::OnCreate(lpCreateStruct) == -1)
    return -1;

  CRect rectDummy;
  rectDummy.SetRectEmpty();
  auto result = xbim.OnCreate(lpCreateStruct, m_hWnd);

  if (result == 0)
    AdjustLayout();

  return result;
}

void CBIMXBimBar::OnSize(UINT nType, int cx, int cy)
{
  AdjustLayout();
}

void CBIMXBimBar::AdjustLayout()
{

  CRect rectClient;
  GetClientRect(rectClient);
  auto scale = globalUtils.GetDPIScale(); 
  xbim.OnSize(0, int(rectClient.Height()/scale), int(rectClient.Width()/scale));  //<<---

}

I rescaled x,y of client rect coordinates by DPI value. It works on my computer but dont on another one. The size of embedded control is twice oversized in mfc client rect view

1 Answer 1

0

So. My invertigation gave me some information. The hosted WPF control via HwndSource does not get OnDpiChange event. It is a bug or a feature. My MFC app does not allow catch WM_DPICHANGE event to throw one to WPF exactly. So I just set

var m = new HwndSource.CompositionTarget.TransformToDevice();
 WpfControl.LayoutTransform = new System.Windows.Media.ScaleTransform(1 / m.M11, 1 / m.M22);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.