Re: recreate a window
On 10 Nov., 20:43, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Mon, 10 Nov 2008 10:26:29 -0800 (PST), ".rhavin grobert" <cl...@yahoo.=
de> wrote:
On 10 Nov., 18:59, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Mon, 10 Nov 2008 08:09:56 -0800 (PST), ".rhavin grobert" <cl...@yah=
oo.de> wrote:
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 unabl=
e
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 treat the failure to
have the wrong styles as an error. Not sure why you are bothering t=
o work around a bug
that shouldn't exist. If this happens, you ASSERT and then fix the =
dialog at design time,
and omit ALL the code below.
CComboBox is not *supposed* to be able to modify this style after the =
control is created,
so it is not "unable to correctly modify this style" because it was ne=
ver defined that
this is even possible.
****
thats why i recreate it.
***
My point is, a program which has one of these which is NOT defined as CBS=
_OWNERDRAWFIXED
is an erroneous program, so you fix it in the dialog template once, and n=
ever again worry
about it.
****
if there's no way to let my code correct the error, i'd assert. but i
thought to use this flags myself, e.g. recreate a control with the
appropriate windowsflags needed for the control, and use the user-
defined flags for my own implementation (in this case, calling a user-
defined drawing routine instead of my own default drawing routine.)
____________________________________________
//-------------------------------------------------------------------=
----
// 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 n=
eed for the above
line.
no it is not. 'this' is a CQControl that has no CWnd as baseclass! for
example, the
CQComboBox is a public CComboBox, public CQControl.
****
That's a different question than the one you asked. You did not specif=
y that you are
using multiple inheritance.
i did'nt say i'm not using it;-) But you're right, assuming direct(?)
inheritance is the default.
But in that case, FromHandle is sufficient.
****
i just wanted to be shure.
****> ASSERT(pWnd != NULL);
ASSERT(pWnd == CWnd::FromHandle(m_hwnd));
if (pWnd == NULL)
return false;
****
The above statements are meaningless. You already have 'this' or yo=
u wouldn't be here. It
doesn't matter about what map it is in; you shouldn't care, either.
see above.
****
You have to provide *all* relevant information in order to get a correct =
answer
****
Note that I use this technique rather often to create a control in a s=
pace formerly
occupied by a CStatic, so I'm changing the entire control type. Thi=
s code is FAR too
complicated for such a simple task.
****
a static in Dialog-Editor would not look like a combobox.
CRect rc;
HWND hParent = GetParent(m_hwnd); =
// [1]
****
CWnd * parent = GetParent();
****
wrong. see above.
****
If you use multiple inheritance, a previously unstated case, then yes. =
But you can't ask
a question without giving all relevant information and expect to get a re=
levant answer
****
// get position and size of current window
GetWindowRect(m_hwnd, &rc); =
// [2]
****
I'm surprised this even compiles. There is no need to use the raw H=
WND. You could just
have written
GetWindowRect(&rc);
and get everything you need.
see above;-)
// following fn's need width and size, we recycle rc
rc.right = rc.Width(); =
=
// [3]
rc.bottom = rc.Height(); =
// [=
4]
***
This code is incorrect. You must not set the right and bottom in th=
is fashion, because
you are working with the window rect, and the width and height are ind=
ependent of the
coordinate system. Lose the two assignments above.
// translate into parents coordinates
ScreenToClient(hParent, &rc.TopLeft()); =
// [5]
****
Why are you not doing something as simple as
CRect rc;
GetWindowRect(&rc);
GetParent()->ScreenToClient(&rc);
this is all you need. You have a complex and convoluted solution to=
a simple problem.
Just translating the top/left coordinate makes no sense, because it wi=
ll 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.
****
Why do you need to define a new structure? You can just do
CRect rc;
::GetWindowRect(m_hWnd, &rc);
::ScreenToClient(parent, &rc);
where, now that I know you are using multiple inheritance, is still simpl=
er than the
complex code you wrote. And by setting the right and bottom to the Wid=
th() and Height(),
BEFORE transforming the top and left, you still get the wrong size.
****
=E4hm, no.. both rects are in pixel.
You have five overly complicated lines doing what two trivial lines wi=
ll accomplish.
****
// let derived class modify rc
OnCreationRect(rc);
****
I have no idea what this does because there is no handler called OnCre=
ationRect and you
have not given the code for this, but there's nothing I know that need=
s to 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)
{
RECT rcDropped;
GetDroppedControlRect(&rcDropped);
rc.bottom = rcDropped.bottom - rcDropped.top;
}
****
Using the 'On' prefix, which is used for handlers, is confusing. Calli=
ng it something
meaningful like ComputeDroppedRect might have made it less ambiguous as t=
o what was going
on.
****
// create a new window at current windows coordinates
HWND hNew = CreateWindowEx(dwStyleEx, QGetClassName(), "", =
dwStyle,
rc.left, rc.top, rc.right, rc.bottom, hParent=
, 0,
::AfxGetInstanceHandle(), NULL);
****
Why are you using the raw CreateWindowEx call? You can do this triv=
ially in MFC:
CWnd temp;
temp.CreateEx(dwStyleEx, QGetClassName=
(), _T(""), dwStyle, rc,
);
Note how simple this is. For that matter, does CQControl have a Cre=
ate method that would
be better?
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 =
will have two controls
with the same ID, but this will be changed momentarily, and causes no =
harm.
oh, i thought it was hMenu.
****
Note that it is specified as being the hMenu for a top-level window and t=
he control ID for
a child window. From the documentation:
"For a child window, hMenu specifies the child-window identifer, an integ=
er value..."
It will have to be cast to an HMENU to satisfy the compiler.
joe
****
But what you didn't do was make sure it is in the right place in the Z=
-order
temp.SetWindowPos(this, 0, 0, 0, 0, SWP_NOMOVE | SWP_N=
OSIZE);
DestroyWindow();
Attach(temp.Detach());
All this use of raw API and HWNDs is unneccessay.
*****
// destroy old window and attach new one
DestroyWindow(pWnd->Detach());
pWnd->Attach(hNew);
m_hwnd = hNew;
****
Get rid of all the above lines.
The convoluted nature of what you are doing is probably what leads to =
the assertion
failure. I wouldn't even try to debug this code, I would rewrite it=
as indicated. Then,
and only then, if there is still a bug, would I worry about it.
****
Since MFC does not normally support multiple inheritance, there can be so=
me confusing side
effects here that may account for it. What is the type of the object d=
isplayed by the
debugger?
it displayes the expected type (CQComboBox)
Is there a reason you chose to use multiple inheritance over direct inher=
itance? You are
working in unsupported areas here.
of course;-) i have a baseclass (CQControl) from with CQButton,
CQTree, CQComboBox and so on derive. Each derived class uses multiple
inheritance to derive from CQControl and its MFC-class. By doind this,
i can do the following:
void SomeFunction(CQControl* pCtrl)
{
pCtrl->QResetContent();
// add an red blinking element with id ELEMENT_ID to the control
pCtrl->QElmSet(ELEMENT_ID, QDS_SHOWN|QDS_BLINK, DYE_RED);
// set text of element ELEMENT_ID with detail id DETAIL_ID to "Some
Text"
// and add an image
pCtrl->QDtlSet(ELEMENT_ID, DETAIL_ID, _T("Some Text"),
ELEMENT_IMAGE);
// Select element ELEMENT_ID
pCtrl->QSelectionSet(ELEMENT_ID);
}
if pCtrl is a CQListView, you set element-row ELEMENT_ID, detail-
column DETAIL_ID to image ELEMENT_IMAGE, detail DETAIL_ID. if pCtrl is
a CQButton and you have more than one element, you get a multibutton.
if you dont have "columns" (Button, ListBox,..), the details appear
tab-separated. So you have the same syntax for all controls. Use in
programm: guess you have a function that shall fill a selection-
control with user-names and some additional infos (an icon per user or
a user-state-color and so on). this function just gets a CQControl*
and fills it. if it fills a Listview, a Treeview, a ListBox, a
ComboBox or even a Button just depents on the design of the GUI. More:
CQControl uses a special worker thread and does all the syncronisation
needed, so you could call the above SomeFunction() from ANY Thread;-)