Re: recreate a window
On 10 Nov., 18:59, Joseph M. Newcomer <newco...@flounder.com> wrote:
On Mon, 10 Nov 2008 08:09:56 -0800 (PST), ".rhavin grobert" <cl...@yahoo.=
a CComboBox and CQControl derived control shall recreate itself, if
the styles given in resource not match the style required for toe
control (here: CBS_OWNERDRAWFIXED must be set). As CComboBox is unable
to correctly modify this style with ModifyStyle(), the recreation is
called and works.
The error is that you did not do this at design time. Essentially, I t=
reat the failure to
have the wrong styles as an error. Not sure why you are bothering to w=
ork around a bug
that shouldn't exist. If this happens, you ASSERT and then fix the dia=
log at design time,
and omit ALL the code below.
CComboBox is not *supposed* to be able to modify this style after the con=
trol is created,
so it is not "unable to correctly modify this style" because it was never=
this is even possible.
thats why i recreate it.
// recreate the underlying hwnd to match required styles
bool CQControl::QRecreateWindow(DWORD dwStyle, DWORD dwStyleEx)
CWnd* pWnd = CWnd::FromHandlePermanent(m_hwnd);
This is unnecessary; 'this' is already the CWnd *. So there is no need=
for the above
no it is not. 'this' is a CQControl that has no CWnd as baseclass! for
CQComboBox is a public CComboBox, public CQControl.
****> ASSERT(pWnd != NULL);
ASSERT(pWnd == CWnd::FromHandle(m_hwnd));
if (pWnd == NULL)
The above statements are meaningless. You already have 'this' or you w=
ouldn't be here. It
doesn't matter about what map it is in; you shouldn't care, either.
Note that I use this technique rather often to create a control in a spac=
occupied by a CStatic, so I'm changing the entire control type. This c=
ode is FAR too
complicated for such a simple task.
a static in Dialog-Editor would not look like a combobox.
HWND hParent = GetParent(m_hwnd); =
CWnd * parent = GetParent();
wrong. see above.
// get position and size of current window
GetWindowRect(m_hwnd, &rc); =
I'm surprised this even compiles. There is no need to use the raw HWND=
.. You could just
and get everything you need.
// following fn's need width and size, we recycle rc
rc.right = rc.Width(); =
rc.bottom = rc.Height(); =
This code is incorrect. You must not set the right and bottom in this =
you are working with the window rect, and the width and height are indepe=
ndent of the
coordinate system. Lose the two assignments above.
// translate into parents coordinates
ScreenToClient(hParent, &rc.TopLeft()); =
Why are you not doing something as simple as
this is all you need. You have a complex and convoluted solution to a =
Just translating the top/left coordinate makes no sense, because it will =
produce a window
that has the wrong size.
no. everything works pretty well. i you insist, one could of course
define a struct RECT_ that has let, top, width and height members, but
apart from that, my way is completely ok.
You have five overly complicated lines doing what two trivial lines will =
// let derived class modify rc
I have no idea what this does because there is no handler called OnCreati=
onRect and you
have not given the code for this, but there's nothing I know that needs t=
o be done to this
rectangle once you have it.
in this case, the derived class uses this virtual as following:
void CQComboBox::OnCreationRect(RECT& rc)
rc.bottom = rcDropped.bottom - rcDropped.top;
// create a new window at current windows coordinates
HWND hNew = CreateWindowEx(dwStyleEx, QGetClassName(), "", dwS=
rc.left, rc.top, rc.right, rc.bottom, hParent, 0=
Why are you using the raw CreateWindowEx call? You can do this trivial=
ly in MFC:
_T(""), dwStyle, rc,
Note how simple this is. For that matter, does CQControl have a Create=
method that would
I have no idea why you have chosen to change the control ID by setting it=
to 0; this kills
off all your handlers in the parent window. For a brief moment you wil=
l have two controls
with the same ID, but this will be changed momentarily, and causes no har=
oh, i thought it was hMenu.
But what you didn't do was make sure it is in the right place in the Z-or=
temp.SetWindowPos(this, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSI=
All this use of raw API and HWNDs is unneccessay.
// destroy old window and attach new one
m_hwnd = hNew;
Get rid of all the above lines.
The convoluted nature of what you are doing is probably what leads to the=
failure. I wouldn't even try to debug this code, I would rewrite it as=
and only then, if there is still a bug, would I worry about it.
however, when the dialog is closed, the line 991 (marked "/******/"
in Wincore.cpp asserts:
if (m_hWnd == NULL)
CHandleMap* pMap = afxMapHWND();
ASSERT(pMap != NULL);
CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
HWND hWndOrig = m_hWnd;
BOOL bResult = ::DestroyWindow(m_hWnd);
if (m_pCtrlSite == NULL)
bResult = ::DestroyWindow(m_hWnd);
bResult = m_pCtrlSite->DestroyControl();
// Note that 'this' may have been deleted at this point,
// (but only if pWnd != NULL)
if (pWnd != NULL)
// Should have been detached by OnNcDestroy
ASSERT(pMap->LookupPermanent(hWndOrig) == NU=
ASSERT(m_hWnd == hWndOrig);
// Detach after DestroyWindow called just in cas=
As i definitively Detached() the hwnd, i'd apprechiate any
Joseph M. Newcomer [MVP]