Prev: Changing the Backcolor of Tab Control in MFC ,Winxp
Next: Multiple closed networks and UDP. Please help me.
From: Luigino on 14 Oct 2009 05:00 Hello everyone!! I'm going to make a custom control which can be loaded on Toolbox to add in a MFC Application as a component. Before I tried creating a MFC ActiveX Control but it's an OCX and plus it uses COM. So I'm trying to create a regular DLL (which could have more than one control...) and I started with creating a new MFC DLL choosing Use MFC in a Shared DLL. Then I added a MFC Class where at the start I want to show a rectangle that redraws every time I resize the control on a resource window in a MFC application. I'd like to know how I can initialize the MFC DLL in the main .CPP file of the DLL in the way I can load the DLL in the Toolbox and have a custom control to apply in a MFC application? Or maybe I shall change the CWnd base in my class with, for example, CDialog? Thanks to everyone in advance for the suggests..... :-) Ciao Luigi Here's the code of custom control's class: // // CaChart.cpp : implementation file // #include "stdafx.h" #include "CACharts.h" #include "CaChart.h" // CCaChart IMPLEMENT_DYNAMIC(CCaChart, CWnd) CCaChart::CCaChart() : iGraphType(GRAPH_BARS) { RegisterWindowClass(); } CCaChart::~CCaChart() { } // Register the window class if it has not already been registered. BOOL CCaChart::RegisterWindowClass() { WNDCLASS wndcls; HINSTANCE hInst = AfxGetInstanceHandle(); if (!(::GetClassInfo(hInst, CACHART_CLASSNAME, &wndcls))) { // otherwise we need to register a new class wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wndcls.lpfnWndProc = ::DefWindowProc; wndcls.cbClsExtra = wndcls.cbWndExtra = 0; wndcls.hInstance = hInst; wndcls.hIcon = NULL; wndcls.hCursor = AfxGetApp()->LoadStandardCursor (IDC_ARROW); wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1); wndcls.lpszMenuName = NULL; wndcls.lpszClassName = CACHART_CLASSNAME; if (!AfxRegisterClass(&wndcls)) { AfxThrowResourceException(); return FALSE; } } return TRUE; } BEGIN_MESSAGE_MAP(CCaChart, CWnd) //{{AFX_MSG_MAP(CCaChart) ON_WM_PAINT() ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() // CCaChart message handlers void CCaChart::OnPaint() { CPaintDC dc(this); // device context for painting // Create memory DC CDC MemDC; if (!MemDC.CreateCompatibleDC(&dc)) return; CRect rect; GetClientRect(rect); MemDC.FillRect(rect, CBrush::FromHandle((HBRUSH)GetStockObject (BLACK_BRUSH))); MemDC.Ellipse(rect); } BOOL CCaChart::OnEraseBkgnd(CDC* pDC) { return CWnd::OnEraseBkgnd(pDC); } void CCaChart::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class // In our case this is not needed - yet - so just drop through to // the base class // Get Size of Display area CWnd::PreSubclassWindow(); } BOOL CCaChart::Create(CWnd* pParentWnd, const RECT& rect, UINT nID, DWORD dwStyle /*=WS_VISIBLE*/) { return CWnd::Create(CACHART_CLASSNAME, _T(""), dwStyle, rect, pParentWnd, nID); } void CCaChart::set_GraphType(GRAPH_TYPE graphtype) { iGraphType = graphtype; } GRAPH_TYPE CCaChart::get_GraphType() { return (GRAPH_TYPE)iGraphType; }
From: Joseph M. Newcomer on 14 Oct 2009 14:39 If you create a custom control in a DLL, you cannot make it something that goes into the ToolBox in VS. You can use it by creating a user-defined resource (a blank rectangle on the dialog template) and assigning it the class name of your control and setting the style bits manually. But if you want a control you can place in the toolbox, it has to be an OCX and use COM. Question: what's the Big Deal with an OCX control that uses COM? Given you've already done this work, stripping it back to be a pure DLL doesn't seem to be a productive thing to do. I usually create a CStatic and give it an ID, then at OnInitialUpdate/OnInitDialog I will create the control with the same ID in the same place and destroy the old control. For example, if I have a CStatic called IDC_MYCONTROL, then I will create a control variable for it, c_MyControlPlace, and add to my class definition CMyControl c_MyControl; In the OnInitialUpdate/OnInitDialog handler, I will do CRect r; c_MyControlPlace.GetWindowRect(&r); ScreenToClient(&r); c_MyControl.Create(r, c_MyControlPlace); c_MyControlPlace.DestroyWindow(); where I have defined BOOL CMyControl::Create(const CRect & r, CWnd wnd) { if(!CWnd::Create(..., &r, ... wnd.GetDlgCtrlId())) return FALSE; SetWindowPos(&wnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); return TRUE; } (I didn't take the time to look up all the parameters, so I've just used ... here and the rest is left as an Exercise For The Reader) Note that this is clumsier than using an ActiveX control. joe On Wed, 14 Oct 2009 02:00:07 -0700 (PDT), Luigino <npuleio(a)rocketmail.com> wrote: >Hello everyone!! > >I'm going to make a custom control which can be loaded on Toolbox to >add in a MFC Application as a component. Before I tried creating a MFC >ActiveX Control but it's an OCX and plus it uses COM. >So I'm trying to create a regular DLL (which could have more than one >control...) and I started with creating a new MFC DLL choosing Use MFC >in a Shared DLL. >Then I added a MFC Class where at the start I want to show a rectangle >that redraws every time I resize the control on a resource window in a >MFC application. > >I'd like to know how I can initialize the MFC DLL in the main .CPP >file of the DLL in the way I can load the DLL in the Toolbox and have >a custom control to apply in a MFC application? Or maybe I shall >change the CWnd base in my class with, for example, CDialog? > >Thanks to everyone in advance for the suggests..... :-) > >Ciao >Luigi > >Here's the code of custom control's class: > >// >// CaChart.cpp : implementation file >// > >#include "stdafx.h" >#include "CACharts.h" >#include "CaChart.h" > >// CCaChart > >IMPLEMENT_DYNAMIC(CCaChart, CWnd) > >CCaChart::CCaChart() >: iGraphType(GRAPH_BARS) >{ > RegisterWindowClass(); >} > >CCaChart::~CCaChart() >{ >} > >// Register the window class if it has not already been registered. >BOOL CCaChart::RegisterWindowClass() >{ > WNDCLASS wndcls; > HINSTANCE hInst = AfxGetInstanceHandle(); > > if (!(::GetClassInfo(hInst, CACHART_CLASSNAME, &wndcls))) > { > // otherwise we need to register a new class > wndcls.style = CS_DBLCLKS | CS_HREDRAW | >CS_VREDRAW; > wndcls.lpfnWndProc = ::DefWindowProc; > wndcls.cbClsExtra = wndcls.cbWndExtra = 0; > wndcls.hInstance = hInst; > wndcls.hIcon = NULL; > wndcls.hCursor = AfxGetApp()->LoadStandardCursor >(IDC_ARROW); > wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1); > wndcls.lpszMenuName = NULL; > wndcls.lpszClassName = CACHART_CLASSNAME; > > if (!AfxRegisterClass(&wndcls)) > { > AfxThrowResourceException(); > return FALSE; > } > } > > return TRUE; >} > >BEGIN_MESSAGE_MAP(CCaChart, CWnd) > //{{AFX_MSG_MAP(CCaChart) > ON_WM_PAINT() > ON_WM_ERASEBKGND() > //}}AFX_MSG_MAP >END_MESSAGE_MAP() > >// CCaChart message handlers >void CCaChart::OnPaint() >{ > CPaintDC dc(this); // device context for painting > > // Create memory DC > CDC MemDC; > if (!MemDC.CreateCompatibleDC(&dc)) > return; > > CRect rect; > GetClientRect(rect); > > MemDC.FillRect(rect, CBrush::FromHandle((HBRUSH)GetStockObject >(BLACK_BRUSH))); > MemDC.Ellipse(rect); >} > >BOOL CCaChart::OnEraseBkgnd(CDC* pDC) >{ > return CWnd::OnEraseBkgnd(pDC); >} > >void CCaChart::PreSubclassWindow() >{ > // TODO: Add your specialized code here and/or call the base >class > // In our case this is not needed - yet - so just drop through >to > // the base class > > // Get Size of Display area > > CWnd::PreSubclassWindow(); >} > >BOOL CCaChart::Create(CWnd* pParentWnd, const RECT& rect, UINT nID, >DWORD dwStyle /*=WS_VISIBLE*/) >{ > return CWnd::Create(CACHART_CLASSNAME, _T(""), dwStyle, rect, >pParentWnd, nID); >} > >void CCaChart::set_GraphType(GRAPH_TYPE graphtype) >{ > iGraphType = graphtype; >} > >GRAPH_TYPE CCaChart::get_GraphType() >{ > return (GRAPH_TYPE)iGraphType; >} > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Luigino on 16 Oct 2009 02:29 On 14 Ott, 20:39, Joseph M. Newcomer <newco...(a)flounder.com> wrote: OK now I finalized to create a Toolbox component, it has to be an OCX Activex COM... > I usually create a CStatic and give it an ID, then at OnInitialUpdate/OnInitDialog I will > create the control with the same ID in the same place and destroy the old control. > > For example, if I have a CStatic called IDC_MYCONTROL, then I will create a control > variable for it, c_MyControlPlace, and add to my class definition > > CMyControl c_MyControl; > > In the OnInitialUpdate/OnInitDialog handler, I will do > > CRect r; > c_MyControlPlace.GetWindowRect(&r); > ScreenToClient(&r); > > c_MyControl.Create(r, c_MyControlPlace); > > c_MyControlPlace.DestroyWindow(); > > where I have defined > > BOOL CMyControl::Create(const CRect & r, CWnd wnd) > { > if(!CWnd::Create(..., &r, ... wnd.GetDlgCtrlId())) > return FALSE; > SetWindowPos(&wnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); > return TRUE; > } > I tried your approach to test its behavior and I compiled the DLL then added the path + .lib in a test project's properties but when I call Create(...) function, which is declared as public static, I get an unresolved reference external error.... why?.... I say before this error I got same error also on constructor and destructor which I had to declare CMyControl c_MyControl; as CMyControl* c_MyControl; any suggest? Thanks Ciao Luigi
From: Luigino on 16 Oct 2009 03:59 I tried this too: CStatic* c_CStaticPlaced = (CStatic *)GetDlgItem(IDC_MYSTATIC); CRect r; c_CStaticPlaced->GetWindowRect(&r); ScreenToClient(&r); CCaChart* c_MyControl = new CCaChart(); CWnd* pWnd = c_CStaticPlaced->GetDlgItem(c_CStaticPlaced->GetDlgCtrlID ()); c_MyControl->Create(r, pWnd); c_CStaticPlaced->DestroyWindow(); but I get this error: 1>test_chartDlg.obj : error LNK2019: unresolved external symbol "public: __thiscall CCaChart::CCaChart(void)" (??0CCaChart@@QAE(a)XZ) referenced in function "protected: virtual int __thiscall Ctest_chartDlg::OnInitDialog(void)" (? OnInitDialog(a)Ctest_chartDlg@@MAEHXZ) but the constructor CaChart isn't declared as virtual in the header's class, plus it's public... Any suggest?... Thanks Ciao Luigi
From: Ismo Salonen on 16 Oct 2009 06:33 Luigino wrote: > I tried this too: > > CStatic* c_CStaticPlaced = (CStatic *)GetDlgItem(IDC_MYSTATIC); > CRect r; > c_CStaticPlaced->GetWindowRect(&r); > ScreenToClient(&r); > CCaChart* c_MyControl = new CCaChart(); > CWnd* pWnd = c_CStaticPlaced->GetDlgItem(c_CStaticPlaced->GetDlgCtrlID > ()); > c_MyControl->Create(r, pWnd); > c_CStaticPlaced->DestroyWindow(); > > but I get this error: > > 1>test_chartDlg.obj : error LNK2019: unresolved external symbol > "public: __thiscall CCaChart::CCaChart(void)" (??0CCaChart@@QAE(a)XZ) > referenced in function "protected: virtual int __thiscall > Ctest_chartDlg::OnInitDialog(void)" (? > OnInitDialog(a)Ctest_chartDlg@@MAEHXZ) > > but the constructor CaChart isn't declared as virtual in the header's > class, plus it's public... > > Any suggest?... > Thanks > Ciao > Luigi This is linker error message. The real reason for the error message is that the linker does not see the implementation. Either you do not have the implementation for the CCaChart:.CCaChart(void) constructor of you are not including relevant object file on command line. ismo ismo
|
Next
|
Last
Pages: 1 2 3 4 5 6 Prev: Changing the Backcolor of Tab Control in MFC ,Winxp Next: Multiple closed networks and UDP. Please help me. |